Au secours ! Terraform est trop lent !

Comment accélérer vos déploiements Terraform ?

Vous vous êtes lancé sur le Cloud et avez décidé d’utiliser Terraform pour le déploiement de vos ressources en mode IaC (Infrastructure as Code). Vous avez créé votre projet Git, ajouté vos premiers fichiers *.tf puis déployé vos premières ressources. Avec le temps, votre infrastructure grossit, le nombre de ressources déployées explose et votre codebase aussi. Bilan, les rafraichissements lors des terraform plan et terraform apply durent une éternité et cela vous donne envie d’abandonner Terraform ?

Dans cet article, nous abordons le sujet de l’optimisation de l’utilisation de Terraform.

Si vous avez utilisé Terraform pour déployer vos ressources sur le Cloud, vous avez peut-être remarqué que la croissance de votre infrastructure et du nombre de ressources déployées peuvent rendre vos commandes terraform plan et terraform apply de plus en plus lentes. Avant de renoncer à l’utilisation de cet outil puissant, nous vous proposons plusieurs stratégies d’optimisation qui pourraient faciliter et accélérer vos déploiements.

Dans le cas d’un déploiement ciblé (un module ou une ressource), l’option la plus simple et la plus efficace pour limiter le nombre de rafraichissements est d’utiliser l’option target. Cette option associée à la commande terraform plan ou terraform apply permet de limiter les modifications à la ressource spécifiée dans l’option target ainsi qu’à ses dépendances.

Exemple de l’utilisation de l’option target :

1
terraform plan -target 'module.mon_super_module'
Remarque
À noter que l’utilisation de l’option target a pour effet de ne mettre à jour l’état (state) que des éléments ciblés. Toute autre mise à jour ne sera donc pas prise en compte.

Dans le cas où vous souhaitez faire un déploiement global, il est possible d’augmenter le nombre d’opérations réalisées en parallèle par Terraform. Par défaut, celui-ci se limite à 10 opérations simultanées. Néanmoins, il est possible d’augmenter (ou de diminuer) ce seuil grâce à l’option parallelism.

Exemple de l’utilisation de l’option target :

1
terraform apply -parallelism 400

Nous allons maintenant évoquer des solutions qui vont impacter votre codebase. Ainsi, la troisième piste d’amélioration est la limitation des ressources non essentielles en évitant par exemple d’utiliser des data quand cela n’est pas nécessaire.

Les deux codes suivants sont équivalents et vont tous deux ajouter une habilitation roles/editor au compte de service mon-sa-1.

Lors du plan sur ce premier code, Terraform va ici considérer trois ressources dont une qui n’est pas utilisée :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
data "google_service_account" "mon_service_account_1" {
  account_id = "mon-sa-1@mon-projet.iam.gserviceaccount.com"
}

data "google_service_account" "mon_service_account_2" {
  account_id = "mon-sa-2@mon-projet.iam.gserviceaccount.com"
}

resource "google_project_iam_member" "project_member_1" {
  project = "mon-projet"
  role    = "roles/editor"
  member  = "serviceAccount:${data.google_service_account.mon_service_account_1.id}"
}

Dans ce deuxième code, Terraform va ici considérer une seule ressource :

1
2
3
4
5
resource "google_project_iam_member" "project_member_1" {
  project = "mon-projet"
  role    = "roles/editor"
  member  = "serviceAccount:mon-sa-1@mon-projet.iam.gserviceaccount.com"
}

Dans le cas présent, le gain est faible ; néanmoins, dans le cas de l’implémentation dans un module appelé une centaine de fois dans votre projet, cela peut être plus intéressant.

La quatrième option est de s’assurer que vous n’utilisez pas des providers Terraform trop anciens. En effet, parmi les fonctionnalités apportées par les nouvelles versions des providers, il arrive que certaines concernent l’optimisation des performances (réduction du nombre d’interrogations des APIs par exemple : https://github.com/hashicorp/go-azure-sdk/pull/753).

Avertissement
Point d’attention cependant concernant cette méthode. À l’inverse des précédentes, celle-ci peut entrainer des changements dans votre code (apparition de “Breaking Changes” dans les providers, etc.).

Dans le cas où les options précédentes n’améliorent toujours pas suffisamment vos temps de déploiements, il reste l’ultime option du redécoupage de votre projet. Cela peut se faire de différentes manières :

  • Découper votre codebase Terraform en plusieurs projets (par périmètre fonctionnel/applicatif par exemple) plutôt que d’avoir un unique projet ;
  • Au sein de vos projets, dissocier votre codebase par environnement (soit par des dossiers, soit par l’utilisation des workspaces Terraform).

Le redécoupage de vos projets, bien que plus complexe à mettre en œuvre, vous permettra d’obtenir un vrai gain lors de vos déploiements. En effet, l’utilisation de plusieurs projets et donc de plusieurs backends vous permettra de paralléliser vos déploiements.

L’optimisation de l’exécution de Terraform est un processus continu qui nécessite une attention constante.

En commençant par des ajustements simples comme l’utilisation de l’option target et l’augmentation du parallélisme, vous pouvez déjà voir des améliorations dans la vitesse de vos déploiements. Cependant, pour des gains plus significatifs, vous devrez peut-être envisager des modifications plus profondes de votre codebase, comme la limitation des ressources non essentielles, la mise à niveau des providers et le redécoupage de vos projets.

Chacune de ces stratégies a ses propres avantages et inconvénients, et il est important de les évaluer en fonction de vos besoins spécifiques. Il faudra notamment mesurer le gain en termes de temps de déploiement versus la complexité engendrée sur la codebase globale de votre infrastructure.