CI/CD 파이프라인 구현 - Git Action workflow .yaml파일 작성
ECS 이미지 배포 yaml 코드
name: Deploy to Amazon ECS
on:
push:
branches: [ "dev" ]
paths:
- 'Task/**'
env:
AWS_REGION: [region]
ECR_REPOSITORY: [ECR Repository name]
ECR_BACKUP_REPOSITORY: [ECR Repository name]
ECS_SERVICE:[ECS Service name]
ECS_CLUSTER: [ECS Cluster name]
CONTAINER_NAME: [ECS Container name]
permissions:
contents: read
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
env:
working-directory: "./Task"
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 }}
# ECR에 로그인하기
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
#각 빌드된 이미지들에게 고유한 태그(github.sha값)를 달아 ECR에 푸시
- name: Build, Unique tag, and push image to Amazon ECR
id: build-unique-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
docker build -t $ECR_REGISTRY/$ECR_BACKUP_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_BACKUP_REPOSITORY:$IMAGE_TAG
echo "image=$ECR_REGISTRY/$ECR_BACKUP_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
working-directory: ${{ env.working-directory }}
#latest 태그를 달아 ECR에 푸시한다. 푸시되는 레포지토리는 각각 다르다.
- name: Build, latest tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: latest
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
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
working-directory: ${{ env.working-directory }}
#가장 최근에 사용한 task정의 파일을 사용할 수 있도록 가져온다.
- name: Retrieve most recent ECS task definition JSON file
id: retrieve-task-def
run: |
aws ecs describe-task-definition --task-definition [task-definition family name] --query taskDefinition > task-definition.json
cat task-definition.json
echo "::set-output name=task-def-file::task-definition.json"
# $GITHUB_OUTPUT
# ECS 태스크 정의에 푸시한 ECR이미지 id를 집어넣는다.
- 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: ${{ steps.retrieve-task-def.outputs.task-def-file }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
# 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
이미지를 푸시할 ECR 이미지를 2개로 나눈 이유
우린 ECR에 이미지를 푸시한 후 배포할 때, latest태그가 붙어있는 이미지를 배포하는 것으로 aws.json의 태스크 정의 파일을 작성했다.
그런데 ECR 레포지토리에 푸시된 이미지를 보니 가장 최근에 배포된 latest태그가 붙어있는 이미지를 제외하고 나머지 이미지들은 태그가 붙어있지 않고있다는 것을 확인해 각 배포되는 이미지에 Unique한 값을 가진 태그를 붙여 서로 구별이 가능하고 만약의 경우에 태그를 지정해서 이미지 작업을 할 수 있도록 했다.
그리고 task.json파일에는 aws리소스의 주소같은 크리티컬한 정보들이 담겨있기 때문에 민감한 정보들의 노출을 최소화하기 위해서 가장 최근에 사용했던 task.json파일을 사용해서 인프라를 배포하도록 코드를 작성했다.
Lambda 이미지 배포 yaml 코드
name: Deploy to Auth Lambda
on:
push:
branches: [ "dev" ]
paths:
- 'Auth/**'
jobs:
deploy:
runs-on: ubuntu-latest
env:
working-directory: "./Auth"
steps:
- name: Checkout
uses: actions/checkout@v3 # 최신 소스 코드를 체크아웃합니다.
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: 14 # 사용할 Node.js 버전을 지정합니다.
- name: Install dependencies
run: npm ci # 필요한 의존성을 설치합니다.
- name: Package Function
run: zip -r function.zip * # 필요한 파일들을 압축합니다.
working-directory: ${{ env.working-directory }}
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # AWS_ACCESS_KEY_ID를 GitHub Secrets에서 가져옵니다.
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # AWS_SECRET_ACCESS_KEY를 GitHub Secrets에서 가져옵니다.
aws-region: ap-northeast-2 # AWS region을 지정합니다.
- name: Deploy to Lambda
run: aws lambda update-function-code --function-name <람다 함수 이름> --zip-file fileb://function.zip # Lambda 함수 이름
working-directory: ${{ env.working-directory }}
S3 정적웹사이트 배포 yaml 코드
name: workflow for S3 Deploy
on:
push:
branches: [ "dev" ]
paths:
- 'Front/**'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
S3_BUCKET_NAME: ${{ secrets.S3_BUCKET_NAME }}
S3_BUCKET_REGION: [region]
jobs:
run:
runs-on: ubuntu-latest
env:
working-directory: "./Front"
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} # AWS_ACCESS_KEY_ID를 GitHub Secrets에서 가져옵니다.
aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} # AWS_SECRET_ACCESS_KEY를 GitHub Secrets에서 가져옵니다.
aws-region: ${{ env.S3_BUCKET_REGION }} # AWS region을 지정합니다.
- name: Deploy to S3
run: |
aws s3 sync ./ s3://${{ env.S3_BUCKET_NAME }}/
working-directory: ${{ env.working-directory }} # 정적 웹 페이지 파일이 위치한 디렉토리를 지정합니다.
CI/CD 파이프라인을 만들면서 개발을 하면서 실제 리소스에서도 잘 돌아가는지 테스트하기 위한 dev브랜치와 진짜 서비스 제공을 위해서 배포하기 위한 버전 코드가 올라가는 main브랜치로 구분해서 CI/CD를 구현하려고 했습니다.
dev브랜치 CI/CD가 배포하는 리소스와 main 브랜치 CI/CD가 배포하는 리소스를 구분해서 배포할 수 있다면 확실하게 개발과 프로덕션 파트를 분리할 수 있을 것이라고 생각한다.
CI/CD 파이프라인 구현을 진행하며
CI/CD파이프라인 구현을 진행하면서 단순히 깃헙에 올라온 코드를 클라우드 리소스 상에 배포하는 것 뿐만 아니라, 개발 - 프로덕션의 단계를 구분해서 배포를 하기위해서는 어떻게 하는 것이 좋을까 제대로 고민해볼 수 있었던 시간이었다.
그리고 한번은 이상한 코드가 dev브랜치의 Front디렉토리 안으로 push되어 배포까지 진행돼버려서 Route53도메인으로 접속했을 때 요상한 화면이 출력된 적이 있는데, 만일 production와 dev의 구분없이 단일 브랜치로 레포지토리 구성을 했다면 production단계에서 앞서 말한 것 같은 끔찍한 일이 생겼을 것이다.
그래서 dev - production을 구분해서 작업하는 것이 굉장히 중요하다는 것을 느꼈고, 어떻게 하면 잘 구분해서 사용할 수 있을지 앞으로도 더 고민해봐야할 숙제다.
'DevOps' 카테고리의 다른 글
[DevOps] 최종 프로젝트 - 구현(IaC) (0) | 2023.06.20 |
---|---|
[DevOps] 최종 프로젝트 회고 - 구현(클라우드 리소스) (0) | 2023.06.20 |
[DevOps] 최종 프로젝트 회고 - 리소스 아키텍처 설계 (0) | 2023.06.19 |
[DevOps] 최종 프로젝트 회고 - 요구사항 분석 (0) | 2023.06.12 |
[DevOps] 모니터링 (0) | 2023.06.08 |