Usando o framework Serverless para gerenciamento de funções AWS Lambda

Diego Rodrigues
Legiti
Published in
4 min readJun 24, 2020

--

Este é o primeiro artigo de uma série de posts que pretendo escrever sobre como construímos APIs de coleta de dados, usando a arquitetura de FaaS (Function as a Service) através de AWS Lambdas.

A Legiti é uma empresa focada em dados. Depois do nosso time incrível, dados são provavelmente os bens mais valiosos que temos para entregar bons resultados aos nossos clientes, e, por essa razão, a coleta de dados é uma parte fundamental de nossa infraestrutura.

Nossa habilidade de decidir corretamente rejeitar ou aprovar pedidos depende diretamente de conseguirmos coletar, de forma confiável, os dados de diferentes fontes, e de os termos rapidamente disponíveis para serem usados no cálculo de features em tempo real para nossos modelos de machine learning.

Tendo escalabilidade e confiabilidade em mente, funções de AWS Lambda mostraram-se um excelente caminho para atingirmos esse objetivo sem termos que nos preocupar com todo o trabalho envolvido em manter um servidor. Isso acontece porque essas funções são escaláveis por definição, possuem zero downtime durante deploys, têm um custo baixo e possuem ferramentas de monitoramento e logs disponíveis sem que seja necessária a inclusão de muita configuração adicional.

E assim, Hermes e Orwell, nossas APIs de coleta de dados de backend e de frontend, e dois de nossos principais serviços, nasceram como funções AWS Lambda.

Mas afinal, como é que fazemos para que alguns arquivos Python, salvos dentro de um repositório do Git, se tornem de fato uma função rodando na AWS? Para responder a essa pergunta, o primeiro componente que eu gostaria de apresentar é o framework que usamos para descrever a infraestrutura dessas funções em forma de código.

O framework Serverless é um projeto open source que abstrai o conceito de templates do Cloud Formation, permitindo que o usuário escreva arquivos YAML descrevendo todos os componentes necessários para o funcionamento da sua função Lambda. Uma vez que o comando de deploy é emitido ao Serverless, ele cria todo o stack do Cloud Formation para subir os elementos definidos no seu arquivo de configuração e também o código da sua Lambda.

Até o momento, estamos bastante satisfeitos com esse framework. Para nosso caso de uso, não encontramos alguma limitação em termos do que é possível definir no arquivo YAML. Se você quiser dar mais uma olhada no Serverless, aqui está um link para a documentação oficial voltada para AWS.

Um ponto muito positivo do Serverless é de ir além do que um simples template de Cloud Formation consegue cobrir, já que está disponível a ele uma vasta quantidade de plugins open source. Na minha opinião, ter uma comunidade bastante ativa dando suporte ao framework é uma de suas maiores vantagens quando comparado ao SAM.

Dentre esses plugins, vale destacar o serverless-offline, que torna o processo de desenvolvimento mais fácil e ágil, ao permitir emular uma versão local do AWS API Gateway com todos os endpoints definidos no seu arquivo YAML de configuração. Isso faz com que não seja necessário um deploy na AWS para testar se o seu código está funcionalmente correto.

Uma outra feature interessante e que utilizamos bastante nos nossos arquivos de configuração são as variáveis de stage: elas permitem carregar credenciais diferentes para ambientes diferentes (credenciais as quais o Serverless consegue baixar automaticamente do nosso AWS SSM Parameters Store durante o deploy), ao mesmo tempo, o arquivo de configuração é compartilhado entre eles. Assim, conseguimos que as definições da infraestrutura sejam as mesmas para os dois ambientes.

Aproveitando o gancho sobre deployments, o processo é bem simples. Para um determinado ambiente, você só precisa executar:

 serverless deploy --stage my_environment

O Serverless se encarregará de criar e conectar todos os componentes para deixar sua Lambda pronta para receber requisições.

Agora você já sabe um pouco mais sobre o que temos usado para gerenciar e realizar deploys de nossas Lambda e da sua infraestrutura subjacente, mas como exatamente executamos o processo de deploy? A Gabriela Melo escreveu esse ótimo post sobre como nós construímos o pipeline de integração contínua dos nossos serviços, e nossas Lambdas também seguem esse padrão, por isso serei um pouco breve aqui:

  1. Rodamos uma etapa de lint e testes unitários e de integração que rodam dentro da instância do circleCI;
  2. Fazemos deploy da Lambda em staging usando serverless deploy — stage staging;
  3. Executamos testes end-to-end;
  4. Se os testes end-to-end em staging falharem, ocorre o rollback automático;
  5. Se tudo estiver ok, repetimos os mesmos passos até que ocorra o deploy em produção;
  6. Se os testes end-to-end em produção falharem, ocorre o rollback automático de ambos os ambientes.

Caso esteja tudo funcionando perfeitamente, nós salvamos a timestamp do deployment em produção, pois o rollback é feito através do seguinte comando:

serverless rollback --timestamp $PROD_SUCCESS_TIMESTAMP

O Serverless facilita bastante o processo de deploy, mas foi necessário um pouquinho de trabalho extra para conseguirmos executar os testes de integração localmente. No próximo post eu pretendo mostrar um pouco de código e escrever sobre como utilizamos o serverless-offline plugin para esse fim. Até lá!

--

--