O blog da AWS

Crie um pipeline com canary deployments para Amazon EKS com AWS App Mesh

Por Tiago Reichert, Arquiteto de Soluções AWS Brasil e
Bruno Emer, Arquiteto de Soluções AWS Brasil

 

Neste post, demonstraremos como utilizar diferentes serviços da AWS em conjunto com o AWS App Mesh para implementar uma estratégia de canary deployments para aplicações em execução no Amazon Elastic Kubernetes Service (Amazon EKS).

Fazendo uso de orquestradores de containers como Amazon EKS e Amazon ECS, clientes em todo o mundo podem executar milhões de containers. No entanto, ao aproveitar o poder dessas ferramentas, os clientes ainda precisam pensar em como gerenciar a conectividade, as operações e a segurança entre microsserviços nessas arquiteturas distribuídas para poder executar grupos de serviços altamente descentralizados.

O AWS App Mesh é um service mesh que facilita o monitoramento e o controle de serviços. O App Mesh padroniza a forma como seus serviços se comunicam, oferecendo visibilidade de ponta a ponta e ajudando a garantir alta disponibilidade para suas aplicações. O App Mesh oferece visibilidade consistente e controles de tráfego de rede para cada serviço em uma aplicação.

 

1. Canary deployments

O processo de implementação de aplicações monolíticas costuma ser doloroso e arriscado, visto que todas as necessidades de negócios existem em um único software e a infraestrutura fornecida para executar estas aplicações precisa ser atualizada com frequência. Essa abordagem pode causar muitos problemas quando os deployments não são bem-sucedidos e as versões antigas das aplicações não existem mais.

Existem, é claro, maneiras de lidar com isso, como backups e blue/green deployments, em que um ambiente totalmente novo é criado e o tráfego muda para a nova versão da aplicação, mantendo o ambiente antigo em funcionamento. A tecnologia de containers também ajuda aqui, desempenhando um papel importante em torno do empacotamento de todos os itens necessários para a execução das aplicações, mas uma coisa que não é endereçada nestas abordagens é a experiência do usuário, e é aqui que o conceito de canary deployments começa a fazer mais sentido.

Com canary deployments (ou canary releases), você alterna o tráfego em pequenos incrementos de porcentagem após implementar uma nova versão de uma determinada aplicação. Um canary deployment também pode monitorar a integridade da nova versão, portanto, se houver um problema, é possível alterar automaticamente o tráfego de volta para a versão antiga, diminuindo drasticamente o impacto de bugs nas novas versões das aplicações. Essa abordagem ajuda não apenas com novos deployments, mas também aborda a necessidade de testes em microsserviços complexos e distribuídos, onde você pode enviar uma quantidade específica de tráfego para versões mais recentes de maneira controlada:

 

2. Visão geral da arquitetura

O diagrama de arquitetura abaixo representa uma visão geral dos serviços da AWS que serão usados para criar o pipeline:

 

Para demonstrar essa arquitetura, usaremos uma aplicação chamada Yelb. Yelb permite que os usuários votem em um conjunto de alternativas, como restaurantes, e atualiza gráficos de pizza dinamicamente com base nos votos. Além disso, Yelb mantém o controle do número de visualizações de página e mostra o hostname do yelb-appserver que atende a solicitação de API em uma votação ou atualização de página. Os componentes Yelb incluem:

  • Um frontend chamado yelb-ui que é responsável por fornecer o código JS ao navegador.
  • Um application server chamado yelb-appserver, uma aplicação Sinatra que lê e grava em um servidor de cache (redis-server) e um banco de dados Postgres (yelb-db).
  • O Redis armazena o número de visualizações de página e o Postgres armazena os votos.

Visão geral da arquitetura de Yelb:

 

 

Yelb utiliza discos efêmeros para todos os containers. A execução de bancos de dados dessa forma é feita apenas para fins de demonstração.

 

3. Configure a infraestrutura

Durante as próximas etapas deste post, usaremos a região AWS chamada Oregon.

Para os próximos passos, você precisará ter um ambiente com algumas ferramentas. Usamos uma instância AWS Cloud9 para executar este tutorial. Se você deseja criar uma instância Cloud9 em sua conta, siga as etapas no workshop EKS do capítulo “Create a Workspace” até “Update IAM settings for your workspace”.

3.1 Requisitos

Existem alguns requisitos a serem instalados e configurados antes de criar o pipeline. Comece clonando o repositório do GitHub:

git clone https://github.com/aws/aws-app-mesh-examples.git
cd aws-app-mesh-examples/blogs/eks-canary-deployments-pipeline/

Para sua comodidade, criamos alguns scripts que estão dentro da pasta setup dos recursos que você acabou de baixar. Esses scripts foram criados para serem usados com uma instância AWS Cloud9. Sinta-se à vontade para lê-los caso queira saber o que exatamente eles fazem.

Você precisará de jq, eksctl, kubectl, aws-cli e helm instalados durante a execução das próximas etapas:

./setup/install_dependencies.sh

Você também terá que exportar algumas variáveis de ambiente (você pode personalizar essas variáveis de acordo com suas necessidades):

./setup/export_environment_variables.sh && source ~/.bash_profile

3.2 Cluster Amazon EKS

O Amazon EKS é um serviço gerenciado que facilita a execução do Kubernetes na AWS, sem a necessidade de instalar, operar e manter seu próprio control plane do Kubernetes. Kubernetes é um sistema de orquestração de código aberto para automatizar a implantação, escalonamento e gerenciamento de aplicações em containers.

Agora vamos criar um cluster EKS para ser usado durante as próximas etapas:

./setup/create_eks_cluster.sh

Demora cerca de 15 minutos para que o cluster seja criado, fique à vontade para tomar um café! Para obter mais detalhes sobre como criar o cluster, você pode consultar esta documentação. Depois de concluído, você pode testar a conectividade do cluster da seguinte forma:

$ kubectl get svc  
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   172.20.0.1   <none>        443/TCP   14m

3.3  Controlador AWS App Mesh para Kubernetes

O AWS App Mesh controller para Kubernetes permite gerenciar recursos do AWS App Mesh, como service meshes, virtual services, virtual nodes, virtual routes e rotas por meio de Kubernetes. Você também adiciona automaticamente as imagens do sidecar container do App Mesh às especificações do pod do Kubernetes. Para obter mais detalhes, você pode consultar esta documentação.

Se você estiver usando um cluster EKS existente, terá que confirmar que não há uma versão de pré-lançamento instalada:

curl -o pre_upgrade_check.sh https://raw.githubusercontent.com/aws/eks-charts/master/stable/appmesh-controller/upgrade/pre_upgrade_check.sh


chmod +x pre_upgrade_check.sh && ./pre_upgrade_check.sh

Deve retornar ” Your cluster is ready for upgrade. Please proceed to the installation instructions “.

Em seguida, instale o App Mesh controller:

./setup/install_appmesh_controller.sh

3.4 Amazon CloudWatch Container Insights

O CloudWatch Container Insights permite que você colete, agregue e resuma métricas e logs de seus aplicativos e microsserviços em containers. As métricas incluem a utilização de recursos como CPU, memória, disco e rede. O Container Insights também fornece informações de diagnóstico, como falhas de reinicialização do contêiner, para ajudá-lo a isolar problemas e resolvê-los rapidamente. Para obter mais detalhes, você pode consultar esta documentação.

./setup/install_cloudwatch_container_insights.sh

 

4. Criação do pipeline

Agora que você tem todos os requisitos instalados e configurados, pode prosseguir com a criação do pipeline.

4.1 Camada do AWS Lambda

Um AWS Lambda Layer que tem kubectl, awscli, helm e jq será utilizado em nosso pipeline para se comunicar com o cluster Amazon EKS. Para obter mais informações sobre o Lambda Layer, usada, acesse este aws-samples:

./setup/aws_lambda_layer.sh

Apenas passe para a próxima etapa se o último comando retornou CREATE_COMPLETE.

4.2 Stack AWS CloudFormation compartilhada

A stack compartilhada do AWS CloudFormation contém várias funções Lambda e uma máquina de estado do AWS Step Functions que será responsável pelo estágio de deploy do pipeline. Como ela aceita todos os parâmetros de configuração como entrada, você pode usar os mesmos recursos para todos os deployments.

./setup/create_shared_cloudformation_stack.sh

Apenas passe para a próxima etapa se o último comando retornou CREATE_COMPLETE.

Depois que a stack do AWS CloudFormation for criada, você precisará adicionar a role IAM da função Lambda do output do AWS CloudFormation ao Kubernetes RBAC para permitir deployments no cluster do Kubernetes.

./setup/add_iam_role_to_rbac.sh

4.3 Stack AWS CloudFormation de pipeline

A stack do AWS CloudFormation de pipeline foi projetada para ser utilizada para cada microsserviço que você possui. Ele criará um repositório AWS CodeCommit e o pipeline que será acionado por novos commits no branch master desse repositório.

Para fins de demonstração, você criará quatro stacks com os microsserviços Yelb. Você pode alterar a variável de ambiente chamada USE_SAMPLE_MICROSERVICES para 'False' para criar todos os recursos necessários para o pipeline com um repositório AWS Code Commit vazio para ser usado com seu próprio código-fonte.

Antes de implantar os microsserviços, você precisará de um namespace Kubernetes e de um mesh do AWS App Mesh para os microsserviços. Vamos criar um namespace e um mesh chamados yelb:

NAMESPACE=yelb MESH=yelb envsubst < setup/namespace_and_mesh.yml | kubectl apply -f -

Agora podemos criar os microsserviços. Como a arquitetura Yelb contém quatro microsserviços, criamos um script que criará todas as stacks do AWS CloudFormation necessárias (você pode abrir o script para ver seus detalhes):

./setup/create_microservice_pipeline_stack.sh

Apenas passe para a próxima etapa se o último comando retornou All four stacks created successfully!

 

5. Testando o pipeline

Agora que você criou completamente a arquitetura, pode começar a examiná-la para ver como funciona.

5.1 Arquivos de configuração

Primeiro, vamos dar uma olhada nos repositórios do AWS CodeCommit, você encontrará uma pasta chamada specfiles em cada repositório com 3 arquivos nela.

1. build.yml tem as etapas para construir a imagem Docker e salvá-la no Amazon ECR. Ele também adiciona dois parâmetros adicionais para deploy.json:

a. container_imageé adicionado ao arquivo deploy.jsoncom o URI da imagem Docker depois dela ser enviada para Amazon ECR.

b. config_fileé adicionado ao arquivodeploy.json com o conteúdo de kubernetes_template.yml codificado em base64.

2. deploy.json tem os parâmetros de configuração para implantar o microsserviço.

a. cluster_name é o nome do cluster EKS no qual você deseja fazer deploy.

b.kubernetes_namespace é o nome da namespace do Kubernetes na qual você deseja fazer deploy.

c.microservice_name é o nome do microsserviço.

d. percentage_step representa a quantidade de tráfego alterada para a nova versão em incrementos.

e.wait_time representa o tempo em segundos de espera entre cada troca de tráfego.

f.failure_threshold_value é opcional e usado para especificar o máximo permitido de resposta código HTTP 5xx antes de acionar um rollback automático. [default = 0]

g. failure_threshold_time é opcional e usado para especificar o intervalo de tempo em segundos para contar a quantidade resposta código HTTP 5xx. O valor mínimo recomendado é 60 porque o filtro de métrica CloudWatch usado agrega e relata a cada minuto. [default = 600]

3. kubernetes_template.yml é o template specfile para criar o novo microsserviço com kubectl. Você notará que tem algumas variáveis:

a. KUBERNETES_NAMESPACE será substituído pelo valor de kubernetes_namespace do arquivo json.

b. MICROSERVICE_NAMEserá substituído pelo valor de microservice_name  do arquivo json.

c. CONTAINER_IMAGE será substituído pela nova imagem do contêiner construída durante a execução do pipeline e armazenada dentro do Amazon ECR.

d. CANARY_VERSION será substituído pela nova versão durante o deploy.

e. CANARY_ROUTES será substituído pelos incrementos de troca de tráfego durante o deploy.

Todo o restante dentro dos repositórios AWS CodeCommit é o código-fonte da aplicação Yelb.

5.2 Recursos do pipeline

A maneira mais fácil de examinar os recursos criados é abrir o AWS CodePipeline. Você verá os quatro pipelines que criou anteriormente:

 

Você pode abrir um deles e ver as etapas Source, Build e Deploy. Essas etapas são todas personalizáveis. Você pode adicionar antes do deploy, por exemplo, verificações de segurança ou aprovações manuais.

 

 

    1. A etapa Source monitora se há alguma alteração no branch master do repositório AWS CodeCommit. Você pode acessar o repositório clicando no link AWS CodeCommit dentro da etapa de origem.
    2. A etapa Build constrói a imagem Docker com AWS CodeBuild e a armazena no Amazon ECR. Você pode ver os logs de construção clicando no link Detalhes da etapa de construção.
    3. A etapa Deploy aciona a máquina de estado do AWS Step Functions criada pela stack do AWS CloudFormation compartilhada. Você pode ver seu status clicando no link Detalhes.

 

 

 

 

 

 

 

 

 

 

 

Clique no link Detalhes da etapa Deploy e você verá a entrada e saída de cada etapa, bem como as funções AWS Lambda e os logs de execução:

 

 

Um deploy bem-sucedido que alterou 100% do tráfego para a nova versão e passou em todas as verificações de integridade se parece com as seguintes imagens:

 

5.3 Deploy de uma nova versão

Agora vamos ver a aplicação Yelb funcionando e fazer algumas alterações para ver como o pipeline se comporta.

echo "http://$(kubectl get -nyelb service/yelb-ui-1 -o json | jq -r '.status.loadBalancer.ingress[0].hostname')"

Abra a URL retornada pelo comando acima em seu navegador preferido. Você deverá ver uma página semelhante à seguinte (pode levar alguns minutos para que o nome DNS seja propagado):

 

Clique em alguns botões para votar e veja como os valores são atualizados. Você notou algo errado ao votar?

Adicionamos intencionalmente um problema ao microsserviço yelb-appserver para que seja incrementado em dois cada vez que houver um voto. Agora vamos corrigir esse problema e ver como isso é aplicado.

Abra o AWS CodeCommit e navegue até o repositório yelb-appserver, abra o arquivo modules/restaurantsdbupdate.rb e clique no botão Editar para corrigir o problema. Mude a linha:

con.prepare('statement1', 'UPDATE restaurants SET count = count +2 WHERE name = $1')

para:

con.prepare('statement1', 'UPDATE restaurants SET count = count +1 WHERE name = $1')

e confirme as alterações.

 

Vá para AWS CodePipeline e após alguns segundos você verá que o yelb-appserver-pipeline está Em andamento. Abra-o para ver o andamento do deploy. Espere até chegar ao estágio Deploy e, em seguida, atualize a aba do navegador com o aplicativo Yelb algumas vezes. Você verá que a versão do App Server (conforme mostrado na imagem abaixo) alternará entre yelb-appserver-1 e yelb-appserver-2, ou seja, o canary deployment está ocorrendo.

 

 

Abra o virtual router do AWS App Mesh para o microsserviço yelb-appserver e você poderá ver como estão os pesos neste momento. Você também pode abrir o arquivo deploy.json no repositório yelb-appserver AWS CodeCommit para ver os parâmetros percentage_step e wait_time para saber quanto tempo levará para alternar todo o tráfego. Para este exemplo, os valores percentage_step: 10 e wait_time: 60 foram usados e levará um total de 10 minutos para alternar todo o tráfego.

Após a conclusão do deployment, você pode tentar votar no aplicativo Yelb novamente e ver que agora ele incrementa os votos de um em um.

5.4 Deploy de uma versão que acione um rollback

Abra o arquivo yelb-appserver.rb do repositório yelb-appserver do AWS CodeCommit e altere a porta da aplicação na configuração de produção (linha 33) de 4567 para 4568 e confirme as alterações.

Isso irá acionar o yelb-appserver-pipeline e implantar uma nova versão do microsserviço yelb-appserver que não funciona. Abra yelb-appserver-pipeline no AWS CodePipeline e aguarde até que o estágio Deploy esteja Em andamento. Em seguida, clique em Detalhes no estágio Deploy. Nesta página, você verá o fluxo visual durante o deploy.

Tente atualizar o aplicativo Yelb algumas vezes. Você verá que, às vezes, ao atualizar, não há dados de voto retornados e você não pode votar. Isso ocorre porque você está sendo redirecionado para a nova versão que não está funcionando.

Aguarde alguns minutos e você verá no fluxo visual que um rollback foi disparado porque a nova versão não passou na verificação de integridade. É importante observar que a verificação de integridade é uma função do AWS Lambda que pode ser personalizada, se necessário.

 

 

Agora você pode atualizar o aplicativo Yelb algumas vezes novamente e ele funcionará corretamente usando a versão anterior (yelb-appserver-2).

 

6. Conclusão

Neste post, demonstramos como você pode usar o AWS App Mesh e implementar uma estratégia de canary deployments em conjunto com outros serviços AWS, como AWS Code Pipeline e AWS Step Functions.

Outra maneira para a realização de canary deployments com AWS App Mesh e Amazon EKS é utilizar o Weave Flagger. O Flagger usa métricas do Prometheus para determinar o sucesso ou falha dos canary deployments e usa os controles de roteamento do App Mesh para mudar o tráfego entre o deployment atual e o canary.

Além disso, alguns links úteis se você quiser se aprofundar no AWS App Mesh:

Você pode acompanhar as próximas funcionalidades por meio do roadmap do App Mesh e experimentar novas funcionalidades usando o App Mesh preview channel. Você também pode se juntar a nós na comunidade App Mesh do Slack para compartilhar experiências.

 

Este artigo foi traduzido do Blog da AWS em Inglês.

 


Sobre os autores

Tiago é Arquiteto de Soluções na AWS Brasil com foco em ajudar parceiros ISV em sua jornada na nuvem. Ele tem grande interesse por IoT, containers e DevOps.

 

 

 

 

Bruno é Arquiteto de Soluções em São Paulo, Brasil. Quando não está trabalhando com clientes ou escrevendo conteúdo, gosta de viajar e ouvir música, principalmente samba e R&B.