Aller au contenu principal

2-06 Créer, refactorer et réutiliser du code avec des modules

Objectifs

  • Savoir gérer sur le long terme un projet modulaire Terraform

Le "style Terraform"

Il existe un guide de style Terraform, augmenté par Terragrunt

Documentation :

On peut reformater automatiquement son code avec la commande fmt


$ terraform fmt -recursive


Utiliser un style commun est la première étape pour rendre son code gérable en équipe.

  • Indentez deux espaces pour chaque niveau d'imbrication.

  • Lorsque plusieurs arguments avec des valeurs sur une seule ligne apparaissent sur des lignes consécutives au même niveau d'imbrication, alignez leurs signes égal :

## BAD 
ami = "abc123"
type_instance = "t2.micro"

## GOOD
ami = "abc123"
type_instance = "t2.micro"


  • Dans un corps de bloc les arguments vont ensemble en haut, séparés par une ligne des blocs imbriqués.

  • Utilisez des lignes vides pour séparer des groupes logiques d'arguments dans un bloc.

  • Pour les blocs contenant à la fois des arguments et des "méta-arguments" (tels que définis par la sémantique du langage Terraform), répertoriez d'abord les méta-arguments et séparez-les des autres arguments par une ligne vide. Placez les blocs de méta-arguments en dernier et séparez-les des autres blocs par une ligne vide.


ressource "aws_instance" "exemple" {
count = 2 # méta-argument en premier

ami = "abc123"
type_instance = "t2.micro"

interface réseau {
# ...
}

lifecycle { # bloc de méta-arguments en dernier
create_before_destroy = true
}
}

  • Utilisez des lignes vides pour séparer les blocs de niveau supérieur et les blocs imbriqués sauf si ces derniers sont du même type .

  • Limitez à 120 colonnes la longueur de ligne, sauf pour les chaînes de description dans les blocs de variable et de sortie, où les chaînes à une seule ligne sont préférées.

  • Utilisez le camel_case pour les étiquettes de bloc, les variables et les sorties, ex: example_instance et non ExampleInstance ou example-instance.


Créer un code modulaire de qualité

Les fondamentaux pour passer avoir une architecture Terraform prête pour la production implique d'avoir :

  • des modules atomiques
  • des modules composables
  • des modules testables
  • des modules versionnés

Les fonctions / contenus d'un module

Il est important avant d'écrire un module d'avoir en tête une liste de toutes les opérations potentielles dans le Devops.

TypeDescriptionOutils
InstallerInstaller les fichiers binaires du logiciel et toutes les dépendances.Bash, Ansible, Docker, Packer
ConfigurerConfigurer le logiciel lors de l'exécution. Inclut les paramètres de port, les certificats TLS, la découverte de services, les leaders, les suiveurs, la réplication, etc.Chef, Ansible, Kubernetes
Mise à dispositionProvisionner l'infrastructure. Inclut les serveurs, les équilibreurs de charge, la configuration réseau, les paramètres de pare-feu, les autorisations IAM, etc.Terraform, CloudFormation
DéployerDéployer le service au-dessus de l'infrastructure. Déployer les mises à jour sans temps d'arrêt. Inclut les déploiements bleu-vert, roulant et canari.ASG, Kubernetes, ECS
ÉvolutivitéÉchelle vers le haut et vers le bas en réponse à la charge. Évoluer horizontalement (plus de serveurs) et/ou verticalement (plus gros serveurs).Auto scaling, réplication
PerformancesOptimiser l'utilisation du CPU, de la mémoire, du disque, du réseau et du GPU. Comprend le réglage des requêtes, l'analyse comparative, les tests de charge et le profilage.Dynatrace, Valgrind, VisualVM
RéseauConfigurer les adresses IP statiques et dynamiques, les ports, la découverte de services, les pare-feu, le DNS, l'accès SSH et l'accès VPN.VPC, pare-feu, Route 53
SécuritéChiffrement en transit (TLS) et sur disque, authentification, autorisation, gestion des secrets, durcissement des serveurs.ACM, Let's Encrypt, KMS, Vault
MétriquesMétriques de disponibilité, métriques commerciales, métriques d'application, métriques de serveur, événements, observabilité, traçage et alerte.CloudWatch, Datadog
JournauxRotation des journaux sur le disque. Agrégation des données du journal dans un emplacement central.Pile élastique, Sumo Logic
DocumentsDocumentez du code, de votre architecture et vos pratiques. Playbooks pour répondre aux incidents.README, wikis, Slack, IaC
EssaisÉcrivez des tests automatisés pour votre code d'infrastructure. Exécutez des tests après chaque commit et tous les soirs.Terratest, tflint, OPA, InSpec

Caractéristiques d'une bonne modularisation.

Maintenant que vous avez vu tous les ingrédients de la création de code Terraform de qualité, il est temps de les assembler.

La prochaine fois que vous commencerez à travailler sur un nouveau module, utilisez le processus suivant :

  • Parcourez la liste précédente et identifiez explicitement les éléments que vous implémenterez et les éléments que vous ignorerez.

  • Créez un dossier d'exemples et écrivez d'abord l'exemple de code, en l'utilisant pour définir la meilleure expérience utilisateur et l'API la plus propre à laquelle vous pouvez penser pour vos modules.

  • Créez un exemple pour chaque permutation importante de votre module et incluez suffisamment de documentation et des valeurs par défaut raisonnables pour rendre l'exemple aussi facile à déployer que possible.

  • Créez un dossier de modules et implémentez l'API que vous avez créée sous la forme d'une collection de petits modules réutilisables et composables.

  • Utilisez une combinaison de Terraform et d'autres outils tels que Docker, Packer et Bash pour implémenter ces modules.

  • Assurez-vous de verrouiller les versions de toutes vos dépendances, y compris le noyau Terraform, vos fournisseurs Terraform et les modules Terraform dont vous dépendez.

  • Créez un dossier de test et écrivez des tests automatisés pour chaque exemple.


Pièges courants de Terraform, difficultés de refactorisation

Avec une architecture modulaire, que se passe-t-il quand on renomme une ressource par exemple?

Le même probkème se pose quand on passe à une structure modulaire.

Par exemple l'objet


aws_iam_user.app

devient


module.iam.aws_iam_user["app"].user

La ressource n'est plus la même que celle définie dans l'état et Terraform va vouloir créer une nouvelle ressource.


Comment gérer ce problème ? La solution simple à ce changement est d'opérer une modification de l'état en déplaçant la ressource dans le fichier.

$ terraform state mv aws_iam_user.app module.iam[\"app\"].aws_iam_user.user
Move "aws_iam_user.app to "module.iam[\"app1\"].aws_iam_user.user
Successfully moved 1 object(s).

On peut également importer des ressources existantes, si le provider le permet.


$ terraform import module.iam[\"app\"].aws_iam_user.user app1-svc-account


Rappel des objectifs

  • Savoir gérer sur le long terme un projet modulaire Terraform