AWS ECS 개발기 2
Series
클러스터 생성하기
그럼 이제 컨테이너를 실행할 ECS 클러스터를 생성해보죠.
(2023년부터 AWS의 ECS 웹콘솔이 새로운 디자인으로 변경되었습니다.)
EC2 키페어 생성
우선 ECS 인스턴스를 EC2로 할 예정이기 때문에 EC2 키페어를 먼저 생성하겠습니다.
EC2 - 네트워크 및 보안 - 키페어로 들어갑니다.
IAM 설정
ecs 정책 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
"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/*:*"
]
}
]
}
신뢰 정책 수정
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
ECS 클러스터 생성
EC2의 인스턴스 유형은 아래 링크를 참고해주세요. 저는 간단한 샘플 테스트용 이기 때문에 t2.nano를 사용하였습니다.
https://aws.amazon.com/ko/ec2/instance-types/
특히 인스턴스별 vCPU와 메모리에 따라 나중에 Task가 사용할 수 있는 vCPU와 메모리가 달라지므로 매우 주의해야 합니다.
Task(작업) 정의하기
ECS에서 Task는 Docker 컨테이너 설정을 위해 사용됩니다.
어떤 Docker 이미지를 가지고 Docker 컨테이너를 생성하는지를 Task에서 정의할 수 있고, 하나의 Task에 여러 개의 Docker 컨테이너 설정을 해줄 수 있습니다.
시작 유형 호환성 선택(Fargate EC2 External) - 사용할 컨테이너 이미지 설정
- 애플리케이션을 위해 개방할 포트 설정
- CPU/메모리 리소스 할당 설정
- 작업의 컨테이너에 사용할 데이터 볼륨 설정
Dynamic Port Mapping 하기
배포가 될 때마다 테스크가 수정되며 reverse-proxy-container의 host port는 계속해서 바뀔 수 있습니다.
따라서 reverse-proxy-container의 host port는 0으로 설정하여 모든 포트가 가능하도록 해줍니다.
그리고 ECS 클러스터가 생성한 EC2 인스턴스의 보안 그룹의 인바운드 규칙에 모든 TCP (0 - 65535)를 추가해줍니다.
테스크의 크기는 위에서 선택한 EC2의 vCPU와 메모리 입력하면 됩니다.
vCPU에 따라 정의할 수 있는 메모리값도 정해져 있습니다. 해당 값들은 AWS 레퍼런스를 참고해주세요. (AWS 레퍼런스)
서비스 생성하기
대상 그룹 생성하기
ECS cluster가 생성한 auto scaling group의 EC2 인스턴스와 VPC가 같아야 합니다.
로드 밸런서 생성하기
Application Load Balancer 선택
로드밸런서 보안 그룹 수정
ECS 서비스 생성하기
최소 실행 작업 비율과 최대 실행 작업 비율을 각각 0%와 100%로 설정해야 합니다.
롤링 업데이트 유형으로 배포하면 현재 실행 중인 컨테이너 버전을 최신 버전으로 바꾸는데, 최소 실행 작업 비율을 100%, 최대 실행 작업 비율을 200%로 하면 도커의 port가 중복되어 배포가 진행되지 않고 에러가 발생합니다.
참고 : https://stackoverflow.com/questions/46018883/best-practice-for-updating-aws-ecs-service-tasks
서비스를 실행하면 배포가 안되는 것을 확인할 수 있습니다. 왜 그럴까요?
클러스터의 컨테이너 인스턴스, 클러스터를 생성할 때 선언한 EC2를 확인해보면 가용 메모리가 466mb인 것을 확인할 수 있습니다.
하지만 우리가 테스크를 정의할 때 테스크의 메모리를 500mb로 설정하였죠. 따라서 우린 테스크 메모리를 466mb보다 작게 설정해야 합니다.
테스크의 메모리를 450mb로 수정 후 이전의 배포 중이던 테스크는 중지하고 ECS 서비스를 업데이트해보겠습니다.
확인해보니 배포는 진행되지만 작업이 중단되었습니다.
확인해보니 테스크 정의 중 컨테이너 정의에서 reverse-proxy-container와 example-app-container간의 순서를 정의와 링크를 하지 않았습니다. 이를 위해 테스크를 수정해보겠습니다.
그리고 cloudwatch에서 로그를 확인하기 위해 Auto-configure CloudWatch Logs를 활성화하겠습니다.
example-app-container의 포트 매핑도 수정하겠습니다.
테스크는 AWS ECS 신규 콘솔보다 이전 버전의 콘솔에서 더 자세하게 수정할 수 있습니다.
그리고 이전 단계와 똑같이 ECS 서비스를 업데이트했습니다.
이제 정상적으로 작동하는 ECS 서비스를 확인할 수 있습니다!
ECS 환경 변수 설정하기
한번 Load balancers의 DNS로 API를 요청해보겠습니다.
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 암호 생성
IAM 권한 설정
위에서 작업 정의를 위해 생성한 ecs-ec2-role 역할에 권한 정책을 추가하겠습니다.
1 2 3 4 5 6 7 8 9 10
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["secretsmanager:GetSecretValue"], "Resource": ["arn:aws:secretsmanager:{region}:{aws_account_id}:{secret:secret_name}"] } ] }
작업 정의의 새 개정 생성
AWS Amazon S3 버킷 생성 후 environmentFiles 저장
버킷에 env 파일을 업로드하기 위해서는 파일 이름이 필수입니다.
IAM 권한 설정
environmentFiles을 저장한 버킷에서 object를 가져오기 위한 정책을 생성합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"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}"
}
}
}
]
}
S3 버킷 정책 생성
environmentFiles은 서비스의 보안적으로 중요한 변수들을 저장한 파일입니다. 따라서 S3 객체로 업로드하여도 퍼블릭으로 접근하면 당연히 안됩니다. 이를 위해 특정 역할에서만 접근하고 일부 액션만 가능하도록 설정해야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"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/*"
}
]
}
참고 자료 : https://inpa.tistory.com/entry/AWS-📚-S3-버킷-생성-사용법-실전-구축
작업 정의의 새 개정 생성
해당 env 파일을 사용하는 example-app-container 컨테이너의 환경 파일에 S3 버킷에 저장한 environmentFile의 ARN을 입력합니다.
ECS 서비스 업데이트
새로 생성된 작업 정의 버전으로 ECS 서비스를 업데이트합니다.
배포가 완료된 후 API를 호출해 보겠습니다.
환경변수로 설정한 저자의 이름이 정상적으로 출력됩니다!
다음 장에서는 GitHub 소스 코드 리포지토리와 GitHub Actions로 Amazon ECS에 배포된 애플리케이션의 CI/CD 파이프라인을 구축하는 방법을 살펴보겠습니다.


























































