Начало работы с созданием и управлением кластером AWS ECS с помощью Terraform
16 мая 2022 г.AWS ECS с Fargate — это бессерверная вычислительная платформа, которая делает запуск контейнерных сервисов на AWS проще, чем когда-либо прежде. До Fargate пользователям, которые хотели бы развернуть сервисы в кластере AWS ECS, приходилось управлять одним или несколькими экземплярами EC2 одинакового или разного размера и выяснять, как масштабировать их по мере необходимости.
С Fargate пользователь просто определяет вычислительные ресурсы, такие как ЦП и память, которые потребуются для запуска службы, а Fargate самостоятельно управляет тем, где запускать контейнер. Нет необходимости в настройке экземпляра EC2.
Terraform — это инструмент «инфраструктура как код», созданный Hashicorp для того, чтобы сделать работу с инфраструктурой более простой и управляемой. Файлы Terraform используют декларативный синтаксис, в котором пользователь указывает ресурсы и их свойства, такие как модули, развертывания, службы и входы. Затем пользователи могут использовать интерфейс командной строки Terraform для предварительного просмотра и применения ожидаемой инфраструктуры.
Когда желательны изменения, пользователь просто обновляет и повторно применяет тот же файл или набор файлов; затем Terraform обрабатывает создание, обновление и удаление ресурсов по мере необходимости.
Следуя этому руководству, вы узнаете, как определять ресурсы AWS с помощью Terraform и как определения ресурсов преобразуются в фактические ресурсы, созданные в AWS. Когда все будет запущено, у вас будет собственная масштабируемая служба «Hello World», работающая в облаке!
Зависимости проекта для Terraform и AWS Fargate
Вы будете использовать Terraform для развертывания всех необходимых ресурсов в кластере ECS. Не забудьте зарегистрировать учетную запись AWS. Поставщику AWS Terraform потребуются учетные данные для программного доступа к вашему аккаунту, поэтому создайте их в соответствии с этими документами. #access-keys-and-secret-access-keys), если вы еще этого не сделали.
Если у вашего пользователя еще нет прикрепленных политик, вы можете добавить политику ниже. Эта политика должна разрешать доступ ко всем ресурсам AWS, поэтому вам не нужно беспокоиться о них для этого руководства.
«Версия»: «2012-10-17»,
"Заявление": [
«Эффект»: «Разрешить»,
"Действие": ["*"],
"Ресурс": "*"
При желании вы можете установить AWS CLI, если хотите получить больше информации о развертывании Terraform, не переходя к панель управления AWS.
Определение ресурсов AWS ECS с помощью Terraform
Terraform требует, чтобы пользователь использовал специальный язык под названием HCL, что означает язык конфигурации Hashicorp. Создайте папку с именем terraform-example, в которой будут храниться файлы HCL, затем измените каталоги на эту папку. Поставщики Terraform должны быть определены и установлены для использования определенных типов ресурсов.
В этом руководстве будет использоваться только поставщик AWS. Провайдеры легко загружаются и устанавливаются с помощью нескольких строк HCL и одной команды.
Создайте файл с именем versions.tf
, в котором будут определены поставщики, и добавьте следующий код:
терраформировать {
required_providers {
авс = {
источник = "hashicorp/aws"
провайдер "aws" {
регион = "США-Восток-2"
access_key = "
secret_key = "
Обязательно замените <your_aws_access_key>
и <your_aws_secret_key>
на ключи для вашей учетной записи. Теперь, когда необходимый провайдер определен, его можно установить, выполнив команду `terraform init
.
Убедитесь, что команда запущена в той же папке, что и versions.tf
. Команда должна вывести что-то вроде того, что показано ниже, что означает, что Terraform готов начать создание ресурсов AWS:
Инициализация бэкенда...
Инициализация подключаемых модулей провайдера...
- Повторное использование предыдущей версии hashicorp/aws из файла блокировки зависимостей.
- Установка hashicorp/aws v3.32.0...
- Установлен hashicorp/aws v3.32.0 (подписано HashiCorp)
Terraform успешно инициализирован!
Теперь вы можете начать работать с Terraform. Попробуйте запустить «план терраформирования», чтобы увидеть
любые изменения, необходимые для вашей инфраструктуры. Все команды Terraform
теперь должно работать.
Если вы когда-либо устанавливали или изменяли модули или конфигурацию серверной части для Terraform,
повторно запустите эту команду, чтобы повторно инициализировать рабочий каталог. Если вы забудете, другие
команды обнаружат это и при необходимости напомнят вам сделать это.
Обратите внимание, что вместе с файлом versions.tf
была создана папка с именем .terraform
. В этой папке хранятся установленные поставщики для использования в последующих процессах Terraform.
Теперь, когда предварительные условия для запуска Terraform завершены, можно создать определения ресурсов AWS. Добавьте файл рядом с файлом versions.tf
с именем variables.tf
.
Этот файл будет содержать определение одной переменной, которая будет передана в командной строке позже при масштабировании ресурсов. Добавьте в файл variables.tf
следующее:
переменная "app_count" {
тип = число
по умолчанию = 1
Сохраните и закройте файл. Создайте еще один файл с именем main.tf в том же каталоге, что и Variables.tf, где будут храниться определения ресурсов AWS. Начните с добавления блока данных для зон доступности AWS, таких как:
данные "aws_availability_zones" "доступные_зоны" {
состояние = "доступно"
Этот блок захватит зоны доступности, доступные для вашей учетной записи. Они будут использоваться для других определений ресурсов, и, чтобы сохранить небольшую площадь для этого руководства, будут использоваться только две зоны доступности.
При развертывании задач в кластере AWS ECS Fargate рекомендуется использовать несколько зон доступности, так как Fargate обеспечит высокую доступность за счет максимально равномерного распределения задач одного типа между зонами доступности.
Затем добавьте определение ресурса в main.tf
с помощью этого кода:
ресурс "aws_vpc" "по умолчанию" {
cidr_block = "10.32.0.0/16"
Ресурсы, которые будут созданы, будут определены внутри VPC. AWS VPC обеспечивает логическую изоляцию ресурсов друг от друга.
Все ресурсы, которые будут определены, будут находиться в одном VPC. Далее будут созданы четыре подсети. Две из них будут общедоступными, а две другие — частными, причем в каждой зоне доступности будет по одной из них.
Добавьте определения ресурсов подсети в main.tf
:
ресурс "aws_subnet" "общедоступный" {
количество = 2
cidr_block = cidrsubnet(aws_vpc.default.cidr_block, 8, 2 + count.index)
зона_доступности = data.aws_зоны_доступности.доступные_зоны.названия[количество.индекс]
vpc_id = aws_vpc.default.id
map_public_ip_on_launch = истина
ресурс "aws_subnet" "частный" {
количество = 2
cidr_block = cidrsubnet(aws_vpc.default.cidr_block, 8, count.index)
зона_доступности = data.aws_зоны_доступности.доступные_зоны.названия[количество.индекс]
vpc_id = aws_vpc.default.id
То, что должно быть общедоступным, например балансировщик нагрузки, будет добавлено в общедоступную подсеть. В частную подсеть будут добавлены другие объекты, которым не требуется прямой обмен данными с Интернетом, например служба Hello World, определенная внутри кластера ECS.
Определите шесть сетевых ресурсов со следующими блоками HCL:
ресурс "aws_internet_gateway" "шлюз" {
vpc_id = aws_vpc.default.id
ресурс "aws_route" "internet_access" {
route_table_id = aws_vpc.default.main_route_table_id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gateway.id
ресурс "aws_eip" "шлюз" {
количество = 2
vpc = правда
depend_on = [aws_internet_gateway.gateway]
ресурс "aws_nat_gateway" "шлюз" {
количество = 2
subnet_id = элемент (aws_subnet.public.*.id, count.index)
location_id = элемент(aws_eip.gateway.*.id, count.index)
ресурс "aws_route_table" "частный" {
количество = 2
vpc_id = aws_vpc.default.id
маршрут {
cidr_block = "0.0.0.0/0"
nat_gateway_id = элемент (aws_nat_gateway.gateway.*.id, count.index)
ресурс "aws_route_table_association" "частный" {
количество = 2
subnet_id = элемент (aws_subnet.private.*.id, count.index)
route_table_id = элемент (aws_route_table.private.*.id, count.index)
Эти шесть ресурсов управляют сетью и связью с Интернетом и из Интернета за пределами VPC. Например, интернет-шлюз — это то, что вообще обеспечивает связь между VPC и Интернетом.
Шлюз NAT позволяет ресурсам внутри VPC обмениваться данными с Интернетом, но предотвращает связь с VPC из внешних источников. Все это связано с ассоциацией таблицы маршрутов, где частная таблица маршрутов, включающая шлюз NAT, добавляется к частным подсетям, определенным ранее.
Затем необходимо будет добавить группы безопасности, чтобы разрешать или отклонять трафик более точным образом, как от балансировщика нагрузки, так и от службы приложений. Добавьте ресурс группы безопасности балансировщика нагрузки в main.tf
примерно так:
ресурс "aws_security_group" "фунт" {
имя = "пример-alb-группа безопасности"
vpc_id = aws_vpc.default.id
вход {
протокол = "TCP"
от_порт = 80
to_port = 80
cidr_blocks = ["0.0.0.0/0"]
выход {
из_порта = 0
to_port = 0
протокол = "-1"
cidr_blocks = ["0.0.0.0/0"]
Группа безопасности балансировщика нагрузки будет разрешать трафик к балансировщику нагрузки только через порт 80, как указано в блоке "ingress" в блоке ресурсов.
Трафик от балансировщика нагрузки будет разрешен в любом месте на любом порту с любым протоколом с настройками в блоке «выход». Затем добавьте три ресурса для балансировщика нагрузки со следующим кодом:
ресурс "aws_lb" "по умолчанию" {
имя = "пример-фунт"
подсети = aws_subnet.public.*.id
security_groups = [aws_security_group.lb.id]
ресурс "aws_lb_target_group" "hello_world" {
имя = "пример-целевая-группа"
порт = 80
протокол = "HTTP"
vpc_id = aws_vpc.default.id
target_type = "IP"
ресурс "aws_lb_listener" "hello_world" {
load_balancer_arn = aws_lb.default.id
порт = "80"
протокол = "HTTP"
default_action {
target_group_arn = aws_lb_target_group.hello_world.id
тип = "вперед"
Первый блок определяет сам балансировщик нагрузки и присоединяет его к общедоступной подсети в каждой зоне доступности с группой безопасности балансировщика нагрузки. Целевая группа при добавлении в прослушиватель балансировщика нагрузки сообщает балансировщику нагрузки перенаправлять входящий трафик через порт 80 туда, где подключен балансировщик нагрузки.
В этом случае это будет служба ECS, определенная позже. Определите кластер ECS с помощью блока ниже:
ресурс "aws_ecs_task_definition" "hello_world" {
семья = "привет-мир-приложение"
network_mode = "awsvpc"
требует_совместимости = ["ФАРГАТ"]
процессор = 1024
память = 2048
container_definitions = <<ОПРЕДЕЛЕНИЕ
"image": "heroku/nodejs-hello-world",
"процессор": 1024,
"память": 2048,
"имя": "привет-мир-приложение",
"сетевой режим": "awsvpc",
"сопоставления портов": [
"контейнерный порт": 3000,
"хостПорт": 3000
ОПРЕДЕЛЕНИЕ
Определение задачи определяет, как должно запускаться приложение hello world. Здесь указано, что платформа будет Fargate, а не EC2, поэтому управление экземплярами EC2 не требуется.
Это означает, что необходимо указать ЦП и память для выполняемой задачи. Используемое изображение представляет собой простой API, который возвращает «Hello World!» и доступен в виде общедоступного образа Docker.
Контейнер Docker предоставляет API на порту 3000, поэтому он указан как порты хоста и контейнера. Для сетевого режима установлено значение «awsvpc», которое сообщает AWS, что при выполнении задаче должен быть назначен эластичный сетевой интерфейс и частный IP-адрес.
Далее создайте группу безопасности для службы ECS со следующим HCL:
ресурс "aws_security_group" "hello_world_task" {
name = "пример-задача-группа безопасности"
vpc_id = aws_vpc.default.id
вход {
протокол = "TCP"
от_порт = 3000
to_port = 3000
security_groups = [aws_security_group.lb.id]
выход {
протокол = "-1"
из_порта = 0
to_port = 0
cidr_blocks = ["0.0.0.0/0"]
Группа безопасности для задачи приложения указывает, что ее следует добавить в VPC по умолчанию и разрешить трафик только через TCP на порт 3000 приложения.
Параметры входа также включают группу безопасности балансировщика нагрузки, поскольку это разрешает трафик от сетевых интерфейсов, которые используются с этой группой безопасности. Это разрешает весь исходящий трафик из любого протокола, как показано в настройках выхода.
Наконец, добавьте службу ECS и блоки кластера, как показано ниже:
ресурс "aws_ecs_cluster" "основной" {
имя = "пример-кластер"
ресурс "aws_ecs_service" "hello_world" {
имя = "привет-мир-сервис"
кластер = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.hello_world.arn
требуемый_счет = var.app_count
launch_type = "ФАРГЕЙТ"
конфигурация сети {
security_groups = [aws_security_group.hello_world_task.id]
подсети = aws_subnet.private.*.id
load_balancer {
target_group_arn = aws_lb_target_group.hello_world.id
container_name = "Привет-мир-приложение"
контейнер_порт = 3000
depend_on = [aws_lb_listener.hello_world]
Служба ECS указывает, сколько задач приложения должно быть запущено со свойствами task_definition
и desired_count
в кластере. Тип запуска — Fargate, поэтому управление экземпляром EC2 не требуется.
Задачи будут выполняться в частной подсети, как указано в блоке network_configuration, и будут доступны из внешнего мира через балансировщик нагрузки, как указано в блоке load_balancer.
Наконец, сервис не должен создаваться до тех пор, пока не будет создан балансировщик нагрузки, поэтому прослушиватель балансировщика нагрузки включается в массив `depends_on
.
Остался последний шаг в настройке Terraform, чтобы упростить тестирование развернутых ресурсов. Вы будете знать, что все работает правильно, если приложение, работающее в ECS, возвращает пустую страницу с текстом «Hello World!».
Чтобы получить доступ к службе, требуется URL-адрес балансировщика нагрузки. Вы можете найти его на панели инструментов AWS, но Terraform может упростить его. Добавьте файл с именем outputs.tf
в тот же каталог, что и main.tf
, затем добавьте следующий код:
вывод "load_balancer_ip" {
значение = aws_lb.default.dns_name
Этот файл будет включен в конфигурацию Terraform при запуске команд, а выходные данные будут указывать Terraform на печать URL-адреса балансировщика нагрузки после применения плана.
Когда вся конфигурация Terraform завершена, запустите команду terraform plan -out="tfplan"
, чтобы увидеть, что будет создано при применении конфигурации. Это должно выглядеть примерно так:
План выполнения был создан и показан ниже.
Действия ресурсов обозначаются следующими символами:
- создать
Terraform выполнит следующие действия:
aws_ecs_cluster.main будет создан
- ресурс "aws_ecs_cluster" "основной" {
- arn = (известно после применения)
- id = (известно после применения)
- main_route_table_id = (известно после применения)
- owner_id = (известно после применения)
План: 23 добавить, 0 изменить, 0 уничтожить.
Изменения в выходах:
- load_balancer_ip = (известно после применения)
Этот план был сохранен в: tfplan
Чтобы выполнить именно эти действия, выполните следующую команду:
terraform применить "tfplan"
Если вас устраивает план, примените конфигурацию к AWS, запустив terraform apply "tfplan"
. Этот шаг, скорее всего, займет несколько минут. После того, как Terraform применит план, нижняя часть вывода должна выглядеть так, как показано ниже:
Заявка завершена! Ресурсы: добавлено 23, изменено 0, уничтожено 0.
Состояние вашей инфраструктуры было сохранено в пути
ниже. Это состояние необходимо для изменения и уничтожения вашего
инфраструктуры, так что держите ее в безопасности. Для проверки полного состояния
используйте команду terraform show
.
Путь состояния: terraform.tfstate
Выходы:
load_balancer_ip = "пример-lb-1284172108.us-east-2.elb.amazonaws.com"
Обратите внимание, что IP-адрес балансировщика нагрузки был напечатан последним, потому что выходные данные были определены как часть конфигурации. Скопируйте URL-адрес и вставьте его в браузер. Вы должны увидеть текст «Hello World!» печатается в левом верхнем углу страницы.
Отличная работа! Теперь у вас есть общедоступное приложение, созданное Terraform и работающее на AWS ECS.
Используйте Terraform для изменения существующих ресурсов AWS
Что происходит, когда ожидается увеличение трафика для приложения? Может быть полезно иметь возможность горизонтального масштабирования приложения без простоев. По этой причине переменная app_count
включена в файл variables.tf
в конфигурации.
Ресурс службы ECS задает для свойства desired_count
значение переменной app_count
, поэтому все, что вам нужно сделать, это установить большее число и повторно применить конфигурацию для горизонтального масштабирования приложения.
Сначала попробуйте спланировать изменение с помощью следующей команды:
план терраформирования -var app_count=3 -out=tfplan
Самая важная часть вывода находится внизу и должна выглядеть так:
План выполнения был создан и показан ниже.
Действия ресурсов обозначаются следующими символами:
~ обновление на месте
Terraform выполнит следующие действия:
aws_ecs_service.hello_world будет обновляться на месте
~ ресурс "aws_ecs_service" "hello_world" {
~ требуемый_счет = 1 -> 3
id = "arn:aws:ecs:us-east-2:914808004132:service/example-ecs-cluster/hello-world-service"
имя = "привет-мир-сервис"
теги = {}
(скрыты 12 неизменных атрибутов)
(скрыты 3 неизменных блока)
План: 0 добавить, 1 изменить, 0 уничтожить.
Этот план был сохранен в: tfplan
Чтобы выполнить именно эти действия, выполните следующую команду:
terraform применить "tfplan"
Применение этого плана увеличит количество контейнеров приложений до трех, что увеличит емкость. Подайте заявку на план с помощью команды terraform apply "tfplan"
.
Выходные данные плана должны показывать, что был изменен только сервисный ресурс ECS, и выглядеть примерно так, как показано ниже:
aws_ecs_service.hello_world: Изменение... [id=arn:aws:ecs:us-east-2:914808004132:service/example-ecs-cluster/hello-world-service]
aws_ecs_service.hello_world: Изменения завершены через 1 с [id=arn:aws:ecs:us-east-2:914808004132:service/example-ecs-cluster/hello-world-service]
Заявка завершена! Ресурсы: 0 добавлено, 1 изменено, 0 уничтожено.
Состояние вашей инфраструктуры было сохранено в пути
ниже. Это состояние необходимо для изменения и уничтожения вашего
инфраструктуры, так что держите ее в безопасности. Для проверки полного состояния
используйте команду terraform show
.
Путь состояния: terraform.tfstate
Выходы:
load_balancer_ip = "пример-lb-1448833153.us-east-2.elb.amazonaws.com"
Если вы хотите подтвердить, что масштабирование завершено, не стесняйтесь перейти на панель инструментов AWS ECS, а затем выбрать кластер с именем «example-ecs-cluster».
Обратите внимание, что «Количество запущенных задач» должно быть установлено на «3 Fargate, 0 EC2». Теперь ваше приложение масштабируется по горизонтали, чтобы обрабатывать больше трафика!
Когда вы будете готовы, вы должны очистить ресурсы, используемые в этом руководстве. Чтобы увидеть, что будет уничтожено, не предпринимая пока никаких действий, запустите команду «terraform plan -destroy -out=tfplan». Вывод должен выглядеть примерно так:
План выполнения был создан и показан ниже.
Действия ресурсов обозначаются следующими символами:
- разрушать
Terraform выполнит следующие действия:
aws_ecs_cluster.main будет уничтожен
- ресурс "aws_ecs_cluster" "основной" {
- arn = "arn:aws:ecs:us-east-2:914808004132:cluster/example-ecs-cluster" -> null
- capacity_providers = [] -> ноль
- owner_id = "914808004132" -> ноль
- теги = {} -> ноль
План: 0 добавить, 0 изменить, 23 уничтожить.
Изменения в выходах:
- load_balancer_ip = "example-lb-1448833153.us-east-2.elb.amazonaws.com" -> null
Этот план был сохранен в: tfplan
Чтобы выполнить именно эти действия, выполните следующую команду:
terraform применить "tfplan"
Запустите команду terraform apply "tfplan"
, когда будете готовы все разрушить.
Этот шаг, скорее всего, займет несколько минут, но по завершении последняя строка вывода должна сигнализировать о том, что все было уничтожено, как и ожидалось, и выглядеть так:
Заявка завершена! Ресурсы: 0 добавлено, 0 изменено, 23 уничтожено.
Узнайте больше о том, как Architect может развернуть ваше приложение на AWS и в других местах
Terraform может легко развернуть ваше приложение на AWS после написания шаблонов и определения всех ресурсов. Но что произойдет, когда появится следующая лучшая вещь? Конечно, Terraform сможет справиться с развертыванием вашего приложения на другой платформе, но это потребует большего обслуживания и, вероятно, полного переписывания всех шаблонов Terraform.
С Architect ваше приложение нужно определить только один раз, чтобы его можно было развернуть где угодно. Узнайте больше о развертывании компонентов Architect в наших документах и попробуйте!
Если у вас есть какие-либо вопросы или комментарии, не стесняйтесь обращаться к команде в Твиттере @architect_team.
Также опубликовано [здесь] (https://www.architect.io/blog/2021-03-30/create-and-manage-an-aws-ecs-cluster-with-terraform/).
Оригинал