본문 바로가기!

Terraform

[테라폼] ECS배포 및 revision관리

728x90
반응형

1.  Amazon ECS 란?

  • ECS(Elastic Container Service)는 컨테이너화된 애플리케이션을 쉽게 배포, 관리, 스케일링할 수 있도록 도와주는 완전 관리형 컨테이너 오케스트레이션 서비스
  • API호출을 사용해서 컨테이너 기반의 애플리케이션을 시작 중지 가능
  • ECS의 인프라는 Fargate(서버리스), EC2, 외부(External) 인스턴스로 호스팅에 대한 레이어를 선택하여 생성 가능

 

2.  ECS의 구성 요소

2-1) Cluster 

  • 작업 또는 서비스의 논리적 그룹으로 Fargate, EC2, External 선택하여 사용

2-2) Task Definition

  • 애플리케이션을 구성하기위한 텍스트(JSON)를 정의하는 것
    • 시작유형(Fargate, EC2, External)
    • 컨테이너 이미지 
    • CPU/메모리 리소스 할당
    • 데이터 볼륨
    • 포트
  • Task Definition을 통해 Task를 실행하는 방법과 Service를 생성하는 방법 2가지가 존재
    • Task Definition으로 직접 실행된 Task의 경우 처음 실행되고나면 이후 관리되지 않음

2-3) Task

  • Task Definition에서 정의된 설정으로 Cluster의 EC2나 Fargate에 배포하는 것
  • Fargate의 경우 예약작업이 가능하며 Batch서버와 같이 (매출데이터 집계, 사용자로그 수집 후 유저군 업데이트, 상품데이터 수집 후 검색 서버에 색인 등) 여러개의 작업 실행 후 종료가 가능하기에 Batch인스턴스를 따로 띄울 필요X

 

2-4) Service

  • 클러스터에서 지정된 수의 작업을 동시에 실행하고 관리 가능한 구성으로 Service에는 Task가 포함되어 있으며, Auto Scaling과 Load Balancing 또한 관리 가능

 

 

3.  ECS Fargate 배포 (w. Terraform)

3-0) 사전 준비 작업 

1. ECR Repository Image Push

# ECR Repository Image Push

# ECR에 Image Push를 위한 login
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin {AWS AccountID}.dkr.ecr.ap-northeast-2.amazonaws.com

# dockerfile 생성 
cat > ./dockerfile << EOF
FROM nginx:1.21.1
COPY ./index.html /usr/share/nginx/html/index.html
EXPOSE 80
EOF

cat > ./index.html << EOF
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Nginx Page</title>
</head>
<body>
    <h1>Hello, this is my Nginx page!</h1>
    <p>first</p>
</body>
</html>
EOF

# docker file을 통한 Image 생성
docker build -t nginx:local-build .

# ECR로 Image Push
docker tag nginx:local-build {AWS AccountID}.dkr.ecr.ap-northeast-2.amazonaws.com/{RepoName}:0.1
docker push {AWS AccountID}.dkr.ecr.ap-northeast-2.amazonaws.com/{RepoName}:0.1

 

 

2. task ECR에서 이미지를 다운받을 있는 권한 생성

# task excution role
data "aws_iam_policy_document" "task_excution_role_policy" {
  statement {
    sid     = ""
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ecs-tasks.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "task_excution_role" {
  name               = "${local.company}-${local.env}-TaskExcutionRole"
  assume_role_policy = data.aws_iam_policy_document.task_excution_role_policy.json
  tags               = { Name = "${local.company}-${local.env}-TaskExcutionRole" }
}

resource "aws_iam_role_policy_attachment" "taskexcutionrole_policy_attach" {
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
  role       = aws_iam_role.task_excution_role.name
}


# task role
data "aws_iam_policy_document" "task_role_policy" {
  statement {
    sid     = ""
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ecs-tasks.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "task_role" {
  name               = "${local.company}-${local.env}-Task-Role"
  assume_role_policy = data.aws_iam_policy_document.task_role_policy.json
  tags               = { Name = "${local.company}-${local.env}-Task-Role" }
}

resource "aws_iam_role_policy_attachment" "task_policy_attach" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
  role       = aws_iam_role.task_role.name
}

 

3. (옵션) LB생성

- Service생성시 public IP를 붙여 서비스 접근 가능하지만 해당 문서에서는 LB를 따로 생성하여 Service 구축 

- (해당 과정 설명 생략)

 

3-1) ECS Cluster 생성

resource "aws_ecs_cluster" "ecs_cluster" {
  name = "${local.company}-${local.env}-ecs-clstr-apne2"

  setting {
    name  = "containerInsights"
    value = "enabled"
  }
}
  • setting -  CloudWatch Container Insights를 활성화

> 생성 확인

 

 

3-2) Task Definition 생성

resource "aws_ecs_task_definition" "web" {
  family                   = "${local.company}-${local.env}-webtest"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  cpu                      = 512
  memory                   = 1024
  execution_role_arn       = aws_iam_role.task_excution_role.arn
  task_role_arn            = aws_iam_role.task_role.arn
  skip_destroy             = true

  runtime_platform {
    operating_system_family = "LINUX"
    cpu_architecture        = "X86_64"
  }

  container_definitions = <<TASK_DEFINITION
[
  { 
    "name": "web", 
    "image": "128079576215.dkr.ecr.ap-northeast-2.amazonaws.com/{ECR Repo Name}:0.2", 
    "cpu": 0, 
    "portMappings": [ 
      { 
        "name": "web-80-tcp", 
        "containerPort": 80, 
        "hostPort": 80, 
        "protocol": "tcp", 
        "appProtocol": "http" 
      } 
    ],
    "essential": true, 
    "environment": [], 
    "environmentFiles": [], 
    "mountPoints": [], 
    "volumesFrom": [], 
    "ulimits": [], 
    "logConfiguration": { 
      "logDriver": "awslogs", 
      "options": { 
        "awslogs-create-group": "true", 
        "awslogs-group": "/ecs/${local.company}-${local.env}-web", 
        "awslogs-region": "ap-northeast-2", 
        "awslogs-stream-prefix": "ecs" 
      } 
    } 
  } 
]
  TASK_DEFINITION

  tags = {
    Name = "${local.company}-${local.env}-web"
  }
}

 

> 생성 확인

 

 

3-3) Service 생성

resource "aws_ecs_service" "web" {
  name            = "${local.company}-${local.env}-svc-web"
  cluster         = aws_ecs_cluster.ecs_cluster.id
  task_definition = aws_ecs_task_definition.web.arn
  desired_count   = 2
  launch_type     = "FARGATE"

  network_configuration {
    security_groups  = [aws_security_group.web_sg.id]
    subnets          = aws_subnet.pri_subnet[*].id
    assign_public_ip = "false"
  }

  load_balancer {
    target_group_arn = aws_lb_target_group.web_target_group.arn
    container_name   = "web"
    container_port   = "80"
  }

  tags = {
    Name = "${local.company}-${local.env}-svc-web"
  }
}

 

> 생성 확인 및 LB를 통한 서비스 확인

 

 

4) Terraform을 통한 revision관리

테스트 시 문제점1)

  • 문제점: 이전 Revision 삭제 
    • Terraform을 통해 Task Definition를 관리하게 되면 latest revision만 남고 이전 revision들이 지워지게됨.
    • AWS에서 ECS Task Definition의 이전 revision들만 지워지는 것처럼 보이지만 실제론 Task Definition이 지워졌다 다시 생김. (Task Definition이 지워지고 다시 생성되는데 revision 이름은 예전 revision 정보가 있는지 1부터 시작되지 않음.. 의문..)
  • 해결 방법: skip destroy 옵션을 통해 이전 revision삭제 방지  

 

테스트 시 문제점2)

  • 문제점 : Task Definition을 통해 Service 생성 시 lastest revision만 가져와 Service 동작
    • Task Definition의 skip_destroy 옵션을 통해 삭제 방지로 이전 revision들이 삭제가 되지 않았지만 state 파일에는 최신 revision의 정보만 남아있기에 Service 생성 시 최신 revision으로 서비스 동작
  • 해결 방법: Service 생성시 특정 버전 명시를 통해 Service 실행

 

728x90
반응형