DEV Community

Cover image for Como Estruturei um Template de AWS Lambda com Terraform e GitHub Actions
Marcos Vilela
Marcos Vilela

Posted on

Como Estruturei um Template de AWS Lambda com Terraform e GitHub Actions

Recentemente, desenvolvi um template reutilizável para aplicações AWS Lambda em Python, integrando infraestrutura como código via Terraform e automação de CI/CD com GitHub Actions. Neste artigo, compartilho minha experiência, decisões de arquitetura e exemplos práticos para quem deseja acelerar projetos serverless na AWS.

Motivação

A necessidade de padronizar e acelerar entregas de funções Lambda me levou a criar um template que pudesse ser facilmente adaptado para diferentes projetos. O objetivo era garantir segurança, rastreabilidade e facilidade de manutenção, sem depender de nomes de empresas ou clientes.
Ao longo do tempo, percebi que cada projeto serverless traz desafios recorrentes: integração com múltiplos triggers, controle de ambientes, versionamento de código, automação de deploy e governança de permissões. Centralizar essas soluções em um template robusto foi essencial para evitar retrabalho e garantir consistência. A busca por automação e segurança guiou cada decisão técnica.

Estrutura do Projeto

A estrutura que utilizei foi a seguinte:

.
├── app/
│   └── handler.py              # Código da Lambda
├── infra/
│   └── terraform/
│       ├── main.tf             # Infra principal
│       ├── variables.tf        # Variáveis
│       ├── outputs.tf          # Outputs
│       ├── version.tf          # Provider e backend
│       └── envs/
│           ├── prod/
│           │   └── terraform.tfvars
│           └── staging/
│               └── terraform.tfvars
Enter fullscreen mode Exit fullscreen mode

Lambda Handler Genérico

Implementei um handler que detecta automaticamente o tipo de evento recebido (HTTP, EventBridge, SNS, S3) e responde de forma adequada. Veja um exemplo simplificado:

import json
import logging
from datetime import datetime, timezone
from typing import Dict, Any

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event: Dict[str, Any], context: Any) -> Dict[str, Any]:
    logger.info("Lambda invocada - Request ID: %s", context.aws_request_id)
    logger.info("Evento recebido: %s", json.dumps(event, default=str))

    response_data = {
        "message": "Hello World!",
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "request_id": context.aws_request_id,
        "event_type": get_event_type(event),
        "function_name": context.function_name,
        "function_version": context.function_version,
        "memory_limit_mb": context.memory_limit_in_mb,
    }

    logger.info("Resposta: %s", json.dumps(response_data))

    if is_http_event(event):
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps(response_data),
        }
    return {"statusCode": 200, "body": response_data}
Enter fullscreen mode Exit fullscreen mode

Infraestrutura como Código com Terraform

Utilizei módulos oficiais da AWS para Lambda, API Gateway, EventBridge, SNS e S3. A configuração de variáveis permite habilitar ou desabilitar triggers conforme o ambiente. Exemplo de variáveis para produção:

aws_region   = "us-east-1"
environment  = "prod"
project_name = "my-lambda-app"
lambda_runtime     = "python3.12"
lambda_timeout     = 60
lambda_memory_size = 512
enable_eventbridge = false
enable_api_gateway = false
enable_function_url = false
Enter fullscreen mode Exit fullscreen mode

A detecção automática de Lambda Layers foi feita via local no Terraform:

locals {
  layers_path = "${path.module}/../../app/layers"
  layer_files = fileset(local.layers_path, "*.zip")
  auto_detected_layers = {
    for file in local.layer_files :
    replace(file, ".zip", "") => {
      layer_name          = replace(file, ".zip", "")
      description         = "Auto-detected layer from ${file}"
      compatible_runtimes = [var.lambda_runtime]
      source_path         = file
      skip_destroy        = false
    }
  }
  all_layers = merge(
    local.auto_detected_layers,
    { for layer in var.lambda_layers : layer.layer_name => layer }
  )
}
Enter fullscreen mode Exit fullscreen mode

CI/CD com GitHub Actions

Implementei pipelines para validação, lint, scan de segurança, deploy em staging e produção, além de automação de releases e rollback. O workflow principal para produção segue este padrão:

on:
  push:
    branches:
      - main

jobs:
  validate-lambda:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v5
      - name: Setup Python
        uses: actions/setup-python@v5
      - name: Check Python syntax
        working-directory: app
  # ... outros jobs para lint, scan, terraform, release
Enter fullscreen mode Exit fullscreen mode

Boas Práticas Adotadas

  • Separação clara entre ambientes (staging/prod)
  • Uso de variáveis para habilitar/desabilitar recursos
  • Detecção automática de Lambda Layers
  • Templates de PR e rollback para padronizar processos
  • Outputs detalhados para facilitar integrações

Conclusão

Esse template acelerou significativamente o desenvolvimento de funções Lambda, garantindo padronização e segurança. Recomendo fortemente a abordagem para quem busca agilidade e governança em projetos serverless na AWS.

O código completo está disponível em repositórios privados, mas os exemplos acima podem ser adaptados para qualquer contexto. Se quiser discutir mais sobre arquitetura serverless, estou à disposição para trocar ideias.

Top comments (0)