Pular para conteúdo

AWS SAM (Serverless Application Model)

Guia de uso do AWS SAM para desenvolvimento e deploy serverless.

O que é SAM?

AWS SAM é um framework open-source para construir aplicações serverless na AWS.

Benefícios: - Templates CloudFormation simplificados - Local testing e debugging - Deploy simplificado - Built-in best practices

Instalação

# macOS
brew install aws-sam-cli

# Linux
pip install aws-sam-cli

# Verificar
sam --version

Template SAM

template.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: People Tech App

Globals:
  Function:
    Timeout: 30
    Runtime: python3.11
    MemorySize: 512
    Environment:
      Variables:
        ENVIRONMENT: !Ref Environment
        LOG_LEVEL: INFO

Parameters:
  Environment:
    Type: String
    AllowedValues: [staging, production]
    Description: Environment name

Resources:
  # API Gateway
  AppApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref Environment
      Cors:
        AllowOrigin: "'*'"
        AllowHeaders: "'*'"
        AllowMethods: "'GET,POST,PUT,DELETE,OPTIONS'"

  # Lambda Function
  UserFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.users.lambda_handler
      Events:
        GetUsers:
          Type: Api
          Properties:
            RestApiId: !Ref AppApi
            Path: /users
            Method: GET
        CreateUser:
          Type: Api
          Properties:
            RestApiId: !Ref AppApi
            Path: /users
            Method: POST
      Policies:
        - AWSSecretsManagerGetSecretValuePolicy:
            SecretArn: !Ref DatabaseSecret
        - DynamoDBCrudPolicy:
            TableName: !Ref UsersTable
      Environment:
        Variables:
          DATABASE_SECRET_ARN: !Ref DatabaseSecret
          USERS_TABLE: !Ref UsersTable

  # SQS Queue
  UserEventsQueue:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: !Sub '${AWS::StackName}-user-events'
      VisibilityTimeout: 300
      MessageRetentionPeriod: 345600  # 4 days
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt UserEventsDLQ.Arn
        maxReceiveCount: 3

  UserEventsDLQ:
    Type: AWS::SQS::Queue
    Properties:
      QueueName: !Sub '${AWS::StackName}-user-events-dlq'

  # Event Processor Lambda
  EventProcessor:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.workers.event_processor
      Events:
        SQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt UserEventsQueue.Arn
            BatchSize: 10

  # SNS Topic
  ProductUpdatesTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: Product Updates
      Subscriptions:
        - Endpoint: !GetAtt EmailSender.Arn
          Protocol: lambda

  # Database Secret
  DatabaseSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: !Sub '/${AWS::StackName}/database'
      SecretString: !Sub |
        {
          "username": "app_user",
          "password": "${DatabasePassword}",
          "host": "${DatabaseHost}",
          "port": 5432,
          "database": "app_db"
        }

Outputs:
  ApiUrl:
    Description: API Gateway URL
    Value: !Sub 'https://${AppApi}.execute-api.${AWS::Region}.amazonaws.com/${Environment}/'
    Export:
      Name: !Sub '${AWS::StackName}-ApiUrl'

  QueueUrl:
    Description: SQS Queue URL
    Value: !Ref UserEventsQueue

Configuração

samconfig.toml:

version = 0.1

[default.global.parameters]
stack_name = "people-tech-app"

[default.build.parameters]
cached = true
parallel = true

[default.deploy.parameters]
capabilities = "CAPABILITY_IAM"
confirm_changeset = true
resolve_s3 = true
region = "us-east-1"

[staging]
[staging.deploy.parameters]
stack_name = "people-tech-app-staging"
parameter_overrides = "Environment=staging"

[production]
[production.deploy.parameters]
stack_name = "people-tech-app-production"
parameter_overrides = "Environment=production"

Comandos

Build

# Build application
sam build

# Build com Docker (recomendado)
sam build --use-container

# Build função específica
sam build UserFunction

Local Testing

# Iniciar API local
sam local start-api

# Invocar função
sam local invoke UserFunction -e events/user-created.json

# Start Lambda local
sam local start-lambda

Deploy

# Deploy para staging
sam deploy --config-env staging

# Deploy para production
sam deploy --config-env production

# Deploy com confirmação
sam deploy --guided

# Deploy forçando upload
sam deploy --config-env production --force-upload

Logs

# Tail logs de função
sam logs -n UserFunction --tail

# Logs com filtro
sam logs -n UserFunction --filter "ERROR"

Sync (Hot reload)

# Watch e deploy mudanças automaticamente
sam sync --watch --config-env staging

Layers

Para compartilhar código entre Lambdas:

Resources:
  SharedLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: shared-dependencies
      ContentUri: layers/shared/
      CompatibleRuntimes:
        - python3.11
    Metadata:
      BuildMethod: python3.11

  UserFunction:
    Type: AWS::Serverless::Function
    Properties:
      Layers:
        - !Ref SharedLayer

Environment Variables

Globals:
  Function:
    Environment:
      Variables:
        ENVIRONMENT: !Ref Environment
        LOG_LEVEL: INFO
        # Resolve from SSM
        API_ENDPOINT: '{{resolve:ssm:/app/api-endpoint}}'
        # Resolve from Secrets Manager
        DB_PASSWORD: '{{resolve:secretsmanager:db-secret:SecretString:password}}'

Best Practices

✅ Fazer

  • Usar sam build --use-container (consistência)
  • Versioning de Layers
  • Separate resources per environment (staging/prod stacks)
  • Use samconfig.toml (não hardcode params)
  • Tags para todos os resources

❌ Evitar

  • Hardcode values no template
  • Deployar sem build
  • Usar sam deploy --guided no CI (use config file)
  • Secrets em plaintext

Troubleshooting

Build failed

# Limpar cache
rm -rf .aws-sam/

# Build verboso
sam build --use-container --debug

Deploy failed

# Ver changesets
aws cloudformation describe-change-set \
  --stack-name people-tech-app-staging \
  --change-set-name <changeset-id>

# Rollback
sam delete --stack-name people-tech-app-staging

Referências