Thomas Derflinger Blog

Créer une instance EC2 Spot avec Terraform

Cloud comme dans le Cloud Computing

Terraform est un outil Infrastructure as Code (IaC) par HashiCorp. En l’utilisant, vous pouvez créer de manière reproductible des instances de serveurs sur des fournisseurs de cloud comme AWS ou Digital Ocean. Dans cet article je vous montre comment créer un serveur d’instance AWS EC2 Spot avec Terraform.

Les instances AWS EC2 Spot sont des instances EC2 disponibles à prix réduits. EC2 (Elastic Compute Cloud) est le terme d’Amazon pour leurs serveurs dans leur centre de données que vous pouvez faire pratiquement tout ce que vous voulez avec. Vous pouvez l’utiliser pour exécuter des logiciels. Dans mon cas, j’utilise une instance pour créer un serveur Linux CentOS à des fins de test. Après le test l’instance EC2 Spot est détruite.

Tout d’abord, vous devez vous inscrire à AWS et installer l’outil en ligne de commande AWS (CLI).

Terraform accède au CLI AWS et utilise les informations d’identification que vous y avez configurées. Après l’installation de Terraform, nous définissons un fichier Terraform qui contient la configuration. Le fichier a une terminaison de nom de fichier .tf.

La création d’une instance EC2 est un peu plus compliquée, car il faut définir les règles de mise en réseau et de sécurité.

Vous pouvez trouver le code source sur ma page GitHub sous: https://github.com/tderflinger/terraform-ec2-spot

VPC

Tout d’abord, vous définissez votre réseau VPC (Virtual Private Cloud) qui est un sous-réseau logiquement isolé du cloud AWS.

resource "aws_vpc" "test-env" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
}

resource "aws_subnet" "subnet-uno" {
  # creates a subnet
  cidr_block        = "${cidrsubnet(aws_vpc.test-env.cidr_block, 3, 1)}"
  vpc_id            = "${aws_vpc.test-env.id}"
  availability_zone = "us-east-1a"
}

Cette définition utilise le concept d’adresses CIDR. Le concept des adresses réseau est bien expliqué dans l’article Digital Ocean.

La zone de disponibilité est la us-east-1a, mais vous pouvez choisir celle que vous préférez. Vous pouvez consultez votre zone de disponibilité dans cet article de AWS.

Groupes de sécurité

Ensuite, vous devez définir vos groupes de sécurité. Ils sont comme un pare-feu. Dans ce cas, j’autorise les ports 22 (SSH), 80 (HTTP) et 443 (HTTPS). La partie entrée est l’ingress. La sortie est l’egress et tout peut s’écouler.

resource "aws_security_group" "ingress-ssh-test" {
  name   = "allow-ssh-sg"
  vpc_id = "${aws_vpc.test-env.id}"

  ingress {
    cidr_blocks = [
      "0.0.0.0/0"
    ]

    from_port = 22
    to_port   = 22
    protocol  = "tcp"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "ingress-http-test" {
  name   = "allow-http-sg"
  vpc_id = "${aws_vpc.test-env.id}"

  ingress {
    cidr_blocks = [
      "0.0.0.0/0"
    ]

    from_port = 80
    to_port   = 80
    protocol  = "tcp"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "ingress-https-test" {
  name   = "allow-https-sg"
  vpc_id = "${aws_vpc.test-env.id}"

  ingress {
    cidr_blocks = [
      "0.0.0.0/0"
    ]

    from_port = 443
    to_port   = 443
    protocol  = "tcp"
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Passerelle Internet

Ensuite, vous devez définir votre adresse IP élastique, c’est-à-dire l’adresse IP IPv4 où vous pouvez atteindre votre serveur. Vous devez également déclarer quelques ressources comme une Passerelle Internet qui sert de traduction d’adresse réseau (NAT) et de tables de routage.

resource "aws_eip" "ip-test-env" {
  instance = "${aws_spot_instance_request.test_worker.spot_instance_id}"
  vpc      = true
}

resource "aws_internet_gateway" "test-env-gw" {
  vpc_id = "${aws_vpc.test-env.id}"
}

resource "aws_route_table" "route-table-test-env" {
  vpc_id = "${aws_vpc.test-env.id}"

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "${aws_internet_gateway.test-env-gw.id}"
  }
}

resource "aws_route_table_association" "subnet-association" {
  subnet_id      = "${aws_subnet.subnet-uno.id}"
  route_table_id = "${aws_route_table.route-table-test-env.id}"
}

Accès SSH

Ensuite, vous voudrez vous connecter en toute sécurité à votre serveur. Pour cela vous définissez la clé publique avec laquelle vous pouvez vous connecter. Vous devez adapter le chemin d’accès du fichier de votre clé publique sur votre système.

resource "aws_key_pair" "spot_key" {
  key_name   = "spot_key"
  public_key = "${file("/home/xx/.ssh/id_rsa.pub")}"
}

Demande de spot

La dernière pièce du fichier de définition Terraform est le spot actuel demande d’instance. Là, vous devez définir la Amazon Machine Image (AMI). L’AMI est essentiellement un fichier image qui contient le système d’exploitation. Dans notre cas, c’est CentOS 7.4. Vous trouverez une liste des AMI publics de votre région dans la console AWS sous le menu EC2.

Vous devez également définir un type d’instance approprié. Sur la page AWS, vous trouverez une liste des types d’instance. Les autres propriétés sont des références à la clé SSH, au groupe de sécurité et l’identifiant du sous-réseau. Dans l’entrée spotprice, vous indiquez combien l’instance spot EC2 devrait coûter au maximum par minute. La blockdurationminutes spécifie l’heure de la durée de l’instance. Après ce délai, l’instance est automatiquement détruite.

resource "aws_spot_instance_request" "test_worker" {
  ami                    = "ami-66a7871c"
  spot_price             = "0.016"
  instance_type          = "t3.small"
  spot_type              = "one-time"
  block_duration_minutes = "120"
  wait_for_fulfillment   = "true"
  key_name               = "spot_key"

  security_groups = ["${aws_security_group.ingress-ssh-test.id}", "${aws_security_group.ingress-http-test.id}",
  "${aws_security_group.ingress-https-test.id}"]
  subnet_id = "${aws_subnet.subnet-uno.id}"
}

Exécution de Terraform

Pour appliquer et créer l’instance spot EC2, vous devez appeler Terraform dans le répertoire où vous avez stocké le fichier de définition.

Sachez que votre utilisateur AWS que vous avez configuré dans votre CLI AWS doit avoir le droit de créer des instances EC2. Utilisez la console AWS IAM pour créer les droits nécessaires.

Utilisez les deux commandes suivantes pour lancer la création de l’instance spot EC2:

terraform init
terraform apply

Il vous demandera la région et si tout va bien. Après la création réussie, il y aura un fichier terraform.tfstate. Vous y trouverez l’adresse IP publique de l’instance. De plus, dans l’interface web de l’AWS, vous pouvez accéder à la section EC2. Vous y trouverez votre instance et vous pourrez également obtenir l’adresse IP publique.

Vous pouvez alors vous connecter avec SSH à l’instance publique comme ceci:

Lorsque vous n’avez plus besoin de l’instance, exécutez la commande destroy:

terraform destroy

Conclusion

Une instance de serveur sur Amazon EC2 n’est pas aussi facile à configurer que sur d’autres fournisseurs comme Digital Ocean. Mais vous avez plus de possibilités de configuration. Avec Terraform, vous avez la possibilité d’un système automatique et facilement configurable. Le mantra de l’infrastructure en tant que code est d’être capable d’automatiser autant que possible toutes les tâches d’administration du système. Terraform est un outil essentiel à cet égard.

Dans l’un de mes prochains articles, je vous montrerai comment utiliser Ansible pour provisionner l’instance spot EC2.

Sources et lectures complémentaires

Publié le 12 juillet 2019

Thomas Derflinger

Thomas Derflinger

Je suis entrepreneur indépendant et développeur de logiciels.

DevOps est un sujet que j'aime beaucoup. Prenons contact!