Configuração do Elastic Beanstalk para melhorar a tolerância a falhas e o dimensionamento automático

Carlos Filho - May 15 - - Dev Community

Olá a todos, o artigo de hoje, como você viu no título, trata da configuração do Elastic Beanstalk, especificamente do balanceador da AWS e do número de instâncias do TagretGroup, dependendo das condições de que precisamos.

Introdução ao Elastic Beanstalk

O Elastic Beanstalk é uma plataforma de serviços de alto nível que automatiza a implantação de aplicativos na nuvem. O EB configura automaticamente a infraestrutura e os recursos necessários, como instâncias EC2 (servidores virtuais), grupos de segurança, objetos S3 para armazenar arquivos de versão de aplicativos, bancos de dados RDS, balanceadores de carga Elastic Load Balancing e muito mais para garantir que o aplicativo seja lançado com o mínimo de tempo e esforço por parte do desenvolvedor.

Os principais componentes do Elastic Beanstalk são:

  1. Aplicativo é a unidade básica. Primeiro, você cria um aplicativo que serve como um contêiner para suas versões e ambientes.

  2. Um ambiente é uma versão do aplicativo que é implantada em uma infraestrutura específica do AWS e serve a uma função específica, como um ambiente de teste ou de produção.

Recursos com os quais estaremos lidando:

  • EC2 (Elastic Compute Cloud) são servidores virtuais que podem ser locados na nuvem da AWS para executar aplicativos.

  • Grupo de destino (Target Group) é um conceito usado na AWS para gerenciar o tráfego no nível do aplicativo. Os Target Groups permitem que você especifique exatamente para onde o tráfego que chega ao Load Balancer deve ser direcionado. Cada Target Group está associado a um recurso específico, como EC2 ou funções lambda.

  • Os Auto Scaling Groups permitem que o número de instâncias do EC2 seja dimensionado automaticamente em resposta a alterações na carga ou em outros fatores.

Após uma breve descrição do EB, vamos ao tópico do artigo.

  • Introdução e desafios

Image descriptionImagem 1

O aplicativo estava sendo executado em uma única instância c5.xlarge e todas as verificações de status do AWS mostravam “Sucesso”, a máquina estava no estado “Em execução”, mas o aplicativo não estava respondendo. Depois de examinar os logs do servidor, percebemos que o problema era devido à reinicialização do IIS (esse é um procedimento padrão - geralmente acontece a cada 29 horas, mas você também pode definir o período individualmente).

Elastic Beanstalk

O Elastic Beanstalk não foi projetado para funcionar com uma única máquina, então, criamos esse estágio:

  • 2x c5.large (c5.large é exatamente 2 vezes mais barato que c5.xlarge);

  • Se em 5 minutos a carga da CPU for >80%, adicionaremos outra instância.

  • Se a carga da CPU for <40% em 5 minutos, removeremos uma instância.

Image descriptionImagem 2

Resources:
  AWSEBAutoScalingGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    Properties:
      MinSize: 2
      MaxSize: 3

  AWSEBCloudwatchAlarmHigh:
    Type: "AWS::CloudWatch::Alarm"
    Properties:
      EvaluationPeriods: 1 
      MetricName: CPUUtilization
      Namespace: AWS/EC2
      Period: 300
      Statistic: Average
      ComparisonOperator: GreaterThanOrEqualToThreshold
      Threshold: 80
      Unit: Percent
      AlarmActions:
        - Ref: "AWSEBAutoScalingScaleUpPolicy"

  AWSEBCloudwatchAlarmLow:
    Type: "AWS::CloudWatch::Alarm"
    Properties:
      EvaluationPeriods: 1
      MetricName: CPUUtilization
      Namespace: AWS/EC2
      Period: 300
      Statistic: Average
      ComparisonOperator: LessThanOrEqualToThreshold
      Threshold: 40
      Unit: Percent
      AlarmActions:
        - Ref: "AWSEBAutoScalingScaleDownPolicy"

  AWSEBAutoScalingScaleUpPolicy:
    Type: "AWS::AutoScaling::ScalingPolicy"
    Properties:
      AdjustmentType: ChangeInCapacity
      AutoScalingGroupName:
        Ref: "AWSEBAutoScalingGroup"
      Cooldown: 360
      ScalingAdjustment: 1
Enter fullscreen mode Exit fullscreen mode

O principal problema com essa solução é que ela não funcionará como pretendido - por padrão, o AWS presume que, se todas as verificações de status em uma instância forem aprovadas, não há problema em permitir o tráfego nela. O que é errado para o nosso estudo de caso - precisamos adicionar nosso próprio HealthCheck.

Vamos começar!

Configuração
Para a configuração, precisamos de um ID de ambiente e dessas guias na barra lateral do EC2, procure por Target Groups e posteriormente vamos em Auto Scaling Groups:

Image descriptionImagem 3

Vamos seguir a ordem:

  1. Target Groups Aqui precisamos definir a configuração do Target Group de acordo com nossos critérios de tempo de atividade. Em nosso caso, consideramos suficiente detectar uma máquina não saudável após 1 minuto: 3 solicitações a cada 15 segundos + timeouts (5 segundos) = 1 minuto.

Image descriptionImagem 4

Além disso, na guia Attributes (Atributos), há um parâmetro importante: Deregistration delay (Atraso no cancelamento do registro). Quando um registro deixa de responder no /hc, ele deve ser substituído no tempo especificado nesse parâmetro:

Image descriptionImagem 5

Resources:
  AWSEBV2LoadBalancerTargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      HealthCheckIntervalSeconds: 15
      HealthCheckPath: /hc
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 5
      UnhealthyThresholdCount: 3
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: '20'
Enter fullscreen mode Exit fullscreen mode
  1. Auto Scaling Groups Habilitar HealthChecks e definir período de carência.

O parâmetro mais importante, sem o qual todas as configurações acima não serão aplicadas:

Image descriptionImagem 6

Para adicionar verificações de ELB, clique em “Ativar verificações de integridade do Elastic Load Balancing” e defina o período de carência da verificação de integridade.

O período de carência da verificação de integridade é um período de espera durante o qual o AWS não tomará nenhuma medida para remover ou substituir instâncias recém-criadas (ou em execução) em um Auto Scaling Group, mesmo que elas falhem na verificação de integridade.

Imagine que, acabamos de lançar um novo aplicativo e ele precisa de algum tempo para ser totalmente inicializado e começar a funcionar corretamente. Se o AWS começasse a verificar imediatamente se ele está funcionando como deveria e ainda visse que algo está errado (porque o aplicativo ainda precisa de tempo para concluir todos os processos de inicialização), o AWS o rotularia como não saudável e tentaria reiniciá-lo ou criar uma nova instância.

Image descriptionImagem 7

Selecionar o período de carência ideal não é a tarefa mais trivial. Simplesmente medimos quanto tempo leva, em média, para que um novo aplicativo comece a enviar 200 solicitações. Para o nosso exemplo, esse tempo é inferior a 8 minutos, portanto, definimos o valor de 500 segundos com uma reserva.

Atenção: Você deve levar em conta diferentes fatores que podem aumentar o tempo de carregamento do aplicativo: migrações de banco de dados ou atualizações importantes do aplicativo. Nesses casos, você precisará aumentar o período de carência manualmente.

Resources:
  AWSEBAutoScalingGroup:
    Type: "AWS::AutoScaling::AutoScalingGroup"
    Properties:
      HealthCheckType: ELB
      HealthCheckGracePeriod: 500
Enter fullscreen mode Exit fullscreen mode

Política de manutenção de instâncias

Também precisamos permitir que o ELB exceda o limite de N instâncias caso uma delas não esteja respondendo, mas ainda não tenha sido removida do EB. Ou seja, queremos permitir que uma instância seja adicionada preventivamente enquanto a que não está funcionando estiver sendo excluída. Como resultado, teremos 1 instância a mais do que o permitido no EB de uma só vez. Para fazer isso, selecione o parâmetro “Instance maintenance policy” (Política de manutenção de instância) no Auto Scaling Group e defina-o como Launch before terminating (Iniciar antes de encerrar):

Image descriptionImagem 8

Experimento (hora da verdade)
Vamos verificar como o balanceador se comportará se pararmos propositalmente nosso aplicativo em uma instância (por exemplo, com o comando Stop-Service)

Vamos alterar ligeiramente nossa configuração para o experimento - o número máximo de instâncias será 2, mantendo os mesmos parâmetros de CPU:

Image descriptionImagem 9

Vemos instâncias de trabalho:

Image descriptionImagem 10

Provisionei uma EC2 Windows Server para teste:

Image descriptionImagem 11

Em um minuto (de acordo com nossas configurações de TargetGroups), veremos a seguinte imagem:

Image descriptionImagem 12

A instância falhou logicamente no HealthCheck e agora todo o tráfego vai para a única instância restante.

E, ao mesmo tempo (como lembramos, em 20 segundos), uma nova instância é iniciada, mesmo antes de a anterior ser excluída! Como resultado, vemos 3 instâncias (é claro, sempre haverá apenas 2 instâncias funcionando):

Image descriptionImagem 13

Depois de excluir uma instância que não está funcionando, nosso sistema retorna a um estado estável de duas máquinas funcionando.

Isso também pode ser visto nos Eventos de Envio do EB:

Image descriptionImagem 14

Espero que você tenha aprendido mais sobre a configuração do Elastic Beanstalk no AWS.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .