안녕하세요.
이번 시간에는 AWS ECS 블루/그린 배포를 위한 CodePipeline 구성을 해보는 실습을 진행하겠습니다.
0. 참고 자료
https://docs.aws.amazon.com/ko_kr/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html
자습서: Amazon ECR 소스 및 CodeDeploy 배포 ECS로 파이프라인 생성
이미지 정의 파일 참조
1. 블루/그린 배포란?
컨테이너 기반의 애플리케이션은 여러 가지 배포 전략을 통해서 업데이트할 수 있습니다.
대표적인 배포 전략은 롤링 업데이트, 블루/그린 배포, 카나리 배포 등이 있으며 이번 실습에서는 블루/그린 배포를 선택했습니다.
[블루/그린 배포]를 선택하는 이유
(1) 서비스 중단이 허용되지 않는 경우
(2) 리소스가 충분한 경우
블루/그린 배포는 주로 위 요구사항에 따라 배포 전략으로 선택하게 됩니다.
또한 블루/그린 배포는 중단 시간이 없고 빠르게 복구할 수 있다는 장점을 가지고 있어 실제 운영 환경에서 많이 쓰이게 됩니다.
블루/그린 배포 작업을 위한 코드 파이프라인 구성입니다. 블루 그린 배포에서는 taskdef.json, appspec.yaml 파일을 저장소에 정의하여 사용합니다.
CodeCommit 레포지토리에 taskdef.json, appspec.yaml이 Push 되거나 ECR 레포지토리에 Image가 Push 되면 파이프라인이 동작합니다.
2. 실습 전 알아두면 좋은 개념
아티팩트 (Artifacts)
빌드 및 배포 과정에서 생성되는 산출물을 의미합니다. 일반적으로 다음과 같은 항목이 포함됩니다.
(1) 빌드 산출물
애플리케이션의 컴파일 결과물, 예를 들어 JAR, WAR, ZIP 파일 등.
테스트 결과물(예: JUnit 테스트 리포트)이나 로그 파일도 포함될 수 있습니다.
(2) 소스 파일
소스 코드와 설정 파일이 배포를 위해 패키징된 형태.
(3) 배포 가능한 패키지
배포 과정에서 사용되는 파일, 예를 들어 Docker 이미지나 AWS Lambda 함수 코드.
AWS CodeSeries에서의 아티팩트 역할:
(1) AWS CodeBuild
빌드 단계에서 생성된 산출물을 S3 버킷 또는 Docker 이미지 레지스트리에 업로드.
다음 단계(CodeDeploy, CodePipeline 등)에서 사용.
(2) AWS CodePipeline
빌드, 테스트, 배포 각 단계 간에 전달되는 데이터로 사용.
CodePipeline은 지정된 S3 위치나 다른 저장소에서 아티팩트를 관리.
(3) AWS CodeDeploy
배포 단계에서 해당 산출물을 활용하여 애플리케이션을 EC2, Lambda 또는 온프레미스 서버에 배포.
1. taskdef.json
AWS ECS에서 사용하는 작업 정의 파일입니다. ECS에서 서비스나 태스크를 생성할 때 해당 파일을 참조하여 서비스와 태스크를 생성하게 됩니다.
2. appspec.yaml
AWS CodeDeploy 단계에서 참조하는 파일입니다. 배포 시에 해당 파일 내용을 참조하여 구성에 알맞게 배포가 수행됩니다.
3. 이미지 정의 파일
(1) imagedefinition.json (컨테이너 이미지를 업데이트하기 위해 사용)
AWS ECS에서 서비스 업데이트 시 사용할 컨테이너 이미지 정보를 지정하는 파일입니다.
주로 CodePipeline과 CodeDeploy를 사용할 때 사용되며, ECS 태스크 정의에 포함된 컨테이너 이미지를 업데이트합니다.
[
{
"name": "container-name",
"imageUri": "repository/image-name:tag"
}
]
name | ECS 태스크 정의의 컨테이너 이름과 일치해야 함. 태스크 정의에서 변경할 컨테이너를 명시 |
imageUri | ECR 또는 Docker Hub와 같은 소스 공급자에 저장된 컨테이너 이미지의 URI. repository/image-name:tag 형식 |
CodePipeline 배포 단계에서 이 파일을 사용하여 ECS에 새로운 이미지를 적용합니다.
S3, CodeCommit 등에서 제공된 파일을 읽어 배포를 자동화하니 수동으로 제공할 필요가 없습니다.
(2) imageDetail.json (컨테이너 이미지를 업데이트하기 위해 사용)
Amazon ECR에서 빌드된 이미지를 CodePipeline과 같은 서비스로 전달하기 위해 사용됩니다.
CodeBuild의 빌드 결과물로 생성되며, 컨테이너 이미지의 메타데이터를 포함합니다.
{
"registry": "aws_account_id.dkr.ecr.region.amazonaws.com",
"repositoryName": "repository-name",
"imageDigest": "sha256:hash",
"imageTags": ["tag1", "tag2"]
}
registry | 컨테이너 이미지를 호스팅하는 Amazon ECR 레지스트리의 URI 형식: aws_account_id.dkr.ecr.region.amazonaws.com |
repositoryName | Amazon ECR의 이미지 리포지토리 이름 |
imageDigest | 컨테이너 이미지의 고유 식별자 이미지의 무결성을 확인하는 데 사용 |
imageTags | 해당 이미지의 태그 목록 예: latest, v1.0 |
빌드 결과를 다음 파이프라인 단계로 전달하는 파일입니다. CodePipeline에서 ECR 이미지를 추적하고 전달하는 데 사용됩니다. CodePipeline에서 빌드 단계에서 배포 단계로 넘어갈 때 자동으로 생성됩니다.
CodeBuild가 새로운 이미지를 빌드한 후 imageDetail.json 파일을 생성하여 다음 단계로 전달합니다.
항목 | imagedefinition.json | imageDetail.json |
사용 목적 | ECS 태스크 정의 업데이트 | CodeBuild 결과물 전달 |
생성 주체 | 사용자, CI/CD 파이프라인에서 직접 생성 | CodeBuild가 자동 생성 |
포함 정보 | 컨테이너 이름과 이미지 URI | 레지스트리, 레포지토리, 이미지 Digest 및 태그 |
주요 사용처 | CodeDeploy를 통한 ECS 서비스 배포 | CodePipeline 빌드 및 배포 단계 연결 |
다음과 같이 imagedefinition과 imageDetail은 비슷한 역할을 하지만 목적, 주체, 정보, 사용처가 모두 다릅니다.
3. Amazon ECR 소스 및 CodeDeploy 배포 ECS로 파이프라인 생성
1. CodeCommit 생성하기
다음과 같이 CodeCommit 레포지토리 이름을 설정한 후 [생성]을 눌러 생성해 줍니다.
2. EC2 Linux 인스턴스를 시작하고 Docker를 설치한 후 이미지를 생성합니다.
# nginx용 이미지를 풀 다운합니다. 이 명령은 nginx:latest 이미지를 제공합니다.
docker pull nginx
# docker images를 실행합니다. 목록에 이미지가 나타나야 합니다.
docker images
3. Amazon Linux에는 기본적으로 awscli가 설치되어 있어 Profile을 설정합니다.
# AWS CLI profile 설정하기
aws configure
ACCESS KEY: 액세스 키 입력
SECRET KEY: 시크릿 키 입력
REGION: 리전 입력
DEFAULT OUTPUT FORMAT: Enter
4. Amazon ECR 레포지토리를 생성하고 이미지를 Push합니다.
# 이미지를 저장할 Amazon ECR 레포지토리를 생성합니다. 출력에서 repositoryUri를 입력합니다.
aws ecr create-repository --repository-name ecs-codepipeline-ecr-repo
위 CLI 명령어를 실행하면 다음과 같이 ECR 레포지토리가 생성됩니다.
레포지토리를 선택하면 우측 상단에 [푸시 명령 보기]가 있는데 선택하면 ECR에 Push 하기 위한 간단한 명령어들을 보여줍니다.
# ECR 로그인 및 도커 로그인
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin <AWS ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com
# 빌드가 필요한 경우만 실행
docker build -t ecs-codepipeline-ecr-repo .
# 이미지 태그를 조금 변경하기
docker tag nginx <AWS ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/ecs-codepipeline-ecr-repo:nginx
# Nginx 이미지 레포지토리로 Push하기
docker push <AWS ACCOUNT_ID>.dkr.ecr.ap-northeast-2.amazonaws.com/ecs-codepipeline-ecr-repo:nginx
다음 명령어를 통해 레포지토리에 이미지가 Push 되는 것을 확인할 수 있습니다.
5. Task Definition 및 AppSpec 소스 파일을 생성하고 CodeCommit 레포지토리로 Push 하기
(1) taskdef.json 생성하기
vi taskdef.json
{
"executionRoleArn": "arn:aws:iam::<AWS_ACCOUNT_ID>:role/ecsTaskExecutionRole",
"containerDefinitions": [
{
"name": "nginx-website",
"image": "nginx",
"essential": true,
"portMappings": [
{
"hostPort": 80,
"protocol": "tcp",
"containerPort": 80
}
]
}
],
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "256",
"memory": "512",
"family": "ecs-taskdef"
}
다음과 같이 편집 프로그램을 이용하여 taskdef.json 파일을 생성해 줍니다.
aws ecs register-task-definition --cli-input-json file://taskdef.json
CLI를 통해 방금 생성한 taskdef.json 파일로 [태스크 정의]를 생성합니다.
다음과 같이 태스크 정의가 생성된 것을 확인할 수 있습니다.
(2) appspec.yaml 생성하기
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "task-definition-ARN"
LoadBalancerInfo:
ContainerName: "container-name"
ContainerPort: container-port-number
# Optional properties
PlatformVersion: "LATEST"
NetworkConfiguration:
AwsvpcConfiguration:
Subnets: ["subnet-name-1", "subnet-name-2"]
SecurityGroups: ["security-group"]
AssignPublicIp: "ENABLED"
#Hooks:
#- BeforeInstall: "BeforeInstallHookFunctionName"
#- AfterInstall: "AfterInstallHookFunctionName"
#- AfterAllowTestTraffic: "AfterAllowTestTrafficHookFunctionName"
#- BeforeAllowTraffic: "BeforeAllowTrafficHookFunctionName"
#- AfterAllowTraffic: "AfterAllowTrafficHookFunctionName"
다음 코드는 appspec.yaml의 샘플 코드입니다. 여기서 TaskDefinition, ContainerName, ContainerPort, Subnet, SecurityGroups를 입력해야 합니다. 이때 AwsvpcConfiguration 항목은 리소스 이름이 아닌 리소스의 ID 값을 입력해야 합니다.
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: <TASK_DEFINITION>
LoadBalancerInfo:
ContainerName: "container-name"
ContainerPort: container-port-number
Documents에는 다음과 같이 <TASK_DEFINITION> 자리 표시자 텍스트가 있는데 이걸 변경하지 않아도 됩니다. 파이프라인이 실행되면 자동으로 이 값이 업데이트됩니다.
(3) CodeCommit에 파일 푸시/업로드하기
/root
| ecs-codepipeline
|--appspec.yaml
|--taskdef.json
CodeCommit 레포지토리로 파일을 푸시하거나 업로드해야 합니다. 이 파일들은 배포 작업에 대해 [파이프라인 생성] 과정에서 소스 아티팩트로 제공됩니다. 이 파일들은 위와 같이 로컬 디렉터리에 나타납니다.
생성한 ecs-codepipline 레포지토리의 [HTTPS 복제]를 선택합니다.
그전에 IAM - [사용자] - AWS CodeCommit에 대한 [HTTPS Git 자격 증명을 생성] 해야 합니다. 나온 자격증명은 CodeCommit에 연결할 때 자격증명 정보로 입력해야 합니다. (SSH로 연결하려는 경우 SSH 퍼블릭 키를 업로드합니다.)
# 디렉터리를 해당 로컬 레포지토리로 변경합니다.
cd /root/ecs-codepipeline
# 다음 명령어를 실행하여 원격 저장소를 지정합니다.
git remote add origin <HTTPS 붙여넣기>
# 자격증명 입력
<다운로드 받은 자격증명을 입력합니다>
# 다음 명령어를 실행하여 모든 파일을 한 번에 스테이징합니다.
git add *
# 다음 명령어를 실행하여 커밋 메세지와 함께 파일을 커밋합니다.
git commit -m "ecs-codepipeline-v1"
# 다음 명령어를 실행하여 로컬 레포지토리 파일을 CodeCommit 레포지토리에 푸시합니다.
git push origin master
다음과 같이 명령어를 수행합니다.
CodeCommit에는 appspec.yaml과 taskdef.json 파일만 올라가도 됩니다. 필요시 Build 단계에서 사용할 Dockerfile을 제공할 수도 있습니다.
(4) 로드밸런서 및 타겟 그룹 생성하기
네트워크는 ECS와 동일한 VPC이고 ECS 대상을 등록하기 위해 내부로 선택합니다
[대상 그룹 생성]을 누르고 대상 그룹을 생성합니다.
컨테이너의 사설 IP를 입력하여 대상 그룹의 대상으로 등록합니다.
Blue 타겟 그룹: 기존 애플리케이션 버전이 연결
Green 타겟 그룹: 새 애플리케이션이 연결될 빈 상태의 타겟 그룹
Blue/Green 배포를 위해 대상 그룹을 2개 생성해주어야 합니다. 다음과 같이 설정한 후 [대상 그룹 생성]을 눌러줍니다.
Blue는 기존 떠 있는 컨테이너의 사설 IP를 등록해 주시고 Green은 빈 타겟 그룹을 생성해 줍니다.
그 후 생성한 대상 그룹과 로드밸런서를 연결한 후 [로드 밸런서 생성]을 선택합니다.
만들어진 두 번째 대상 그룹을 로드밸런서와 연결하기 위해 [리스너 추가]를 눌러줍니다.
다음과 같이 설정한 후 리스너를 추가해야 합니다. 보안 그룹에서 인바운드 허용이 필요합니다.
(5) ECS Cluster 생성 및 서비스 구성하기
다음과 같이 ECS에서 [클러스터 생성]을 누르고 클러스터 이름을 지정한 후 [생성]을 눌러준 후 생성이 될 때까지 기다립니다.
(6) CLI를 이용한 서비스 생성하기
vi create-service.json
{
"taskDefinition": "family:revision-number",
"cluster": "my-cluster",
"loadBalancers": [
{
"targetGroupArn": "target-group-arn",
"containerName": "sample-website",
"containerPort": 80
}
],
"desiredCount": 1,
"launchType": "FARGATE",
"schedulingStrategy": "REPLICA",
"deploymentController": {
"type": "CODE_DEPLOY"
},
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": [
"subnet-1",
"subnet-2"
],
"securityGroups": [
"security-group"
],
"assignPublicIp": "ENABLED"
}
}
}
aws ecs create-service --service-name ecs-codepipeline-service --cli-input-json file://create-service.json
다음과 같이 CLI를 이용해서 서비스를 생성합니다. 이때 필요한 정보에 맞게 끔 수정해주셔야 합니다.
이때 주의할 점은 ContainerName과 Port는 taskDefinition 설정과 같아야 하고 awsvpcConfiguration은 모두 ID 값이 위치해야 합니다.
정상적으로 서비스가 생성되었다면 CodeDeploy를 구성해야 합니다.
(7) 애플리케이션 및 배포 그룹 생성하기 CodeDeploy
애플리케이션 - [애플리케이션 생성]을 선택합니다.
애플리케이션 이름 - 컴퓨팅 플랫폼 - [애플리케이션 생성]을 통해 애플리케이션을 생성합니다.
애플리케이션이 생성되면 [배포 그룹 생성]을 선택합니다.
배포 그룹 이름과 CodeDeploy 권한이 있는 서비스 역할을 선택합니다.
ECS 클러스터와 서비스를 선택한 후 로드밸런서 구성에서 생성해 둔 로드밸런서와 타겟 그룹을 지정합니다.
다음과 같이 [즉시 트래픽 다시 라우팅]으로 변경하고 테스트를 위해 배포 대기 시간을 5분으로 설정합니다. 기본은 1시간인데 1시간으로 설정하면 Blue/Green 배포 후 1시간 동안 Blue가 삭제되지 않고 대기합니다. 바꿨다면 [배포 그룹 생성]을 선택합니다. (테스트 용도이거나 일정 시간 대기가 필요한 작업이 아니라면 [원래 개정 종료]를 빠르게 하는 게 비용을 아낄 수 있습니다.)
다음과 같이 배포 그룹이 정상적으로 생성되었다면 CodePipeline을 구성합니다.
(8) CodePipeline 구성하기
CodePipeline 서비스를 선택한 후 [파이프라인 생성]을 눌러줍니다.
다음과 같이 파이프라인 설정을 진행하고 [다음]을 선택합니다.
소스 스테이지 설정은 다음과 같이 진행해 주시고 [다음]을 눌러줍니다.
이번 실습에서 빌드 과정은 필요 없기 때문에 빌드 스테이지는 건너뛰겠습니다.
다음과 같이 설정을 진행한 후 [파이프라인 생성]을 통해 파이프라인을 생성합니다.
(8) CodePipeline 실행하기
우측 상단에 있는 [변경 사항 릴리스]를 눌러서 CodePipeline을 실행합니다.
파이프라인이 실행되면서 ECS 서비스에 Green 배포가 되는 것을 확인할 수 있습니다.
5분의 대기 시간이 지나면 기존 Blue가 중지되는 것을 확인할 수 있습니다.
다음과 같이 Deploy가 성공으로 나오게 되면 정상적으로 Blue/Green 배포가 된 것입니다. Blue/Green 배포가 비용은 다소 발생하나 무중단 배포가 가능하고 롤백이 다른 배포에 비해 쉽기 때문에 실제 운영 환경에서 사용하는 배포 전략입니다.
파이프라인 세부 정보의 입력을 확인하면 다음과 같이 설정되어 있습니다.
(9) 정의 파일 수정 후 다시 Push 하기
CodeCommit에 Push 했을 때 자동으로 Trigger 되어 Deploy까지 이어지는 것을 확인할 수 있습니다.
이번 시간에는 AWS ECS 블루/그린 배포를 위한 CodePipeline 구성을 해보는 실습을 진행해 봤습니다.
다음 시간에는 소스 공급자가 CodeCommit이 아닌 Amazon ECR을 기준으로 ECR > Deploy 방식으로 파이프라인 구성하는 방법에 대해 소개하겠습니다.
감사합니다
'Cloud > Amazon Cloud' 카테고리의 다른 글
[AWS] CloudWatch Logs Agent를 이용하여 서버 로그 정리하기 (0) | 2024.12.20 |
---|---|
[AWS] Korea PLES GameDay 2024 Network Topology Titans 참여 후기 (0) | 2024.09.25 |
[AWS] ECR에 이미지 올려서 ECS Fargate Redis 구성하고 접속하기 (0) | 2024.08.06 |
[AWS] CodePipeline에서 다른 VPC에 있는 사내 GitLab에 연동하는 방법 (0) | 2024.06.26 |
[AWS] Lambda를 이용한 Serverless 형태의 Slack 챗봇 사용하기 - 2 (0) | 2023.11.30 |
클라우드, 개발, 자격증, 취업 정보 등 IT 정보 공간
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!