O blog da AWS

Estratégias de Publicação de APIs com Amazon API Gateway e AWS Lambda

Por Raphael Lima, Solutions Architect, Enterprise e
Leonardo Piedade, Solutions Architect, DNB/ISV

 

Como comentado no blogpost anterior, o AWS Lambda Alias em conjunto com os Stages do Amazon API Gateway, simplificam e flexibilizam o processo de desenvolvimento de uma aplicação usando arquitetura Serverless. Com isso é possível aumentar o controle da distribuição das novas versões da sua aplicação e elevar a maturidade do processo de publicação das APIs.

Existem diferentes mecanismos para a publicação de funções Lambdas, a forma mais comum é a AllAtOnce, onde todas as requisições dos consumidores são direcionadas para a última versão imediatamente após sua publicação. Para reduzir os riscos de impactos que possíveis erros podem causar aos usuários da aplicação após a instalação de uma nova versão, usaremos a técnica Canary Deployment. Perceba que o termo “Canary” se refere a disponibilização de uma versão da aplicação para uma pequena parte dos usuários. Com o uso do AWS Lambda Aliases, múltiplas versões da mesma função Lambda estão disponíveis para execução, utilizando o controle de tráfego, é possível gerenciar a porcentagem das requisições que é direcionada para cada versão específica.

Esse post está dividido conforme as seções abaixo:

  • Arquitetura
  • Instalação inicial
  • Seção I: Canary Deployment com AWS Lambda;
  • Seção II: Canary Deployment com Amazon API Gateway;
  • Seção III: Canary Deployment com Amazon API Gateway e AWS Lambda.

 

Arquitetura

O diagrama a seguir apresenta uma solução a qual permite o controle das diversas versões das funções Lambda em diferentes ambientes da sua aplicação. Nesta solução, cada Stage do Amazon API Gateway funciona como um ambiente separado e através de Stage Variables é possível definir o Lambda Alias que será utilizado no momento da requisição.

 

Para executar os passos é necessário que você tenha a arquitetura apresentada, funcionando na sua conta AWS. Você pode seguir os passos do blogpost anterior ou executar a seção de Instalação Inicial.

 

Instalação Inicial

Para a instalação da solução, execute os passos a seguir:

  1. Faça download do template AWS CloudFormation para provisionar a solução.
  2. Acesse a console do serviço: https://console.aws.amazon.com/cloudformation/ e clique em Create Stack.
  3. Na tela de criação da Stack, selecione a opção “Upload a template file” e faça upload do arquivo e clique em Next.
  4. Na tela de detalhes, digite um nome para sua Stack e clique em Next.
  5. Na tela de opções, clique em Next.

Na tela de revisão, marque a opção “I acknowledge that AWS CloudFormation might create IAM resources” e clique em Next.

  1. Aguarde até que a criação dos recursos esteja completa. Esse processo levará em média 3 minutos.
  2. Na aba de “Outputs”, copie o endereço dos endpoints: APIEndpointDev e Veja o exemplo abaixo:

 

 

Pronto, você já está com a solução provisionada em sua conta AWS.

 

Seção I: Canary Deployment com AWS Lambda

Nessa seção vamos alterar o código da função Lambda e controlar a distribuição de requisições entre as múltiplas versões usando um mecanismo chamado Weighted Alias.

Execute os passos a seguir:

  1. Acesse a função Lambda criada na console do serviço: http://console.aws.amazon.com/lambda/
  2. Acesse a última versão função, clicando na opção “Qualifiers”, selecione a aba “Versions” e escolha a opção “$LATEST”.

 

 

3. Desça a página até a seção “Function Code” e edite o código conforme abaixo:

 

import json
def lambda_handler(event, context):
    if event['queryStringParameters']:
        return {
            'statusCode': 200,
            'body': json.dumps(f"Hello {event['queryStringParameters']['name']}!")
        }
    else:
        return {
            'statusCode': 200,
            'body': json.dumps('Hello World!')
        }

 

4. Após a edição do código, clique em Deploy.

5. Para criar uma nova versão da sua função, clique em “Actions” e depois em “Publish new version”. Coloque a descrição da versão “v2” e clique em Publish.

6. Altere o alias prod. Acesse o menu “Version”, na aba “Aliases”, clique no alias prod.

7. Desça a página até a seção “Alias Configuration” e clique em Edit.

8. Na tela de edição do alias, selecione a opção “Weighted alias”, escolha a última versão criada e coloque o peso em 20%.

 

 

Dessa forma vamos direcionar 20% do tráfego para a última versão criada e 80% para versão anterior.

Agora usando os endereços da API de prod e dev que você anotou na seção de “Instalação Inicial”, você verá que o retorno de dev já foi alterado para a nova versão da função. Porém o retorno do endpoint de prod irá variar entre as duas versões da função, sendo que aproximadamente 20% dos testes serão direcionados para a versão mais recente.

Abaixo você pode conferir os dois resultados esperados para o mesmo endpoint no Stage de prod:

 

 

Desta forma, é possível ter um controle simplificado de versões das APIs publicadas para o ambiente de produção, sem indisponibilidade durante qualquer parte do processo de publicação. A distribuição de carga entre as versões pode ser alterada a qualquer momento, de acordo com o critério de aceite da sua empresa.

 

 

Para rotear todas as requisições para a nova versão v2 da função lambda, siga os passos abaixo:

  1. Altere o alias prod. Acesse o menu “Version“, na aba “Aliases”, clique no alias prod.
  2. Desça a página até a seção “Alias Configuration” e clique em Edit.
  3. Na tela de edição do alias, selecione a opção “Weighted alias”, no campo “Additional Version” escolha a opção “<none>” e acima no campo “Version” selecione a versão “2” e clique em Save.

 

Seção II: Canary Deployment com Amazon API Gateway

Nessa seção vamos alterar a configuração dos parâmetros no Amazon API Gateway. Depois usando o mecanismo chamado Canary Release, iremos atualizar o ambiente de prod com as novas configurações da API.

Para a criar a nova configuração no Stage de dev, execute os passos a seguir:

  1. Acesse a API criada na console do serviço: https://console.aws.amazon.com/apigateway
  2. Na seção “Resources” no API Gateway, clique no método “GET” e depois em “Method Request” do lado direito.

 

 

3. Expanda a opção “URL Query String Parameters” e clique em Add query string, adicione o parâmetro “name” e selecione a opção “Required”. Logo acima, em “Request Validator” selecione a opção para validar “query string parameters and headers”.

 

 

4. Agora vamos aplicar a nova configuração no Stage de dev. Ao lado de “Resources”, clique em Actions, selecione a opção “Deploy API”, selecione o Stage dev, adicione uma descrição caso queira e clique em Deploy. Aguarde alguns segundos para que a configuração seja aplicada.

 

 

Ao realizarmos os testes utilizando o endpoint de dev, será exibida uma mensagem sobre a falta do parâmetro criado.

 

 

Adicione a query string “?name=Raphael” ao final do seu endpoint para efetuar a requisição com sucesso.

 

 

Para o Stage de prod, não iremos atualizar as configurações para todas as requisições, e sim testar com um tráfego menor primeiro e depois redirecionar o restante o tráfego para as novas configurações. Para isso vamos utilizar a funcionalidade de “Canary release” do Amazon API Gateway.

Para a criar a nova configuração no Stage de prod, execute os passos a seguir:

  1. No API Gateway, acesse o menu esquerdo a opção “Stages” e selecione o Stage de prod, clique na última aba “Canary” e então clique em Create Canary.

 

 

2.  Na aba “Canary”, altere a porcentagem de requisições para Canary, nesse exemplo vamos colocar 20%.

 

 

3. Retorne para a seção de “Resources” e clique em Actions e selecione a opção “Deploy API”, seleciona o Stage de prod. Note que ele mostra que o mecanismo de Canary está habilitado e você fará a alteração somente para o Canary. Clique em Deploy.

 

 

Ao realizar os testes do endpoint de prod. São esperados dois resultados, a mensagem de sucesso para 80% das requisições e a mensagem sobre a falta do parâmetro “name” para aproximadamente 20% das requisições. Agora o Canary Release já está funcionado!

 

 

Após a validação da nova versão em Canary no Stage de prod, então podemos incrementar o tráfego ou simplesmente promover para prod. Nesse exemplo vamos promover a versão em Canary.

Acesse no menu esquerdo, a opção “Stages”, selecione o Stage de prod, na aba “Canary”, clique em Promote Canary e depois em Update.

 

 

Agora a API com a validação do parâmetro “name” está atualizada no Stage de prod com 100% do tráfego direcionada para ela.

 

Seção III: Canary Deployment com Amazon API Gateway e AWS Lambda

Até este ponto, usamos a técnica de Canary Deployment com o AWS Lambda, utilizando alias e com o Amazon API Gateway utilizando a funcionalidade Canary, porém fizemos atualizações isoladas. Nessa seção iremos criar um novo Lambda Alias para ser utilizado apenas pelo Canary Release do Amazon API Gateway.

Primeiro, vamos atualizar nossa versão Lambda com um novo código, agora recuperando dois parâmetros obrigatórios: “name” e “lastName”. Dessa vez não vamos colocar uma condição caso o parâmetro não exista. Portanto, iremos utilizar o Canary apenas no Amazon API Gateway.

Para editar o código da função Lambda, execute os passos a seguir:

  1. Acesse a função Lambda criada na console do serviço: http://console.aws.amazon.com/lambda/
  2. Acesse a última versão função, clicando na opção “Qualifiers”, selecione a aba “Versions” e escolha a opção “$LATEST”.
  3. Desça a página até a seção “Function Code” e edite o código conforme abaixo:
import json




def lambda_handler(event, context):

    name = event['queryStringParameters']['name']

    lastName = event['queryStringParameters']['lastName']

    return {

        'statusCode': 200,

        'body': json.dumps(f"Hello {name} {lastName}!")

    }

4. Após a edição do código, clique em Deploy.

Com essa versão de código, o campo “lastName” se tornou obrigatório. Note que o código foi escrito de forma para mostrar a necessidade de alteração nas configurações do Amazon API Gateway.

Para realizar a nova configuração no API Gateway, execute os passos a seguir:

  1. No API Gateway, em “Resources”, selecione o método GET e clique em “Method request”. Na próxima tela expanda a opção “URL Query String Parameters”, adicione o parâmetro “lastName” e selecione a opção “Required”

 

 

2. Agora clique em “Actions”, clique em “Deploy API”, selecione o stage de dev e clique em “Deploy”.

 

 

3. Veja que agora temos a validação de ambos os parâmetros.

 

 

Agora precisamos fazer a atualização no Stage de prod, pois não podemos simplesmente atualizar o alias de prod, pois caso os novos parâmetros não sejam informados a execução da função Lambda irá causar um erro do tipo “500 – Internal Server Error”.

Para publicar uma nova versão e um novo Alias para a função Lambda, execute os passos a seguir:

  1. Acesse a função Lambda criada na console do serviço: http://console.aws.amazon.com/lambda/
  2. Na função Lambda, clique em Actions e selecione a opção “Publish new version”, adicione uma descrição para a versão e clique em Publish.

 

 

3. Crie um alias chamado “prod-canary” e atribua a nova versão ao alias. Clique em Action, selecione “Create alias”, adicione o nome do alias e a última versão criada, neste exemplo a versão de número 7, esse número pode ser diferente no seu ambiente.

 

4. Como criamos um novo alias, precisamos dar permissão para que o API Gateway possa executá-lo. Utilizando o awscli, execute o comando abaixo substituindo os valores de account-number, apigw-id e statement-id com os do seu ambiente.

 

aws lambda add-permission --function-name "arn:aws:lambda:us-east-1:<account-number>:function:HelloWorld:prod-canary" --source-arn "arn:aws:execute-api:us-east-1:<account-number>:<apigw-id>/*/GET/v1/hello" --principal apigateway.amazonaws.com --statement-id <statement-id> —action lambda:InvokeFunction

 

Agora vamos realizar a nova configuração do API Gateway no Stage de prod utilizando o Canary Release.

  1. Acesse a API criada na console do serviço: https://console.aws.amazon.com/apigateway.
  2. No menu lateral esquerdo, acesse “Resources”, selecione o método GET e clique em Method Request.
  3. Na tela de configuração, expanda a opção “URL Query String Parameters”, adicione o parâmetro “lastName” e marque a opção “Required”.
  4. Selecione “Resources”, clique em Actions e selecione a opção “Deploy API”.
  5. Na tela de publicação, escolha o Stage de prod (Canary Enabled) e clique em Deploy.
  6. Na tela de configurações do Canary do Stage de prod, perceba que você também pode adicionar Stage Variables para o Canary, como nosso lambda alias de prod ainda está direcionado para uma versão antiga, vamos precisar apontar para o novo alias criado com a última versão. Então edite a variável “lambdaAlias”, digitando “prod-canary” na coluna “Canary Override Value”.
  7. Acima, na mesma página, edite o percentual de tráfego direcionado para o Canary deixando em 20%.

 

 

Teste a API usando o endpoint de prod, enviando os dois parâmetros (“?name=Raphael&lastName=Lima”), perceba que em aproximadamente 80% das chamadas é exibido somente o primeiro nome, referente a antiga versão da função lambda, e que nos 20% restantes são exibidos os dois parâmetros como retorno, referente a nova versão da função lambda.

Exemplo dos resultados esperados:

 

Após todos os testes realizados, é necessário promover a nova versão para todos os consumidores da API. Para promover a versão de Canary do Stage de prod no Amazon API Gateway, execute os passos a seguir:

  1. Acesse a API criada na console do serviço: https://console.aws.amazon.com/apigateway.
  2. No menu lateral esquerdo, acesse “Stages”, selecione o Stage de prod.
  3. No editor de configurações do Stage, acesso a aba “Canary”.
  4. Na aba “Canary”, edite o valor da porcentagem de requisições direcionados para o Canary, alterando para 100%. Obs: Não promova a versão Canary nesse passo.

 

 

Nesta etapa vamos ajustar o alias “prod” da função Lambda para a versão que validamos no ambiente de Canary.

  1. Retorne a sua função na console do serviço Lambda: http://console.aws.amazon.com/lambda/.
  2. Na função Lambda selecione o Alias de prod.
  3. Na tela de edição da função Lambda, na sessão “Alias configuration”, clique em Edit.
  4. Selecione a versão que foi validada, a mesma utilizada pelo Alias “prod-canary” e clique em Save.

Como último passo, vamos realizar a promoção do ambiente de Canany no Amazon API Gateway.

  1. Acesse a API criada na console do serviço: https://console.aws.amazon.com/apigateway.
  2. No menu lateral esquerdo, acesse “Stages”, selecione o Stage de prod.
  3. No editor de configurações do Stage, acesse a aba “Canary”.
  4. Na aba “Canary”, clique em Promote Canary,
  5. Na tela de promoção, não deixe marcado a opção de “Update with Canary’s stage variables”, caso contrário o lambda Alias de “prod” será substituído pelo “prod-canary”, o “prod-canary” será utilizado para os próximos processos de publicação.
  6. Clique em Update.

 

 

Pronto, a API está totalmente atualizada com a nova versão da função lambda e a mudança de parâmetros de query string no AmazonAPI Gateway. Utilizando a estratégia de Canary Deployment, todas as operações foram realizadas sem causar qualquer tipo de impacto aos consumidores.

Veja os resultados esperados abaixo:


 

Conclusão

Esse post apresentou formas de utilizar a técnica Canary Deployment com os serviços Amazon API Gateway e AWS Lambda, permitindo o controle da distribuição de requisições entre diferentes versões, facilitando a sua validação e tornando o processo de publicação mais seguro.

 

Referências

 

 


Sobre os autores

Raphael Lima é arquiteto de soluções na AWS, com mais de 10 anos trabalhando com infraestrutura, DevOps, arquitetura de microsserviços, serverless e segurança. Atua com clientes Enterprise, ajudando em sua jornada para a nuvem.

 

 

 

 

Leonardo Piedade é arquiteto de soluções na AWS. Trabalha a mais de 15 anos em desenvolvimento de software. Entusiasta da plataforma Java e tecnologias de Blockchain. Atualmente trabalha com foco em aplicações distribuídas e arquiteturas serverless.