En combinant des Remote Backends soigneusement structurés, une conception réfléchie des outputs et une utilisation ciblée de la source de données terraform_remote_state, vous pouvez établir un flux d'informations contrôlé entre différents niveaux de locataires - et ce, sans compromettre l'isolation des mandants individuels.
L'utilisation efficace du Remote State pour l'échange d'informations entre unités organisationnelles nécessite une configuration soigneuse de l'environnement Terraform. L'élément central ici est le choix et la configuration d'un Storage Backend approprié pour le stockage des données d'état dans les fichiers dits State Files.
Configuration d'un Remote Backend
Terraform propose divers Backends officiels pour le stockage des données d'état. Les options officiellement supportées par HashiCorp sont :
Exemple de configuration | |
---|---|
HashiCorp Consul |
terraform { backend "consul" { address = "consul.example.com:8500" scheme = "https" path = "terraform/network/global" lock = true } } |
HashiCorp Terraform Enterprise |
terraform { backend "remote" { hostname = "terraform.example.com" organization = "ict-technology" workspaces { name = "network-global" } } } |
HashiCorp Terraform Cloud |
terraform { backend "remote" { hostname = "app.terraform.io" organization = "ict-technology" workspaces { name = "network-global" } } } |
Ces Storage Backends offrent plusieurs avantages par rapport aux fichiers d'état locaux :
- Stockage centralisé : Tous les membres de l'équipe travaillent avec le même état.
- Mécanismes de verrouillage : Empêche les modifications parallèles et les conflits associés.
- Versionnage : Enregistre l'historique des modifications.
- Contrôle d'accès : Permet des concepts d'autorisations différenciés.
Lors du choix d'un Backend, vous devez prendre en compte les besoins de votre organisation.
Consul est un excellent choix pour les entreprises utilisant la version gratuite de Terraform.
Terraform Cloud et Terraform Enterprise ont, en revanche, une architecture client/serveur et intègrent déjà un Storage Backend côté serveur. Il n'est donc pas nécessaire de se soucier de cet aspect, et il est possible d'utiliser directement le stockage intégré. Terraform Cloud/Enterprise offre en outre des fonctionnalités supplémentaires telles que Policy-as-Code pour l'implémentation et l'application des politiques, les contrôles de gouvernance et des fonctions avancées de collaboration.
Il existe également d'autres Backends pris en charge par Terraform. Il s'agit notamment de Backends tels que Amazon S3, HTTPS, diverses bases de données et bien d'autres.
Cependant, il y a une particularité importante : HashiCorp ne fournit de support que pour les fichiers d'état locaux, Consul et Terraform Cloud/Enterprise.
Vous pouvez utiliser d'autres Backends, mais en cas de problème, vous ne pouvez pas attendre d'assistance ou de résolution de problème de la part de HashiCorp, même avec un contrat de support Enterprise existant.
Dans des environnements de production critiques, vous devez donc exclusivement utiliser Consul ou Terraform Cloud/Enterprise comme Remote State Backends.
Si vous utilisez un Backend non supporté par HashiCorp, vous devez impérativement veiller à ce que ce Backend propose un mécanisme de verrouillage !
Sinon, vous courez le risque qu'en cas d'exécution parallèle d'une commande terraform apply, les instances Terraform parallèles se chevauchent et écrasent mutuellement les fichiers d'état, ce qui rendrait votre infrastructure complètement incohérente. Par exemple, des Backends comme un partage NFSv3 ou un Backend HTTPS sont probablement des choix discutables et vous risquez des pertes de données.
Mécanismes de sécurité
Le stockage des fichiers d'état est critique, car ils peuvent contenir des informations sensibles telles que des identifiants d'accès et des détails sur l'infrastructure.
Chiffrement
Dans Terraform Cloud/Enterprise, les données d'état sont automatiquement chiffrées au repos et pendant leur transmission. Avec Consul, vous devez activer TLS pour la connexion ainsi que les fonctions de chiffrement propres à Consul :
terraform { backend "consul" { address = "consul.example.com:8500" access_token = var.consul_acl_token scheme = "https" path = "terraform/network/global" ca_file = "/etc/ssl/certs/ca.pem" cert_file = "/etc/ssl/certs/cert.pem" key_file = "/etc/ssl/private/key.pem" } }
Contrôle d'accès
Dans Terraform Cloud/Enterprise, la gestion des utilisateurs propose des rôles et des autorisations détaillés. Par exemple, différents rôles peuvent disposer de différentes autorisations :
- Équipe Network-Admins : Accès complet au Workspace network-global.
- Équipe App-Developers : Accès en lecture au Workspace network-global.
Dans Consul, vous utilisez les ACL, que vous assignez à un rôle. Voici par exemple l'ACL qui accorde au groupe App-Developers les autorisations en lecture :
# Consul ACL policy key_prefix "terraform/network/global" { policy = "read" }
Dans les environnements de production, vous devriez également utiliser un jeton ACL pour empêcher l'accès non autorisé par d'autres clients :
data "terraform_remote_state" "global_network" { backend = "consul" config = { address = "consul.example.com:8500" path = "terraform/network/global" scheme = "https" token = var.consul_acl_token } }
Versionnement et restauration
Terraform Cloud/Enterprise crée automatiquement des snapshots de vos States après chaque exécution réussie. Ces snapshots peuvent être utilisés pour restaurer l'état d'un environnement en cas d'échec. Utilisez à cet effet soit l'interface utilisateur (UI) soit l'interface en ligne de commande (CLI) avec la commande terraform state pull pour consulter l'historique des versions et restaurer la version souhaitée.
Avec Consul, vous pouvez configurer des clusters hautement disponibles avec des réplicas dans d'autres centres de données pour prévenir toute perte de données. Vous pouvez également créer des snapshots du stockage Raft.
Structure des fichiers State pour une gestion optimale du multi-tenancy
L'organisation des States doit refléter votre structure organisationnelle tout en facilitant les flux d'informations.
Dans Terraform Cloud/Enterprise, les différentes configurations sont organisées en tant que "Workspaces". Dans Consul, la séparation s'effectue via des "Paths", qui correspondent à un namespace logique.
Une structure éprouvée pourrait ressembler à ceci :
Infrastructure | Workspace/Path |
---|---|
Systèmes et services globaux nécessaires | global-infrastructure |
Sites régionaux | region-{region_name} |
Infrastructure spécifique aux clients | customer-{customer_name} |
Infrastructure spécifique aux équipes | team-{team_name} |
Infrastructure spécifique aux applications | app-{app_name} |
Une telle structure permet une séparation claire des responsabilités et facilite la recherche des States pertinents.
Dans Terraform Cloud/Enterprise, vous pouvez également utiliser le marquage des Workspaces (Workspace-Tagging) pour regrouper des Workspaces connexes. Cela permet, par exemple, d'établir un lien logique entre l'infrastructure d'une application et celle de l'équipe correspondante.
Exemples de code pour l'héritage de données entre tenants
L'héritage effectif des données s'effectue via la Data Source terraform_remote_state, qui permet d'accéder aux outputs d'autres configurations Terraform.
Exemple : Configuration réseau dans un environnement multi-tenant
Équipe réseau globale (dans le Workspace global-infrastructure) :
module "global_network" {
source = "./modules/network"
name = "global-vcn"
description = "Global customer network"
cidr_block = "10.0.0.0/16"
parent_id = var.root_compartment_id
}
output "global_vcn_id" {
value = module.global_network.id
}
Équipe régionale (dans le Workspace region-dc1) :
data "terraform_remote_state" "global_network" { backend = "remote" config = { organization = "ict-technology" workspaces = { name = "network-global" } } } module "regional_network" { source = "./modules/network" name = "regional-subnet-dc1" description = "Subnet of europe region" parent_id = data.terraform_remote_state.global_network.outputs.global_vcn_id cidr_block = "10.0.1.0/24" } output "regional_subnet_id" { value = module.regional_network.id }
Équipe client (dans le Workspace customer-acme) :
data "terraform_remote_state" "regional_network" { backend = "remote" config = { organization = "ict-technology" workspaces = { name = "region-europe" } } } module "customer_environment" { source = "./modules/environment" name = "customer-instance" description = "customer instance" parent_id = var.customer_compartment_id subnet_id = data.terraform_remote_state.regional_network.outputs.regional_subnet_id instance_shape = "VM.Standard2.1" }
Un modèle particulièrement recommandé est l'utilisation d'outputs structurés. Au lieu de fournir de nombreuses valeurs individuelles, un output structuré permet d'exporter diverses informations regroupées :
output "network_config" { value = { vcn_id = module.global_network.id cidr_block = module.global_network.cidr_block dns_label = module.global_network.dns_label subnets = { public = module.subnet_public.id private = module.subnet_private.id } } }
Ainsi, une configuration dépendante peut cibler directement les informations pertinentes :
module "app_server" { source = "./modules/compute" name = "app-server" description = "application server in private subnet" parent_id = var.customer_compartment_id subnet_id = data.terraform_remote_state.network.outputs.network_config.subnets.private instance_shape = "VM.Standard2.1" }
Dans le prochain chapitre, nous examinerons les pièges potentiels, les bonnes pratiques et quelques astuces lors de l'utilisation des Remote States.