energy-systems-and-sustainability
Déploiement d'infrastructure automatique pour les applications sans serveur avec Terraform
Table of Contents
L'informatique sans serveur a transformé la façon dont les équipes construisent et déploient des applications, offrant une évolutivité, un prix à la carte et une réduction des frais généraux opérationnels. Cependant, exécuter des applications sans serveur dans la production implique bien plus que d'écrire du code de fonction. Vous devez fournir et gérer des dizaines de ressources en nuage – passerelles API, files d'attente, bases de données, rôles IAM, configurations de journalisation et composants de réseautage – qui doivent toutes être reproduites de façon cohérente dans les environnements de développement, de mise en scène et de production.
Qu'est-ce que Terraform?
Terraform est un outil IaC open source créé par HashiCorp qui vous permet de fournir et de gérer l'infrastructure à travers plusieurs fournisseurs de cloud en utilisant un langage de configuration déclaratif connu sous le nom de HCL (HashiCorp Configuration Language). Au lieu d'écrire des scripts impérieux qui exécutent des commandes étape par étape, vous déclarez l'état souhaité de votre infrastructure – quelles ressources vous voulez, leurs propriétés et comment elles se rapportent – et Terraform détermine les actions nécessaires pour atteindre cet état.
Terraform compare votre configuration avec l'état actuel de l'infrastructure et produit un plan détaillé de ce qui sera créé, mis à jour ou détruit. Ce plan peut être revu (et approuvé dans les pipelines CI/CD) avant qu'il ne soit appliqué, vous donnant une boucle de rétroaction sûre qui empêche les changements involontaires. Terraform suit également les ressources dans un fichier d'état, qui maquille la configuration en objets cloud réels. Ce fichier d'état est essentiel pour que Terraform sache ce qu'il gère et détecte la dérive.
Terraform prend en charge des centaines de fournisseurs, y compris toutes les grandes plateformes cloud (AWS, Azure, Google Cloud), ainsi que les services SaaS comme Cloudflare, Datadog et GitHub. Pour les applications sans serveur sur AWS, vous utiliserez généralement le AWS provider pour définir les fonctions Lambda, API REST de API Gateway, tables DynamoDB, files d'attente SQS, flux Kinesis, piscines utilisateurs Cognito et toutes les politiques IAM qui les relient.
Pourquoi les applications sans serveur ont besoin d'infrastructure comme code
Les applications sans serveur sont composées de nombreux petits services spécialement conçus qui communiquent asynchronement ou synchrone. Une architecture typique basée sur les événements peut inclure une passerelle API qui reçoit des requêtes HTTP, une fonction Lambda pour les traiter, une table DynamoDB pour stocker les résultats, et une file d'attente SQS pour tamponner pour une seconde fonction Lambda. La création de ces ressources à la main est fastidieuse et sujette aux erreurs, d'autant plus que votre architecture se développe pour inclure des dizaines de fonctions et services auxiliaires.
- Incohérence: Différents environnements (dev, stading, prod) dérivent inévitablement lorsqu'ils sont créés manuellement.
- Aucun historique de version: Qui a changé la capacité de lecture de DynamoDB? Quand? Pourquoi? Sans code, vous perdez la vérification.
- Création cauchemar: Après un désastre, vous devriez tout reconfigurer à partir de zéro, en espérant que vous vous souveniez de chaque réglage.
- Filt de temps:[ Cliquer sur la console pour chaque ressource consomme des heures qui devraient entrer dans la logique d'application.
IaC résout ces problèmes en transformant l'infrastructure en logiciel. Chaque changement est une requête de traction. Chaque environnement est un déploiement répétable. Et toute votre architecture peut être démolie et reconstruite en minutes. Pour les applications sans serveur, où la proposition de valeur est la vitesse et l'agilité, IaC n'est pas optionnelle – il est le fondement d'un flux de production fiable.
Principaux avantages de l'utilisation de Terraform pour sans serveur
Alors que tout outil IaC pourrait être utilisé pour gérer une infrastructure sans serveur, Terraform offre des avantages distincts qui correspondent bien aux besoins des équipes sans serveur.
Automatisation du cycle de vie complet
Terraform gère non seulement la provisionnement, mais aussi la mise à jour et la destruction des ressources. Lorsque vous devez changer la taille de mémoire d'une fonction Lambda ou l'attribut TTL d'une table DynamoDB, vous mettez simplement à jour la configuration et exécutez . Lorsque vous avez terminé avec une ressource, le même code qui l'a créé va la nettoyer.
Gestion de la dépendance déclarative
Une fonction Lambda dépend d'un rôle IAM, qui peut dépendre d'une politique, qui peut dépendre d'une table DynamoDB ARN. Terraform construit un graphique de ressources à partir de vos déclarations et détermine automatiquement l'ordre des opérations. Elle crée des ressources avant qu'elles ne soient référencées et attend que les dépendances deviennent disponibles. Cela vous libère de l'écriture de scripts sujets à des erreurs qui suivent manuellement les commandes.
Cohérence multi-environnement
En utilisant des espaces de travail ou des structures de répertoire Terraform, vous pouvez réutiliser la même configuration dans plusieurs environnements avec différentes valeurs variables. Une configuration Lambdas peut être identique dans dev, stage et production, sauf pour les variables spécifiques à l'environnement telles que les noms de table, les niveaux de log ou les paramètres VPC.
Contrôle par l'État granulaire
La gestion de l'état est une préoccupation critique. Terraform vous permet de stocker l'état à distance dans des moteurs comme S3 (avec blocage DynamoDB), Terraform Cloud ou HashiCorp Consul. L'état distant permet la collaboration d'équipe : plusieurs ingénieurs peuvent appliquer en toute sécurité des changements à la même infrastructure sans conflit.
Débuter avec Terraform pour le déploiement sans serveur
Let , par exemple, exposera une API REST simple via API Gateway qui déclenche une fonction Lambda, qui écrit des données sur une table DynamoDB. Nous couvrirons également les autorisations IAM requises.
Préalables
- Terraform installé (téléchargement)
- Compte AWS avec des identifiants configurés (via des variables d'environnement ou )
- Node.js installé (pour compiler le code Lambda)
Structure du projet
serverless-terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── lambda/
│ └── index.js
└── terraform.tfvars
1. Définir le fournisseur Terraform
Dans , configurer le fournisseur AWS et spécifier la région:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "serverless-app/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}
provider "aws" {
region = var.aws_region
}
2. Créer le rôle de l'IAM pour Lambda
data "aws_iam_policy_document" "lambda_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
}
}
resource "aws_iam_role" "lambda_exec" {
name = "serverless-lambda-role"
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role.json
}
resource "aws_iam_policy" "lambda_dynamodb_policy" {
name = "lambda-dynamodb-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["dynamodb:PutItem", "dynamodb:GetItem", "dynamodb:UpdateItem"]
Effect = "Allow"
Resource = aws_dynamodb_table.items.arn
},
{
Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"]
Effect = "Allow"
Resource = "*"
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy_attach" {
role = aws_iam_role.lambda_exec.name
policy_arn = aws_iam_policy.lambda_dynamodb_policy.arn
}
3. Déployer la table DynamoDB
resource "aws_dynamodb_table" "items" {
name = "items"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
tags = {
Environment = var.environment
}
}
4. Package et déploiement de la fonction Lambda
D'abord, créez une fonction Lambda simple dans :
exports.handler = async (event) => {
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();
const id = event.pathParameters.id;
const params = {
TableName: process.env.TABLE_NAME,
Item: { id, timestamp: Date.now(), data: event.body }
};
await dynamodb.put(params).promise();
return {
statusCode: 200,
body: JSON.stringify({ id })
};
};
Ensuite, dans votre configuration Terraform, référez-vous au code de fonction:
data "archive_file" "lambda_zip" {
type = "zip"
source_dir = "${path.module}/lambda"
output_path = "${path.module}/lambda_function_payload.zip"
}
resource "aws_lambda_function" "api_handler" {
filename = data.archive_file.lambda_zip.output_path
function_name = "serverless-api-handler"
role = aws_iam_role.lambda_exec.arn
handler = "index.handler"
runtime = "nodejs18.x"
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
environment {
variables = {
TABLE_NAME = aws_dynamodb_table.items.name
}
}
}
5. Exposer la Lambda via API Gateway
resource "aws_api_gateway_rest_api" "api" {
name = "serverless-api"
}
resource "aws_api_gateway_resource" "items" {
rest_api_id = aws_api_gateway_rest_api.api.id
parent_id = aws_api_gateway_rest_api.api.root_resource_id
path_part = "items"
}
resource "aws_api_gateway_resource" "item" {
rest_api_id = aws_api_gateway_rest_api.api.id
parent_id = aws_api_gateway_resource.items.id
path_part = "{id}"
}
resource "aws_api_gateway_method" "put_item" {
rest_api_id = aws_api_gateway_rest_api.api.id
resource_id = aws_api_gateway_resource.item.id
http_method = "PUT"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "lambda" {
rest_api_id = aws_api_gateway_rest_api.api.id
resource_id = aws_api_gateway_resource.item.id
http_method = aws_api_gateway_method.put_item.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = aws_lambda_function.api_handler.invoke_arn
}
resource "aws_lambda_permission" "apigw" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.api_handler.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_api_gateway_rest_api.api.execution_arn}/*/*"
}
resource "aws_api_gateway_deployment" "prod" {
depends_on = [aws_api_gateway_integration.lambda]
rest_api_id = aws_api_gateway_rest_api.api.id
stage_name = "prod"
}
6. Définir les produits
Dans , exposer le paramètre API:
output "api_endpoint" {
value = "${aws_api_gateway_deployment.prod.invoke_url}/items/"
}
7. Appliquer
terraform init
terraform plan
terraform apply
Après avoir appliqué, vous pouvez émettre une demande PUT au point final avec un corps JSON. La fonction Lambda écrit les données à DynamoDB. Pour abattre toute la pile, exécutez .
Structurer les projets Terraform pour les sans serveurs
Les applications sans serveur sont trop grandes pour un seul fichier de configuration. L'adoption d'une structure de projet évolutive est essentielle. Voici des modèles communs:
Utiliser des modules pour encapsuler des composants réutilisables
Les modules Terraform vous permettent de regrouper les ressources en unités logiques. Pour les modules sans serveur, vous pouvez créer des modules pour :
- Un module de fonction de base Lambda (avec le rôle IAM, les permissions de base CloudWatch et la configuration VPC en option)
- Un module d'intégration API Gateway + Lambda
- Un module de table DynamoDB avec des attributs standardisés et l'auto-calcalisation
- Un module de file d'attente SQS avec files d'attente en lettres mortes
Les modules peuvent être stockés dans votre propre dépôt Git ou publiés dans le Terraform Registry. Ils simplifient les configurations spécifiques à l'environnement : vous instituez un module avec différentes variables par environnement.
Environnements séparés avec répertoires ou espaces de travail
Il existe deux approches communes pour la gestion des environnements :
- Répertoire par environnement:[ Créer des dossiers comme , , , chacun avec ses propres et éventuellement un . Cela isole les fichiers d'état et empêche les changements cross-environnement accidentels.
- Terraform Workspaces: Utilisez la fonction de l'espace de travail intégré pour créer des instances nommées de la même configuration. Les espaces de travail sont plus légers mais peuvent devenir confus lorsqu'ils traitent avec plusieurs équipes.
Pour la plupart des équipes sans serveur, l'approche du répertoire est plus claire car elle rend les limites d'environnement explicites dans la base de codes.
État distant avec verrouillage
Ne jamais stocker l'état localement pour les projets d'équipe. Utilisez un moteur S3 avec verrouillage DynamoDB. Le seau S3 tient le fichier d'état, et DynamoDB fournit des verrous de cohérence de sorte qu'un seul fonctionne à la fois. Exemple de configuration de moteur a été montré plus tôt. Assurez-vous que le seau S3 et la table DynamoDB sont créés en dehors de Terraform (bootstrapez-les avec un script séparé ou utilisez la gestion d'état intégrée Terraform Cloud).
Gérer les secrets en toute sécurité
Les applications sans serveur nécessitent souvent des secrets comme les mots de passe de base de données, les clés API ou les jetons de signature JWT. Ne jamais les coder avec du dur dans les configurations Terraform.
- AWS Secrets Manager ou SSM Parameter Store, référencé par ou sources de données
- Fournisseur de Vault pour récupérer des secrets dynamiques
- Fichiers variables chiffrés spécifiques à l'environnement (p. ex. ] avec des outils comme )
Meilleures pratiques pour l'automatisation de l'infrastructure avec Terraform
Pour maximiser la fiabilité et la vitesse de l'équipe, suivez ces pratiques éprouvées :
Version Contrôler tout
Toutes les configurations Terraform, y compris les modules, doivent être stockées dans Git avec des messages de commit significatifs. Les versions d'étiquettes et les branches d'utilisation pour les changements.
Toujours exécuter le plan et l'examen
Dans le développement local, toujours exécuter avant . Dans le CI/CD, exiger une étape d'approbation manuelle pour les déploiements de production. Terraform Cloud et Atlantis sont des outils populaires qui intègrent les workflows de plan/application dans les requêtes de tirage.
Mettre en oeuvre l'IC/DC pour l'infrastructure
Traitez les changements d'infrastructure comme les changements de code. Utilisez un pipeline qui exécute et sur les requêtes de tirage, puis exécutez , et—après fusion—exécute . Pour les serveurs, vous pouvez exécuter des tests d'intégration après l'application pour vérifier que les paramètres de l'API répondent correctement.
Utiliser pour la détection de la dérive
Même avec CI/CD, quelqu'un peut modifier manuellement une ressource à travers la console. Planifier régulièrement fonctionne (par exemple, la nuit) pour détecter la dérive et alerter l'équipe. Des outils comme Terraform Cloud , la détection de dérive peut automatiser cela.
Testez vos configurations Terraform
Le code d'infrastructure de test unitaire est possible avec des outils comme Terratest, une bibliothèque Go qui fait tourner de vraies ressources cloud, vérifie leur comportement et les déchire. Pour les serveurs, vous pouvez déployer des piles dans des comptes de test isolés, exécuter des tests HTTP contre l'API et valider le contenu DynamoDB.
Utiliser la politique comme code
Définir les règles de conformité à l'échelle de l'organisation en utilisant HashiCorp Sentinel (Cloud) ou Open Policy Agent. Par exemple, exiger que toutes les fonctions Lambda aient un traçage X-Ray activé, ou empêcher les tables publiques DynamoDB. Ces politiques sont appliquées au moment du plan, rendant la sécurité et la gouvernance des coûts systématiques.
Défis et solutions communs
Verrouillage du fichier d'état et conflits
Lorsque plusieurs membres de l'équipe courent simultanément, la corruption d'état peut survenir. Solution : utilisez toujours un moteur de verrouillage (S3 + DynamoDB) et ne lancez jamais directement à partir de branches parallèles. Utilisez des pipelines CI/CD pour sérialiser s'applique.
Manipulation de grands nombres de fonctions Lambda
La gestion des fonctions de Lambda 50+ dans une configuration unique devient difficile. Solution : utiliser ou avec une carte de définitions de fonctions. Mieux encore, organiser les fonctions en configurations Terraform distinctes qui partagent des sources de données d'état. Par exemple, une configuration centrale -core -exporte des sorties (noms de table DynamoDB, URLs de file d'attente SQS) que les configurations en aval importent via .
Ordre de dépendance dans les architectures complexes
Bien que Terraform gère la plupart des dépendances automatiquement, les dépendances circulaires (par exemple, deux services qui se référent mutuellement ARNs) peuvent causer des problèmes. Solution : briser le cycle en introduisant une troisième ressource (comme un sujet SNS central) ou en utilisant des blocs explicites .
Déployer des modifications de code Lambda
Terraform est conçu pour l'infrastructure, non pour déployer en permanence le code d'application. Pousser les nouvelles versions de Lambda en ré-appliquant Terraform à chaque fois est lent et non idéal pour les itérations de code rapides. Solution : séparer le déploiement de l'infrastructure (créé une fois par environnement) du déploiement de code. Utilisez les pipelines CI/CD qui mettent à jour le code de fonction Lambda via le SDK AWS ou des outils comme le Cadre sans serveur, tandis que Terraform gère les ressources environnantes.
Conclusion
En définissant chaque ressource dans les fichiers HCL contrôlés par version, vous obtenez des déploiements répétables, une gestion sûre du changement et des pistes d'audit complètes. Un projet Terraform bien structuré avec modules, état distant et intégration CI/CD permet aux équipes de gérer des centaines de fonctions Lambda, les paramètres API et les stockages de données sans perdre de temps dans la fourniture manuelle ou la dérive de l'environnement.
Comme les architectures sans serveur continuent à se développer dans la complexité – avec des workflows animés par des événements, des fonctions d'étape et une infrastructure globale répartie dans plusieurs régions – l'importance de l'IaC robuste ne fait qu'augmenter. À partir des modèles et des exemples de cet article, vous pouvez construire une fondation qui s'échelle avec votre application et votre organisation.