Terraform을 활용한 ECS와 ECR 개념정리

Process

Terraform Packer가 AMI를 빌드하는 것과 비슷하게 도커를 사용해서 도커 이미지를 빌드할 수 있습니다.

해당 이미지는 도커 엔진이 설치된 모든 리눅스 호스트에서 실행 가능합니다.

ECR

provider "aws" {
  region = var.AWS_REGION
}

resource "aws_ecr_repository" "myapp" {
  name = "myapp"
}

output "myapp-repository-URL" {
  value = aws_ecr_repository.myapp.repository_url
}
docker build -t {AWS account ID}.dkr.ecr.{Region Code}.amazonaws.com/{REPOSITORY}:{TAG} .

ECR에 엑세스하기 위해선 Docker 로그인이 필요합니다.

ECR 리포지토리에 있는 Docker 이미지에 대한 보안 액세스 및 관리가 Docker CLI의 인증 메커니즘을 사용하여 보장되기 때문입니다.

따라서 aws ecr get-login-password 을 통해 임시 토큰(credential)을 사용하여 임시 자격증명을 생성하고 토큰이 Docker CLI에서 AWS 계정에 대해 인증하는 데 사용되어 Docker 클라이언트가 특정 ECR 리포지토리에 액세스할 수 있는 권한이 있는지 확인합니다.

aws ecr get-login-password \\
      --region {Region Code} \\
  | docker login
      --username AWS \\
      --password-stdin {AWS account ID}.dkr.ecr.{Region Code}.amazonaws.com
docker push {AWS account ID}.dkr.ecr.{Region Code}.amazonaws.com/{REPOSITORY}:{TAG}

ECS

ECR로 업로드된 이미지가 있다면 ECS로 시작할 수 있습니다.

아마존에서 유지 관리되는 AMI에는 ECS 에이전트가 포함되어 있습니다. ECS가 온라인되면 클러스터에서 작업과 서비스를 시작할 수 있습니다.

클러스터는 단순히 ECS 에이전트가 있는 EC2 인스턴스 그룹으로 이해할 수 있고 이를 ECS를 통해 관리하는 것입니다.

ECS 태스크 정의

도커 앱을 시작하기 전에 태스크 정의가 필요하며 클러스터에서 실행할 도커 컨테이너를 정의해야합니다.

태스크는 태스크 정의의 설정 값으로 만들어지며 태스크는 실행된 Cluster 하위 인스턴스 or Fargate 컨테이너로 관리됩니다.

하나의 컨테이너가 어떻게 실행되어야하는지를 지정할 수 있습니다.

# app.json.tpl
[
  {
    "essential": true,
    "memory": 256,
    "name": "myapp",
    "cpu": 256,
    "image": "${REPOSITORY_URL}:1",
    "workingDirectory": "/app",
    "command": ["npm", "start"],
    "portMappings": [
        {
            "containerPort": 3000,
            "hostPort": 3000
        }
    ]
  }
]
resource "aws_ecs_task_definition" "myapp-task-definition" {
  family                = "myapp"
  container_definitions = templatefile("templates/app.json.tpl", {
    REPOSITORY_URL = replace(aws_ecr_repository.myapp.repository_url, "https://", "")
  })
}

ECS 서비스 정의

서비스 정의는 태스크 정의를 기반으로 만들어진 특정 양의 컨테이너를 실행시키는 방식을 정의합니다. 이 외에도 실행된 컨테이너가 어떻게 연결되는지를 정의할 수 있습니다.

설정값

컨테이너들이 어떤 환경에서 실행되어야하는지를 지정할 수 있습니다.

resource "aws_launch_configuration" "ecs-example-launchconfig" {
  name_prefix          = "ecs-launchconfig"
  image_id             = var.ECS_AMIS[var.AWS_REGION]
  instance_type        = var.ECS_INSTANCE_TYPE
  key_name             = aws_key_pair.mykeypair.key_name
  iam_instance_profile = aws_iam_instance_profile.ecs-ec2-role.id
  security_groups      = [aws_security_group.ecs-securitygroup.id]
  user_data            = "#!/bin/bash\\necho 'ECS_CLUSTER=example-cluster' > /etc/ecs/ecs.config\\nstart ecs"
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_autoscaling_group" "ecs-example-autoscaling" {
  name                 = "ecs-test-autoscaling"
  vpc_zone_identifier  = [aws_subnet.main-public-1.id, aws_subnet.main-public-2.id]
  launch_configuration = aws_launch_configuration.ecs-example-launchconfig.name
  min_size             = 1
  max_size             = 1
  tag {
    key                 = "Name"
    value               = "ecs-ec2-container"
    propagate_at_launch = true
  }
}
ssh -i mykey {public_ip} -l ec2-user

Service

클러스터에

회고

ECS 클러스터는 만들어지고 정상적으로 실행은 되는데 접근이 안됐다.

이것도 마찬가지로 직접 옵션을 살펴보고 콘솔로 만들고나니 어떤 옵션이 필요한지 이해하게 되었고 각 태스크, 서비스가 무슨 옵션을 설정하는 것인지 이해가 되었다.

이후에 다시 정리해보는게 좋을거같다