Мой первый опыт изучения Terraform и Amazon ECS + AWS Fargate

Привет всем!

Как у вас дела сегодня? Надеюсь, у вас все отлично. Мне очень хочется изучить Terraform, поэтому я пишу эту статью, чтобы задокументировать свой опыт и заметки.

Меня зовут Бервианто Лео Пратама. Я инженер-программист, который хочет узнать больше о мире DevOps. Я надеюсь, что вам понравится моя статья, а также дайте совет и прокомментируйте мой контент. Я не являюсь экспертом в мире DevOps, особенно IAC (Infrastructure as Code). Я считаю, что мне еще нужно узнать больше о DevOps.

Подготовка

Вам понадобится инструмент (Terraform), если вы хотите попробовать код. Вы можете скачать Terraform CLI здесь. В любом случае, моя версия Terraform CLI — 1.11.7.

Подготовьте пользователя

Поскольку я только изучаю и хочу узнать больше о Terraform и AWS. Пока что я использую наивысшие привилегии. Я использую AdministratorAccess. Пожалуйста, всегда используйте наименьшие привилегии для производственного использования.

Дополнительно

Вам может понадобиться использовать Terraform Cloud. Если вы используете Terraform Cloud, пожалуйста, воспользуйтесь этим руководством. Однако сейчас это не требуется.

Давайте начнем

TLDR о моей цели. В качестве сервиса я использую Nginx. Кроме того, я использую Amazon ECS Fargate и ALB (Application Load Balancer). В общем, я хочу получить доступ к своим сервисам с помощью Load Balancer и использовать Nginx для выборки.

1. Подготовьте main.tf и добавьте AWS в качестве провайдера.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}
Войдите в полноэкранный режим Выйдите из полноэкранного режима

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

2. Настройте нашего провайдера AWS

provider "aws" {
  alias  = "ap-southeast-1"
  region = "ap-southeast-1"
}
Войдите в полноэкранный режим Выйти из полноэкранного режима

Примечание: Пожалуйста, настройте желаемый регион. Я использую ap-southeast-1 (Сингапур).

3. Настройка сети

resource "aws_default_vpc" "my-personal-web" {
  provider = aws.ap-southeast-1

  tags = {
    env = "dev"
  }
}

resource "aws_default_subnet" "my-personal-web" {
  provider          = aws.ap-southeast-1
  availability_zone = "ap-southeast-1a"

  tags = {
    env = "dev"
  }
}

resource "aws_default_subnet" "my-personal-web-1" {
  provider          = aws.ap-southeast-1
  availability_zone = "ap-southeast-1b"


  tags = {
    env = "dev"
  }
}

resource "aws_security_group" "my-personal-web" {
  provider = aws.ap-southeast-1

  name        = "allow_http"
  description = "Allow HTTP inbound traffic"
  vpc_id      = aws_default_vpc.my-personal-web.id

  ingress {
    description = "Allow HTTP for all"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Примечание: Я использую vpc & подсеть по умолчанию и настроил новую группу безопасности, чтобы открыть только порт 80. Поскольку я буду использовать nginx в качестве службы. Вам нужно будет правильно настроить vpc & subnet для производственного использования.

4. Настройка балансировщика нагрузки

resource "aws_lb" "my-personal-web" {
  provider = aws.ap-southeast-1

  name               = "my-personal-web-lb-tf"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.my-personal-web.id]
  subnets            = [aws_default_subnet.my-personal-web.id, aws_default_subnet.my-personal-web-1.id]
  tags = {
    env = "dev"
  }
}


resource "aws_lb_target_group" "my-personal-web" {
  provider = aws.ap-southeast-1

  name        = "tf-my-personal-web-lb-tg"
  port        = 80
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_default_vpc.my-personal-web.id
}

resource "aws_lb_listener" "my-personal-web" {
  provider = aws.ap-southeast-1

  load_balancer_arn = aws_lb.my-personal-web.arn
  port              = "80"
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.my-personal-web.arn
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Примечание: Я просто использую порт 80. Возможно, для производственного использования вам понадобится 443.

5. Настройте Amazon ECS

resource "aws_ecs_cluster" "my-personal-web" {
  provider = aws.ap-southeast-1
  name     = "my-personal-web-api-cluster"
}

resource "aws_ecs_cluster_capacity_providers" "my-personal-web" {
  provider = aws.ap-southeast-1

  cluster_name = aws_ecs_cluster.my-personal-web.name

  capacity_providers = ["FARGATE"]
}

resource "aws_ecs_task_definition" "my-personal-web" {
  provider = aws.ap-southeast-1

  family                   = "service"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = 1024
  memory                   = 2048
  container_definitions = jsonencode([
    {
      name      = "my-personal-web-api"
      image     = "nginx"
      cpu       = 1024
      memory    = 2048
      essential = true
      portMappings = [
        {
          containerPort = 80
          hostPort      = 80
        }
      ]
    }
  ])
}

resource "aws_ecs_service" "my-personal-web" {
  provider = aws.ap-southeast-1

  name            = "my-personal-web"
  cluster         = aws_ecs_cluster.my-personal-web.id
  task_definition = aws_ecs_task_definition.my-personal-web.arn
  desired_count   = 2
  launch_type     = "FARGATE"

  network_configuration {
    subnets          = [aws_default_subnet.my-personal-web.id, aws_default_subnet.my-personal-web-1.id]
    security_groups  = [aws_security_group.my-personal-web.id]
    assign_public_ip = true
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.my-personal-web.arn
    container_name   = "my-personal-web-api"
    container_port   = 80
  }

  tags = {
    env = "dev"
  }
}
Войдите в полноэкранный режим Выход из полноэкранного режима

Полный код

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  alias  = "ap-southeast-1"
  region = "ap-southeast-1"
}

resource "aws_default_vpc" "my-personal-web" {
  provider = aws.ap-southeast-1

  tags = {
    env = "dev"
  }
}

resource "aws_default_subnet" "my-personal-web" {
  provider          = aws.ap-southeast-1
  availability_zone = "ap-southeast-1a"

  tags = {
    env = "dev"
  }
}

resource "aws_default_subnet" "my-personal-web-1" {
  provider          = aws.ap-southeast-1
  availability_zone = "ap-southeast-1b"


  tags = {
    env = "dev"
  }
}

resource "aws_security_group" "my-personal-web" {
  provider = aws.ap-southeast-1

  name        = "allow_http"
  description = "Allow HTTP inbound traffic"
  vpc_id      = aws_default_vpc.my-personal-web.id

  ingress {
    description = "Allow HTTP for all"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_lb" "my-personal-web" {
  provider = aws.ap-southeast-1

  name               = "my-personal-web-lb-tf"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.my-personal-web.id]
  subnets            = [aws_default_subnet.my-personal-web.id, aws_default_subnet.my-personal-web-1.id]
  tags = {
    env = "dev"
  }
}


resource "aws_lb_target_group" "my-personal-web" {
  provider = aws.ap-southeast-1

  name        = "tf-my-personal-web-lb-tg"
  port        = 80
  protocol    = "HTTP"
  target_type = "ip"
  vpc_id      = aws_default_vpc.my-personal-web.id
}

resource "aws_lb_listener" "my-personal-web" {
  provider = aws.ap-southeast-1

  load_balancer_arn = aws_lb.my-personal-web.arn
  port              = "80"
  protocol          = "HTTP"
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.my-personal-web.arn
  }
}


resource "aws_ecs_cluster" "my-personal-web" {
  provider = aws.ap-southeast-1
  name     = "my-personal-web-api-cluster"
}

resource "aws_ecs_cluster_capacity_providers" "my-personal-web" {
  provider = aws.ap-southeast-1

  cluster_name = aws_ecs_cluster.my-personal-web.name

  capacity_providers = ["FARGATE"]
}

resource "aws_ecs_task_definition" "my-personal-web" {
  provider = aws.ap-southeast-1

  family                   = "service"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = 1024
  memory                   = 2048
  container_definitions = jsonencode([
    {
      name      = "my-personal-web-api"
      image     = "nginx"
      cpu       = 1024
      memory    = 2048
      essential = true
      portMappings = [
        {
          containerPort = 80
          hostPort      = 80
        }
      ]
    }
  ])
}

resource "aws_ecs_service" "my-personal-web" {
  provider = aws.ap-southeast-1

  name            = "my-personal-web"
  cluster         = aws_ecs_cluster.my-personal-web.id
  task_definition = aws_ecs_task_definition.my-personal-web.arn
  desired_count   = 2
  launch_type     = "FARGATE"

  network_configuration {
    subnets          = [aws_default_subnet.my-personal-web.id, aws_default_subnet.my-personal-web-1.id]
    security_groups  = [aws_security_group.my-personal-web.id]
    assign_public_ip = true
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.my-personal-web.arn
    container_name   = "my-personal-web-api"
    container_port   = 80
  }

  tags = {
    env = "dev"
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

berviantoleo / my-aws

Мой AWS IAC

Мой AWS IAC (Инфраструктура как код)

Мой AWS IAC.

Модуль ECS является частью поста

ЛИЦЕНЗИЯ

MIT

Посмотреть на GitHub

Давайте обеспечим его!

  1. Запустите terraform init.
  2. Запустите terraform plan. Вы можете проверить, что изменилось на этом шаге.
  3. Запустите terraform apply. Введите yes и Enter.
  4. Подождите, пока не завершится развертывание всех ресурсов. Это может занять много времени.
  5. После завершения и успешного завершения попробуйте получить доступ к нему с помощью вашего публичного балансировщика нагрузки. В качестве примера, вот мой.

Спасибо

Спасибо, что прочитали. Я очень ценю, когда вы читаете эту длинную (потому что код) статью.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *