AWS ECS 개발기 2
NOWIL
by NOWIL
4 min read

Categories

Tags

Series

  1. aws-ecs-개발기 - intro
  2. aws-ecs-개발기 - 1
  3. aws-ecs-개발기 - 2
  4. aws-ecs-개발기 - 3

클러스터 생성하기

그럼 이제 컨테이너를 실행할 ECS 클러스터를 생성해보죠.

(2023년부터 AWS의 ECS 웹콘솔이 새로운 디자인으로 변경되었습니다.)

EC2 키페어 생성

우선 ECS 인스턴스를 EC2로 할 예정이기 때문에 EC2 키페어를 먼저 생성하겠습니다.

EC2 - 네트워크 및 보안 - 키페어로 들어갑니다.

Untitled

Untitled

IAM 설정

ecs 정책 생성

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "ecs:ListServicesByNamespace",
        "ecs:DiscoverPollEndpoint",
        "ecs:PutAccountSettingDefault",
        "ecs:CreateCluster",
        "ecs:DescribeTaskDefinition",
        "ecs:PutAccountSetting",
        "ecs:ListServices",
        "ecs:CreateCapacityProvider",
        "ecs:DeregisterTaskDefinition",
        "ecs:ListAccountSettings",
        "ecs:DeleteAccountSetting",
        "ecs:ListTaskDefinitionFamilies",
        "ecs:RegisterTaskDefinition",
        "ecs:ListTaskDefinitions",
        "ecs:CreateTaskSet",
        "ecs:ListClusters"
      ],
      "Resource": "*"
    },
    {
      "Sid": "VisualEditor1",
      "Effect": "Allow",
      "Action": "ecs:*",
      "Resource": [
        "arn:aws:ecs:*:{account_id}:cluster/*",
        "arn:aws:ecs:*:{account_id}:task/*/*",
        "arn:aws:ecs:*:{account_id}:capacity-provider/*",
        "arn:aws:ecs:*:{account_id}:task-set/*/*/*",
        "arn:aws:ecs:*:{account_id}:container-instance/*/*",
        "arn:aws:ecs:*:{account_id}:service/*/*",
        "arn:aws:ecs:*:{account_id}:task-definition/*:*"
      ]
    }
  ]
}

신뢰 정책 수정

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Untitled

Untitled

Untitled

Untitled

Untitled

ECS 클러스터 생성

Untitled

Untitled

EC2의 인스턴스 유형은 아래 링크를 참고해주세요. 저는 간단한 샘플 테스트용 이기 때문에 t2.nano를 사용하였습니다.

https://aws.amazon.com/ko/ec2/instance-types/

Untitled

특히 인스턴스 별 vCPU와 메모리에 따라 추후 Task의 사용할 수 있는 vCPU와 메모리가 달라지므로 매우 주의해야 합니다.

Untitled

Untitled

Untitled

Task(작업) 정의하기

ECS에서 Task는 Docker 컨테이너 설정을 위해 사용됩니다.

어떤 Docker 이미지를 가지고 Docker 컨테이너를 생성하는지를 Task에서 정의할 수 있고, 하나의 Task에 여러 개의 Docker 컨테이너 설정을 해줄 수 있습니다.

  • 시작 유형 호환성 선택(Fargate EC2 External)
  • 사용할 컨테이너 이미지 설정
  • 애플리케이션을 위해 개방할 포트 설정
  • CPU/메모리 리소스 할당 설정
  • 작업의 컨테이너에 사용할 데이터 볼륨 설정

Untitled

Untitled

Untitled

Dynamic Port Mapping 하기

Untitled

배포가 될 때마다 테스크가 수정되며 reverse-proxy-container의 host port는 계속해서 바뀔 수 있습니다.

Untitled

따라서 reverse-proxy-container의 host port는 0으로 설정하여 모든 포트가 가능하도록 해줍니다.

Untitled

그리고 ECS 클러스터를 통해 생성된 EC2 인스턴스의 보안 그룹의 인바운드 규칙에 모든 TCP (0 - 65535)를 추가해줍니다.

Untitled

테스크의 크기는 위에서 선택한 EC2의 vCPU와 메모리 입력하면 됩니다.

Untitled

서비스 생성하기

대상 그룹 생성하기

Untitled

Untitled

Untitled

로드 밸런서 생성하기

Untitled

Application Load Balancer 선택

Untitled

로드밸런서 보안 그룹 수정

Untitled

ECS 서비스 생성하기

Untitled

Untitled

최소 실행 작업 비율과 최대 실행 작업 비율을 각각 0%와 100%로 해줘야 합니다. 롤링 업데이트 유형으로 배포가 되면 현재 실행 중인 컨테이너 버전을 최신 버전으로 바꾸는데 만약 최소 실행 작업 비율을 100%, 최대 실행 작업 비율을 200%으로 하게될 경우 도커의 port가 중복이 되기 때문에 배포가 진행이 안되며 에러가 발생합니다. 참고 : https://stackoverflow.com/questions/46018883/best-practice-for-updating-aws-ecs-service-tasks

Untitled

서비스를 실행하면 배포가 안되는 것을 확인할 수 있습니다. 왜 그럴까요?

클러스터의 컨테이너 인스턴스, 클러스터를 생성할 때 선언한 EC2를 확인해보면 가용 메모리가 466mb인 것을 확인할 수 있습니다.

Untitled

하지만 우리가 테스크를 정의할 때 테스크의 메모리를 500mb로 설정하였죠. 따라서 우린 테스크 메모리를 466mb보다 작게 설정해야 합니다.

Untitled

Untitled

테스크의 메모리를 450mb로 수정 후 이전의 배포 중이던 테스크는 중지하고 ECS 서비스를 업데이트해보겠습니다.

Untitled

Untitled

Untitled

확인해보니 배포는 진행되지만 작업이 중단되었습니다.

Untitled

확인해보니 테스크 정의 중 컨테이너 정의에서 reverse-proxy-container와 example-app-container간의 순서를 정의와 링크를 하지 않았습니다. 이를 위해 테스크를 수정해보겠습니다.

Untitled

Untitled

Untitled

그리고 cloudwatch에서 로그를 확인하기 위해 Auto-configure CloudWatch Logs를 활성화하겠습니다.

Untitled

example-app-container의 포트 매핑도 수정하겠습니다.

Untitled

그리고 이전 단계와 똑같이 ECS 서비스를 업데이트했습니다.

이제 매우 정상적으로 작동하는 ECS 서비스를 확인할 수 있습니다!

Untitled

ECS 환경 변수 설정하기

한번 Load balancers의 DNS로 API를 요청해보겠습니다.

Untitled

localhost에서 실행한 컨테이너 앱에서 나왔던 저자 이름이 ECS에서 실행한 컨테이너 앱 상에서는 나오지 않았습니다. 저자의 이름은 환경변수로 설정하였는데 ECS 작업 정의 단계에서 환경변수를 설정하지 않았기에 당연히 저자의 이름은 나올 수가 없습니다.

ECS에서 환경 변수를 정의하는 방법으로는 크게 4가지가 있습니다.

  • ECS 작업 정의에 변수를 저장합니다.
  • 변수를 Amazon Simple Storage Service(Amazon S3) 버킷 내부의 environmentFiles 객체로 전달합니다.
  • AWS Systems Manager Parameter Store에 변수를 저장합니다.
  • AWS Secrets Manager 내부에 변수를 저장합니다.

출처 : https://repost.aws/knowledge-center/ecs-task-environment-variables

그 중에 첫번째는 추후 github actions등을 통해 배포하는 과정에서 어려움이 많습니다. 따라서 AWS Secrets Manager를 사용하거나 Amazon S3 버킷 내부의 environmentFiles를 사용하는 방법 중에서 이번엔 AWS Amazon S3 버킷 내부의 environmentFiles를 사용하겠습니다.

  • AWS Secrets Manager 사용

    AWS Secrets Manager 암호 생성

    Untitled Untitled

    IAM 권한 설정

    위에서 작업 정의를 위해 생성한 ecs-ec2-role 역할에 권한 정책을 추가하겠습니다.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["secretsmanager:GetSecretValue"],
          "Resource": ["arn:aws:secretsmanager:{region}:{aws_account_id}:{secret:secret_name}"]
        }
      ]
    }
    

    Untitled Untitled

    작업 정의의 새 개정 생성

    컨테이너 정의 후 서비스를 업데이트합니다. Untitled Untitled

AWS Amazon S3 버킷 생성 후 environmentFiles 저장

Untitled

버킷에 env 파일을 업로드하기 위해서는 파일 이름이 필수입니다.

IAM 권한 설정

environmentFiles을 저장한 버킷에서 object를 가져오기 위한 정책을 생성합니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:*"],
      "Resource": ["arn:aws:s3:::ecs-sample-env/*"],
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:ecs:ap-northeast-2:{account_id}:*"
        },
        "StringEquals": {
          "aws:SourceAccount": "{account_id}"
        }
      }
    }
  ]
}

Untitled

S3 버킷 정책 생성

environmentFiles은 서비스의 보안적으로 중요한 변수들을 저장한 파일입니다. 따라서 S3 객체로 업로드하여도 퍼블릭으로 접근하면 당연히 안됩니다. 이를 위해 특정 역할에서만 접근하고 일부 액션만 가능하도록 설정해야 합니다.

Untitled

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::{account_id}:role/{ecs_task_role}"
      },
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::ecs-sample-env/*"
    }
  ]
}

Untitled

참고 자료 : https://inpa.tistory.com/entry/AWS-📚-S3-버킷-생성-사용법-실전-구축

작업 정의의 새 개정 생성

해당 env 파일을 사용하는 example-app-container 컨테이너의 환경 파일에 S3 버킷에 저장한 environmentFile의 ARN을 입력합니다.

Untitled

ECS 서비스 업데이트

새로 생성된 작업 정의 버전으로 ECS 서비스를 업데이트합니다.

Untitled

Untitled

배포가 완료된 후 API를 호출해 보겠습니다.

Untitled

환경변수로 설정한 저자의 이름이 정상적으로 출력됩니다!

다음 장엔 GitHub를 소스 코드 리포지토리에서 GitHub Actions를 사용하여 Amazon ECS에 배포된 애플리케이션을 위한 CI/CD 파이프라인을 구축하는 방법을 살펴보겠습니다.