Terraform, mutualisation des ressources hors production

Terraform, mutualisation des ressources hors production

Jusqu’à présent, j’étais très fier de mes infrastructures par environnement construites à l’aide de Terraform. Tout était paramétrable, on passait de l’intégration à la recette en changeant simplement une valeur ou deux, etc.

Jusqu'à récemment où je me suis fait la remarque : “pourquoi construire un moteur de base de données pour l’intégration et un pour la recette alors que chacun est très peu utilisé ?”


Prenons une architecture simple : 

Infrastructure de base

Un load balancer avec une IP publique, un firewall pour filtrer le trafic entrant, un storage pour délivrer les fichiers statiques (html, css, js), une exécution de container pour l’api et un moteur de base de données. 


Mutualisée, cette architecture devient : 

Infrastructure mutualisée


Quatre principaux cas de figure se présentent : 

  • les ressources qui ne sont pas impactées par la mutualisation. C’est le cas du firewall, il filtre le trafic entrant qui est le même pour chaque environnement. 
  • les ressources qui sont spécifiques à chaque environnement. C’est le cas du storage et de l’exécution du container. 
  • les ressources qui sont mutualisables. C’est le cas de la base de données dont le moteur est mutualisable, sur lequel on crée des instances dédiées. 
  • les ressources dont la configuration évolue lors de la mutualisation. C’est le cas du load balancer, les règles de redirection en fonction du nom de domaine évoluent lors de l’ajout d’un nouvel environnement. 

Je ne parle pas des deux premiers cas qui n’ont pas de difficulté particulière.

Une façon de résoudre le troisième cas est de construire l’environnement en deux étapes. Lors d’un premier script Terraform, on construit les ressources partagées (le moteur de base de données). Dans un second temps, on ajoute des éléments à cette ressource (les instances de base de données). 


Le dernier cas m’a posé beaucoup plus de problèmes. 

La solution à laquelle je suis arrivée est d’utiliser les primitives count(), dynamic, for_each et index() de Terraform. Concrètement, j’ai défini deux variables env_context et env_list. env_context indique le contexte dans lequel vont se situer les environnements (par exemple sandbox, production). env_list est une liste de noms d’environnements (par exemple [“int”, “rec”] pour la liste des environnements d’intégration et de recette). 

Dans n’importe quelle ressource créée via Terraform, ajouter count = length(var.env_list) dans la déclaration va créer autant de ressources que d’éléments dans la liste, pour la création des storages par exemple. Par la suite, on peut référencer les ressources comme des éléments de tableau (google_storage_bucket.cloud_storage[0]).  


resource "google_storage_bucket" "cloud_storage"  
  count = length(var.env_list)

}
        


Les primitives dynamic et for_each vont permettre d’itérer au sein d’une ressource. Par exemple sur la configuration du load balancer. 

resource "google_compute_url_map" "url_map" {
 
  dynamic "host_rule" {
    for_each = var.env_list
  
    content {
      hosts        = ...
      path_matcher = "frontend-${host_rule.value}"
    }
  }

}        


Lors de la création, l’ordre du tableau est respecté dans toutes les ressources. L’attribut count.index permet de retrouver le pas de l’itération, il permet de référencer les autres ressources pour l’environnement courant. 

Dans les cas les plus complexes, la primitive index() va permettre de retrouver l’index à partir d’un tableau et d’un élément. 


Et l’environnement de production dans tout ça ? 

Tous les scripts Terraform sont applicables pour la production. Il ne s’agit que d’un cas particulier pour lequel le contexte est production (env_context=production) la liste des environnements se résume à un seul élément (env_list=[“prod”]). 


En conclusion, la solution optimise l’utilisation des ressources qui peuvent être partagées (bdd, load balancer, …). Le gain est aussi financier. 

La solution préserve aussi le cloisonnement entre les environnements puisqu’ils ont chacun leur instance de BDD, leur login de connexion, leur storage, … 


Un grand merci à Sandra PARLANT, Tony JARRIAULT et Corentin DEHAY pour leurs remarques perspicaces.

Jarriault Tony

Solutions Architect @Sogeti part of CapGemini

2 ans

Sylvain MACHARD : c'est toujours un plaisir de partager les retours d'expériences

Identifiez-vous pour afficher ou ajouter un commentaire

Autres pages consultées

Explorer les sujets