1 2 3 Lambda (con Terraform)

March 14, 2019 0 Comments Terraform, AWS, Lambda

Oplà!

Chi di voi lavora costantemente con AWS si è trovato sicuramente di fronte al dilemma di gestire le Lambda.

Cosa sono le Lambda?

Le Lambda sono dei "container" che Amazon gestisce per voi in autonomia. In base al numero di invocazioni istanzia uno o più container in modo tale da avere sempre una risposta veloce alle richieste. Quello che si paga è il tempo di esecuzione totale in millisecondi.

Fatta questa introduzione veloce, vi lascio la pagina di Amazon dove spiega meglio cosa sono le Lambda https://aws.amazon.com/it/lambda/features/ .

Terraform con le Lambda

Ci sono varie metodologie per pacchettizzare e caricare le Lambda su AWS, la prima delle quali è creare manualmente lo zip e poi invocare aws cli per il caricamento del codice nella lambda.

Questo metodo però è poco riproducibile ed è demandato sopratutto ad un operazione manuale. Inoltre bisogna andare manualmente a creare tutte le risorse di contorno su amazon, come le policy di esecuzione, il ruolo, i permessi, le eventuali variabili d'ambiente etc.

Ma posso farlo anche con Jenkins!

Si, volendo è possibile creare dei Job CI che gestiscano le lambda automatizzando tutti questi passaggi. Il problema di gestire le lambda in questo modo è che non si ha un unico punto in cui si ha lo stato corrente di tutte le lambda "deployate" e inoltre non è facile eliminarle e ricrearle nel caso serva.

Ho creato un progetto su GitHub che serve come base al deploy di una qualsiasi lambda, il link è il seguente: https://github.com/nutellinoit/terraform-aws-lambda-skeleton

Il processo che viene utilizzato da questo modulo di terraform è il seguente:

1) Si aggiorna la variabile lambda_version
2) questa variabile è utilizzata come trigger in una null_resource che si occupa di creare lo zip del codice con un nome del file dipendente dal valore della variabile lambda_version;
3) questa modifica fa si che la risorsa aws_lambda_function sia modificata tramite il nome del file
4) Terraform quindi ricaricherà il codice su AWS

Per effettuare deploy successivi del codice si dovrà agire sempre e solo sul valore della variabile lambda_version.

Perché questo workaround?

Tutti gli esempi che trovate in rete, e anche nella documentazione ufficiale di terraform utilizzano la risorsa archive_file. Il problema è che questa risorsa viene eseguita ad ogni run di terraform essendo di tipo data, creando quindi un nuovo zip. Questo nuovo zip fa si che la risorsa aws_lambda_function sia sempre modificata.

Perché è un problema?

Perché se la nostra lambda è formata da una grande quantità di librerie che vengono solitamente ignorate con un file .gitignore, possiamo trovarci di fronte ad un caricamento parziale del codice e quindi trovarci con una lambda "rotta" . (Questo l'ho provato sulla mia pelle, e non è bello).

Evitando quindi di utilizzare qualcosa che viene eseguito ad ogni apply di terraform abbiamo un controllo più granulare sull'update di una lambda.

Esempio di utilizzo del modulo (lo trovate anche sul README.md del progetto):

module "lambda-skeleton"{  
  source = "git::https://github.com/nutellinoit/terraform-aws-lambda-skeleton.git?ref=master"
  lambda_version = "1" # change this value to trigger another deploy
  name = "CoolLambda"
  environment_1 = "1"
  environment_2 = "2"
  environment_3 = "3"
}
Samuele Chiocca
Padova, italy Website