Utilizando AWS Fargate Spot para economizar até 70% em aplicações ECS
Tags: cloud, aws, java, finops
Published: 2022-07-26 16:45:19

Um forma simples de configurar instâncias Fargate Spot para containers ECS, sendo pelo console ou CloudFormation

Escrevi este artigo após identificar uma necessidade na empresa em que trabalho, acredito que possa ser útil para quem utiliza o Elastic Container Service (ECS) no dia a dia e deseja diminuir custos, principalmente em ambiente de desenvolvimento e homologação, assim como foi o meu caso!

Antes de tudo, o ECS é um orquestrador de containers que permite provisionar aplicações de uma forma simples e rápida, possibilitando escalabilidade e um rápido deploy. Com ele é possível utilizar instâncias EC2, onde a infraestrutura fica por nossa conta, ou por meio do AWS Fargate onde não há necessidade por parte do cliente de gerenciar máquinas (Essa segunda opção é a que vamos utilizar).

Em 2019 foi lançado o Fargate Spot que segue o mesmo conceito das instâncias Spot para Amazon EC2, ele busca oferecer uma forma de econômica para os usuários da cloud fornecendo capacidade não utilizada pela AWS. Então quando solicitadas tarefas Spot será desta capacidade ociosa que elas sairão. Clientes que adquirem instâncias dedicadas tem preferência para tais recursos, por conta disso essa capacidade pode ser retirada a qualquer momento para que estes clientes, que optaram pela opção mais cara, possam utilizar. Você receberá uma notificação dois minutos antes da AWS precisar destes recursos de volta. Contudo, o principal motivo para utilizar Instâncias Spot é cortar custos, o preço (por hora de CPU e GB) de uma Task Spot é variável, com um desconto de 50% a 70% sobre o preço de uma tarefa sob demanda. Então, não se preocupe, definindo a estratégia certa seu sistema não ficará indisponível. Contudo, antes de utilizar em ambiente produtivo pense bem na estratégia que irá implantar, para assim evitar problemas de indisponibilidade ocasionais (📝#dica do Jean ).

> Como sempre busco em meus artigos, para exemplificar de forma prática vamos subir uma aplicação Spring Boot com a infra sendo provisionada por um CloudFormation.

Então, com os conceitos básicos explicados, vamos começar criando os recursos necessários em nosso Console AWS, e caso queira pular para o template CloudFormation acesse [aqui](https://github.com/jjeanjacques10/springboot-ecs-fargate/blob/main/template.yml).

Existem dois tipos de configuração, uma sendo no Cluster, a qual será replicada para todos os serviços dentro dele e a feita para um serviço específico. Caso seu Cluster possua mais de um Service e você apenas queira implementar essa estratégia em um único, neste cenário não é necessário configurar o Cluster, apenas o Service.

## Criando um Cluster

E é aqui que faremos a configuração para aceitar a estratégia de Fargate Spot. Na aba do serviço Elastic Container Service selecione a opção “Networking only”

![Criação do cluster](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xi7ylrzwgvcqvmze4mxw.png)

Após provisionar o Cluster podemos verificar que por padrão nosso Capacity Providers já está configurado para aceitar ambos: **FARGATE ** e **FARGATE_SPOT**.
 
![Tela de configuração do Cluster Digimon](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fzh63gvlj4gwdvabrxeq.png)

Para definir quais estratégias queremos utilizar devemos clicar no botão de “Update” no canto superior direito.
 
![Configuração do capacity provider strategy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0pu8rjjg07ivswjugcg.png)

Nesta tela de configuração selecionamos a estratégia que nosso cluster irá utilizar, nesse caso selecionei ambos os provedores de capacidade. Defini o peso (weight) de 1 para **FARGATE** e 5 para **FARGATE_SPOT**. Com esses valores definidos para cada seis tarefas, cinco são iniciadas no **FARGATE_SPOT** e uma no FARGATE. Claro que você deverá escolher a estratégia que melhor se encaixa com sua necessidade, o que dependerá também de qual ambiente está realizando essas modificações. Por exemplo, o ambiente de desenvolvimento tem menos necessidade de instâncias apenas FARGATE e quanto mais Spots menor a conta no final do mês.

### CloudFormation: Cluster

Para realizar configuração do Fargate Spot por meio do Cloudformation devemos adicionar ao nosso Cluster os atributos de CapacityProvider, neles definimos o peso que cada estratégia deve ter como fizemos pelo Console AWS.

``` yml
EcsCluster:
  Type: 'AWS::ECS::Cluster'
  Properties:
    ClusterName: !Sub '${EcsClusterName}'
    CapacityProviders:
      - FARGATE
      - FARGATE_SPOT
    DefaultCapacityProviderStrategy:
      - CapacityProvider: FARGATE
        Weight: 1
      - CapacityProvider: FARGATE_SPOT
        Weight: 1
```

## Criando uma Task Definition

No lado esquerdo clique em “Task Definitions”, vamos criar uma nova task do tipo “FARGATE”, no caso é a primeira opção:

![Opção de Fargate no AWS Console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/729towd996rnnga516l7.png)
 
Faça as configurações básicas de Role, network e sistema operacional e configuração do container que será utilizado. Para simular criei uma imagem no Amazon Elastic Container Registry (ECR) com a aplicação SpringBoot dentro dela, pode utiliza-la ou fazer com uma imagem própria.

> [ECR Public Gallery — digimonapi](https://gallery.ecr.aws/o2n5f4o6/digimonapi)

Nesta etapa não precisamos configurar nada relacionado a instância **Fargate Spot**, apenas nos certificarmos que a opção selecionada foi “Fargate”.

### CloudFormation: Task Definition

No Cloudformation um ponto de atenção é adicionar o atributo “**RequiresCompatibilities**” sendo igual a FARGATE.

``` yml
TaskDefinition:
  Type: 'AWS::ECS::TaskDefinition'
  Properties:
    ContainerDefinitions:
      - Name: !Sub '${ContainerName}'
        Image: !Ref ImageDocker
        PortMappings:
          - ContainerPort: !Ref ListenerContainerPort
            HostPort: !Ref ListenerContainerPort
        Cpu: !Ref ContainerCpu
        Memory: !Ref ContainerMemory
        MemoryReservation: !Ref ContainerMemoryReservation
        Essential: true
    Family: !Sub 'family-${FeatureName}-${MicroServiceName}'
    NetworkMode: awsvpc
    Memory: !Ref ContainerMemoryReservation
    Cpu: !Ref ContainerCpu
    ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
    TaskRoleArn: !Ref TaskExecutionRole
    RequiresCompatibilities:
      - FARGATE
``` 

## Criando um Service

Agora vamos criar um serviço para gerenciar melhor as Tasks que ficarão rodando. Vá até seu Cluster entre na aba de “Services” e clique em “Create”. Podemos fazer a mesma configuração de estratégia que fizemos para o Cluster ao nível de Service.

![Como é apresentado no console AWS a mudança do Service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ia1u174rbvmgailaz2tb.png)
 
### CloudFormation: Service

A configuração aqui também é bem semelhante, iremos passar o “_CapacityProvider_” criando uma estratégia personalizada para este serviço.

``` yml
Service:
  Type: "AWS::ECS::Service"
  Properties:
    ServiceName: !Sub service-${FeatureName}-${MicroServiceName}
    Cluster: !Ref EcsClusterName
    DeploymentConfiguration:
      MinimumHealthyPercent: 100
      MaximumPercent: 200
    DesiredCount: 2
    HealthCheckGracePeriodSeconds: 40
    CapacityProviderStrategy:
      - CapacityProvider: FARGATE_SPOT
        Weight: 5
      - CapacityProvider: FARGATE
        Weight: 1
    PlatformVersion: '1.4.0'
    LoadBalancers:
      - ContainerName: !Sub ${ContainerName}
        ContainerPort: !Ref ListenerContainerPort
        TargetGroupArn: !Ref TargetGroup
    SchedulingStrategy: REPLICA
    TaskDefinition: !Ref TaskDefinition
    NetworkConfiguration:
      AwsvpcConfiguration:
        AssignPublicIp: ENABLED
        SecurityGroups:
          - !Ref SecurityGroup
        Subnets: !Ref PrivateSubnets
```

## Rodando as aplicações

Com tudo configurado vamos ativar nosso service para provisionar novas instâncias e observar o comportamento delas.

![Tarefas do service rodando](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trtl19bhq737dj124yv6.png)

Acessando as tasks para ter uma visão mais detalhada podemos verificar quais delas foram provisionadas como FARGATE_SPOT. A primeira está como FARGATE e a partir da segunda task já temos o desconto de 50% à 70% por tarefa rodando.
 
![Image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otzvd3yjdprcuy2qn8bn.png)
 
Os exemplos descritos neste artigo estão melhor detalhados no seguinte repositório (qualquer dúvida abra uma Issue ou comente):

> **Repositório GitHub**
https://github.com/jjeanjacques10/springboot-ecs-fargate


## Conclusão

Seguindo esse passo a passo podemos provisionar tarefas em nossos ECS’s com desconto na Cloud AWS, nos testes que realizei consegui ver a diferença de custos em média de 72%. Claro que em alguns casos essa abordagem não é a melhor, principalmente porquê estes recursos podem ser solicitados pela AWS quando necessário. Então analise o que faz mais sentido para o seu cenário atual e suas necessidades.

Agora é buscar aplicar estes conceitos em suas aplicações, sugiro como novamente que façam testes em ambiente não produtivo, que na minha opinião é o ideal, não queremos ter instâncias não dedicadas sendo utilizadas diretamente pelo cliente final.

Gostaria de agradecer a [Kamila Peres](https://www.linkedin.com/in/kamiladekassiaperes) por ter me apresentado esse conceito e me incentivado a ir mais a fundo nos estudos.

----

Caso tenha alguma crítica, sugestão ou dúvida fique a vontade para me enviar uma mensagem:

Linkedin: <https://www.linkedin.com/in/jjean-jacques10/>

Até a próxima!


## Referências

- AWS Fargate Spot Now Generally Available | AWS News Blog (amazon.com) <https://aws.amazon.com/blogs/aws/aws-fargate-spot-now-generally-available/>

- AWS Fargate Spot vs. Fargate price comparison <https://tomgregory.com/aws-fargate-spot-vs-fargate-price-comparison/>

- Fully Managed Container Solution — Amazon Elastic Container Service (Amazon ECS) — Amazon Web Services<https://aws.amazon.com/ecs/>

- Provision Infrastructure As Code — AWS CloudFormation — Amazon Web Services <https://aws.amazon.com/cloudformation/>

- The trouble with Fargate Spot — The Scale Factory <https://www.scalefactory.com/blog/2020/07/27/the-trouble-with-fargate-spot/>