O blog da AWS

Utilizando AWS Copilot para criar uma infraestrutura de Amazon ECS com AWS AppMesh

Por João Melo, Solutions Architect, Financial Services
Amanda Quinto, Sr. Solutions Architect, Public Sector

 

Introdução

O deploy de aplicações, a gestão de ecossistemas de microsserviços, a criação e monitoramento de orquestradores de contêineres são aspectos que profissionais de TI devem analisar ao criar ambientes de infraestrutura desacoplados na nuvem. Existem diversas ferramentas que podem ajudar a resolver esses desafios, porém implementá-las (mesmo com infraestrutura como código) acabam gerando mais complexidade tornando os templates/scripts cada vez mais extensos e acoplados.

Neste blog iremos explicar como utilizar ferramentas AWS para facilitar a implementação e monitoramento de microsserviços, reduzindo a complexidade utilizando o AWS Copilot como uma opção de infraestrutura como código, o Amazon Elastic Container Service (Amazon ECS) como orquestrador de conteinêres, e realizar a gestão de observabilidade e tráfego com o AWS App Mesh e AWS X-Ray.

Entendendo os conceitos

Antes de entrarmos na solução técnica, vamos entender os conceitos por trás das tecnologias utilizadas.

Estrutura como Código

A criação de serviços e soluções de infraestrutura utilizando código é a prática conhecida como IaC – Infrastructure as a Code, que trouxe para o ambiente de infraestrutura padronização, testes, automação e escala mantendo o dinamismo necessário para ambientes em nuvem. Esta base de código deve ser mantida assim como qualquer código fonte de sistemas e softwares, em alguma ferramenta de versionamento de código como o AWS CodeCommit ou o Github, gerando auditabilidade deste conteúdo. E tudo isto permite a criação de templates que definem os padrões aplicados a todo o ambiente, garantindo que todas as versões dos servidores são as mesmas e que as definições de segurança são mantidas entre serviços.

Service Mesh

O Service Mesh é uma camada de infraestrutura dedicada que fornece uma maneira uniforme de conectar, proteger e monitorar a intercomunicação entre microsserviços. Mas, para entender o conceito de Service Mesh e porque ele se tornou tão importante, é necessário primeiro ter uma base sobre microsserviços. Isto porque o desacoplamento de aplicações trouxe soluções como a agilidade na criação de novas features, o isolamento de problemas e o escalonamento individual das aplicações. Entretanto, este novo padrão de arquitetura também trouxe novos problemas. Um vasto ecossistema de microsserviços possui desafios que aplicações monolíticas estariam isentas. Comunicação entre microsserviços, capacidade de gerenciar rotas, gestão de circuit breaker, controle da alteração de estado das aplicações são algumas das novas complexidades criadas com este padrão de desenvolvimento de software.

Para gerenciar uma operação escalável de microsserviços é necessário ter uma camada desacoplada para endereçar as complexidades listadas. Neste cenário surgiu o conceito de Service Mesh, que é uma camada de infraestrutura dedicada que fornece uma maneira uniforme de conectar, proteger e monitorar a intercomunicação entre microsserviços.

Serviços utilizados

Amazon ECS

O Amazon Elastic Container Service (Amazon ECS) é um serviço de gerenciamento de contêineres altamente escalável e rápido. Você pode usá-lo para executar, parar e gerenciar contêineres em um cluster.

AWS Copilot

O AWS Copilot é uma CLI desenvolvida pela AWS para acelerar a implementação de aplicações no Amazon ECS ou AWS App Runner utilizando as melhores práticas de arquitetura recomendadas pelo AWS Well Architected Framework para criação do ambiente.

AWS App Mesh

O AWS App Mesh é um service mesh que oferece redes para aplicativos a fim de facilitar a comunicação dos serviços entre si e entre vários tipos de infraestrutura de computação. O App Mesh padroniza o modo de comunicação dos seus serviços, oferecendo visibilidade de ponta a ponta e garantindo alta disponibilidade para seus aplicativos.

Overview da Solução

Nesse tutorial iremos demonstrar como criar uma estrutura para orquestrar seus microsserviços na AWS utilizando contêineres através do Amazon ECS e fazer o monitoramento e gestão de rotas utilizando o App Mesh e X-Ray, tudo isto criado através da ferramenta de IaC, AWS Copilot, que facilita a manutenção e atualizações do ambiente através de uma CLI própria.

Figura 1 – Diagrama da Solução

Pré requisitos

Passo a Passo

  1. Inicializando o aplicativo
  2. Inicializando o ambiente
  3. Implantando os serviços da aplicação
    • App Mesh Gateway
    • Crystal Service
    • NodeJS Service
    • FrontEnd Service
  4. Testando a aplicação
    • Acessando o Network Load Balancer
    • Acessando a console do App Mesh
    • Observabilidade com o X-Ray
  5. Desprovisionando os recursos

1.      Inicializando o aplicativo

Para esse tutorial precisamos clonar o seguinte repositório do AWS Samples, executando os seguintes comandos no terminal do seu desktop/laptop:

git clone https://github.com/aws-samples/aws-appmesh-xray-with-copilot.git

cd appmeshcopilot
git clone https://github.com/aws-containers/ecsdemo-nodejs.git
git clone https://github.com/aws-containers/ecsdemo-crystal.git
git clone https://github.com/aws-containers/ecsdemo-frontend.git
rm -rf ecsdemo-frontend/copilot
export appName=ecsdemo-workshop
export envName=dev

copilot app init $appName

Em uma configuração limpa, o Copilot criará a pasta copilot e o arquivo “.workspace” automaticamente, mas para esse exemplo a pasta copilot já está pré-criada com os arquivos necessários e customizações para o deploy já com o App Mesh e X-Ray.

O comando “copilot app init” gera uma pilha do CloudFormation e prepara as funções para que o CloudFormation possa criar recursos de aplicativos (como S3, ECR, SNS etc.).

2.      Inicializando o ambiente

Neste exemplo, o arquivo manifest do aplicativo já foi criado pelo Copilot, então podemos avançar e criar o ambiente com:

copilot env init --name $envName

Este comando pedirá a credencial configurada na AWS CLI (neste exemplo usamos a padrão configurada no setup do AWS CLI) e a configuração do ambiente (padrão ou importada) e criará um arquivo de manifesto para o esse ambiente. Também usará o CloudFormation para criar as Roles e um bucket S3 para armazenar os artefatos necessárias.

  1. Qual é a sua credencial? Padrão
  2. Você gostaria de usar a configuração padrão para um novo ambiente? Sim, use o padrão (você pode customizar os recursos de infraestrutura ou até mesmo importar uma infraestrutura existente para o deploy da aplicação)
    1. Uma nova VPC com 2 AZs,
    2. 2 sub-redes públicas e 2 sub-redes privadas
    3. Um novo cluster do ECS
    4. Novas Roles do IAM para gerenciar serviços e tarefas em seu ambiente

Agora podemos fazer o deploy do ambiente para criar os recursos necessários (VPC, sub-rede, IGW, funções, cluster do Amazon ECS). Use o comando:

copilot env deploy --name $envName

Agora estamos prontos para implantar os componentes e o gateway do aplicativo.

3.      Implantando os Serviços de Aplicação

3.1.  Implantando os serviços da aplicação  –  App Mesh Gateway

Vamos começar implantando o App Mesh Gateway. Ele será o ponto de entrada para seu Application Service Mesh. Toda comunicação externa (fora da Mesh) precisa ser enviada por meio de um Network Load Balancer para o Envoy Gateway em execução no Amazon ECS Fargate.

cd appmesh-gateway
copilot init -n ecsdemo-envoygw -t "Load Balanced Web Service"

Selecione a opção “./Dockerfile”.

O Copilot fará a seguinte pergunta: “Você gostaria de implantar um ambiente de teste?”, como já criamos um ambiente (recursos de infraestrutura) para a aplicação no nosso cenário não vamos criar um ambiente de teste, respondendo N.  Vale lembrar que a criação de um ambiente de teste é uma prática recomendada. Em seguida execute o comando de deploy do serviço:

copilot svc deploy --name ecsdemo-envoygw --env $envName

Anote o endereço público do Network Load Balancer. Ele será usado para testar seu aplicativo.

Os recursos que o copilot criará estão relacionados ao tipo de serviço que você escolher. Para o serviço de gateway selecionamos Load Balanced Web Service e, em seguida, personalizamos o manifest.yml para criar um NLB em vez de um ALB padrão (você pode verificar o arquivo de manifesto na pasta copilot/ecsdemo-envoygw).

Os parâmetros que podem ser usados no arquivo de manifesto do copilot, como healthchecks, variáveis para tarefas do Amazon ECS, etc. podem ser verificados em CopilotDocs.

Agora temos a infraestrutura e o gateway prontos, vamos implantar as outras camadas(serviços) da aplicação juntamente com os componentes do App Mesh (sidecars, Virtual Nodes e Virtual Services).

3.2.  Implantando os serviços da aplicação – Crystal Service

O App Mesh exige dois itens em cada tarefa/contêiner que pertence ao Mesh:

  • uma função do IAM que tenha permissão para appMesh:streamAggregatedResources, para que a tarefa possa enviar informações para o serviço App Mesh.
  • um envoy proxy (sidecar contêiner) anexado ao contêiner com uma variável contendo o ARN de um nó virtual criado no App Mesh.

Ambos os componentes serão adicionados por meio dos Copilot addons (arquivos de modelo do Cloudformation na pasta Addons). Vamos implantar nossos serviços de aplicativos com as configurações necessárias do App Mesh (Virtual Nodes):

cd ../ecsdemo-crystal
copilot init -n ecsdemo-crystal -t "Backend Service"

Selecione a opção “./Dockerfile” e novamente responda “N” a pergunta: “Você gostaria de implantar um ambiente de teste?”. Em seguida:

copilot svc deploy --name ecsdemo-crystal --env $envName

3.3.  Implantando os serviços da aplicação – NodeJS Service

Realizaremos o mesmo processo do passo anterior, criando um novo serviço no ECS Fargate e automaticamente um novo Virtual Node e Virtual Service no App Mesh (você pode checar como criar os componentes do App Mesh para cada serviço na pasta copilot/addons).

cd ../ecsdemo-nodejs
copilot init -n ecsdemo-nodejs -t "Backend Service"

Selecione a opção “./Dockerfile” e novamente responda “N” a pergunta: “Você gostaria de implantar um ambiente de teste?”. Em seguida:

copilot svc deploy --name ecsdemo-nodejs --env $envName

Observação: Este passo pode demorar vários minutos, pois o Copilot irá executar um build de imagem de contêiner usando Docker, enviar a imagem ao repositório do Amazon ECR, implantar e testar a disponibilidade do serviço no Amazon ECS Fargate.

3.4.  Implantando os serviços da aplicação – FrontEnd Service

Realizaremos o mesmo processo do passo anterior, criando um novo serviço no Amazon ECS Fargate e automaticamente um novo Virtual Node e Virtual Service no App Mesh (você pode checar como criar os componentes do App Mesh para cada serviço na pasta copilot/addons).

Vale mencionar que apesar desse serviço ser o nosso frontend, estamos criando-o como Backend, pois todo o tráfego externo via Load Balancer será recebido primeiro pelo App Mesh Gateway e só então será redirecionado para o frontend.

cd ../ecsdemo-frontend
copilot init -n ecsdemo-frontend -t "Backend Service"

Selecione a opção “./Dockerfile” e novamente responda “N” a pergunta: “Você gostaria de implantar um ambiente de teste?”. Em seguida:

copilot svc deploy --name ecsdemo-frontend --env $envName

Observação: Este passo pode demorar vários minutos, pois o Copilot irá executar um build de imagem de contêiner usando Docker, enviar a imagem ao repositório do Amazon ECR, implantar e testar a disponibilidade do serviço no Amazon ECS Fargate.

4.      Testando a aplicação

4.1.  Acessando o Network Load Balancer

Verifique sua aplicação, apontando seu navegador para a URL do Network Load Balancer anotado na sessão “Implantando os serviços da aplicação – App Mesh Gateway“. Caso não tenha anotado, você pode verificar o endereço do Network Load Balancer com o comando “sh copilot svc show —name ecsdemo-envoygw” e procurar a URL, ou caso tenha o jq instalado, use o comando “sh copilot svc show —name ecsdemo-envoygw —json | jq .routes [] .url“. 

Na tela do navegador (Chrome ou Firefox), pressione F12 para acessar as ferramentas de desenvolvedor, selecione a aba “Network” e você verá uma lista de chamadas.

No Chrome, clique no botão vermelho a esquerda para parar os network logs, e na lista de logs selecione qualquer log cujo o nome seja igual ao do network load balancer.

Figura 2 – Ferramentas de Desenvolvedor no Chrome

No Firefox, selecione qualquer log cujo o campo “File” seja “/” (caso a lista de logs esteja “desaperecendo”, clique no ícone de engrenagem do lado direto e habilite a opção “Persist Logs”).

Figura 3 – Ferramentas de Desenvolvedor no Firefox

Note que o cabeçalho de Resposta (Response Header) contém “server:envoy”. Isso significa que sua solicitação externa foi enviada via proxy (App Mesh) usando o Envoy e agora você pode controlar suas rotas e regras para cada serviço.

4.2.  Acessando a console do AWS App Mesh

Verifique os Virtual Nodes, os quais representam cada um de nossos recursos/endpoints(serviços do ECS, deployments do EKS ou instâncias do Amazon EC2), hostnames e listeners.

Figura 4 – App Mesh Virtual Nodes

Verifique se o frontend Virtual Node possui 2 serviços de backend (Crystal e nodejs). Como o nosso frontend envia tráfego de saída para estes dois elementos, dizemos que o Virtual Node frontend possui 2 serviços de backend (repare que a referência é aos serviços e não aos nodes).

Figura 5 – App Mesh FrontEnd Virtual Node

Verifique os Virtual Services. Os virtual services representam uma abstração de cada serviço real representado por um Virtual Node ou por um Virtual Router(mais detalhes abaixo) que temos no nosso mesh/aplicação. Quando um serviço  depende de outro, eles utilizam o nome do Virtual Service para comunicação e esse tráfego é enviado para o Virtual Node ou Virtual Router que está prestando aquele serviço de aplicação.

Figura 6 – App Mesh Virtual Services

Verifique o Virtual Gateway. O Virtual gateway é utilizado para permitir comunicação de fora para dentro do mesh, como um acesso de usuário ou recurso que não faz parte do mesh. No nosso cenário criamos um Network Load Balancer para receber os clientes externos e então enviar para o Virtual Gateway (porta de entrada do mesh), que por sua vez tem uma única rota enviando para o frontend-router.

Figura 7 – App Mesh Virtual Gateway

Verifique o Virtual Router e suas rotas. O Virtual Router é utilizado para gerenciar rotas para diferentes Virtual Nodes, especificando caminhos(paths), pesos, timeouts, retries, entre outros. Por exemplo, no nosso cenário podemos utilizar o Virtual Router (ao invés de enviar o tráfego diretamente para um Virtual Node) para redirecionar diferentes versões do nosso frontend, sendo cada versão um Virtual Node. Esse recurso se torna útil principalmente quando estamos implementando estratégias de deploy canary ou blue/green para determinados serviços da aplicação.

Figura 8 – App Mesh Virtual Router e Rotas

4.3.  Observabilidade com o X-Ray

Abra o serviço Amazon CloudWatch usando a Console de Gerenciamento da AWS e na seção X-Ray traces no menu do lado esquerdo, selecionar “Service map”.

Explore o mapa do nosso aplicativo, o tempo de resposta por serviço, métricas, e rastreamentos para cada nível.

Figura 9 – X-Ray service map

No service map do X-Ray é possível verificar de forma gráfica o mapa de comunicação entre os serviços, o tempo médio em cada componente, e a quantidade de chamadas por minuto.

Figura 10 – X-Ray tempo de resposta por node

No menu esquerdo, ainda na seção “X-Ray traces” selecione “Traces”. Dessa forma, é possível ter uma visualização da lista de cada uma das chamadas de aplicação e o tempo total decorrido (desde a entrada até a saída de uma requisição). Um exemplo, seria visualizar o caminho e tempo de resposta que um usuário recebeu ao interagir com a aplicação.

Figura 11 – X-Ray lista de traces (rastreamento por chamada)

Ao clicar em um ID da lista de traces, é possível detalhar cada uma das chamadas internas para aquele cliente/acesso em específico, mostrando todo o caminho percorrido pela aplicação. Essa visualização pode ser utilizada principalmente em cenários de resolução de problemas afim de identificar erros que afetam grupos específicos de usuários.

Figura 12 – X-Ray trace detalhado de uma chamada

5.      Desprovisionando os recursos

Usando a CLI do AWS Copilot é possível, de maneira simples, apagar todos os recursos criados com alguns comandos. O AWS Copilot irá deletar todos os scripts de CloudFormations e recursos criados.

copilot svc delete -n ecsdemo-frontend --yes
copilot svc delete -n ecsdemo-crystal --yes
copilot svc delete -n ecsdemo-nodejs --yes
copilot svc delete -n ecsdemo-envoygw --yes
copilot app delete -n $appName --yes

Conclusão

Neste blog, vimos a construção de uma estrutura robusta para suportar workloads conteinerizados utilizando um orquestrador, incluindo observabilidade e gestão de rotas. Essas ferramentas podem facilitar testes a/b, deploys com abordagem canary ou blue/green, tudo isto usando infraestrutura como código, provisionando todos os recursos sem a necessidade de adaptações e scripts complementares, facilitando muito o dia a dia do time de desenvolvimento.

Próximos Passos 

Como próximos passos você pode executar o deploy de um FrontendV2 (conforme o repositório do Github) afim de explorar as configurações de rotas e health checks do App Mesh.

Além disso, explorar os Pipelines do Copilot, que utiliza os serviços do AWS CodeBuild e AWS CodePipeline, para implementação simplificada de um pipeline CI/CD.

 


Sobre o autores

Joao Melo é Arquiteto de Soluções atendendo clientes Enterprise com foco em mercado financeiro. Com mais de 10 anos de experiência, João iniciou sua carreira como desenvolvedor Java e .NET, e posteriormente se especializou em infraestrutura como Engenheiro de Sistemas na Cisco Systems. Formado pela FEI, é entusiasta de Containers, DeFi, Sistemas de Pagamento e apaixonado por cinema e jogos.

 

 

 

 

Amanda Quinto é Arquiteta de Soluções da AWS no time de Public Sector com foco em Nonprofits Organization. Amanda já atuou em diversos projetos ajudando os times de desenvolvimento e sustentação em arquitetar sistemas resilientes e escaláveis. Formada pela FATEC-SP, é entusiasta de Devops, machine learning, e apaixonada por Kombis.