Terraform + AWS. Деплой кластера серверов с Elastic Load Balancer

Пример деплоя кластера серверов с балансировщиком нагрузки на AWS с помощью Terraform.

В этой статье мы напишем код, чтобы задеплоить простую HTML страничку, но в то же время у нас уже будет отказоустойчивый кластер Web-серверов. 


Вначале пройдёмся по кускам кода, а в самом конце сложим их воединно.

Полностью рабочий код вы можете забрать в моём репозитории на GitHub: https://github.com/yatakoi/terraform

Теория

AWS предлагает три типа балансировщика нагрузки:

Application Load Balancer (ALB)

Лучший выбор балансировки нагрузки HTTP и HTTPS трафика. Обслуживается на 7 уровне модели OSI.


Network Load Balancer (NLB)

Лучший выбор балансировки нагрузки TCP, UDP и TLS трафика. Обслуживается на 4 уровне модели OSI. NLB предназначен для масштабирования до десятков миллионов запросов в секунду.


Classic Load Balancer (CLB)

«Устаревший» балансировщик нагрузки, предшествующий как ALB, так и NLB. Он может обрабатывать HTTP, HTTPS, TCP и TLS трафик, но с гораздо меньшими возможностями, чем ALB или NLB. Работает как на прикладном уровне (L7), так и на транспортном уровне (L4) модели OSI.


На сегодня большинство сервисов должны использовать ALB или NLB, но из-за простоты примера будет использоваться ALB.

ALB состоит из нескольких частей:

Listener

Прослушивает определенный порт (например, 80) и протокол (например, HTTP).


Listener rule

Принимает запросы от Listener и отправляет их по определенному пути (например, в /path1 и /path2) или на определенные хосты (например, sub1.domain.ru и sub2.domain.ru).


Target groups

Целевая группа — это один или несколько серверов, которые получают запросы от балансировщика нагрузки. Запросы от Listener rules отправляются в ту целевую группу, которая доступна и/или наименее загружена. К тому же целевая группа выполняет проверки работоспособности хостов.


Деплой кластера серверов с балансировщиком нагрузки

В каком регионе будет наш кластер серверов

provider "aws" {
  region = "us-east-2"
}


Где:

  • region - дата-центр, ресурсы которого мы будет использовать.

Создание групп безопасности

Необходимо создать две группы безопасности.

Группа 1
Эта группа безопасности применяется к ресурсу aws_launch_configuration, который находится внутри Target Group (на рисунке выше квадраты path1 и path2). В группе разрешаем только входящий трафик.

resource "aws_security_group" "instance" {
  name = "terraform-instance-security-group"

  ingress {
    from_port = 8080
    to_port  = 8080
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    }
}


Где:

  • instance - произвольное имя ресурса.
  • name - имя группы, в которую входит ресурс Security Groups.
  • ingress - определение правил для входящего трафика.


Группа 2

По умолчанию все AWS-ресурсы, включая ALB, запрещают любой входящий/исходящий трафик. Поэтому настроим группу безопасности, которая разрешит входящий трафик на 80 порт и исходящий на любой.


resource "aws_security_group" "alb" {
    name = "terraform-alb-security-group"

    # Разрешить входящие HTTP
    ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    }
    
# Разрешить все исходящие
    egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    }
}


Где:

  • instance - произвольное имя ресурса.
  • name - имя группы, в которую входит ресурс Security Groups.
  • ingress - определение правил для входящего трафика.
  • egress - определение правил для исходящего трафика.

Создание ресурса ALB

resource "aws_lb" "alb" {
    name = "terraform-alb"
    load_balancer_type = "application"
    subnets = data.aws_subnet_ids.default.ids
    security_groups = [aws_security_group.alb.id]
}

Где:

  • alb — имя ресурса.
  • name — имя балансировщика.
  • load_balancer_type — тип балансировщика.
  • subnets — имя подсети. В этом случае подсеть указана как default. Вообще, по умолчанию при регистрации в AWS для всех регионов автоматически создаются подсети с именем default.
  • security_groups — имя группы безопасности, которую создали выше.

Создание ресурса listener

resource "aws_lb_listener" "http" {
    load_balancer_arn = aws_lb.alb.arn
    port = 80
    protocol = "HTTP"

# Страница 404 если будут запросы, которые не соответствуют никаким правилам прослушивателя
    default_action {
        type = "fixed-response"
        fixed_response {
        content_type = "text/plain"
        message_body = "404: страница не найдена"
        status_code = 404
        }
    }
}


Где:

  • http — имя ресурса прослушивателя.
  • load_balancer_arn — имя вышесозданного ALB. В нашем случае имя alb.

Остальные опции думаю очевидны.


Создание ресурса listener rule

Создадим правило прослушивателя, которое отправляет запросы, соответствующие любому пути, в целевую группу для ASG.

resource "aws_lb_listener_rule" "asg-listener_rule" {
    listener_arn    = aws_lb_listener.http.arn
    priority        = 100
    
    condition {
        field   = "path-pattern"
        values  = ["*"]
    }
    
    action {
        type = "forward"
        target_group_arn = aws_lb_target_group.asg-target-group.arn
    }
}

Создание target group

resource "aws_lb_target_group" "asg-target-group" {
    name = "terraform-asg-example"
    port = var.server_port
    protocol = "HTTP"
    vpc_id = data.aws_vpc.default.id
    health_check {
        path = "/"
        protocol = "HTTP"
        matcher = "200"
        interval = 15
        timeout = 3
        healthy_threshold = 2
        unhealthy_threshold = 2
    }
}


Где:

  • vpc_id — Virtual Private Cloud, который создается автоматически при регистрации в AWS с именем default. Синтаксис: data.<PROVIDER>_<TYPE>.<NAME>.<ATTRIBUTE>.
  • health_check — проверка инстанса на «здоровье». Проверка по HTTP и если возврат 200 ОК, значит все ОК smile Но если инстанс упадёт или будет перегружен, то произойдёт переключение на доступный инстанс.

Создание ресурсов кластера серверов

Чтобы целевая группа знала, на какие инстансы надо отправлять запросы, их надо к ней (целевой группе) приаттачить. Для этого есть первокласная интеграция ASG (Auto Scaling Group) + ALB (Application Load Balancer).


resource "aws_autoscaling_group" "ubuntu-ec2" {
    launch_configuration = aws_launch_configuration.ubuntu-ec2.name
    vpc_zone_identifier = data.aws_subnet_ids.default.ids
    
    # Включаем интеграцию между ASG и ALB, указав аргумент target_group_arns 
    # на целевую группу aws_lb_target_group.asg-target_group.arn,
    # чтобы целевая группа знала, в какие инстансы EC2 отправлять запросы.   
    target_group_arns = [aws_lb_target_group.asg-target-group.arn]
    health_check_type = "ELB"
        
    min_size = 2
    max_size = 10
    
    tag {
    key = "Name"
    value = "terraform-asg-ubuntu-ec2"
    propagate_at_launch = true
    }
}

resource "aws_launch_configuration" "ubuntu-ec2" {
    image_id = "ami-0c55b159cbfafe1f0"
    instance_type = "t2.micro"

    security_groups = [aws_security_group.instance.id]
                user_data = <<-EOF
                #!/bin/bash
                echo "Hello, World" > index.html
                nohup busybox httpd -f -p 8080 &
                EOF

    # Требуется при использовании launch configuration совместно с auto scaling group.
    # https://www.terraform.io/docs/providers/aws/r/launch_configuration.html
    lifecycle {
        create_before_destroy = true
    }
}



Где:

  • web-server-cluster — имя ресурса.
  • launch_configuration — имя ресурса aws_launch_configuration, который будет создан ниже. Мое имя ec2_instance.
  • target_group_arns — приаттаченная целевая группа.
  • health_check_type — тип проверки Elastic Load Balancer. Проверка работоспособности «ELB» более надежна, поскольку она инструктирует ASG использовать проверку работоспособности целевой группы, чтобы определить, является ли инстанс здоровым и
    автоматически заменять инстансы, если целевая группа сообщит, что что-то с ними не так. Поэтому, инстансы будут заменены не только, если они полностью отключены, но и, если, например, они перестали обслуживать запросы из-за нехватки памяти или сбоя критического процесса.
  • min_size / max_size — количество одновременно запущенных инстансов. Минимально будет запущено два инстанса и если им не будет хватать ресурсов, то буду включаться другие вплоть до 10 штук.
  • propagate at launch — разрешить инстансам разможаться при запуске.

Создание инстанса

Чтобы ресурс кластера серверов (aws_autoscaling_group), который мы создали выше, понимал, какие инстансы надо запускать — определим, что за инстанс мы будем использовать. В этой статье будем использовать самый простой EC2-инстанс t2.micro.


resource "aws_autoscaling_group" "ubuntu-ec2" {
    launch_configuration = aws_launch_configuration.ubuntu-ec2.name
    vpc_zone_identifier = data.aws_subnet_ids.default.ids
    
    # Включаем интеграцию ASG + ALB, указав аргумент target_group_arns 
    # на целевую группу aws_lb_target_group.asg-target_group.arn,
    # чтобы целевая группа знала, в какие инстансы EC2 отправлять запросы.   
    target_group_arns = [aws_lb_target_group.asg-target-group.arn]
    health_check_type = "ELB"
        
    min_size = 2
    max_size = 10
    
    tag {
    key = "Name"
    value = "terraform-asg-ubuntu-ec2"
    propagate_at_launch = true
    }
}

resource "aws_launch_configuration" "ubuntu-ec2" {
    image_id = "ami-0c55b159cbfafe1f0"
    instance_type = "t2.micro"

    security_groups = [aws_security_group.instance.id]
                user_data = <<-EOF
                #!/bin/bash
                echo "Hello, World" > index.html
                nohup busybox httpd -f -p 8080 &
                EOF

    # Требуется при использовании launch configuration совместно с auto scaling group.
    # https://www.terraform.io/docs/providers/aws/r/launch_configuration.html
    lifecycle {
        create_before_destroy = true
    }
}


Где (ресурс aws_autoscaling_group):

  • ubuntu-ec2 — в ресурсах "aws_autoscaling_group" и "aws_launch_configuration" я использую имя ubuntu-ec2 для понимания, что за AMI-образ будет использоваться и что это используется совсестно.
  • launch_configuration - в параметре "launch_configuration" сообщаем, что мы хотим совместно использовать ресурс "aws_launch_configuration" имя которого "ubuntu-ec2".
  • vpc_zone_identifier - имя VPC-подсети.
  • min_size / max_size - сообщаем AWS, что минимальное количество инстансов должно быть два, но если они будут перегружены, то AWS будет увеличивать их количество до десяти.

Где (ресурс aws_launch_configuration):

  • image_id — образ AWS. В данном случае Ubuntu.
  • instance_type — тип инстанса. t2.micro в какой-то мере бесплатный, поэтому отлично подходит для экспериментов.
  • security_groups — та самая группа безопасности, которая разрешает только входящий трафик и имя её instance.
  • user_data — это простой скрипт HTML страничка. Выведет её содержимое в браузере.

Выходные данные

И наконец, выходные данные, которые вы увидите в самом конце после того, как сделаете terraform apply. AWS сообщит DNS-адрес нашего задеплоенного сайта.

output "alb_dns_name" {
    value = aws_lb.alb.dns_name
    description = "Доменное имя ALB"
}


Итоговый файл конфигурации main.tf

Теперь создайте файл main.tf и вставьте туда весь код. Расширение tf означает Terraform File.

#############################################################################
# КАКОЙ ИСПОЛЬЗУЕТСЯ ПРОВАЙДЕР И РЕГИОН
#############################################################################

provider "aws" {
  region = "us-east-2"
}


#############################################################################
# ПАРАМЕТРЫ БЕЗОПАСНОСТИ
############################################################################

# Чтобы ресурс ASG работал, к нему надо приаттачить VPC-подсеть.
# subnet_ids указывает, в какие VPC-подсети должны быть развернуты иснтансы EC2. 
# Синтаксис data.<PROVIDER>_<TYPE>.<NAME>.<ATTRIBUTE>

# Получить ID VPC-подсетей из источника данных aws_vpc.
data "aws_subnet_ids" "default" {
    vpc_id = data.aws_vpc.default.id
}

# Найти в VPC-подсетях Default VPC.
data "aws_vpc" "default" {
default = true
}


# По умолчанию все AWS-ресурсы, включая ALB, запрещают любой входящий/исходящий трафик. 
# Поэтому настроим группу безопасности, которая разрешит входящий трафик на 80 порт ресурса ALB и исходящий на любой порт этого же ресурса.

resource "aws_security_group" "alb" {
    name = "terraform-alb-security-group"

    # Разрешить входящие HTTP
    ingress {
    from_port = 80
    to_port = 80
    protocol = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    }
    # Разрешить все исходящие
    egress {
    from_port = 0
    to_port = 0
    protocol = "-1"
    cidr_blocks = ["0.0.0.0/0"]
    }
}

# Эта группа безопасности применяется к ресурсу aws_launch_configuration
resource "aws_security_group" "instance" {
  name = "terraform-instance-security-group"

  ingress {
    from_port        = 8080
    to_port            = 8080
    protocol        = "tcp"
    cidr_blocks        = ["0.0.0.0/0"]
    }
}


#############################################################################
# ALB (Application Load Balancer)
#############################################################################


# alb — имя ресурса.
# name — имя балансировщика.
# load_balancer_type — тип балансировщика.
# subnets — имя VPC-подсети. В этом случае подсеть указана как default. 
# К сведению. По умолчанию при регистрации в AWS для всех регионов автоматически 
# создаются подсети с именем default.
# security_groups — имя группы безопасности, которую создали выше.

resource "aws_lb" "alb" {
    name = "terraform-alb"
    load_balancer_type = "application"
    subnets = data.aws_subnet_ids.default.ids
    security_groups = [aws_security_group.alb.id]
}

# Создание listener
# http — имя ресурса прослушивателя.
# load_balancer_arn — имя ресурса вышесозданного ALB. В нашем случае имя alb.

resource "aws_lb_listener" "http" {
    load_balancer_arn = aws_lb.alb.arn
    port = 80
    protocol = "HTTP"

# Страница 404 если будут запросы, которые не соответствуют никаким правилам прослушивателя.
    default_action {
        type = "fixed-response"
        fixed_response {
        content_type = "text/plain"
        message_body = "404: страница не найдена"
        status_code = 404
        }
    }
}

# Включаем правило прослушивателя, которое отправляет запросы,
# соответствующие любому пути, в целевую группу для ASG.
resource "aws_lb_listener_rule" "asg-listener_rule" {
    listener_arn    = aws_lb_listener.http.arn
    priority        = 100
    
    condition {
        field   = "path-pattern"
        values  = ["*"]
    }
    
    action {
        type = "forward"
        target_group_arn = aws_lb_target_group.asg-target-group.arn
    }
}

# Создаём целевую группу aws_lb_target_group для ASG.
# Каждые 15 сек. будут отправляться HTTP запросы и если ответ 200, то все ОК, иначе
# произойдет переключение на доступный инстанс. 
resource "aws_lb_target_group" "asg-target-group" {
    name = "terraform-aws-lb-target-group"
    port = 8080
    protocol = "HTTP"
    vpc_id = data.aws_vpc.default.id

    health_check {
        path                = "/"
        protocol            = "HTTP"
        matcher             = "200"
        interval            = 15
        timeout             = 3
        healthy_threshold   = 2
        unhealthy_threshold = 2
    }
}


#############################################################################
# ИНСТАНСЫ
#############################################################################

# FILEOVER ВЕБ-СЕРВЕР НА UBUNTU 
resource "aws_autoscaling_group" "ubuntu-ec2" {
    launch_configuration = aws_launch_configuration.ubuntu-ec2.name
    vpc_zone_identifier = data.aws_subnet_ids.default.ids
    
    # Включаем интеграцию между ASG и ALB, указав аргумент target_group_arns 
    # на целевую группу aws_lb_target_group.asg-target_group.arn,
    # чтобы целевая группа знала, в какие инстансы EC2 отправлять запросы.   
    target_group_arns = [aws_lb_target_group.asg-target-group.arn]
    health_check_type = "ELB"
        
    min_size = 2
    max_size = 10
    
    tag {
    key = "Name"
    value = "terraform-asg-ubuntu-ec2"
    propagate_at_launch = true
    }
}

resource "aws_launch_configuration" "ubuntu-ec2" {
    image_id = "ami-0c55b159cbfafe1f0"
    instance_type = "t2.micro"

    security_groups = [aws_security_group.instance.id]
                user_data = <<-EOF
                #!/bin/bash
                echo "Hello, World" > index.html
                nohup busybox httpd -f -p 8080 &
                EOF

    # Требуется при использовании launch configuration совместно с auto scaling group.
    # https://www.terraform.io/docs/providers/aws/r/launch_configuration.html
    lifecycle {
        create_before_destroy = true
    }
}


#############################################################################
# DNS ALB
############################################################################

output "alb_dns_name" {
    value = aws_lb.alb.dns_name
    description = "Доменное имя ALB"
}

После сохранения файла надо выполнить команды:
1. terraform init
Когда вы впервые начинаете использовать Terraform вам нужно запустить terraform init, чтобы Terraform просканировал код, выяснил, каких провайдеров вы используете, и скачал для них код. По умолчанию код провайдера будет загружен в каталог .terraform.

[root@centos-2gb-nbg-vpn aws]# terraform init

Initializing the backend...

Initializing provider plugins...

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.41"

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.

2. terraform plan
Команда terraform plan позволяет вам увидеть, что будет делать Terraform, прежде чем вносить какие-либо изменения. После того как вы запутсите terraform plan все, что будет иметь знак плюс (+) убедет добавлено в ASW, а все, что имеет знак минус (-), будет удалено, и все, что имеет знак тильды (~), будет изменено.

[root@centos-2gb-nbg-vpn aws]# 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.

data.aws_vpc.default: Refreshing state...
data.aws_subnet_ids.default: Refreshing state...

------------------------------------------------------------------------

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_autoscaling_group.ubuntu-ec2 will be created
  + resource "aws_autoscaling_group" "ubuntu-ec2" {
      + arn                       = (known after apply)
      + availability_zones        = (known after apply)
      + default_cooldown          = (known after apply)
      + desired_capacity          = (known after apply)
      + force_delete              = false
      + health_check_grace_period = 300
      + health_check_type         = "ELB"
      + id                        = (known after apply)
      + launch_configuration      = (known after apply)
      + load_balancers            = (known after apply)
      + max_size                  = 10
      + metrics_granularity       = "1Minute"
      + min_size                  = 2
      + name                      = (known after apply)
      + protect_from_scale_in     = false
      + service_linked_role_arn   = (known after apply)
      + target_group_arns         = (known after apply)
      + vpc_zone_identifier       = [
          + "subnet-026593b732390094b",
          + "subnet-029d6d12004440fd0",
          + "subnet-06ecfc7c1fb9aab08",
        ]
      + wait_for_capacity_timeout = "10m"

      + tag {
          + key                 = "Name"
          + propagate_at_launch = true
          + value               = "terraform-asg-ubuntu-ec2"
        }
    }

  # aws_launch_configuration.ubuntu-ec2 will be created
  + resource "aws_launch_configuration" "ubuntu-ec2" {
      + associate_public_ip_address = false
      + ebs_optimized               = (known after apply)
      + enable_monitoring           = true
      + id                          = (known after apply)
      + image_id                    = "ami-0c55b159cbfafe1f0"
      + instance_type               = "t2.micro"
      + key_name                    = (known after apply)
      + name                        = (known after apply)
      + security_groups             = (known after apply)
      + user_data                   = "67e34b406ab639a606a64fe06965b26bf8036a9c"

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + no_device             = (known after apply)
          + snapshot_id           = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

  # aws_lb.alb will be created
  + resource "aws_lb" "alb" {
      + arn                        = (known after apply)
      + arn_suffix                 = (known after apply)
      + dns_name                   = (known after apply)
      + enable_deletion_protection = false
      + enable_http2               = true
      + id                         = (known after apply)
      + idle_timeout               = 60
      + internal                   = (known after apply)
      + ip_address_type            = (known after apply)
      + load_balancer_type         = "application"
      + name                       = "terraform-alb"
      + security_groups            = (known after apply)
      + subnets                    = [
          + "subnet-026593b732390094b",
          + "subnet-029d6d12004440fd0",
          + "subnet-06ecfc7c1fb9aab08",
        ]
      + vpc_id                     = (known after apply)
      + zone_id                    = (known after apply)

      + subnet_mapping {
          + allocation_id = (known after apply)
          + subnet_id     = (known after apply)
        }
    }

  # aws_lb_listener.http will be created
  + resource "aws_lb_listener" "http" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + load_balancer_arn = (known after apply)
      + port              = 80
      + protocol          = "HTTP"
      + ssl_policy        = (known after apply)

      + default_action {
          + order = (known after apply)
          + type  = "fixed-response"

          + fixed_response {
              + content_type = "text/plain"
              + message_body = "404: страница не найдена"
              + status_code  = "404"
            }
        }
    }

  # aws_lb_listener_rule.asg-listener_rule will be created
  + resource "aws_lb_listener_rule" "asg-listener_rule" {
      + arn          = (known after apply)
      + id           = (known after apply)
      + listener_arn = (known after apply)
      + priority     = 100

      + action {
          + order            = (known after apply)
          + target_group_arn = (known after apply)
          + type             = "forward"
        }

      + condition {
          + field  = "path-pattern"
          + values = [
              + "*",
            ]
        }
    }

  # aws_lb_target_group.asg-target-group will be created
  + resource "aws_lb_target_group" "asg-target-group" {
      + arn                                = (known after apply)
      + arn_suffix                         = (known after apply)
      + deregistration_delay               = 300
      + id                                 = (known after apply)
      + lambda_multi_value_headers_enabled = false
      + name                               = "terraform-aws-lb-target-group"
      + port                               = 8080
      + protocol                           = "HTTP"
      + proxy_protocol_v2                  = false
      + slow_start                         = 0
      + target_type                        = "instance"
      + vpc_id                             = "vpc-0328cccb38b16e844"

      + health_check {
          + enabled             = true
          + healthy_threshold   = 2
          + interval            = 15
          + matcher             = "200"
          + path                = "/"
          + port                = "traffic-port"
          + protocol            = "HTTP"
          + timeout             = 3
          + unhealthy_threshold = 2
        }

      + stickiness {
          + cookie_duration = (known after apply)
          + enabled         = (known after apply)
          + type            = (known after apply)
        }
    }

  # aws_security_group.alb will be created
  + resource "aws_security_group" "alb" {
      + arn                    = (known after apply)
      + description            = "Managed by Terraform"
      + 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      = ""
              + from_port        = 80
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 80
            },
        ]
      + name                   = "terraform-alb-security-group"
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + vpc_id                 = (known after apply)
    }

  # aws_security_group.instance will be created
  + resource "aws_security_group" "instance" {
      + arn                    = (known after apply)
      + description            = "Managed by Terraform"
      + egress                 = (known after apply)
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = ""
              + from_port        = 8080
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 8080
            },
        ]
      + name                   = "terraform-instance-security-group"
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + vpc_id                 = (known after apply)
    }

Plan: 8 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.
Возьмите за правило всегда запускать terraform plan перед terraform apply, иначе можете получить много неприятных сюрпризов.
3. И наконец, terraform apply
Запустив terraform apply, Terraform начнёт проверку всё ли ОК в коде и если ДА, то появится сообщение о том, что надо подтвердить намерение задеплоить вашу конфигурацию, введя YES.

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

aws_lb_target_group.asg-target-group: Creating...
aws_security_group.instance: Creating...
aws_security_group.alb: Creating...
aws_lb_target_group.asg-target-group: Creation complete after 3s [id=arn:aws:elasticloadbalancing:us-east-2:384630389492:targetgroup/terraform-aws-lb-target-group/54087f51a83fbd43]
aws_security_group.instance: Creation complete after 4s [id=sg-080784c81753f13cc]
aws_launch_configuration.ubuntu-ec2: Creating...
aws_security_group.alb: Creation complete after 4s [id=sg-0affaa6d747c636e5]
aws_lb.alb: Creating...
aws_launch_configuration.ubuntu-ec2: Creation complete after 1s [id=terraform-20191216063641320300000001]
aws_autoscaling_group.ubuntu-ec2: Creating...
aws_lb.alb: Still creating... [10s elapsed]
aws_autoscaling_group.ubuntu-ec2: Still creating... [10s elapsed]
aws_lb.alb: Still creating... [20s elapsed]
aws_autoscaling_group.ubuntu-ec2: Still creating... [20s elapsed]
aws_lb.alb: Still creating... [30s elapsed]
aws_autoscaling_group.ubuntu-ec2: Still creating... [30s elapsed]
aws_lb.alb: Still creating... [40s elapsed]
aws_autoscaling_group.ubuntu-ec2: Still creating... [40s elapsed]
aws_lb.alb: Still creating... [50s elapsed]
aws_autoscaling_group.ubuntu-ec2: Still creating... [50s elapsed]
aws_lb.alb: Still creating... [1m0s elapsed]
aws_autoscaling_group.ubuntu-ec2: Still creating... [1m0s elapsed]
aws_lb.alb: Still creating... [1m10s elapsed]
aws_autoscaling_group.ubuntu-ec2: Still creating... [1m10s elapsed]
aws_autoscaling_group.ubuntu-ec2: Creation complete after 1m18s [id=tf-asg-20191216063642359000000002]
aws_lb.alb: Still creating... [1m20s elapsed]
aws_lb.alb: Still creating... [1m30s elapsed]
aws_lb.alb: Still creating... [1m40s elapsed]
aws_lb.alb: Still creating... [1m50s elapsed]
aws_lb.alb: Still creating... [2m0s elapsed]
aws_lb.alb: Still creating... [2m10s elapsed]
aws_lb.alb: Still creating... [2m20s elapsed]
aws_lb.alb: Creation complete after 2m27s [id=arn:aws:elasticloadbalancing:us-east-2:384630389492:loadbalancer/app/terraform-alb/920131d23f25a48b]
aws_lb_listener.http: Creating...
aws_lb_listener.http: Creation complete after 1s [id=arn:aws:elasticloadbalancing:us-east-2:384630389492:listener/app/terraform-alb/920131d23f25a48b/3ecc1cea41110144]
aws_lb_listener_rule.asg-listener_rule: Creating...
aws_lb_listener_rule.asg-listener_rule: Creation complete after 1s [id=arn:aws:elasticloadbalancing:us-east-2:384630389492:listener-rule/app/terraform-alb/920131d23f25a48b/3ecc1cea41110144/8c0fe588ffdb4f87]

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

Outputs:

alb_dns_name = terraform-alb-88393961.us-east-2.elb.amazonaws.com

В самом конце строчка "alb_dns_name = terraform-alb-88393961.us-east-2.elb.amazonaws.com". Это и есть наше доменное имя.

Чтобы уничтожить все ресурсы AWS выполните команду terraform destroy.

Ссылки по теме

Ресурсы AWS

AWS: https://aws.amazon.com
Документация по инстансам EC2: https://docs.aws.amazon.com/...
Документация по образам AMI: https://docs.aws.amazon.com/...
Документация по VPC-подсетям: https://docs.aws.amazon.com/...
Документация по EC2 Security Groups: https://docs.aws.amazon.com/...
Общая информации по Elastic Load Balancing: https://docs.aws.amazon.com/...
Документация по Launch Configuration и Auto Scaling: https://docs.aws.amazon.com/...

Ресурсы Terraform

Terraform: https://www.terraform.io
Terraform CLI: https://www.terraform.io/docs/cli-index.html
Команды Terraform для AWS: https://www.terraform.io/docs/providers/aws/

Комментариев 4

  1. Офлайн
    Vlad
    Vlad 23 июня 2021 13:38
    + +2 -
        condition {
          path_pattern {
            values = ["*"]
          }
        }
    #work in terraform 1.0.0
  2. Офлайн
    noname
    noname 14 июля 2022 15:27
    + 0 -
    статья взята из книги Terraform infrastruktura na urovne koda Brikman
  3. Офлайн
    yatakoi 15 июля 2022 08:47
    + 0 -
    Цитата: noname
    статья взята из книги Terraform infrastruktura na urovne koda Brikman

    Не совсем. За основу взята глава из книги Terraform Up and Running.
    1. Офлайн
      noname)
      noname) 23 июля 2022 12:52
      + 0 -
      да всё верно в оригинале она называется Terraform Up and Running автор Yevgeniy Brikman, на русский перевели криво) Инфраструктура на уровне кода https://www.piter.com/collection/bestsellery-oreilly/product/terraform-infrastruktura-na-urovne-koda

Добавить комментарий