Introdução
Nesse artigo vamos fazer uma introdução ao Serverless Framework na versão 4 como uma ferramenta de IaC para criarmos uma infraestrutura na AWS de forma rápida sem gerenciar os recurso manualmente no console, ou escrever grande scripts para ferrametas de IaC nativas como CloudFormation ou Terraform.
Eu não irei detalhar o que cada item faz, o objetivo é mostrar como é rápido e fácil subir um ambiente na AWS com o Serverless Framework.
Requisitos
Para seguir com esse artigo, é importante que você preencha os requistos a seguir:
- Ter o Node.js instalado
- Ter uma conta ativa na AWS
- Ter configurado a CLI da AWS na sua maquina
- Ter instalado o Serverless Framework (npm install -g serverless)
O que é Serverless Framework
Ele é uma ferramenta que abstrai a complexidade dos serviços nativos da nuvem como o CloudFormation da AWS, permitindo que você gerencie sua arquitetura de forma elegante e concisa.
Diferente de outras ferramentas, ele, além de gerenciar sua infraestrutura, também gerencia o seu código. Outro ponto, é que ele suporta diferentes tipos de linguagens como Python, Node.js e Go.
Funções, eventos e recursos
O Serverless Framework é gerenciado em arquivo de serviço chamado: serverless.yml
nele você controla os seus recursos, funções e eventos, funcionando da seguinte maneira:
O código é lançado e executado na AWS como uma função lambda. Cada função é subida e executada individualmente com uma única responsabilidade, funcionando quase como um microserviço. Por exemplo: uma função para salvar o usuário em um banco de dados.
Essas funções são disparadas através de eventos que vem de recursos da AWS. Por exemplo: quando uma requisição HTTP é feita no API Gateway, uma lambda é disparada.
As funções criadas podem precisar de um recursos da AWS, como um banco de dados, um bucket de armazenamento, um bucket de arquivos, etc. Dentro do Serverless é possível provisionar esses recursos.
Começando nossa API
Para usar os comandos serverless na versão 4, é necessário fazer o login na plataforma, então crie uma conta e utilize o comando a seguir:
serverless login
Vamos começar criando um novo projeto. Uma vez que você digitar o comando abaixo, será necessário escolher uma opção, vamos seguir com: “AWS – Node.js – HTTP API”.
Depois, escolha um nome para o projeto, no meu caso estarei usando o nome: ‘customers-api’.
Por fim, ele deve pedir para você vincular esse projeto a um app da dashboard, pode selecionar o ‘Skip Adding an App’ e continuar.
serverless
Uma vez que o projeto foi iniciado, vamos entrar na pasta e instalar as depedências necessárias:
cd customers-api
npm install
O deploy dos serviços podem demorar um pouco, então mesmo que nenhuma função tenha sido criada, vamos fazer o primeiro deploy com a estrutura inicial da nossa API.
A partir de agora vamos usar a abreviação do comando serverless como ‘sls’.
sls deploy
Se tiver algum tipo de problema com o deploy, revise suas configurações de CLI da AWS e tente novamente os passos anteriores
Agora vamos testar nosso endpoint para ver se esta funcionando corretamente.
Lembre-se de utilizar a sua URL.
curl https://zxwwdsj8ol.execute-api.us-east-1.amazonaws.com/
# output
# {"message":"Go Serverless v4! Your function executed successfully!"}
Criando os endpoints e organizando o projeto
Antes de atualizar o arquivo serverless.yml
, vamos criar os endpoints da nossa aplicação.
Eu gosto de organizar o projeto colocando as funções dentro de uma src
. Dentro dela, vamos nossa primeira função chamada createCustomer.js
que irá salvar um novo cliente no nosso banco de dados usando o DynamoDB.
Para facilitar nosso desenvolvimento vamos instalar os pacotes da AWS.
npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb
Agora vamos criar o arquivo createCustomer.js
'use strict'
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb')
const { DynamoDBDocumentClient, PutCommand } = require('@aws-sdk/lib-dynamodb')
module.exports.handler = async (event) => {
const body = JSON.parse(Buffer.from(event.body, 'base64').toString())
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}))
const putParams = {
TableName: process.env.DYNAMODB_CUSTOMER_TABLE,
Item: {
primary_key: body.name,
email: body.email,
},
}
await ddb.send(new PutCommand(putParams))
return {
statusCode: 201,
}
}
Agora vamos criar o arquivo para exibir a lista de clientes getCustomers.js
:
'use strict'
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb')
const { DynamoDBDocumentClient, ScanCommand } = require('@aws-sdk/lib-dynamodb')
module.exports.handler = async () => {
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}))
const result = await ddb.send(
new ScanCommand({
TableName: process.env.DYNAMODB_CUSTOMER_TABLE,
})
)
if (!result.Count || result.Count === 0) {
return {
statusCode: 404,
}
}
return {
statusCode: 200,
body: JSON.stringify({
total: result.Count,
items: result.Items.map((customer) => ({
name: customer.primary_key,
email: customer.email,
})),
}),
}
}
Atualizando o arquivo serverless.yml
Agora vamos atualizar o arquivo serverless.yml
adicionando os endpoints e recursos necessários.
Nosso serverless.yml
deve começar da seguinte igual o arquivo abaixo, caso seu esteja diferente faça as modificações:
org: daniilomello
service: customers-api
provider:
name: aws
runtime: nodejs20.x
architecture: arm64
package:
individually:
Agora vamos adicionar os endpoints, que são funções lambdas integradas com o API Gateway. Para isso vamos adicionar o seguinte:
functions:
createCustomer:
handler: src/createCustomer.handler
events:
- httpApi:
path: /customers
method: post
getCustomers:
handler: src/getCustomers.handler
events:
- httpApi:
path: /customers
method: get
Agora vamos adicionar o nosso recuso do dynamoDB para usarmos como banco de dados:
resources:
Resources:
CustomerTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: primary_key
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: primary_key
KeyType: HASH
TableName: CustomerTable
Para que as nossas funções tenham permissão de realizar operações no nosso banco de dados, precisamos configura o IAM da AWS no nosso provider. Para isso faça o seguite:
provider:
iam:
role:
statements:
- Effect: 'Allow'
Action:
- 'dynamodb:PutItem'
- 'dynamodb:Get*'
- 'dynamodb:Scan*'
- 'dynamodb:UpdateItem'
- 'dynamodb:DeleteItem'
Resource: !GetAtt CustomerTable.Arn
Além disso, nossas funções chamam o nome da tabela através de uma variável de ambiente. Vamos configura essa variável dentro do nosso provider:
provider:
environment:
DYNAMODB_CUSTOMER_TABLE: !Ref CustomerTable
Nosso arquivo final yml
deve ficar da seguinte forma:
org: daniilomello
service: customers-api
provider:
name: aws
runtime: nodejs20.x
architecture: arm64
environment:
DYNAMODB_CUSTOMER_TABLE: !Ref CustomerTable
iam:
role:
statements:
- Effect: 'Allow'
Action:
- 'dynamodb:PutItem'
- 'dynamodb:Get*'
- 'dynamodb:Scan*'
- 'dynamodb:UpdateItem'
- 'dynamodb:DeleteItem'
Resource: !GetAtt CustomerTable.Arn
package:
individually: true
custom:
esbuild:
bundle: true
minify: false
sourcemap: false
exclude:
- '@aws-sdk/*'
target: node20
functions:
createCustomer:
handler: src/createCustomer.handler
events:
- httpApi:
path: /customers
method: post
getCustomers:
handler: src/getCustomers.handler
events:
- httpApi:
path: /customers
method: get
resources:
Resources:
CustomerTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: primary_key
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: primary_key
KeyType: HASH
TableName: CustomerTable
Agora que está tudo configurado, vamos testar criar um novo cliente, e exibir a lista de clientes.
Lembre-se de utilizar a sua URL.
Criando um cliente:
curl -X POST -d '{"name":"Danilo Mello","email":"mello@daniilo.dev"}' --url https://zxwwdsj8ol.execute-api.us-east-1.amazonaws.com/customers
# output
# {"statusCode":201}%
Listando os clientes:
curl --url https://zxwwdsj8ol.execute-api.us-east-1.amazonaws.com/customers
# output
# {"total":1,"items":[{"name":"Danilo Mello","email":"mello@daniilo.dev"}]}%
Conclusão
Nesse artigo você viu como é rapido e simples subir um ambiente na AWS com o Serverless Framework.
Agora com o Serverless Framework você consegue:
- Criar APIs com o API Gateway
- Criar bancos de dados no DynamoDB
- Criar funções lambdas na AWS
- Criar permissões usando o IAM
- Fazer o deploy da sua infraestrutura por linha de comando
Agora vai de você explorar e se aprofundar mais nessa ferramenta.