Código de exemplo de uma API Rest utilizando API Gateway e Lambda da AWS, com deploy através do Terraform no LocalStack.
Artigo descrevendo o processo, tecnologias e ferramentas desse exemplo: DEV ou meu blog.
Esse exemplo utiliza um banco de dados PostgreSQL e o LocalStack através do docker-compose.
Sua configuração pode ser copiada com:
cp .env.example .env
E os serviços iniciados com:
docker-compose up
Para realizar algumas etapas do processo é necessário utilizar o AWS CLI que precisa ser instalado (usado neste exemplo o LocalStack AWS CLI). Para isso, primeiramente crie um virtualenv com Python 3, atualize esse ambiente e instale o CLI:
python3 -m venv env
. env/bin/activate
pip install -U pip setuptools wheel
pip install -r requirements-local.txt
Esse é um exemplo de deploy manual utilizando o AWS CLI diretamente.
O primeiro recurso a ser criado é uma "role" para definir as permissões com as quais os lambdas irão executar:
awslocal iam create-role \
--role-name exemploapi_lambda \
--assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"Service": ["lambda.amazonaws.com", "apigateway.amazonaws.com"]}, "Action": "sts:AssumeRole"}]}'
Para fazer o deploy dos lambdas, primeiramente é necessário cria um arquivo "Zip" contento o código fonte, que pode ser feito com:
zip arquivo.zip arquivo.py
Para criar o lambda, deve-se seguir o exemplo a baixo:
awslocal lambda create-function \
--function-name exemploapi_funcao \
--role arn:aws:iam::000000000000:role/exemploapi_lambda \
--runtime python3.8 \
--zip-file fileb://arquivo.zip \
--handler arquivo.handler \
--publish
--environment Variables={KeyName1=string,KeyName2=string}
A atualização do código ou configuração podem ser feitas segundo os comandos a baixo respectivamente:
awslocal lambda update-function-code \
--function-name exemploapi_funcao \
--zip-file fileb://arquivo.zip
awslocal lambda update-function-configuration \
--function-name exemploapi_funcao
--environment Variables={KeyName1=string,KeyName2=string}
A execução do lambda pode ser feito através do comando:
awslocal lambda invoke \
--function-name exemploapi_funcao \
--payload '{"key": "value"}' \
output.json
Para ver o log da execução é necessário buscar o grupo de log do lambda, verificar os logs disponíveis (o último é o mais atual), e por fim recuperar o log:
awslocal logs describe-log-groups \
--query logGroups[*].logGroupName
awslocal logs describe-log-streams \
--log-group-name /aws/lambda/exemploapi_funcao
--query logStreams[*].logStreamName
awslocal logs get-log-events \
--log-group-name /aws/lambda/exemploapi_funcao
--log-stream-name 2021/08/30/[LATEST]dface06f
A lista dos lambdas configurados pode ser recuperado com:
awslocal lambda list-functions
O API Gateway é o responsável por permitir a interação com os lambdas através de um endereço HTTP, para isso uma API Rest deve ser criada:
awslocal apigateway create-rest-api \
--name exemploapi
Para os próximos passos é necessário possuir o id
da API criada, que pode ser obtido na saída do comando anterior ou listando todas as APIs:
awslocal apigateway get-rest-apis
Para associar um lambda é necessário obter o id
do caminho também, o qual pode ser verificado com:
awslocal apigateway get-resources \
--rest-api-id mea14qi3dw
Um novo caminho pode ser criado com:
awslocal apigateway create-resource \
--rest-api-id mea14qi3dw \
--parent-id gv27z1cb9l \
--path-part caminho
Também é necessário informar os métodos que devem ser aceitos em cada caminho:
awslocal apigateway put-method \
--rest-api-id mea14qi3dw \
--resource-id 6g97u23fj2 \
--http-method GET \
--authorization-type NONE
A associação do lambda com a requisição do caminho em determinado método pode ser feita com:
awslocal apigateway put-integration \
--rest-api-id mea14qi3dw \
--resource-id 6g97u23fj2 \
--http-method GET \
--type AWS_PROXY \
--integration-http-method POST \
--uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:exemploapi_funcao \
--credentials arn:aws:iam::000000000000:role/exemploapi_lambda
Para publicar é necessário fazer um deploy:
awslocal apigateway create-deployment \
--rest-api-id mea14qi3dw \
--stage-name main
No LocalStack, o API Gateway pode ser acessado através da URL base http://localhost:4566/restapis/<api_id>/<stage_name>/_user_request_
, exemplo de requisição usando o HTTPie:
http -v GET http://localhost:4566/restapis/mea14qi3dw/main/_user_request_/caminho
Outra opção de deploy é com o Terraform. Para guardar o estado dos recursos criados e permitir a execução do Terraform de locais diferentes é necessário criar um bucket S3:
awslocal s3api create-bucket \
--bucket config
Após isso é necessário iniciar o Terraform para que ele se configure utilizando o bucket S3:
terraform init
As configurações dos módulos pode ser copiada com:
cp config.tfvars.example config.tfvars
Após isso é possível verificar o que será criado ou aplicar as alterações com:
terraform plan -var-file=config.tfvars
terraform apply -var-file=config.tfvars
Exemplo em vídeo: