Contents
Что такое Терраформ?

Hashicorp Terraform — чрезвычайно полезный и гибкий инструмент для безопасного и эффективного построения, изменения и управления версиями инфраструктуры. Он основан на концепции «инфраструктура как код» — управлении всей инфраструктурой с использованием машиночитаемых файлов конфигурации, а не интерактивных команд и инструментов настройки.
Terraform — одно из предложений Hashicorp, предназначенных для автоматизации. Версия Terraform для командной строки с открытым исходным кодом доступна для всех через GitHub .
Terraform хорошо работает с широким спектром поставщиков частных облаков, таких как VMWare vSphere, а также с поставщиками общедоступных облаков, такими как Google Cloud Platform (GCP), Microsoft Azure и Amazon AWS. Полный список поддерживаемых провайдеров можно посмотреть здесь .
В этом подробном руководстве я расскажу вам, как начать управлять инфраструктурой AWS с помощью Terraform с нуля. Вот как будет выглядеть наша архитектура AWS:

Предпосылки
Прежде чем мы сможем начать использовать Terraform для управления инфраструктурой AWS, нам необходимо настроить следующее:
IAM-пользователь
В соответствии с рекомендациями AWS создайте пользователя IAM с программным доступом и присоедините к нему следующие политики с помощью управления идентификацией и доступом (IAM) в консоли AWS:
– Администратор сети
– AmazonEC2FullAccess
– AmazonS3FullAccess
Если вы еще не создали пользователя IAM, вот полезное руководство, которым вы можете воспользоваться. В конце процесса создания пользователя IAM вам должна быть представлена следующая страница с идентификатором ключа доступа и секретным ключом доступа . Пожалуйста, скопируйте эти значения и сохраните их где-нибудь (приватно), потому что мы будем использовать их позже.
Для этого урока я создал пользователя с именем terraform-user :

Помните: всегда держите эти учетные данные в тайне ! Не беспокойтесь обо мне, эти учетные данные больше не будут работать, как только я опубликую этот урок!
Ведро S3
Создайте корзину S3, в которой будет храниться наш файл terraform.tfstate . Файлы состояния Terraform объясняются на следующем шаге в этом руководстве.
Если вы еще не создавали корзину S3, вот полезное руководство, которое вы можете использовать. Для этого урока я создал корзину S3 под названием terraform-s3-bucket-testing :

Помните: пожалуйста, заблокируйте ВЕСЬ публичный доступ к корзине и ко всем объектам в корзине.
Монтаж
Теперь мы готовы установить Terraform!
Сначала откройте окно терминала и создайте рабочий каталог для нашего проекта Terraform. Обратите внимание, что в этом руководстве я использую macOS, поэтому вам могут понадобиться другие команды, соответствующие вашей рабочей станции.
mkdir ~/terraform-aws cd ~/terraform-aws
На момент написания последняя версия командной строки Terraform — 0.12.29. Поддерживается установка Terraform на следующих платформах:
- macOS (64-разрядная версия)
- FreeBSD (32-разрядная, 64-разрядная и ARM)
- Linux (32-разрядная, 64-разрядная и ARM)
- OpenBSD (32-битная и 64-битная)
- Солярис (64-разрядная версия)
- Windows (32-разрядная и 64-разрядная версии)
Для этого урока я использую macOS, поэтому мне нужно загрузить соответствующий Zip-файл:
wget https://releases.hashicorp.com/terraform/0.12.29/terraform_0.12.29_darwin_amd64.zip
Кроме того, вы можете посетить страницу загрузки , где вы можете найти последние исполняемые файлы для вашей соответствующей платформы.
Затем разархивируйте исполняемый файл и покажите двоичный файл terraform .
which terraform
Переместите двоичный файл в место в вашем $PATH. Я бы предложил перенести terraform в /usr/local/bin:
mv terraform /usr/local/bin
Убедитесь, что двоичный файл terraform доступен в текущем $PATH:
which terraform
Если в выводе отображается /usr/local/bin/terraform , значит все готово! Запустите эту последнюю команду, чтобы проверить версию Terraform:
santino:terraform-aws santino$ terraform - version Terraform v0.12.29 santino:terraform-aws santino$
Состояние терраформирования
Terraform сохраняет сопоставление реальных ресурсов поставщика (в нашем случае Amazon AWS) с нашей локальной конфигурацией. Это достигается за счет поддержки файла terraform.tfstate , который по умолчанию хранится в локальном рабочем каталоге.
Это хорошо работает, если вы один поддерживаете нашу инфраструктуру AWS с помощью Terraform. Однако при работе с группами каждый, кому необходимо выполнить terraform, также должен иметь копию файла terraform.tfstate в своем локальном рабочем каталоге.
Подход к решению этой проблемы состоит в том, чтобы зафиксировать файл terraform.tfstate в репозитории Git, чтобы каждый мог работать с одним и тем же файлом. Однако такой подход небезопасен, учитывая, что файл состояния содержит много ценной информации о вашей инфраструктуре AWS. Фактически, файлы .gitignore в официальном git-репозитории Terraform не позволяют Git управлять этим файлом:
terraform.tfstate
terraform.tfstate.backup
.terraform/*
Наилучший подход к этой проблеме — использовать удаленный репозиторий состояния terraform. Этого можно добиться несколькими способами, но в этом руководстве мы будем использовать корзину S3 для хранения нашего файла terraform.tfstate .
Определите поставщика и удаленное местоположение
Создайте наш первый файл .tf с помощью вашего любимого редактора, который будет содержать информацию о провайдере (AWS) и корзине S3, в которой будет храниться наше удаленное состояние.
провайдер.tf
# Define AWS as our provider provider "aws" { region = "eu-central-1" }# Terraform remote state terraform { backend "s3" { bucket = "terraform-s3-bucket-testing" key = "terraform-s3-bucket-testing/terraform.tfstate" region = "eu-central-1" } }
Следующим шагом является определение двух переменных среды, которые будут содержать идентификатор ключа доступа и секретный ключ доступа из предыдущего раздела.
export AWS_ACCESS_KEY_ID="AKIAUN57B3YGREQNABE4" export AWS_SECRET_ACCESS_KEY="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"
После определения нашего провайдера, местоположения нашей корзины S3 и учетных данных для входа в нашу учетную запись AWS мы теперь можем инициализировать наш проект Terraform с помощью команды terraform init .
Вот пример вывода:
santino:terraform-aws santino$ terraform initInitializing the backend...Successfully configured the backend "s3"! Terraform will automatically use this backend unless the backend configuration changes.Initializing provider plugins... - Checking for available provider plugins... - Downloading plugin for provider "aws" (hashicorp/aws) 2.70.0...The following providers do not have any version constraints in configuration, so the latest version was installed.To prevent automatic upgrades to new major versions that may contain breaking changes, it is recommended to add version = "..." constraints to the corresponding provider blocks in configuration, with the constraint strings suggested below.* provider.aws: version = "~> 2.70"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 working directory. If you forget, other commands will detect it and remind you to do so if necessary. santino:terraform-aws santino$
Управление сетью
После успешной инициализации нашего проекта Terraform теперь мы можем приступить к созданию ресурсов в нашей учетной записи AWS.
Начнем с сети. Нам нужно создать несколько сетевых объектов:
- ВКК
- Подсети
- Интернет-шлюз
- Таблица маршрутов
vpc.tf
## Demo VPC resource "aws_vpc" "terraform-demo-vpc" { cidr_block = "10.0.0.0/16" instance_tenancy = "default" enable_dns_support = "true" enable_dns_hostnames = "true" enable_classiclink = "false" tags = { Name = "terraform-demo-vpc" } }
подсети.tf
## Demo subnets# Web tier subnet resource "aws_subnet" "terraform-demo-snet-web" { vpc_id = aws_vpc.terraform-demo-vpc.id cidr_block = "10.0.0.0/21" map_public_ip_on_launch = "true" availability_zone = "eu-central-1a" tags = { Name = "terraform-demo-snet-web" } }# Application tier subnet resource "aws_subnet" "terraform-demo-snet-app" { vpc_id = aws_vpc.terraform-demo-vpc.id cidr_block = "10.0.8.0/21" map_public_ip_on_launch = "false" availability_zone = "eu-central-1a" tags = { Name = "terraform-demo-snet-app" } }# Database tier subnet resource "aws_subnet" "terraform-demo-snet-db" { vpc_id = aws_vpc.terraform-demo-vpc.id cidr_block = "10.0.16.0/21" map_public_ip_on_launch = "false" availability_zone = "eu-central-1a" tags = { Name = "terraform-demo-snet-db" } }
igw.tf
## Internet Gateway
resource "aws_internet_gateway" "terraform-demo-igw" {
vpc_id = aws_vpc.terraform-demo-vpc.id
tags = {
Name = "terraform-demo-igw"
}
}
route-table.tf
## Route table resource "aws_route_table" "terraform-demo-rtable" { vpc_id = aws_vpc.terraform-demo-vpc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.terraform-demo-igw.id } tags = { Name = "terraform-demo-rtable" } }# Route table associations resource "aws_route_table_association" "terraform-demo-rtassoc1" { subnet_id = aws_subnet.terraform-demo-snet-web.id route_table_id = aws_route_table.terraform-demo-rtable.id } resource "aws_route_table_association" "terraform-demo-rtassoc2" { subnet_id = aws_subnet.terraform-demo-snet-app.id route_table_id = aws_route_table.terraform-demo-rtable.id } resource "aws_route_table_association" "terraform-demo-rtassoc3" { subnet_id = aws_subnet.terraform-demo-snet-db.id route_table_id = aws_route_table.terraform-demo-rtable.id }
Быстрое объяснение!
Обратите внимание, что синтаксис для определения ресурса выглядит следующим образом:
resource "<resource type>" "<resource name>"
Затем мы можем ссылаться на этот ресурс при создании других ресурсов, используя синтаксис <тип ресурса>.<имя ресурса>.<свойство> .
Например, мы определили наш VPC как:
## Demo VPC
resource “aws_vpc” “terraform-demo-vpc” {
…
При создании подсети нам нужно связать ее с VPC, в котором она должна находиться. Таким образом, мы определяем эту связь с параметром vpc_id и идентификатором VPC:
resource “aws_subnet” “terraform-demo-snet-web” {
vpc_id = aws_vpc.terraform-demo-vpc.id
…
Применение наших изменений
Используйте команду terraform plan , чтобы просмотреть изменения, которые Terraform будет выполнять в нашей инфраструктуре AWS, прежде чем применять их.
Пример вывода:
santino:terraform-aws santino$ 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: + createTerraform will perform the following actions:# aws_internet_gateway.terraform-demo-igw will be created + resource "aws_internet_gateway" "terraform-demo-igw" { + arn = (known after apply) + id = (known after apply) + owner_id = (known after apply) + tags = { + "Name" = "terraform-demo-igw" } + vpc_id = (known after apply) }<CUT># aws_vpc.terraform-demo-vpc will be created + resource "aws_vpc" "terraform-demo-vpc" { + arn = (known after apply) + assign_generated_ipv6_cidr_block = false + cidr_block = "10.0.0.0/16" + 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 = false + enable_classiclink_dns_support = (known after apply) + enable_dns_hostnames = true + enable_dns_support = true + id = (known after apply) + instance_tenancy = "default" + 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" = "terraform-demo-vpc" } }Plan: 9 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.santino:terraform-aws santino$
Чтобы окончательно создать объекты в AWS, запустите команду terraform apply . Вам будет предоставлен последний шанс просмотреть изменения, и вам будет предложено, хотите ли вы продолжить. После ответа yes Terraform модифицирует AWS, чтобы отразить желаемое состояние.
Пример вывода:
santino:terraform-aws santino$ terraform applyAn execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + createTerraform will perform the following actions:# aws_internet_gateway.terraform-demo-igw will be created + resource "aws_internet_gateway" "terraform-demo-igw" { + arn = (known after apply) + id = (known after apply) + owner_id = (known after apply) + tags = { + "Name" = "terraform-demo-igw" } + vpc_id = (known after apply) }<CUT># aws_vpc.terraform-demo-vpc will be created + resource "aws_vpc" "terraform-demo-vpc" { + arn = (known after apply) + assign_generated_ipv6_cidr_block = false + cidr_block = "10.0.0.0/16" + 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 = false + enable_classiclink_dns_support = (known after apply) + enable_dns_hostnames = true + enable_dns_support = true + id = (known after apply) + instance_tenancy = "default" + 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" = "terraform-demo-vpc" } }Plan: 9 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: yesaws_vpc.terraform-demo-vpc: Creating... aws_vpc.terraform-demo-vpc: Creation complete after 2s [id=vpc-03ae143c2a8e3284c] aws_internet_gateway.terraform-demo-igw: Creating... aws_subnet.terraform-demo-snet-app: Creating... aws_subnet.terraform-demo-snet-db: Creating... aws_subnet.terraform-demo-snet-web: Creating... aws_subnet.terraform-demo-snet-app: Creation complete after 1s [id=subnet-0b6474b59034abcb0] aws_subnet.terraform-demo-snet-db: Creation complete after 1s [id=subnet-0c5f28652ff57e71b] aws_internet_gateway.terraform-demo-igw: Creation complete after 1s [id=igw-05519819650e3f727] aws_route_table.terraform-demo-rtable: Creating... aws_subnet.terraform-demo-snet-web: Creation complete after 2s [id=subnet-06bd93be3e1b13772] aws_route_table.terraform-demo-rtable: Creation complete after 1s [id=rtb-08a56a903445b0c7c] aws_route_table_association.terraform-demo-rtassoc3: Creating... aws_route_table_association.terraform-demo-rtassoc2: Creating... aws_route_table_association.terraform-demo-rtassoc1: Creating... aws_route_table_association.terraform-demo-rtassoc1: Creation complete after 1s [id=rtbassoc-0d9d2fe02770cf4fd] aws_route_table_association.terraform-demo-rtassoc2: Creation complete after 1s [id=rtbassoc-04e0a5bdcddd03f22] aws_route_table_association.terraform-demo-rtassoc3: Creation complete after 1s [id=rtbassoc-0daec5cb8a9545d2a]Apply complete! Resources: 9 added, 0 changed, 0 destroyed. santino:terraform-aws santino$
Теперь вы можете войти в консоль AWS, чтобы проверить созданные объекты. Вот как теперь выглядит моя панель инструментов:

Файл terraform.tfstate также будет создан в корзине S3, которую мы определили ранее:

Развертывание серверов
Теперь, когда наш VPC готов, мы можем развернуть серверы.
Группы безопасности
Во-первых, давайте определим 3 группы безопасности:
- Группа безопасности, которая разрешит входящий доступ к нашим веб-серверам в подсети terraform-demo-snet-web из Интернета.
- Группа безопасности, которая разрешит доступ к нашим серверам приложений в подсети terraform-demo-snet-app из подсети terraform-demo-snet-web .
- Группа безопасности, которая разрешит доступ к нашим серверам баз данных в подсети terraform-demo-snet-db из подсети terraform-demo-snet-app .
secgroups.tf
## Security groups# Web tier security group resource "aws_security_group" "terraform-demo-secgrp-webpub" { vpc_id = aws_vpc.terraform-demo-vpc.id name = "terraform-demo-secgrp-webpub" description = "Allow web traffic from the internet" ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] description = "Plain HTTP" } ingress{ from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] description = "Secure HTTP" } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "terraform-demo-secgrp-webpub" } }# Application tier security group resource "aws_security_group" "terraform-demo-secgrp-app" { vpc_id = aws_vpc.terraform-demo-vpc.id name = "terraform-demo-secgrp-app" description = "Allow traffic from the web tier" ingress{ from_port = 8080 to_port = 8080 protocol = "tcp" cidr_blocks = ["10.0.0.0/21"] description = "Plain HTTP" } ingress{ from_port = 8443 to_port = 8443 protocol = "tcp" cidr_blocks = ["10.0.0.0/21"] description = "Secure HTTP" } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "terraform-demo-secgrp-app" } }# Database tier security group resource "aws_security_group" "terraform-demo-secgrp-db" { vpc_id = aws_vpc.terraform-demo-vpc.id name = "terraform-demo-secgrp-db" description = "Allow traffic from the app tier" ingress{ from_port = 5432 to_port = 5432 protocol = "tcp" cidr_blocks = ["10.0.8.0/21"] description = "PostgreSQL" } ingress{ from_port = 3306 to_port = 3306 protocol = "tcp" cidr_blocks = ["10.0.8.0/21"] description = "MySQL" } ingress{ from_port = 27017 to_port = 27017 protocol = "tcp" cidr_blocks = ["10.0.8.0/21"] description = "mongodb" } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "terraform-demo-secgrp-db" } }
Снова запустите ту же команду плана terraform ранее и просмотрите предложенные изменения, затем запустите terraform apply и ответьте « да» на приглашение.
Пример вывода:
santino:terraform-aws santino$ terraform apply aws_vpc.terraform-demo-vpc: Refreshing state... [id=vpc-03ae143c2a8e3284c] <CUT> aws_route_table_association.terraform-demo-rtassoc3: Refreshing state... [id=rtbassoc-0daec5cb8a9545d2a]An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + createTerraform will perform the following actions:<CUT># aws_security_group.terraform-demo-secgrp-webpub will be created + resource "aws_security_group" "terraform-demo-secgrp-webpub" { + arn = (known after apply) + description = "Allow web traffic from the internet" + 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 = [ + "0.0.0.0/0", ] + description = "Plain HTTP" + from_port = 80 + ipv6_cidr_blocks = [] + prefix_list_ids = [] + protocol = "tcp" + security_groups = [] + self = false + to_port = 80 }, + { + cidr_blocks = [ + "0.0.0.0/0", ] + description = "Secure HTTP" + from_port = 443 + ipv6_cidr_blocks = [] + prefix_list_ids = [] + protocol = "tcp" + security_groups = [] + self = false + to_port = 443 }, ] + name = "terraform-demo-secgrp-webpub" + owner_id = (known after apply) + revoke_rules_on_delete = false + tags = { + "Name" = "terraform-demo-secgrp-webpub" } + vpc_id = "vpc-03ae143c2a8e3284c" }Plan: 3 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: yesaws_security_group.terraform-demo-secgrp-db: Creating... aws_security_group.terraform-demo-secgrp-app: Creating... aws_security_group.terraform-demo-secgrp-webpub: Creating... aws_security_group.terraform-demo-secgrp-app: Creation complete after 2s [id=sg-0d920e06fa8dd370f] aws_security_group.terraform-demo-secgrp-webpub: Creation complete after 2s [id=sg-029d4f9c83b6fed54] aws_security_group.terraform-demo-secgrp-db: Creation complete after 2s [id=sg-049704a710b385483]Apply complete! Resources: 3 added, 0 changed, 0 destroyed. santino:terraform-aws santino$
Определения сервера
Наконец-то мы можем развернуть наши серверы!
Во-первых, мы запросим идентификатор последней официальной версии Centos 7 AMI. Далее мы создадим ресурс ключа SSH на основе нашего открытого ключа в ~/.ssh/id_rsa.pub . Наконец, мы создадим наш веб-сервер, наш сервер приложений и 2 сервера баз данных, все в соответствующих подсетях. Мы также связали бы каждый сервер с соответствующей группой безопасности, созданной ранее.
серверы.tf :
## Query the latest AMI for Centos 7 data "aws_ami" "centos7" { owners = ["679593333241"] most_recent = true filter { name = "name" values = ["CentOS Linux 7 x86_64 HVM EBS *"] } filter { name = "architecture" values = ["x86_64"] } filter { name = "root-device-type" values = ["ebs"] } }## SSH Key pair resource "aws_key_pair" "terraform-demo-sshkey-santino" { key_name = "terraform-demo-sshkey-santino" public_key = file("~/.ssh/id_rsa.pub") tags = { Name = "terraform-demo-sshkey-santino" } }### Server definitions # Web server resource "aws_instance" "terraform-demo-web" { ami = data.aws_ami.centos7.id instance_type = "t2.micro" key_name = aws_key_pair.terraform-demo-sshkey-santino.key_name subnet_id = aws_subnet.terraform-demo-snet-web.id vpc_security_group_ids = [aws_security_group.terraform-demo-secgrp-webpub.id] tags = { Name = "terraform-demo-web" } } # Application server resource "aws_instance" "terraform-demo-app" { ami = data.aws_ami.centos7.id instance_type = "t2.micro" key_name = aws_key_pair.terraform-demo-sshkey-santino.key_name subnet_id = aws_subnet.terraform-demo-snet-app.id vpc_security_group_ids = [aws_security_group.terraform-demo-secgrp-app.id] tags = { Name = "terraform-demo-app" } } # Database server - Postgresql resource "aws_instance" "terraform-demo-postgres" { ami = data.aws_ami.centos7.id instance_type = "t3a.medium" key_name = aws_key_pair.terraform-demo-sshkey-santino.key_name subnet_id = aws_subnet.terraform-demo-snet-db.id vpc_security_group_ids = [aws_security_group.terraform-demo-secgrp-db.id] tags = { Name = "terraform-demo-postgres" } } # Database server - MySQL resource "aws_instance" "terraform-demo-mysql" { ami = data.aws_ami.centos7.id instance_type = "t3a.medium" key_name = aws_key_pair.terraform-demo-sshkey-santino.key_name subnet_id = aws_subnet.terraform-demo-snet-db.id vpc_security_group_ids = [aws_security_group.terraform-demo-secgrp-db.id] tags = { Name = "terraform-demo-mysql" } }
Снова запустите ту же команду плана terraform ранее и просмотрите предложенные изменения, затем запустите terraform apply и ответьте « да» на приглашение.
santino:terraform-aws santino$ terraform apply data.aws_ami.centos7: Refreshing state... aws_vpc.terraform-demo-vpc: Refreshing state... [id=vpc-03ae143c2a8e3284c] aws_subnet.terraform-demo-snet-app: Refreshing state... [id=subnet-0b6474b59034abcb0] aws_internet_gateway.terraform-demo-igw: Refreshing state... [id=igw-05519819650e3f727] aws_subnet.terraform-demo-snet-web: Refreshing state... [id=subnet-06bd93be3e1b13772] aws_subnet.terraform-demo-snet-db: Refreshing state... [id=subnet-0c5f28652ff57e71b] aws_security_group.terraform-demo-secgrp-db: Refreshing state... [id=sg-049704a710b385483] aws_security_group.terraform-demo-secgrp-app: Refreshing state... [id=sg-0d920e06fa8dd370f] aws_security_group.terraform-demo-secgrp-webpub: Refreshing state... [id=sg-029d4f9c83b6fed54] aws_route_table.terraform-demo-rtable: Refreshing state... [id=rtb-08a56a903445b0c7c] aws_route_table_association.terraform-demo-rtassoc3: Refreshing state... [id=rtbassoc-0daec5cb8a9545d2a] aws_route_table_association.terraform-demo-rtassoc1: Refreshing state... [id=rtbassoc-0d9d2fe02770cf4fd] aws_route_table_association.terraform-demo-rtassoc2: Refreshing state... [id=rtbassoc-04e0a5bdcddd03f22]An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create -/+ destroy and then create replacementTerraform will perform the following actions:# aws_instance.terraform-demo-app will be created + resource "aws_instance" "terraform-demo-app" { + ami = "ami-0e8286b71b81c3cc1" + 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 = "terraform-demo-sshkey-santino" + network_interface_id = (known after apply) + outpost_arn = (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 = "subnet-0b6474b59034abcb0" + tags = { + "Name" = "terraform-demo-app" } + 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) }+ metadata_options { + http_endpoint = (known after apply) + http_put_response_hop_limit = (known after apply) + http_tokens = (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) + device_name = (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) } }<CUT>Plan: 7 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<CUT> aws_instance.terraform-demo-mysql: Creation complete after 13s [id=i-029c67de608e848b5] aws_instance.terraform-demo-web: Still creating... [20s elapsed] aws_instance.terraform-demo-app: Still creating... [20s elapsed] aws_instance.terraform-demo-app: Creation complete after 22s [id=i-01363d0b335a46378] aws_instance.terraform-demo-web: Still creating... [30s elapsed] aws_instance.terraform-demo-web: Creation complete after 32s [id=i-059f9773402b1eb34]Apply complete! Resources: 7 added, 0 changed, 0destroyed. santino:terraform-aws santino$
Войдите в панель управления EC2 и перейдите к экземплярам, чтобы проверить созданные серверы:

Поздравляем! Вы только что внедрили свою инфраструктуру AWS с помощью Terraform!
Статья является переводом medium.com