Sägetstrasse 18, 3123 Belp, Switzerland +41 79 173 36 84 info@ict.technology

      Terraform @ Scale - Partie 1c : Mise en œuvre pratique des flux de données Remote State

      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.

      Datacenter View FR

      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 :

      InfrastructureWorkspace/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.