[FR] TERRAFORM, MANAGE YOUR INFRA WITH CODE

Présentation

Proposé par HashiCorp, Terraform est un puissant outil qui vous permet de construire, modifier et de contrôler votre infrastructure en toute sécurité et efficacement (couplé à un système de gestion de version comme Github, GitLab ou encore Bitbucket). Il est capable de gérer une multitude de providers (fournisseurs de services), dans les plus connus vous avez AWS, CloudFlare, Docker, DigitalOcean, Azure, OVH, Scaleway, OpenStack, ... Vous trouverez la liste complète par ici. L'outil évolue très rapidement, n'hésitez donc pas à consulter la page de temps en temps !

Fonctionnement

Le principe de fonctionnement est simple, vous définissez votre infrastructure à partir de vos fichiers sources. Il effectue un calcul différenciel entre l'existant et ce qui est configuré dans vos fichiers. Bien évidement ce qui est configuré sur votre provider et pas dans vos fichiers sera écrasé à la prochaine exécution, disons que ça a des avantages comme des inconvéniants.

Installation

Terraform fonctionne sur plusieurs types de plateforme (et ça c'est cool) : macOS, FreeBSD, OpenBSD, Linux, Solaris et Windows. L'exécutable peut être téléchargé à partir de ce lien, à vous de le placer à l'endroit que vous souhaitez. Dans le cas d'une montée de version, la documentation liste les changements et les modifications à y apporter.

La gestion s'effectue en CLI (Command Line Interface) mais qui n'est vraiment pas compliqué. Pour ma part, j'utilise principalement plan pour vérifier les changement, apply pour appliquer les changements et destroy pour les supprimer (j'utilise ce dernier que pour les tests bien évidement).

Usage: terraform [--version] [--help] <command> [args]

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Environment management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a new or existing Terraform configuration
    output             Read an output from a state file
    plan               Generate and show an execution plan
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

La documentation de Terraform étant très complète, vous retrouverez les détails de chaque commande par ici.

Premier projet

Dans cet article, j'ai utiliser le provider Scaleway (parce que j'ai l'habitude de l'utiliser). L'idée ici est juste de comprendre le fonctionnement. L'article aura pour but de déployer un SecurityGroup avec quelques règles de bases (http/https/ssh).

Les fichiers .tf définissent l'intrastructure à gérer. La configuration peut donc être répartie dans plusieurs fichiers qui seront alors lu dans l'ordre alphabétique, analysés et enfin appliqués.

Parmis les fichiers, nous pouvons retrouver :

  • Le main.tf qui est le fichier principal (dans la plus part des cas, n'oubliez pas que c'est pris dans l'ordre alphabétique ensuite)
  • Le variables.tf qui regroupe vos variables non sensibles comme par exemple votre région, le provider, ...
  • Le terraform.tfvars qui regroupe vos variables sensibles comme par exemple vos identifiants, vos tokens, ...
  • Le terraform.tfstate qui regroupe l'état de votre infrastructure, il est généré de manière automatique lors du apply, il est important pour le bon fonctionnement de l'application

La création d'un projet demande au minimum 2 fichiers (c'est votre point de départ dirons-nous) :

Exemple avec mon fichier variables.tf :

variable "scaleway_organization" {
    description = "Default access key"
    default     = "xxxxxxxxxx-xxxxxxxxxx"
    type        = "string"
}

variable "scaleway_token" {
    description = "Default access token"
    default     = "xxxxxxxxxx-xxxxxxxxxx"
    type        = "string"
}

variable "scaleway_region" {
    description = "Default region"
    default     = "par1"
    type        = "string"
}

Exemple avec mon fichier main.tf :

provider "scaleway" {
    organization    = "${var.scaleway_organization}"
    token           = "${var.scaleway_token}"
    region          = "${var.scaleway_region}"
}

resource "scaleway_security_group" "default" {
    name            = "Default Security Group"
    description     = "This is a default security group"
}

resource "scaleway_security_group_rule" "http" {
    security_group  = "${scaleway_security_group.default.id}"
    action          = "accept"
    direction       = "inbound"
    ip_range        = "0.0.0.0/0"
    protocol        = "TCP"
    port            = 80
}

resource "scaleway_security_group_rule" "https" {
    security_group  = "${scaleway_security_group.default.id}"
    action          = "accept"
    direction       = "inbound"
    ip_range        = "0.0.0.0/0"
    protocol        = "TCP"
    port            = 443
}

resource "scaleway_security_group_rule" "ssh" {
    security_group  = "${scaleway_security_group.default.id}"
    action          = "accept"
    direction       = "inbound"
    ip_range        = "163.172.71.242"
    protocol        = "TCP"
    port            = 22
}

Il faudra ensuite lancer un terraform init afin d'initier le projet (en mode terraform quoi) :

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your environment. If you forget, other
commands will detect it and remind you to do so if necessary.

Jusqu'ici rien de bien compliqué ! En somme vous avez (avec quelques lignes) développé votre infratructure pour avoir un SecurityGroup par défaut avec :

  • Une règle ANY pour le port 80/tcp (HTTP)
  • Une règle ANY pour le port 443/tcp (HTTPS)
  • Une règle depuis 163.172.71.242 pour le port 22/tcp (SSH)

Déploiement

Avant de faire n'importe quoi, il est toujours recommandé de vérifier la bonne syntax de son code. C'est facile car terraform intègre la commande terraform validate pour ça, c'est toujours utile (et c'est une habitude à prendre) !

La commande terraform plan vous permettra de vérifier le plan de changement de votre infrastructure, en gros, tout ce qui être créé, modifié, détruit. Dans cet exemple nous partont de rien, donc tout sera créé :

+ scaleway_security_group.default
    description: "This is a default security group"
    name:        "Default Security Group"

+ scaleway_security_group_rule.http
    action:         "accept"
    direction:      "inbound"
    ip_range:       "0.0.0.0/0"
    port:           "80"
    protocol:       "TCP"
    security_group: "${scaleway_security_group.default.id}"

+ scaleway_security_group_rule.https
    action:         "accept"
    direction:      "inbound"
    ip_range:       "0.0.0.0/0"
    port:           "443"
    protocol:       "TCP"
    security_group: "${scaleway_security_group.default.id}"

+ scaleway_security_group_rule.ssh
    action:         "accept"
    direction:      "inbound"
    ip_range:       "163.172.71.242/32"
    port:           "22"
    protocol:       "TCP"
    security_group: "${scaleway_security_group.default.id}"

Plan: 4 to add, 0 to change, 0 to destroy.

La dernière ligne vous résume les changements, c'est toutefois bien pratique. Maintenant que vous avez vu les changements qui seront appliqués, vous pouvez lancer un terraform apply pour appliquer les changements :

scaleway_security_group.default: Creating...
  description: "" => "This is a default security group"
  name:        "" => "DefaultSecurityGroup"
scaleway_security_group.default: Creation complete (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.https: Creating...
  action:         "" => "accept"
  direction:      "" => "inbound"
  ip_range:       "" => "0.0.0.0/0"
  port:           "" => "443"
  protocol:       "" => "TCP"
  security_group: "" => "xxxxxxxxxx-xxxxxxxxxx"
scaleway_security_group_rule.ssh: Creating...
  action:         "" => "accept"
  direction:      "" => "inbound"
  ip_range:       "" => "163.172.71.242/32"
  port:           "" => "22"
  protocol:       "" => "TCP"
  security_group: "" => "xxxxxxxxxx-xxxxxxxxxx"
scaleway_security_group_rule.http: Creating...
  action:         "" => "accept"
  direction:      "" => "inbound"
  ip_range:       "" => "0.0.0.0/0"
  port:           "" => "80"
  protocol:       "" => "TCP"
  security_group: "" => "xxxxxxxxxx-xxxxxxxxxx"
scaleway_security_group_rule.https: Creation complete (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.ssh: Creation complete (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.http: Creation complete (ID: xxxxxxxxxx-xxxxxxxxxx)

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Top ! Nous avons créé notre SecurityGroup et les 3 rules. La dernière ligne spécifie "4 added" car il compte les 3 règles ainsi que le groupe en lui même.

Vous pouvez désormais vérifier sur votre interface de Scaleway que tout est bien présent (y'a pas de raison) :)

Ceci étant pour faire des tests, détruisons maintenant ce que nous venons de faire. Rien de plus simple puisque la commande terraform destroy est faite pour ça (il faudra quand même confirmer la chose) :

Do you really want to destroy?
  Terraform will delete all your managed infrastructure.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

scaleway_security_group.default: Refreshing state... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.https: Refreshing state... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.http: Refreshing state... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.ssh: Refreshing state... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.https: Destroying... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.http: Destroying... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.ssh: Destroying... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group_rule.https: Destruction complete
scaleway_security_group_rule.ssh: Destruction complete
scaleway_security_group_rule.http: Destruction complete
scaleway_security_group.default: Destroying... (ID: xxxxxxxxxx-xxxxxxxxxx)
scaleway_security_group.default: Destruction complete

Destroy complete! Resources: 4 destroyed.

Et voilà, nos 4 données (3 règles + le SecurityGroup lui même) ont été détruit. Si toutefois vous avez d'autres SecurityGroup, ils ne seront pas détruit puisqu'inconnu dans vos fichiers terraform.

Conclusion

Pour ma part, je trouve que Terraform est vraiment un outil formidable (et qui évolue rapidement) si vous souhaitez faire votre IAAS (Infrastructure As A Code). C'est encore plus magique avec Packer et Ansible mais je pense que j'en parlerais dans un prochain article :)

Si vous avez quelques heures de libres, ce serait intéressant de tester ! Ce ne sera jamais des heures de perdues puisque (je pense) que c'est un outil qui sera de plus en plus demandé à l'avenir dans le déploiement d'infrastructure et avoir un minimum d'exprérience dans ce domaine sera toujours une bonne chose !

Enjoy!
XorHak