Dimarts, febrer 10, 2026
CLOUD & DEVOPS

Automatitzar tasques amb AWS Lambda

Migrar tasques programades des de servidors tradicionals a entorns serverless sovint ens porta directament a AWS Lambda combinada amb EventBridge. La proposta és clara: execucions sense necessitat de mantenir infraestructura, amb escalat automàtic, integració nativa amb altres serveis d’AWS i una interfície declarativa per a definir horaris. Sobre el paper, sembla una alternativa òbvia al cron de sempre.

Però quan es comença a operar tasques recurrents a Lambda, el que semblava una simple substitució revela matisos que no solen estar documentats. Les limitacions de temps d’ execució, la gestió de dependències, el control d’ entorn, les fallades silencioses o els reintents automàtics són alguns dels punts que, si no s’ ajusten bé des del començament, poden provocar problemes difícils de detectar o de depurar més endavant.

Aquesta entrada se centra en l’ ús real de Lambda per a tasques periòdiques, especialment aquelles programades mitjançant regles d’ EventBridge. No com a exercici d’ arquitectura ideal, sinó com a part d’ una operació estable. L’objectiu no és cobrir totes les possibilitats, sinó mostrar patrons que funcionen de forma consistent, configuracions que eviten errors comuns i decisions que val la pena prendre abans de desplegar el primer cron al núvol.

1. Pensar en cron al núvol: disseny inicial

Configurar una Lambda amb EventBridge de tipus cron és ràpid. AWS proveeix una interfície directa, i si fas servir infraestructura com a codi, pots tenir-lo enllestit en minuts. El problema apareix amb les següents preguntes:

  • Quin ingrés necessita la funció?
  • Quin rol hauria de tenir?
  • Què passa si falla?
  • Com garanteixo que no s’executi més d’una vegada per un error de desplegament?

En nodes tradicionals, aquestes preguntes es resolen barrejant scripts, variables d’entorn amagades a /etc, modificacions manuals i debug directe. Al núvol, pots cometre molts dels mateixos errors, només que escalen sense que t’ adonis.

2. Trigger: EventBridge en UTC, no local

Les regles cron de CloudWatch/ EventBridge funcionen a UTC. Si necessites executar alguna cosa en hora local, cal calcular l’òfset manualment. En CET, si vols que alguna cosa corri a les 3 AM hora local (UTC+1 o +2 segons l’època de l’any), has de programar “cron(0 1 * * ? *)” o “cron(0 2 * * ? *)” i canviar l’ hora dues vegades a l’ any. L’opció d’aplicar lògica dins de la funció per a evitar execucions inesperades ho complica tot, millor controlar des de la regla.

També el format de cron fa servir 6 camps, amb ? com a comodí en dia de setmana o mes, i no permeten increments tipus */5. Així que definir regles amb iteracions freqüents obliga a fer servir expressions específiques, per exemple:

schedule_expression = "cron(0/5 * * * ? *)" 

Però aquesta expressió no existeix, i AWS no dona cap missatge: senzillament no executa la funció. El més pràctic és fer servir un validator extern o provar regles amb una petita funció que registri trucades i verifiqui que corre en el temps esperat.

3. Funcions idempotents: explicitar dates

Tasques tradicionals fan servir l’hora correguda o date -d yesterday, la qual cosa en un entorn distribuït genera resultats inconsistents si l’execució es retarda per re-aprovisionament o fallida de sincronització horària. A Lambda, les anomenades event-driven han de portar data com a paràmetre:

{
 "execution_date": "2025-07-06T00:00:00Z"
}

Amb aquest execution_date, la funció pot calcular rangs, gestionar execution_date de dies anteriors si necessites replay i generar logs coherents. Facilita el debugging i permet detectar duplicats.

4. Límit de 15 minuts, concurrència i redisseny inevitable

Les funcions Launch poden córrer fins a 15 minuts. Si el teu procés triga 45 minuts, no cap a Lambda sense redisseny. Típicament la forma de lidiar és dividir tasques en parts, invocar sub-funcions en paral·lel o fer servir Step Functions per a funcions encadenades. Si això no és viable, fer servir ECS/Fargate o EC2 continua sent millor opció.

També tingueu en compte la concurrència. Fins i tot el cron bàsic pot disparar tasques repetides (per exemple si es reintenten). A AWS, pots reservar concurrència per a cada funció i així prevenir que una tasca corrent comprometi l’entorn o provoqui throttling inesperat.

5. Logs sota control: rotació i format

CloudWatch Logs no roten per defecte. Cada invocació de funció genera entrades, fins i tot quan no hi ha errors. Si executes una funció cada 5 minuts durant mesos, pots acumular molts GB. El recomanable és definir un resource aws_cloudwatch_log_group amb retention_in_days = 14 o 30 dies, que redueixi cost i control.

Pel que fa al contingut dels logs, si només imprimeixes text pla, després serà un embolic buscar o extreure mètriques. La pràctica efectiva és formatejar logs a JSON, amb camps com execution_date, duration_ms, result_count, error_code. Després mínims dashboards o alertes poden comprovar la qualitat de les execucions sense endivinar al text.

6. Permisos IAM: res per defecte

Moltes guies fan que una Lambda tingui un rol amb permisos amplis com s3:* o dynamodb:*. En equips més grans, això acaba generant problemes d’auditoria: una Lambda que esborra dades per accident i ningú sap qui o per què. L’ideal és assignar permisos mínims, i separar rols per funció. Terraform ajuda aquí:

resource "aws_iam_role_policy" "lambda_policy" {
  name = "daily-task-policy"
  role = aws_iam_role.lambda_role.id
 
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = ["s3:GetObject", "s3:ListBucket"],
        Effect = "Allow",
        Resource = [aws_s3_bucket.bucket.arn, "${aws_s3_bucket.bucket.arn}/*"]
      }
    ]
  })
}

I si més endavant necessites permisos addicionals, revisar el pla abans d’aplicar evita ensurts.

7. Versions i àlies: desplegaments controlats

Entrar a l’editor de Lambda a la consola i pujar un ZIP ja no funciona per a tasques programades. Si canvies el codi, vols que EventBridge apunti a una versió específica, i no a l’àlies $LATEST. Utilitzar àlies evita talls inesperats al cron.

Terraform té bon suport per a versions de Lambda i àlies:

resource "aws_lambda_alias" "live" {
  name             = "live"
  function_name    = aws_lambda_function.task.function_name
  function_version = aws_lambda_function.task.version
}

El cron target apunta a l’àlies. El que sí que és crític: fer rollback si una versió falla. Tenir àlies permet tornar enrere o mantenir múltiples entorns.

8. Alertes: errors no visibles no sumen valor

Si t’oblides de monitoritzar la mètrica Errors de la Lambda, una funció que falla al primer pas pot estar així durant dies sense que ningú s’assabenti. Per a cron, muntar una alarma amb SNS o email a Errors > 0 per cinc minuts és bàsic.

També es pot fer servir DLQ (Dead Letter Queue) fent servir SNS/SQS. D’aquesta manera, si la funció llença una excepció o el runtime falla, l’esdeveniment queda emmagatzemat per a anàlisi posterior. Sense DLQ ni alertes, el cron ha fallat i tots assumeixen que ha complert.

9. Casos d’ús eficients

Neteja de buckets per prefix temporal: una funció llista objectes amb prefix tmp/2025-07-05/, els processa i els esborra. Si falla, només re-calcula aquest prefix.

Report de recursos orfes: una funció que consulta volums EBS no utilitzats i genera un CSV o un PDF diari a S3.

Rotació d’ API keys: una funció accedeix a Vault o Parameter Store, genera una nova key i posa l’ anterior inactiva en un horari controlat.

Aquests patrons no requereixen solucions pesades i poden mantenir-se amb Lambda en molts casos.

10. Evita això

  • Configurar cron amb la consola sense IaC. Deixa la traçabilitat trencada.
  • Executar codi manual des de Lambda sense versionat o àlies. Corres el risc de trencar tasques programades.
  • Ignorar els logs. Si no hi ha monitoratge d’errors, les fallades silencioses es converteixen en deute tècnic.
  • Assignar permisos genèrics, amb comodins *. Concedir només el mínim fa més fàcil detectar errors.

11. Proves abans del primer cron

Un error força comú és desplegar una Lambda amb cron sense haver provat què passa en executar-se fora de l’entorn interactiu. El típic flux és aquest:

  • Es prova el codi local amb poetry run, pytest, etc.
  • Es puja a Lambda.
  • S’ executa manualment a la consola amb un esdeveniment de prova.
  • Tot sembla funcionar.
  • Es configura el cron.
  • A les 2:00 UTC la funció falla perquè falta una variable d’entorn o el rol no té accés.

Per a evitar això, sempre convé fer una prova amb la configuració final: executa la Lambda manualment però fent servir exactament l’esdeveniment que EventBridge li enviarà, amb el seu payload i context. I, si és possible, programar un cron de prova en algun minut puntual (per exemple cron(13 17 * * * * *)) i verificar logs i resultats reals en producció durant aquest horari.

Una altra cosa que sovint passa: si la funció escriu o llegeix de S3, assegura’t de provar en el bucket real, no en un de staging amb altres polítiques. Hi ha vegades que les polítiques en dev-* permeten de tot, però les de prod-* tenen restriccions per IP o per condicions aws:SourceArn.

12. Control d’entorn: evita herències invisibles

Molts entorns serverless acaben depenent de variables implícites: noms de buckets, rutes internes, noms de taules DynamoDB, secrets en SSM. En entorns tradicionals això es compensa amb .env o amb shell scripts que exporten variables abans d’anomenar el cron. A Lambda, aquestes herències no existeixen.

Definir explícitament cada variable d’entorn que fa servir la funció i declarar-les a Terraform (o CloudFormation) és una pràctica que evita problemes amb els canvis d’entorn. Fins i tot si fas servir Parameter Store o Secrets Manager, la referència ha de ser clara i l’accés, explícit en la política d’IAM. En cas contrari, una cosa que funciona en staging pot trencar en producció sense raó aparent.

Per exemple:

environment {
  variables = {
    REPORT_BUCKET = "reports-prod-bucket"
    API_KEY_PARAM = "/prod/api/thirdparty/key"
  }
}

I el rol ha de tenir accés explícit a ssm:GetParameter per a aquesta ruta.

13. Zones i regions: un problema quan el cron depèn de dades locals

Un problema menys visible és executar una funció en una regió i accedir a recursos que estan en una altra. Exemple real: una Lambda en us-east-1 que intenta accedir a un Secret d’ eu-west-1. Per defecte no es pot, i els errors són confusos (temps d’espera, accessos denegats genèrics, etc.).

En tasques periòdiques, això passa molt quan es dissenya el cron des d’una regió i després s’assumeix que podrà orquestrar recursos distribuïts. Si la tasca depèn de latències baixes o d’ accés a dades locals, és millor executar la Lambda a la mateixa regió que les dades. Si no, assumir el cost (tant en complexitat com en temps) d’una arquitectura multiregional ben pensada.

14. Timeouts, reintents i fallades silencioses

Les funcions Lambda tenen un timeout que tu defineixes, fins a 900 segons (15 minuts). Si l’execució el sobrepassa, la funció es mata sense avís, i el cron la reintenta (si està configurat).

Si no defineixes maximumRetryAttempts a EventBridge, AWS intenta diverses vegades amb regles que no són sempre clares: pot executar-se fins a dues vegades més en els següents minuts, però això no sempre passa. I quan sí que passa, pots acabar amb una doble execució que processa les mateixes dades.

Per a evitar això, el més segur és:

  • Fer la funció idempotent (amb checks per execution_date).
  • Afegir control explícit amb maximumRetryAttempts = 0 si no vols reintents.
  • Configurar alertes per a Timeouts a CloudWatch.
  • En logs, imprimir explícitament quan comença i acaba la tasca amb timestamp i execution_id.

15. Dependències: tingues cura de la capa d’execució

Si estàs treballant amb Python, Node.js o Java, tens versions específiques de runtime a Lambda: no sempre està disponible l’última versió. Per exemple, moltes funcions a Python segueixen en 3.9 o 3.10, i en actualitzar localment 3.12 pots començar a tenir errors subtils. El mateix amb dependències: algunes versions de boto3, requests, aws-sdk, etc., funcionen diferent o tenen canvis de signatura de mètodes que trenquen tasques que semblaven trivials.

El recomanable aquí:

  • Defineix versió explícita de Python (o Node) en els teus builds (runtime = “python3.10”).
  • Fes servir pip freeze per a generar un requirements.txt reproduïble.
  • O millor encara, si fas servir Terraform, crea una capa (layer) amb dependències i actualitza-la manualment només quan estàs segur que no hi ha efectes col·laterals.

A Python, un patró estable és compilar les dependències en un contenidor amb Amazon Linux 2:

docker run -v $(pwd):/lambda amazonlinux:2 \
  /bin/bash -c "yum install -y python3-pip zip && pip3 install -r requirements.txt -t /lambda/python"

Després empaquetes /lambda/python com a layer.zip.

16. No facis servir Lambda si…

Tot i que Lambda sembla bona per a tot, hi ha casos on no és l’eina adequada. Si la teva tasca:

  • Depèn de processos que triguen més de 15 minuts.
  • Requereix una connexió persistent a una base de dades.
  • Necessita estat compartit entre execucions concurrents.
  • Llença milers d’esdeveniments simultanis per disseny.

… llavors probablement estiguis millor amb ECS Fargate, Step Functions o fins i tot un job batch d’EC2 puntual.

Lambda està pensada per a tasques petites, contingudes, autònomes. Si la sobrecarregues, el cost de debugging creix exponencialment, i el benefici desapareix.

Conclusió

Fer servir AWS Lambda amb cron jobs funciona bé si es dissenyen amb claredat des del principi. No és un reemplaçament directe del cron de tota la vida: és un entorn nou, amb límits concrets i riscos reals si no es controla. Però si es gestiona bé, redueix la necessitat de servidors, permet escalar automàticament i millora la traçabilitat d’execucions.

La clau està en controlar cada aspecte: entorn, versions, logs, reintents, permisos i monitoratge. I tenir sempre clar quin problema estàs resolent i quin cost operatiu estàs disposat a acceptar per automatitzar-lo amb Lambda.

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *