Как управлять инфраструктурой AWS с помощью Terraform

Как управлять инфраструктурой AWS с помощью Terraform

by moiseevrus

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

Хашикорп Терраформ

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 :

Пользователь IAM для Terraform

Помните: всегда держите эти учетные данные в тайне ! Не беспокойтесь обо мне, эти учетные данные больше не будут работать, как только я опубликую этот урок!

Ведро S3

Создайте корзину S3, в которой будет храниться наш файл terraform.tfstate . Файлы состояния Terraform объясняются на следующем шаге в этом руководстве.

Если вы еще не создавали корзину S3, вот полезное руководство, которое вы можете использовать. Для этого урока я создал корзину S3 под названием terraform-s3-bucket-testing :

Ведро S3 для файла состояния Terraform

Помните: пожалуйста, заблокируйте ВЕСЬ публичный доступ к корзине и ко всем объектам в корзине.

Монтаж

Теперь мы готовы установить 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, чтобы проверить созданные объекты. Вот как теперь выглядит моя панель инструментов:

Информационная панель VPC

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

Сегмент S3, содержащий файл удаленного состояния

Развертывание серверов

Теперь, когда наш VPC готов, мы можем развернуть серверы.

Группы безопасности

Во-первых, давайте определим 3 группы безопасности:

  1. Группа безопасности, которая разрешит входящий доступ к нашим веб-серверам в подсети terraform-demo-snet-web из Интернета.
  2. Группа безопасности, которая разрешит доступ к нашим серверам приложений в подсети terraform-demo-snet-app из подсети terraform-demo-snet-web .
  3. Группа безопасности, которая разрешит доступ к нашим серверам баз данных в подсети 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 и перейдите к экземплярам, ​​чтобы проверить созданные серверы:

Информационная панель EC2

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

Статья является переводом medium.com

You may also like

Leave a Comment