Deploy função lambda em nodejs com OpenTofu na AWS
Como Criar uma Lambda na AWS com Terraform: API com Express.js
Hoje em dia, ferramentas de automação de Infraestrutura como Código (IaC) como Terraform e OpenTofu são amplamente utilizadas para provisionar recursos na nuvem. A Amazon Web Services (AWS) é uma das principais plataformas de nuvem que suporta o OpenTofu, permitindo que você crie e gerencie recursos de forma programática.
Sem uma ferramenta de automação, você teria que criar manualmente cada recurso na AWS, o que pode ser demorado e propenso a erros. Com o OpenTofu, você pode definir sua infraestrutura como código e implantá-la de forma consistente e confiável.
É comum usar funções Lambda da AWS para executar código sem precisar provisionar ou gerenciar servidores. Neste artigo, vamos criar uma função Lambda com uma API usando Nodejs, Api Gateway e OpenTofu.
Esse é o primeiro passo, depois iremos melhorar o projeto adicionando CI/CD, testes e monitoramento.
Eu utilizei uma forma diferente
de realizar a explicação do código, em cada bloco de código tem um áudio que explica o código e como ele funciona, espero que goste dessa abordagem.
Pré-requisitos
Certifique-se de ter as seguintes ferramentas instaladas em seu sistema:
Passo 1: Configurar o Projeto Express.js
Primeiro, crie um novo diretório para o seu projeto e inicialize um novo projeto Node.js:
mkdir lambda-express-api
cd lambda-express-api
npm init -y
Instale as dependências que iremos utilizar:
npm i express serverless-http
Instale as dependências de desenvolvimento que iremos utilizar:
npm i -D nodemon
Alterar o package.json
e adicionar type: module
{
...
"type": "module",
...
}
Adicione o seguinte script no arquivo package.json
:
{
...
"scripts": {
"start": "node local-server.mjs",
"dev": "npx nodemon local-server.mjs"
},
...
}
Crie um arquivo index.mjs
e adicione o seguinte código:
import express from "express";
const app = express();
app.use(express.json());
app.get("/hello", (req, res) => {
res.send("Hello from Lambda!");
});
export default app;
Crie um arquivo chamado handler.mjs para definir a função Lambda:
import serverless from "serverless-http";
import app from "./index.mjs";
const handler = serverless(app);
export { handler };
Crie um arquivo local-server.mjs
para executar o servidor localmente e testar a API:
import app from "./index.mjs";
const port = 3000;
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
Depois de ter criado os arquivos e testado a api, precisamos empacotar o código para fazer o deploy na AWS.
Crie um arquivo chamado lambda-express-api.zip
e adicione os arquivos index.mjs
, handler.mjs
, package.json
e a pasta node_modules
:
Unix/Mac | Windows |
---|---|
zip -r lambda-express-api.zip index.mjs handler.mjs package.json node_modules | Compress-Archive -Path index.mjs, handler.mjs, package.json, node_modules -DestinationPath lambda-express-api.zip |
Passo 2: Configurar o tofu
Crie um diretório chamado opentofu no seu projeto:
mkdir tofu
cd tofu
Crie um arquivo chamado variables.tf
com o seguinte conteúdo:
variable "region" {
description = "The AWS region to deploy resources in"
type = string
default = "us-east-1"
}
variable "profile" {
description = "Default AWS profile to use for deployment"
type = string
default = "default"
}
Crie um arquivo main.tf com o seguinte conteúdo:
provider "aws" {
region = var.region
profile = var.profile
}
resource "aws_iam_role" "lambda_role" {
name = "lambda_execution_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "lambda.amazonaws.com"
}
},
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy" {
role = aws_iam_role.lambda_role.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
resource "aws_lambda_function" "lambda_function" {
filename = "${path.module}/../lambda-express-api.zip"
function_name = "express_api_lambda"
role = aws_iam_role.lambda_role.arn
handler = "handler.handler"
source_code_hash = filebase64sha256("${path.module}/../lambda-express-api.zip")
runtime = "nodejs20.x"
memory_size = 128
timeout = 10
}
resource "aws_api_gateway_rest_api" "api_gateway" {
name = "ExpressAPI"
description = "API Gateway for Express.js Lambda"
}
resource "aws_api_gateway_resource" "hello_resource" {
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
parent_id = aws_api_gateway_rest_api.api_gateway.root_resource_id
path_part = "hello"
}
resource "aws_api_gateway_method" "hello_method" {
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
resource_id = aws_api_gateway_resource.hello_resource.id
http_method = "GET"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "hello_integration" {
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
resource_id = aws_api_gateway_resource.hello_resource.id
http_method = aws_api_gateway_method.hello_method.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "arn:aws:apigateway:${var.region}:lambda:path/2015-03-31/functions/${aws_lambda_function.lambda_function.arn}/invocations"
}
resource "aws_lambda_permission" "allow_api_gateway" {
statement_id = "AllowAPIGatewayInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.lambda_function.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.api_gateway.execution_arn}/*/*"
}
resource "aws_api_gateway_deployment" "api_deployment" {
depends_on = [aws_api_gateway_integration.hello_integration]
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
stage_name = "prod"
}
output "api_url" {
value = "https://${aws_api_gateway_rest_api.api_gateway.id}.execute-api.${var.region}.amazonaws.com/prod/hello"
}
Passo 3: Deploy
Dentro da pasta tofu
, execute os seguintes comandos para fazer o deploy:
tofu init
tofu plan
tofu apply
Após o deploy, você verá a URL da API Gateway que você pode usar para acessar a função Lambda.
Algo parecido com https://<api-id>.execute-api.<region>.amazonaws.com/prod/hello
Passo 4: Testando a API
Para testar a API, você pode usar o cURL ou o Postman:
curl https://<api-id>.execute-api.<region>.amazonaws.com/prod/hello
Voce verá o retorno Hello from Lambda!
na resposta.
Destruindo a Infraestrutura após os testes
Para destruir a infraestrutura, execute o seguinte comando:
tofu destroy
Conclusão
Se você chegou até aqui, quer dizer que você aprendeu como criar uma função Lambda com uma API usando Nodejs, Api Gateway e OpenTofu. Usamos o Express.js para criar a API, recursos nativos do sistema operacional para empacotar a função em arquivo .zip e o OpenTofu para fazer o deploy na AWS.