GitAction을 활용한 자동 배포 설정 가이드
지금까지 매번 수동으로 해줘야했던 작업들을 GitAction을 통해서 자동으로 배포하는 과정을 작성해보겠습니다.
이번 글에서는 AWS ECS에 배포하는 과정을 GitHub Actions를 통해 자동화하는 방법을 설명하겠습니다.
1. YAML 파일 생성
.github/workflows 디렉토리 아래에 YAML 파일을 생성합니다. 예를 들어 deploy.yaml이라는 이름으로 파일을 생성합니다.
2. CI - 지속적 통합 (Continuous Integration)
CI는 빌드와 테스트를 진행합니다. 아래 예제에서는 주석을 자세히 달아두었습니다.
AWS에서 ECR 에 푸쉬할 정책을 생성합니다.
jar 파일을 도커로 이미지로 만들어 ECR에 푸시하는 과정입니다.
name: CI/CD - Build, Push to ECR and Deploy to ECS
on:
push:
branches: [ "main" ]
env:
AWS_REGION: ap-northeast-2
ECR_REPOSITORY: toystory
ECS_SERVICE: toystory-back
ECS_CLUSTER: DevCluster
ECS_TASK_DEFINITION: ./aws/task_definition.json
CONTAINER_NAME: toystory
permissions:
contents: read
jobs:
build-docker-and-push-ecr:
name: Build and Push Docker Image to ECR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Create application.yml
run: |
mkdir -p ./src/main/resources
APPLICATION_YML_PATH=./src/main/resources/application.yml
echo "Writing application.yml"
echo "${{ secrets.APPLICATION_YML }}" > "$APPLICATION_YML_PATH"
- name: Build with Gradle
run: |
chmod +x gradlew
./gradlew bootJar
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
위 설정에서는 소스코드 체크아웃, JDK 설정, 애플리케이션 설정 파일 작성, Gradle 빌드, AWS 자격 증명 설정, Amazon ECR 로그인, 도커 이미지 빌드 및 푸시 작업을 포함하고 있습니다.
3. CD - 지속적 배포 (Continuous Depoyment)
CD는 빌드된 이미지를 ECS 서비스로 배포합니다.
deploy-ecs:
name: Deploy to ECS
needs: build-docker-and-push-ecr
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout
uses: actions/checkout@v3
# AWS 자격 증명을 구성하는 단계입니다.
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# Amazon ECR에 로그인하는 단계입니다.
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# 새로운 이미지 ID를 ECS 작업 정의에 채워 넣는 단계입니다.
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
# 새로운 ECS 작업 정의를 배포하는 단계입니다.
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
Task Definition으로 ECS Service를 배포할 수 있는 정책을 사용하여 ECR 정책과 함께 사용할 수 있는 사용자를 만듭니다.
사용자의 공개키와 비밀키를 이용하여 ECS로 배포합니다.
배포할 태스크 정의에 들어와서 JSON 클릭 후 아래 내용을 복사한다음, 프로젝트에 원하는 곳에다가 두면 됩니다.
저는 root > aws > task_definition.json을 두었습니다.
4. aws 설정
IAM 정책
배포에 필요한 IAM 정책을 사용자에게 부여합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:UpdateService",
"ecs:RegisterTaskDefinition",
"ecs:DescribeServices",
"ecs:DescribeTaskDefinition",
"ecs:DescribeTasks",
"ecs:ListTasks"
],
"Resource": [
"arn:aws:ecs:ap-northeast-2:851725223974:service/DevCluster/toystory-back",
"arn:aws:ecs:ap-northeast-2:851725223974:task-definition/toystoryTASK-definition:*"
]
},
{
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": "arn:aws:iam::851725223974:role/ecsTaskExecutionRole"
},
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "arn:aws:ecr:ap-northeast-2:851725223974:repository/toystory"
}
]
}
이 IAM 정책을 사용하여 새 새용자를 생성하고 해당 사용자의 액세스 키를 GItHub Actions에 등록합니다.
task_definition.json
ECS 태스크 정의를 JSON 형태로 작성합니다. 아래 예시는 root > aws > task_definition.json에 저장합니다.
{
"containerDefinitions": [
{
"name": "toystory",
"image": "851725223974.dkr.ecr.ap-northeast-2.amazonaws.com/toystory:latest",
"cpu": 0,
"portMappings": [
{
"name": "java",
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [
{
"name": "TZ",
"value": "Asia/Seoul"
}
],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/toystoryTASK-definition",
"awslogs-create-group": "true",
"awslogs-region": "ap-northeast-2",
"awslogs-stream-prefix": "ecs"
}
}
}
],
"family": "toystoryTASK-definition",
"executionRoleArn": "arn:aws:iam::851725223974:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"volumes": [],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "512",
"memory": "1024",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"tags": []
}
하지만 위 JSON은 수동으로 직접 등록하는 것이기 때문에 꼭 필요한 내용도 있지만 필요 없는 내용도 있습니다.
이는 workflows 실행시 경고가 나오니 확인해보시고, 지우시면됩니다. 실행하는 것에는 문제 없습니다.
이제 CD 부분에서 ECS에 배포하기 위해서 task 정의를 활용하여 배포할 수 있는 정책을 만들어, 유저를 생성하여 공개키와 비밀키를 등록해봅시다.
우리가 만들었던 클러스터의 서비스에 우리가 만들었던 태스크의 버전 상관없이 배포할 수 있는 권한입니다.
밑에는 ecs Service를 생성할 때 기본으로 제공해주었던 ecsTaskExecutionRole을 사용할 수 있는 권한을 부여했습니다.
또한 CD에서 ECR을 갖고와야하므로 위 계정과 같이 ECR또한 추가해줍니다.
이제 이 정책을 사용하는 유저를 만들어 공개키와 비밀키를 만들어서, CD workflows에서 사용할 수 있도록 GitHub Action Secret에 등록합니다.
IAM 정책
5. GitHub Secrets 설정
GitHub Actions에서 사용할 AWS 자격 증명을 GitHub Secrets에 등록합니다.
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, APPLICATION_YML 등을 설정합니다.
IAM > 사용자 > toystory-CD에 들어와서 액세스키, CLI로 생성하여 GitHub Action에 등록해줍니다.
ECR에 푸시할 수 있는 권한, ECS를 실행할 수 있는 권한이 모두 등록이 완료됐습니다.
Application.yml 또한 등록하여 CI에서 사용할 수 있도록 해줍니다.
최종 CI/CD workflows
name: CI/CD - Build, Push to ECR and Deploy to ECS
on:
push:
branches: [ "main" ]
env:
AWS_REGION: ap-northeast-2
ECR_REPOSITORY: toystory
ECS_SERVICE: toystory-back
ECS_CLUSTER: DevCluster
ECS_TASK_DEFINITION: ./aws/task_definition.json
CONTAINER_NAME: toystory
permissions:
contents: read
jobs:
build-docker-and-push-ecr:
name: Build and Push Docker Image to ECR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Create application.yml
run: |
mkdir -p ./src/main/resources
APPLICATION_YML_PATH=./src/main/resources/application.yml
echo "Writing application.yml"
echo "${{ secrets.APPLICATION_YML }}" > "$APPLICATION_YML_PATH"
- name: Build with Gradle
run: |
chmod +x gradlew
./gradlew bootJar
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# 이미지를 빌드, 태그 및 ECR에 푸시합니다.
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
최종 결과 배포 성공
이제 workflows에서 정한대로 특정 브랜치에 푸시될 때마다 자동으로 ECS가 배포되는 것을 확인하실 수 있을 겁니다~~!!!
'Infra > AWS' 카테고리의 다른 글
AWS ECS 무중단 CI/CD Pipeline 4. ECS Service 배포, HTTP Redirect (0) | 2024.02.05 |
---|---|
AWS ECS 무중단 CI/CD Pipeline 3. 로드밸런서와 리스너, 대상그룹 (0) | 2024.02.05 |
AWS ECS 무중단 CI/CD Pipeline 2. Route 53 & ACM 🔥😡🔥 (0) | 2024.02.04 |
AWS ECS 무중단 CI/CD Pipeline 1. ECS 기본 개념, ECR, Task 정의, IAM, CLI (0) | 2024.02.03 |
AWS ECS 무중단 CI/CD Pipeline 0. ECS 배포하게 된 배경 (0) | 2024.02.03 |