O blog da AWS

Visualização de ambientes usando funções do AWS Lambda em contêineres

Por John Ritsema, arquiteto de soluções principal

 

Os pipelines de integração contínua e entrega contínua (CI/CD) são mecanismos eficazes que permitem que as equipes transformem o código-fonte em aplicativos em execução. Quando um desenvolvedor faz uma alteração no código e a envia para um repositório remoto, um pipeline com uma série de etapas pode processar a alteração. Um pipeline integra uma alteração à base de código completa, verifica o estilo e a formatação, executa verificações de segurança e executa testes unitários. Como etapa final, ele cria o código em um artefato que pode ser implantado em um ambiente para consumo.

Ao usar o GitHub ou muitos outros provedores Git hospedados, uma pull request ou uma solicitação de mesclagem pode ser enviada para uma alteração de código específica. Isso cria um local focado para discussão e colaboração sobre a mudança antes que ela seja aprovada e mesclada em uma ramificação de código compartilhada.

Um mecanismo poderoso de colaboração envolve a implantação de um pull request (PR) em um ambiente em execução. Isso permite que as partes interessadas visualizem as mudanças ao vivo e vejam como elas ficariam. A criação rápida de um ambiente de execução permite que os colegas de equipe forneçam feedback quase imediato, acelerando todo o processo de desenvolvimento.

A implantação de PRs em ambientes efêmeros incentiva as equipes a fazerem muitas pequenas mudanças que podem ser visualizadas e testadas em paralelo. Isso evita a necessidade primeiro de se fundir em uma ramificação de origem comum e implantar em ambientes de longa duração que estão sempre ativos e geram custos.

A criação desse mecanismo tem vários desafios, incluindo complexidade de configuração, tempo de criação do ambiente e custo do ambiente. Esta postagem aborda esses desafios mostrando como criar um pipeline de CI/CD para visualizar alterações em aplicativos web em ambientes efêmeros, rápidos de provisionar, de baixo custo e escaláveis até zero. Esta postagem mostra as etapas necessárias para configurar um aplicativo de amostra.

Arquitetura de exemplo

Os conceitos desta postagem podem ser implementados usando várias ferramentas e provedores Git hospedados que se conectam a pipelines de CI/CD. O código de exemplo compartilhado nesta postagem usa o GitHub Actions para acionar um fluxo de trabalho. O fluxo de trabalho usa um pequeno módulo do Terraform com o Docker para criar o código-fonte do aplicativo em uma imagem de contêiner, enviá-lo para o Amazon Elastic Container Registry (ECR) e criar uma função do AWS Lambda com a imagem.

O contêiner em execução no Lambda pode ser acessado em um navegador da Web por meio de uma URL de função do Lambda. Isso fornece um endpoint HTTPS dedicado para uma função.

Isso é usado em vez do AWS App Runner, do Amazon ECS Fargate com um Application Load Balancer (ALB) ou do Amazon EKS com entrada de ALB devido à velocidade do provisionamento e ao baixo custo. Os URLs da função Lambda são ideais para ambientes de relações públicas efêmeros usados ocasionalmente, pois podem ser provisionados rapidamente. O ambiente computacional escalável até zero do Lambda leva a um custo menor, pois as cobranças são cobradas apenas por solicitações HTTP reais. Isso é útil para PRs que só podem ser revisados com pouca frequência e depois ficam inativos até que o PR seja mesclado ou fechado.

Este é o exemplo de arquitetura:

 

Configurando o exemplo

O projeto de exemplo mostra como implementar esse cenário. Ele consiste em um aplicativo web básico escrito em Node.js. Todo o código necessário para implementar a arquitetura está contido no github. Para habilitar ambientes efêmeros para um novo projeto, copie o diretório.github sem sobrecarregar os arquivos do projeto.

Há dois recursos principais necessários para executar o Terraform dentro do GitHub Actions: uma função do AWS IAM e um local para armazenar o estado do Terraform. As credenciais da AWS são necessárias para dar permissão ao pipeline para provisionar recursos da AWS.

Em vez de usar credenciais de usuário do IAM estáticas que devem ser alternadas e protegidas, assuma uma função do IAM para obter credenciais temporárias. O estado remoto do Terraform é necessário para descartar o ambiente quando o PR é mesclado ou fechado. O projeto de amostra usa um bucket Amazon S3 para armazenar o estado do Terraform.

Você pode usar o módulo Terraform localizado em .github/setup para criar esses recursos necessários.

    1. Forneça o nome da sua organização e repositório do GitHub no arquivo terraform.tfvars como parâmetros de entrada. Você pode substituir aws-samples pelo seu nome de usuário do GitHub:
cat .github/setup/terraform.tfvars
github_org  = "aws-samples"
github_repo = "ephemeral-preview-containers-furl"

2.  Para provisionar os recursos usando o Terraform, execute:

cd .github/setup
terraform init && terraform apply


Armazene o arquivo terraform.tfstate de saída com segurança para que você possa gerenciar esses recursos no futuro, se necessário.

3. Coloque a região, a função do IAM gerada e o nome do bucket no arquivo de configuração localizado em .github/workflows/config.env. Esse arquivo de configuração é lido e usado pelo fluxo de trabalho do GitHub Actions.

export AWS_REGION="<add region from setup>"

export AWS_ROLE="<add role from setup>"

export TF_BACKEND_S3_BUCKET="<add bucket from setup>"

Essa função do IAM tem uma política embutida que contém o conjunto mínimo de permissões necessárias para provisionar os recursos da AWS. Isso pressupõe que seu aplicativo não interaja com serviços externos, como bancos de dados ou caches. Se seu aplicativo precisar desse acesso adicional, você poderá adicionar as permissões necessárias à política localizada aqui.

Executando um servidor web no Lambda

O aplicativo web de amostra (HTTP) inclui um Dockerfile que contém instruções para empacotar o aplicativo web em uma imagem de contêiner baseada em processos. Uma extensão do Lambda chamada Lambda Web Adapter permite que você execute esse processo padrão de servidor web no Lambda. O fluxo de trabalho de CI/CD faz uma cópia do Dockerfile e adiciona a seguinte linha.

COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.6.0 /lambda-adapter /opt/extensions/lambda-adapter

Essa linha copia o binário executável do Lambda Web Adapter de uma imagem ECR pública e o grava no contêiner no diretório /opt/extensions/. Quando o contêiner é iniciado, o Lambda inicia a extensão do Lambda Web Adapter. Isso traduz cargas de eventos do Lambda de acionadores baseados em HTTP em solicitações HTTP reais que são enviadas por proxy para o aplicativo web executado dentro do contêiner. Essa é a arquitetura:

Por padrão, o Lambda Web Adapter pressupõe que o aplicativo web esteja escutando na porta 8080. No entanto, você pode alterar isso no Dockerfile definindo a variável de ambiente PORT.

O aplicativo web em contêineres passa por uma “inicialização a frio”. No entanto, isso provavelmente não é muito preocupante, pois o aplicativo só será visualizado internamente por colegas de equipe.

Fluxo de trabalho

O trabalho do GitHub Actions definido no fluxo de trabalho up.yml é acionado quando um PR é aberto ou reaberto na ramificação principal do repositório. A seguir está um resumo das etapas que o trabalho executa.

  1. Leia a configuração em .github/workflows/config.env
  2. Assuma a função do IAM, que tem permissões mínimas para implantar recursos da AWS
  3. Instale o Terraform CLI
  4. Adicione a extensão Lambda Web Adapter à cópia do Dockerfile
  5. Execute terraform apply para provisionar os recursos da AWS usando o bucket S3 para o estado remoto do Terraform
  6. Obtenha o endpoint HTTPS do Terraform e adicione-o ao PR como um comentário

O trecho de código a seguir mostra as principais etapas (4-6) do fluxo de trabalho up.yml.

- name: Lambda-ify
  run: echo "COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.6.0 /lambda-adapter /opt/extensions/lambda-adapter" >> Dockerfile

- name: Deploy to ephemeral environment 
  id: furl
  working-directory: ./.github/workflows
  run: | terraform init \ -backend-config="bucket=${TF_BACKEND_S3_BUCKET}" \ -backend-config="key=${ENVIRONMENT}.tfstate"

    terraform apply -auto-approve \
      -var="name=${{ github.event.repository.name }}" \
      -var="environment=${ENVIRONMENT}" \
      -var="image_tag=${GITHUB_SHA}"

    echo "Url=$(terraform output -json | jq '.endpoint_url.value' -r)" >> $GITHUB_OUTPUT

- name: Add HTTPS endpoint to PR comment
  uses: mshick/add-pr-comment@v1
  with:
    message: | :rocket: Code successfully deployed to a new ephemeral containerized PR environment! ${{ steps.furl.outputs.Url }}
    repo-token: ${{ secrets.GITHUB_TOKEN }}
    repo-token-user-login: "github-actions[bot]"
    allow

O arquivo main.tf (no mesmo diretório) inclui infraestrutura como código (IaC) que é responsável por criar um repositório ECR, criar e enviar a imagem do contêiner para ele e ativar uma função Lambda com base na imagem. A seguir está um trecho da configuração do Terraform. Você pode ver como isso pode ser configurado de forma concisa.

provider "docker" {
  registry_auth {
    address  = format("%v.dkr.ecr.%v.amazonaws.com", data.aws_caller_identity.current.account_id, data.aws_region.current.name)
    username = data.aws_ecr_authorization_token.token.user_name
    password = data.aws_ecr_authorization_token.token.password
  }
}

module "docker_image" {
  source = "terraform-aws-modules/lambda/aws//modules/docker-build"

  create_ecr_repo = true
  ecr_repo        = local.ns
  image_tag       = var.image_tag
  source_path     = "../../"
}

module "lambda_function_from_container_image" {
  source = "terraform-aws-modules/lambda/aws"

  function_name              = local.ns
  description                = "Ephemeral preview environment for: ${local.ns}"
  create_package             = false
  package_type               = "Image"
  image_uri                  = module.docker_image.image_uri
  architectures              = ["x86_64"]
  create_lambda_function_url = true
}

output "endpoint_url" {
  value = module.lambda_function_from_container_image.lambda_function_url
}

O Terraform gera o endpoint HTTPS gerado. O fluxo de trabalho o envia de volta ao PR como um comentário para que os colegas de equipe possam clicar no link para visualizar as alterações:

O fluxo de trabalho leva cerca de 60 segundos para iniciar um novo aplicativo web em contêiner isolado em um ambiente efêmero que pode ser visualizado.

Colaboração em pull request

A captura de tela a seguir mostra um exemplo de relações públicas enquanto o autor colabora com sua equipe. Depois de implementar esse exemplo, quando um novo PR chega, as alterações são implantadas em um novo ambiente efêmero. As partes interessadas podem usar o link para visualizar a aparência das mudanças e fornecer feedback.

Depois que as alterações são aprovadas e mescladas na ramificação principal, o fluxo de trabalho down.yml do GitHub Actions elimina o ambiente. Isso significa que o ambiente efêmero é desprovisionado, incluindo recursos como a função Lambda e o repositório ECR.

Conclusão

Esta postagem discute alguns dos benefícios do uso de ambientes efêmeros em pipelines de CI/CD. Ele mostra como implementar um pipeline usando URLs de GitHub Actions e Lambda Function para ambientes rápidos, de baixo custo e efêmeros.

Com este exemplo, você pode implantar PRs rapidamente, e o custo é baseado nas solicitações HTTP feitas ao ambiente. Não há custos de computação incorridos enquanto um PR está aberto e ninguém está visualizando o ambiente. As únicas cobranças são pelas invocações do Lambda, enquanto as partes interessadas estão interagindo ativamente com o ambiente. Quando um PR é mesclado ou fechado, a infraestrutura de nuvem é descartada. Você pode encontrar todo o código de exemplo referenciado nesta postagem aqui.

Para obter mais recursos de aprendizado sem servidor, visite Serverless Land.

 

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

 


Sobre o autor

John Ritsema é Arquiteto de Soluções Sênior

 

 

 

 

Tradutor

Charleston Telles é Enterprise Solution Architect na AWS, com mais de 20 anos de experiência em projetos e arquiteturas de T.I. de setores como Aviação, Telecom, Banking, Seguradoras e Online Betting. Charleston é Mestre em Arquitetura de Software pela QUT (Queensland University of Technology – Austrália) e Especialista em arquiteturas Serverless. Ele trabalha apoiando clientes corporativos, auxiliando-os em sua jornada para a nuvem.

https://www.linkedin.com/in/charlestontelles/