Débuter avec AWS et Terraform : déployer une instance EC2

Afin de déployer et maintenir son projet selon les principes de l’infrastructure sous forme de code (ou infrastructure as code en anglais abrégé par IaC), le duo AWS et Terraform représente aujourd’hui une solution efficace et pérenne dans le temps.

Dans ce premier article d’une série consacrée au couple AWS et Terraform, nous allons avoir comme objectif d’obtenir une machine virtuelle Debian Stretch dans AWS que nous déploierons uniquement avec Terraform. Ne ratez pas ma précédente série sur Débuter avec Git, qui pourra vous servir dans les articles de cette série.

Les quelques prérequis et étapes manuelles nécessaires seront également présentés. Les seuls prérequis à l’article sont d’avoir un poste de travail GNU/Linux et un compte AWS.


Besoin d’un architecte système freelance ? Je suis disponible à partir d’octobre. Basé à Paris et/ou télétravail. N’hésitez pas à me contacter : carl.chenet@mytux.fr


Installation de Terraform

L’installation de Terraform se fait directement depuis le site du projet à partir de la section téléchargement.

Nous copions le lien du zip contenant la dernière version de Terraform, à savoir au moment de l’écriture de cet article la 0.12.8.

Sur notre poste de travail nous passons les commandes suivantes pour installer Terraform en tant qu’utilisateur root.

# cd /usr/local/bin/
# wget https://releases.hashicorp.com/terraform/0.12.8/terraform_0.12.8_linux_amd64.zip
# unzip terraform_0.12.8_linux_amd64.zip
# chmod ugo+x terraform
# rm -rf terraform_0.12.8_linux_amd64.zip
# terraform version
 Terraform v0.12.8

Création d’une paire de clés SSH

Nous allons créer immédiatement une paire de clés ssh dédiée à la connexion à nos instances AWS EC2.

$ mkdir ssh-keys
$ cd ssh-keys
$ ssh-keygen -t rsa -f id_rsa_aws

Nous avons maintenant deux fichiers id_rsa_aws et id_rsa_aws.pub dans notre répertoire ssh-keys.

$ tree ssh-keys/
 ssh-keys/
 ├── id_rsa_aws
 └── id_rsa_aws.pub
 0 directories, 2 files

Passons maintenant à la configuration de Terraform.

Configuration de Terraform avec AWS

Le code Terraform est une suite de fichiers avec l’extension .tf contenant des directives décrivant notre infrastructure. Ces fichiers sont regroupés dans un répertoire.

Nous allons créer un premier fichier provider.tf avec le contenu suivant. Ce fichier contiendra des informations générales portant sur Terraform et ses liens avec AWS :

provider "aws" {
   profile    = "default"
   region     = "eu-west-3"
 }

Détaillons le contenu de ce fichier :

  • provider : cette directive définit le fournisseur avec lequel terraform va interagir. Il s’agit ici d’aws.
  • profile : nous précisons que dans les différents profils possibles de notre configuration aws locale, nous allons utiliser default.
  • region : le nom de la région par défaut, ici la nouvelle région AWS Paris.

Créons un fichier ec2.tf avec le contenu suivant. Ce fichier est appelé à recevoir la description de notre instance :

resource "aws_key_pair" "admin" {
   key_name   = "admin"
   public_key = "ssh-rsa AAAAB3NzaC1yc2AAAAADAQBBAAABAQDGm7qYXR3jG601MSaKo+5zZGUgw3bdw2c2cDcUY2ip1KPborFf1QZjMtIZy0oZCV++4WL7prYFoAGefGOLF8VR3qCVy+5ziYuh5D6rZqXm3jfdW76ARm/NNLEK4wnl6bgs2sKyC1pq53US8IRcSyJdZlIjD+fwPLxkHHTmFh/stFRJGSL0GbiXcN14KBqB1WfJqQ20h4l3qVvXU+lhQKrYgsR+0GeRbh6X7FZ8vIrp9O58wM5fVHkkAibugUx+zSArL8aQkhtuhT/F9Rn8b/cY5yF/MDYqth9harKlPc77j1igdRjLuRiZHyPwYXtrX4Q/ISjx4XOaumOP9d170Hhp chaica@fixe"
 }
 resource "aws_instance" "server1" {
   ami           = "ami-045fa58af83eb0ff4"
   instance_type = "t2.micro"
   key_name      = "admin"
 }

Ce fichier contient deux blocs de code commençant par le mot-clé resource. Détaillons le premier bloc de code de ce fichier. :

  • resource : ce mot-clé indique que nous allons définir une resource, qui est un peu l’unité de base de Terraform. Ici elle est de type aws_key_pair, définissant une paire de clés à utiliser pour nous connecter à nos instances EC2.
  • key_name : le nom de la paire de clé, qu’on va utiliser pour l’identifier dans les autres ressources.
  • public_key : la clé publique SSH, qui sera déposée dans vos instances, permettant la connexion via SSH.

Détaillons maintenant la seconde ressource du fichier ec2.tf :

  • resource : contient une ressource de type aws_instance nommée “server1”.
  • ami : l’ami indiquée ici est celle de l’image officielle de la distribution Debian Stretch pour la région choisie (cela varie selon la région).
  • instance_type : le type d’instance AWS, qui définit les performances de la machine virtuelle, ici un gabarit très modeste.
  • key_name : le nom de la paire de clés pour se connecter en SSH à l’instance, définie par la ressource précédente.

Créons ensuite un fichier vpc.tf qui contiendra les informations de notre virtual private cloud (vpc), à savoir une organisation logique et indépendant de notre infrastructure dans le nuage AWS.

La configuration va être très simple.

resource "aws_default_vpc" "default" {
   tags = {
     Name = "Default VPC"
   }
 }
  • aws_default_vpc indique une ressource de type aws_default_vpc, un cas spécial de vpc qui est le vpc par défaut associé à votre compte AWS. Terraform peut le modifier mais pas le supprimer.
  • tags est uniquement l’association d’une étiquette contenant du texte apportant de l’information sur notre ressource. Nous créons ici une étiquette nommée Name à laquelle nous associons le texte Default VPC. Nous verrons cette notion plus amplement dans un prochain article.

Le dernier fichier Terraform dont nous aurons besoin pour cet article est security_group.tf. Un security group est la description d’autorisations de flux accordés à une ou plusieurs ressources rattachées à ce security group.

resource "aws_default_security_group" "default" {
   vpc_id      = "${aws_default_vpc.default.id}"
 ingress {
     # TLS (change to whatever ports you need)
     from_port   = 22
     to_port     = 22
     protocol    = "tcp"
     # Please restrict your ingress to only necessary IPs and ports.
     # Opening to 0.0.0.0/0 can lead to security vulnerabilities.
     cidr_blocks     = ["83.68.192.4/32"]
   }
 egress {
     from_port       = 0
     to_port         = 0
     protocol        = "-1"
     cidr_blocks     = ["0.0.0.0/0"]
   }
 }

La ressource est de type aws_default_security_group, ce qui indique que nous souhaitons manipuler le security group par défaut de notre vpc. Il s’agit d’un objet spécial, Terraform ne porura que le modifier, pas l’effacer.

  • vpc_id définit à quel vpc ce security group appartient.
  • ingress va définir les flux en entrée vers les ressources qui se rattachent à ce security group, dans le cadre de cet article notre instance.
  • from_port pour le port source, ici le 22 pour autoriser SSH.
  • to_port pour le port destination, ici le 22 pour autoriser SSH.
  • protocol pour le type du protocole du flux.
  • cidr_blocks indique une liste d’adresses acceptées en entrée. Il s’agit ici de l’adresse de mon bureau.
  • egress va définir les flux sortant des ressources attachées à notre security group.
  • from_port pour le port source. Ici 0 car nos allons tout autoriser.
  • to_port pour le port destination. Ici 0 car nos allons tout autoriser.
  • protocol pour le type du protocol. Ici un cas spécial avec une valeur à -1 car nous autorisons tous les types de flux en sortie.
  • cidr_blocks pour les adresses de destination. Ici 0.0.0.0/0 pour tout autoriser.

Au final nous devons avoir l’arborescence suivante :

$ tree 
 .
 ├── ec2.tf
 ├── provider.tf
 ├── security_group.tf
 ├── ssh-keys
 │   ├── id_rsa_aws
 │   └── id_rsa_aws.pub
 └── vpc.tf

Création d’un utilisateur AWS pour Terraform

Élément indispensable pour l’accès programmatique de Terraform à AWS, nous allons maintenant créer dans AWS un utilisateur avec les bonnes permissions qui va nous permettre d’utiliser Terraform.

Pour cela nous nous connectons à la console AWS. Le but va être de déclarer un utilisateur autorisée à effectuer toutes les actions possibles sur le service EC2 d’Amazon.

Connexion au service IAM d'Amazon

Nous allons en fait créer un groupe d’utilisateurs auquel nous rattacherons des autorisations, et ferons appartenir l’utilisateur à ce groupe.

Nous commençons par créer l’utilisateur que l’on nomme EC2FullAccessUser.

Puis nous ajoutons l’utilisateur au groupe.

Nous nommons ce groupe EC2FullAccessGroup. Nous rattachons maintenant au groupe les droits nécessaires, à savoir dans notre cas le droit prédéfini AmazonEC2FullAccess proposé dans la liste.

Le groupe existe maintenant, nous pouvons le rattacher à l’utilisateur.

La dernière fenêtre est la plus importante, elle va vous fournir les identifiants de votre utilisateur, à reporter dans votre configuration locale AWS.

Sur notre poste de travail, nous créons maintenant le fichier ~/.aws/credentials :

[default]
 aws_access_key_id=BAIB3UVYMVAFX2LQ5F6L
 aws_secret_access_key=yad8PfZIhD84IFnxYoRc5iZTuYdf7/bAa/GLiuTa

Nous avons donc défini les identifiants de notre utilisateurs AWS autorisé à mener toutes les actions possibles sur le service AWS EC2 que nous faisons correspondre au profil local nommé default.

Nous ajoutons également un fichier ~/.aws/config avec le contenu suivant :

[default]
 region=eu-west-3
 output=json

Vérifier ce qui va être créé

Nous utilisons la commande terraform plan pour voir ce qui va être créer à partir de nos fichiers Terraform. À la racine du répertoire contenant nos fichiers .tf nous passons la commande suivante :

$ terraform plan
 Refreshing Terraform state in-memory prior to plan…
 The refreshed state will be used to calculate this plan, but will not be
 persisted to local or remote state storage.
 
 An execution plan has been generated and is shown below.
 Resource actions are indicated with the following symbols:
 create 
 Terraform will perform the following actions:
 # aws_default_security_group.default will be created
 resource "aws_default_security_group" "default" {
 arn                    = (known after apply)
 egress                 = [ { cidr_blocks      = [ "0.0.0.0/0",
 ]
 description      = ""
 from_port        = 0
 ipv6_cidr_blocks = []
 prefix_list_ids  = []
 protocol         = "-1"
 security_groups  = []
 self             = false
 to_port          = 0
 },
 ]
 id                     = (known after apply)
 ingress                = [ { cidr_blocks      = [ "83.68.192.4/32",
 ]
 description      = ""
 from_port        = 22
 ipv6_cidr_blocks = []
 prefix_list_ids  = []
 protocol         = "tcp"
 security_groups  = []
 self             = false
 to_port          = 22
 },
 ]
 name                   = (known after apply)
 owner_id               = (known after apply)
 revoke_rules_on_delete = false
 vpc_id                 = (known after apply)
 }
 aws_default_vpc.default will be created
 resource "aws_default_vpc" "default" {
 arn                              = (known after apply)
 assign_generated_ipv6_cidr_block = (known after apply)
 cidr_block                       = (known after apply)
 default_network_acl_id           = (known after apply)
 default_route_table_id           = (known after apply)
 default_security_group_id        = (known after apply)
 dhcp_options_id                  = (known after apply)
 enable_classiclink               = (known after apply)
 enable_classiclink_dns_support   = (known after apply)
 enable_dns_hostnames             = (known after apply)
 enable_dns_support               = true
 id                               = (known after apply)
 instance_tenancy                 = (known after apply)
 ipv6_association_id              = (known after apply)
 ipv6_cidr_block                  = (known after apply)
 main_route_table_id              = (known after apply)
 owner_id                         = (known after apply)
 tags                             = { "Name" = "Default VPC"
 }
 }
 aws_instance.server1 will be created
 resource "aws_instance" "server1" {
 ami                          = "ami-045fa58af83eb0ff4"
 arn                          = (known after apply)
 associate_public_ip_address  = (known after apply)
 availability_zone            = (known after apply)
 cpu_core_count               = (known after apply)
 cpu_threads_per_core         = (known after apply)
 get_password_data            = false
 host_id                      = (known after apply)
 id                           = (known after apply)
 instance_state               = (known after apply)
 instance_type                = "t2.micro"
 ipv6_address_count           = (known after apply)
 ipv6_addresses               = (known after apply)
 key_name                     = "admin"
 network_interface_id         = (known after apply)
 password_data                = (known after apply)
 placement_group              = (known after apply)
 primary_network_interface_id = (known after apply)
 private_dns                  = (known after apply)
 private_ip                   = (known after apply)
 public_dns                   = (known after apply)
 public_ip                    = (known after apply)
 security_groups              = (known after apply)
 source_dest_check            = true
 subnet_id                    = (known after apply)
 tenancy                      = (known after apply)
 volume_tags                  = (known after apply)
 vpc_security_group_ids       = (known after apply)
 ebs_block_device {
 delete_on_termination = (known after apply)
 device_name           = (known after apply)
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 snapshot_id           = (known after apply)
 volume_id             = (known after apply)
 volume_size           = (known after apply)
 volume_type           = (known after apply)
 }
 ephemeral_block_device {
 device_name  = (known after apply)
 no_device    = (known after apply)
 virtual_name = (known after apply)
 }
 network_interface {
 delete_on_termination = (known after apply)
 device_index          = (known after apply)
 network_interface_id  = (known after apply)
 }
 root_block_device {
 delete_on_termination = (known after apply)
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 volume_id             = (known after apply)
 volume_size           = (known after apply)
 volume_type           = (known after apply)
 }
 }
 aws_key_pair.admin will be created
 resource "aws_key_pair" "admin" {
 fingerprint = (known after apply)
 id          = (known after apply)
 key_name    = "admin"
 public_key  = "ssh-rsa AAAAB3NzaC1yc2AAAAADAQBBAAABAQDGm7qYXR3jG601MSaKo+5zZGUgw3bdw2c2cDcUY2ip1KPborFf1QZjMtIZy0oZCV++4WL7prYFoAGefGOLF8VR3qCVy+5ziYuh5D6rZqXm3jfdW76ARm/NNLEK4wnl6bgs2sKyC1pq53US8IRcSyJdZlIjD+fwPLxkHHTmFh/stFRJGSL0GbiXcN14KBqB1WfJqQ20h4l3qVvXU+lhQKrYgsR+0GeRbh6X7FZ8vIrp9O58wM5fVHkkAibugUx+zSArL8aQkhtuhT/F9Rn8b/cY5yF/MDYqth9harKlPc77j1igdRjLuRiZHyPwYXtrX4Q/ISjx4XOaumOP9d170Hhp chaica@fixe"
 } 
 Plan: 4 to add, 0 to change, 0 to destroy.
 
 Note: You didn't specify an "-out" parameter to save this plan, so Terraform
 can't guarantee that exactly these actions will be performed if
 "terraform apply" is subsequently run.

La fin de la commande nous résume ce qui va se passer : ici 4 ressources vont être créées. C’est en effet ce résumé du plan qu’il va falloir lire chaque fois avec attention, au cas où un élément inattendu apparaîtrait (comme un 1 to destroy alors que vous n’avez prévu que de créer de nouvelles ressources).

Le cas échéant, il suffit de remonter la sortie de la commande pour voir ce qui va être fait en détail.

Créer les ressources Terraform avec AWS

Nous utilisons maintenant la commande terraform apply pour lancer la construction effective de notre instance AWS EC2.

$ terraform apply
 An execution plan has been generated and is shown below.
 Resource actions are indicated with the following symbols:
 create 
 Terraform will perform the following actions:
 # aws_default_security_group.default will be created
 resource "aws_default_security_group" "default" {
 arn                    = (known after apply)
 egress                 = [ { cidr_blocks      = [ "0.0.0.0/0",
 ]
 description      = ""
 from_port        = 0
 ipv6_cidr_blocks = []
 prefix_list_ids  = []
 protocol         = "-1"
 security_groups  = []
 self             = false
 to_port          = 0
 },
 ]
 id                     = (known after apply)
 ingress                = [ { cidr_blocks      = [ "83.68.192.4/32",
 ]
 description      = ""
 from_port        = 22
 ipv6_cidr_blocks = []
 prefix_list_ids  = []
 protocol         = "tcp"
 security_groups  = []
 self             = false
 to_port          = 22
 },
 ]
 name                   = (known after apply)
 owner_id               = (known after apply)
 revoke_rules_on_delete = false
 vpc_id                 = (known after apply)
 }
 aws_default_vpc.default will be created
 resource "aws_default_vpc" "default" {
 arn                              = (known after apply)
 assign_generated_ipv6_cidr_block = (known after apply)
 cidr_block                       = (known after apply)
 default_network_acl_id           = (known after apply)
 default_route_table_id           = (known after apply)
 default_security_group_id        = (known after apply)
 dhcp_options_id                  = (known after apply)
 enable_classiclink               = (known after apply)
 enable_classiclink_dns_support   = (known after apply)
 enable_dns_hostnames             = (known after apply)
 enable_dns_support               = true
 id                               = (known after apply)
 instance_tenancy                 = (known after apply)
 ipv6_association_id              = (known after apply)
 ipv6_cidr_block                  = (known after apply)
 main_route_table_id              = (known after apply)
 owner_id                         = (known after apply)
 tags                             = { "Name" = "Default VPC"
 }
 }
 aws_instance.server1 will be created
 resource "aws_instance" "server1" {
 ami                          = "ami-045fa58af83eb0ff4"
 arn                          = (known after apply)
 associate_public_ip_address  = (known after apply)
 availability_zone            = (known after apply)
 cpu_core_count               = (known after apply)
 cpu_threads_per_core         = (known after apply)
 get_password_data            = false
 host_id                      = (known after apply)
 id                           = (known after apply)
 instance_state               = (known after apply)
 instance_type                = "t2.micro"
 ipv6_address_count           = (known after apply)
 ipv6_addresses               = (known after apply)
 key_name                     = "admin"
 network_interface_id         = (known after apply)
 password_data                = (known after apply)
 placement_group              = (known after apply)
 primary_network_interface_id = (known after apply)
 private_dns                  = (known after apply)
 private_ip                   = (known after apply)
 public_dns                   = (known after apply)
 public_ip                    = (known after apply)
 security_groups              = (known after apply)
 source_dest_check            = true
 subnet_id                    = (known after apply)
 tenancy                      = (known after apply)
 volume_tags                  = (known after apply)
 vpc_security_group_ids       = (known after apply)
 ebs_block_device {
 delete_on_termination = (known after apply)
 device_name           = (known after apply)
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 snapshot_id           = (known after apply)
 volume_id             = (known after apply)
 volume_size           = (known after apply)
 volume_type           = (known after apply)
 }
 ephemeral_block_device {
 device_name  = (known after apply)
 no_device    = (known after apply)
 virtual_name = (known after apply)
 }
 network_interface {
 delete_on_termination = (known after apply)
 device_index          = (known after apply)
 network_interface_id  = (known after apply)
 }
 root_block_device {
 delete_on_termination = (known after apply)
 encrypted             = (known after apply)
 iops                  = (known after apply)
 kms_key_id            = (known after apply)
 volume_id             = (known after apply)
 volume_size           = (known after apply)
 volume_type           = (known after apply)
 }
 }
 aws_key_pair.admin will be created
 resource "aws_key_pair" "admin" {
 fingerprint = (known after apply)
 id          = (known after apply)
 key_name    = "admin"
 public_key  = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGm8qYXR3jG601MSaKo+5zZGUgw3bdw2c2cDcUY2iv1KPborFf2QZjMtIZy0oZCV++4WL8prYFoAGefGOLF8VR3qCVy+5ziYuh4D6rZqXm3jfdW76ARm/ONLEK4wnl6bgs2sKyC1pq53US9IRcSyJdZlIjD+fwPLxkHHTmFh/stFRJGSL0GbiXcN14KBqB1WfJqQ20h4l3qVvXU+lhQKrYgsR+0GeRbh6X7FZ8vIrp8O58wM5fVHkkFibugUx+zSZrL8aQkhtuhT/F9Rn8b/cY5yJ/MDYqth9harKlPc77j1igdRjLuRiZHyPwYXtrX4Q/ISjx4XOaumOP9d170Hhp chaica@fixe"
 } 
 Plan: 4 to add, 0 to change, 0 to destroy.
 Do you want to perform these actions?
   Terraform will perform the actions described above.
   Only 'yes' will be accepted to approve.
 Enter a value: yes

La commande terraform apply nous redit par rapport au terraform plan ce qu’il va faire. Vous devez confirmer en tapant yes et la création proprement dite commence ensuite.

aws_key_pair.admin: Creating…
 aws_default_vpc.default: Creating…
 aws_instance.server1: Creating…
 aws_key_pair.admin: Creation complete after 1s [id=admin]
 aws_default_vpc.default: Creation complete after 6s [id=vpc-0fbb173527ee83b95]
 aws_default_security_group.default: Creating…
 aws_default_security_group.default: Creation complete after 3s [id=sg-06a5eeaa849e409f2]
 aws_instance.server1: Still creating… [10s elapsed]
 aws_instance.server1: Still creating… [20s elapsed]
 aws_instance.server1: Still creating… [30s elapsed]
 aws_instance.server1: Creation complete after 36s [id=i-091c78d7e33d39058]

Nos ressources Terraform ont bien été créees. Nous pouvons vérifier en nous connectant à la console et en vérifiant la présence d’une nouvelle machine virtuelle dans le service EC2.


ATTENTION de bien avoir à l’esprit que vous êtes maintenant facturé pour les ressources que vous utilisez.


Connexion à la nouvelle instance EC2

Nous allons maintenant nous connecter en SSH à l’instance EC2 nouvellement créée. Pour cela nous utilisons la clé SSH précédemment générée :

$ ssh -i ssh-keys/id_rsa_aws admin@ec2-52-47-79-6.eu-west-3.compute.amazonaws.com
 Linux ip-173-32-44-38 4.9.0-11-amd64 #1 SMP Debian 4.9.189-3 (2019-09-02) x86_64
 The programs included with the Debian GNU/Linux system are free software;
 the exact distribution terms for each program are described in the
 individual files in /usr/share/doc/*/copyright.
 Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
 permitted by applicable law.
 Last login: Tue Sep 10 22:45:19 2019 from 83.68.192.4
 admin@ip-173-32-44-38:~$

Nous obtenons bien un shell sur la nouvelle instance EC2 fraîchement créee.

Suppression des ressources créées

La dernière étape – mais ô combien importante – de ce premier article consistera à nettoyer notre nuage.

En effet laisser une instance ou d’une manière générale des ressources tourner dans le nuage coûte de l’argent. Il est donc nécessaire si on ne les utilise pas de les arrêter quand on peut ou de les supprimer.

Comme c’est la fin de ce premier article, nous allons tout supprimer.

Pour cela nous utiliserons une commande au nom explicite : terraform destroy

$ terraform destroy
 aws_key_pair.admin: Refreshing state… [id=admin]
 aws_default_vpc.default: Refreshing state… [id=vpc-0fbb173527ee83b95]
 aws_instance.server1: Refreshing state… [id=i-091c78d7e33d39058]
 aws_default_security_group.default: Refreshing state… [id=sg-06a5eeaa849e409f2]
 An execution plan has been generated and is shown below.
 Resource actions are indicated with the following symbols:
 destroy 
 Terraform will perform the following actions:
 # aws_default_security_group.default will be destroyed
 resource "aws_default_security_group" "default" {
 arn                    = "arn:aws:ec2:eu-west-3:799961453093:security-group/sg-06a5eeaa849e409f2" -> null
 egress                 = [ { cidr_blocks      = [ "0.0.0.0/0",
 ]
 description      = ""
 from_port        = 0
 ipv6_cidr_blocks = []
 prefix_list_ids  = []
 protocol         = "-1"
 security_groups  = []
 self             = false
 to_port          = 0
 },
 ] -> null
 id                     = "sg-06a5eeaa849e409f2" -> null
 ingress                = [ { cidr_blocks      = [ "83.68.192.4/32",
 ]
 description      = ""
 from_port        = 22
 ipv6_cidr_blocks = []
 prefix_list_ids  = []
 protocol         = "tcp"
 security_groups  = []
 self             = false
 to_port          = 22
 },
 ] -> null
 name                   = "default" -> null
 owner_id               = "799961453093" -> null
 revoke_rules_on_delete = false -> null
 tags                   = {} -> null
 vpc_id                 = "vpc-0fbb173527ee83b95" -> null
 }
 aws_default_vpc.default will be destroyed
 resource "aws_default_vpc" "default" {
 arn                              = "arn:aws:ec2:eu-west-3:799961453093:vpc/vpc-0fbb173527ee83b95" -> null
 assign_generated_ipv6_cidr_block = false -> null
 cidr_block                       = "172.31.0.0/16" -> null
 default_network_acl_id           = "acl-0f521c59535075d1c" -> null
 default_route_table_id           = "rtb-01e102193255b7af9" -> null
 default_security_group_id        = "sg-06a5eeaa849e409f2" -> null
 dhcp_options_id                  = "dopt-2e66ad47" -> null
 enable_dns_hostnames             = true -> null
 enable_dns_support               = true -> null
 id                               = "vpc-0fbb173527ee83b95" -> null
 instance_tenancy                 = "default" -> null
 main_route_table_id              = "rtb-01e102193255b7af9" -> null
 owner_id                         = "799961453093" -> null
 tags                             = { "Name" = "Default VPC"
 } -> null
 }
 aws_instance.server1 will be destroyed
 resource "aws_instance" "server1" {
 ami                          = "ami-045fa58af83eb0ff4" -> null
 arn                          = "arn:aws:ec2:eu-west-3:799961453093:instance/i-091c78d7e33d39058" -> null
 associate_public_ip_address  = true -> null
 availability_zone            = "eu-west-3c" -> null
 cpu_core_count               = 1 -> null
 cpu_threads_per_core         = 1 -> null
 disable_api_termination      = false -> null
 ebs_optimized                = false -> null
 get_password_data            = false -> null
 id                           = "i-091c78d7e33d39058" -> null
 instance_state               = "running" -> null
 instance_type                = "t2.micro" -> null
 ipv6_address_count           = 0 -> null
 ipv6_addresses               = [] -> null
 key_name                     = "admin" -> null
 monitoring                   = false -> null
 primary_network_interface_id = "eni-0b2fd739925adb391" -> null
 private_dns                  = "ip-172-31-45-71.eu-west-3.compute.internal" -> null
 private_ip                   = "172.31.45.71" -> null
 public_dns                   = "ec2-52-47-183-220.eu-west-3.compute.amazonaws.com" -> null
 public_ip                    = "52.47.183.220" -> null
 security_groups              = [
 "default",
 ] -> null
 source_dest_check            = true -> null
 subnet_id                    = "subnet-00e1bc6132bc74a02" -> null
 tags                         = {} -> null
 tenancy                      = "default" -> null
 volume_tags                  = {} -> null
 vpc_security_group_ids       = [
 "sg-06a5eeaa849e409f2",
 ] -> null
 credit_specification {
 cpu_credits = "standard" -> null
 }
 root_block_device {
 delete_on_termination = true -> null
 encrypted             = false -> null
 iops                  = 100 -> null
 volume_id             = "vol-032a7d1f4248a4ca8" -> null
 volume_size           = 8 -> null
 volume_type           = "gp2" -> null
 }
 }
 aws_key_pair.admin will be destroyed
 resource "aws_key_pair" "admin" {
 fingerprint = "85:56:f4:09:f5:c3:c4:1a:53:7f:6e:f5:df:36:ac:c5" -> null
 id          = "admin" -> null
 key_name    = "admin" -> null
 public_key  = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGm8qYXR3jG601MSaKo+5zZGUgw3bdw2c2cDcUY2iv1KPborFf2QZjMtIZy0oZCV++4WL8prYFoAGefGOLF8VR3qCVy+5ziYuh4D6rZqXm3jfdW76ARm/ONLEK4wnl6bgs2sKyC1pq53US9IRcSyJdZlIjD+fwPLxkHHTmFh/stFRJGSL0GbiXcN14KBqB1WfJqQ20h4l3qVvXU+lhQKrYgsR+0GeRbh6X7FZ8vIrp8O58wM5fVHkkFibugUx+zSZrL8aQkhtuhT/F9Rn8b/cY5yJ/MDYqth9harKlPc77j1igdRjLuRiZHyPwYXtrX4Q/ISjx4XOaumOP9d170Hhp chaica@fixe" -> null
 } 
 Plan: 0 to add, 0 to change, 4 to destroy.
 Do you really want to destroy all resources?
   Terraform will destroy all your managed infrastructure, as shown above.
   There is no undo. Only 'yes' will be accepted to confirm.
 Enter a value: yes
 aws_key_pair.admin: Destroying… [id=admin]
 aws_default_security_group.default: Destroying… [id=sg-06a5eeaa849e409f2]
 aws_default_security_group.default: Destruction complete after 0s
 aws_instance.server1: Destroying… [id=i-091c78d7e33d39058]
 aws_default_vpc.default: Destroying… [id=vpc-0fbb173527ee83b95]
 aws_default_vpc.default: Destruction complete after 0s
 aws_key_pair.admin: Destruction complete after 1s
 aws_instance.server1: Still destroying… [id=i-091c78d7e33d39058, 10s elapsed]
 aws_instance.server1: Still destroying… [id=i-091c78d7e33d39058, 20s elapsed]
 aws_instance.server1: Still destroying… [id=i-091c78d7e33d39058, 30s elapsed]
 aws_instance.server1: Destruction complete after 32s
 Destroy complete! Resources: 4 destroyed.

Comme indiqué sur la dernière ligne de la sortie d ela commande, nos 4 ressources ont bien été supprimées.

Conclusion

Nous sommes donc partis d’un compte AWS et d’une station de travail GNU/Linux pour déployer une instance EC2 AWS directement accessible via SSH.

L’article est un peu long, mais a le mérite de détailler complètement la création de votre première instance avec AWS et Terraform.

Les articles suivants de cet série seront sans doute plus courts (j’espère en tout cas), focalisés sur des points précis, même si le but sera également de permettre rapidement au lecteur de répliquer par lui-même le contenu de l’article.

Les sources Terraform de cet article

Les sources Terraform avec l’organisation des répertoires de cet article sont disponibles publiquement sur mon Gitlab : terraform-article-1

Me suivre sur les réseaux sociaux

N’hésitez pas à me suivre directement sur les différents sociaux pour suivre au jour le jour mes différentes projets dans le Logiciel Libre :

5 thoughts on “Débuter avec AWS et Terraform : déployer une instance EC2

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *