CI/CD - (미완성)

반응형

교내에서 소모임 팀프로젝트를 하며, Github actions - S3 - Code Deploy 관련 CI/CD(엄밀히 말하면 CI는 아니지만) 관련 자료를 각 코드 별로 설명을 해보고자 한다.

 

CI: 지속적 통합

개발을 하면서 ‘코드에대한 통합’을 ‘지속적’으로 진행함으로써 품질을 유지하자는 의미.

github, gitlab 등에 코드만 올려놓으면 알아서 빌드와 테스트를 수행해준다면 지속적 통합을 하는데 매우 편리할 것이다.

그렇기에 ci에는 '자동화'라는 키워드가 항상 따라온다.

 

CD: 지속적 제공, 배포

소프트웨어가 항상 신뢰 가능한 수준에서 배포될 수 있도록 지속적으로 관리하자는 개념.

배포 이전에 테스트와 빌드는 필수적이기 때문에,

사실상 CD가 되려면 항상 CI가 선행되어야 한다.

 


 

우리 DjangoCRUD 게시판에서 발췌

(https://github.com/DPS0340/DjangoCRUDBoard)

 

CI/CD 관련 파일

  • .github/workflows - ci.yml, cd.yml
    • ci.yml:
      name: CI # 이름 설정
      on: # 동작 방식 서술?
        push: # push 되었을때
          branches: # 아래 기술한 브랜치에 즉 master 브랜치에 push가 되면 actions 동작
          - master
          
      jobs: # 세부적인 동작에 대한 서술
        docker-build: # 이름 설정
            runs-on: ubuntu-latest # 동작 환경 설정. actions가 돌아갈 가상환경 설정
            steps: # 단계 설정
            -
              name: Set up QEMU # 기본 설정1
              uses: docker/setup-qemu-action@v1 # 사용할 github actions 레포
            -
              name: Set up Docker Buildx # 기본 설정2
              uses: docker/setup-buildx-action@v1
            -
              name: Login to DockerHub # 도커 허브에 로그인
              uses: docker/login-action@v1 
              with:
                username: ${{ secrets.DOCKERHUB_USERNAME }} # 깃허브 레포 시크릿 사용
                password: ${{ secrets.DOCKERHUB_TOKEN }} # 깃허브 레포 시크릿 사용
            -
              name: Build and push # 이름 설정
              id: docker_build # id?! 밑에서 echo에서 불러주기 위해서 설정
              uses: docker/build-push-action@v2 
              with: # 매개변수를 넣는 단계
                push: true # 도커허브에 푸쉬
                tags: a891/djangocrudboard:latest # 우리의 도커허브 이미지 레포
                build-args: Django_secret_key=${{ secrets.DJANGO_SECRET_KEY }}
      					# 깃허브 레포에 있는 시크릿 키의 값을 Django_secret_key 변수에 저장
      					# 도커 이미지내에 매개 변수 전달하는 단계임
      					# 추후 Dockerfile 에서 환경변수화 함
            -
              name: Image digest # 해시값을 불러오는 것? 기본 설정
              run: echo ${{ steps.docker_build.outputs.digest }} 
      				# 이미지의 해시 값 출력?
    • cd.yml
      name: CD # 위 ci와 동일
      on:
        push:
          branches:
          - master
          
      jobs:
        upload:
          runs-on: ubuntu-latest # 가상 환경 이미지 설정
          steps:
            - name: Checkout code # 이름
              uses: actions/checkout@v2 
      				# 깃허브 액션이 동작하는 폴더로 checkout 해주는 레포
      				# 우리의 경우에는 master
            - name: Upload S3 for Codedeploy # 이름
              uses: jakejarvis/s3-sync-action@master # s3 업로드 해주는 레포
              with: # args라는 것을 같이 해서?
                args: --acl public-read --follow-symlinks --delete
              env: # 환경 변수 설정. 해당 스텝이 끝나면 날아감
                AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
                AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
                AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
                AWS_REGION: 'ap-northeast-2'   # optional: defaults to us-east-1
        deploy:
          runs-on: ubuntu-latest
          needs: upload # 의존성 설정, deploy 전에 upload 진행. 
      		# 그 이유는 s3로 코드를 업로드 한 후 배포를 동작해야하기 때문에. 
      		# code-deploy를 하려면 s3와 엮여서 해야함
          steps:
      		- name: Checkout code # 이게 없으면 안돌아가는데 왜인지?!
            uses: actions/checkout@v2
          - name: Configuring aws credentials # 이름 맘대로 정할 수 있음
            uses: aws-actions/configure-aws-credentials@v1 # 레포 이름. aws 인증 기능
            with: # env로 설정안하는 것은 후에도 쓰기 위함
                aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
                aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
                aws-region: 'ap-northeast-2'
          - name: Triggering AWS codedeploy # 이름
            uses: webfactory/create-aws-codedeploy-deployment@v0.2.2
      			# 지금 s3에 있는 코드로 code-deploy를 작동 시키는 레포
  • appspec.yml
# code-deploy에서의 세부적인 행동 서술
version: 0.0 # code-deply 배포되는 파일의 버전
os : linux # ubuntu/linux os
files :
 - source : / # s3 버켓의 루트 폴더
   destination: /home/ubuntu/app/ # 우리 클라우드 서버의(ubuntu) app 디렉토리로 복사

permissions: # 권한
  - object: / # 복사될때 어떤 사용자의 권한을 줄 것인지. obejct는 폴더 경로. s3에서 루트 느낌
    pattern: "**" # 인스턴스에 복사되는 폴더의 권한. 
    owner: ubuntu # 루트 경로에서 전부 ubuntu로 바꿔준다고 생각하면 됨.
    group: ubuntu

hooks: # beforinstall과 afterinstall의 생명주기 상에서 overwrite를 지원안하기에 각각 
# shellscrpit로 만들어 놓음 - aws code-deploy가 overwrite를 지원안함. 옮겨놓고 필요한 것만 가지게 ㅎㅁ
  BeforeInstall:
    - location: beforeinstall.sh # 코드가 바뀌기 전에 실행되는 스크립트
  AfterInstall:
    - location: afterinstall.sh # 코드가 바뀐뒤에 실행되는 스크립트
  ApplicationStart: # 그 다음에 실행되는 것. 여기서 배포를 하게됨.
    - location : deploy.sh # deploy.sh 파일을 실행
      timeout: 1000 # 도커 컴포즈 빌드 시간 늘리기, 도커 컴포즈 완료되는 시간보다 적으면 오류 남
      runas: ubuntu # ubuntu에서 돌아간다는 뜻

# This section controls the action:
branch_config: # 깃허브 액션을 컨트롤 하는 것 같음
    wip\/.*: ~ # 정규식으로 work in progress는 안한다는 의미라고 생각.
    master: # master에 commit 등의 변화가 생겼을시
        deploymentGroupName: djangocrudboard-group # 우리가 code-deploy 콘솔에서 만들어준 그룹 이름
        deploymentGroupConfig: # config는 역할 설정(role 설정), 그룹 바꾸는 것
            serviceRoleArn: arn:aws:iam::058718939924:role/codedeploy-role
        deploymentConfig: # 배포할때 쓰는 설정을 바꾸는 것
            autoRollbackConfiguration: # 이거를 false한 이유는 true로 하면
                enabled: false # 이벤트 리스너가 필요한(sns) 관련 문제 같다고 생각

 

#!/bin/sh

# https://github.com/aws/aws-codedeploy-agent/issues/14 이슈 참조
if [ -d /home/ubuntu/app/ ]; then
    if [ -d /home/ubuntu/app-backup ]; then
        rm -rf /home/ubuntu/app-backup
    fi
    if [ -f /home/ubuntu/app/docker-compose.yml ]; then
        cd /home/ubuntu/app
        sudo docker-compose down -v > /home/ubuntu/app/nohup.out
    fi
    cd /
    mv /home/ubuntu/app /home/ubuntu/app-backup
fi
mkdir -p /home/ubuntu/app

# 기존의 있던 app 폴더를 app-backup 폴더로 옮기고 docker-compose.yml가 있으면
# docker-compose 기존거를 down해주고
# 그리고 폴더가 사라지니까 cd 루트 폴더로 돌아오고 app폴더를 app-backup 폴더로 옮겨줌
# 그리고 또 나중을 대비해서 app 폴더를 만들어 놓음
# 전체적으로는 백업 과정
if [ -d /home/ubuntu/app-backup/ ]; then
    mkdir -p /home/ubuntu/app
    if [ -d /home/ubuntu/app-backup/data ]; then
        mkdir -p /home/ubuntu/app/data
        yes | cp -arpf /home/ubuntu/app-backup/data/* /home/ubuntu/app/data
    fi
    if [ -d /home/ubuntu/app-backup/logs ]; then
        mkdir -p /home/ubuntu/app/nginx
        yes | cp -arpf /home/ubuntu/app-backup/nginx/logs /home/ubuntu/app/nginx/logs
    fi
fi
cp /home/ubuntu/app/nginx/nginx-release.conf /home/ubuntu/app/nginx/nginx-app.conf

# 기존에 있던 log랑 data 데이터를 backup 폴더에서 가져오는 느낌
# 그리고 nginx-realease 파일을 적용
#!/bin/sh

REPOSITORY=$(dirname `which $0`) # dirname which $0 은 지금 실행되는 파일의 경로

sudo chown $(whoami) $REPOSITORY # 자기 자신으로 폴더의 소유권(권한)을 바꿔줌
# 약간 안전빵으로 적어넣은 느낌

cd $REPOSITORY # $는 변수의 값을 가져오는 느낌임

sudo apt-get update \
  && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose
# 혹시나 해서 apt-get update 및 docker-compose 다시 깔아줌

chmod +x ./init-letsencrypt.sh # 해당 파일 실행 권한 추가

sudo ./init-letsencrypt.sh -n # 해당 파일 실행. -n은 overwrite할 상황이 되면 종료하라는 의미

mkdir -p $REPOSITORY/data/db # -p 옵션은 전체 폴더 디렉토리를 생성하는 것. 데이터베이스 관련 폴더

sudo chmod -R 777 $REPOSITORY/data # 해당 폴더에 대해 전체 다 읽기, 실행, 쓰기 가능하게 만들어줌.

sudo chown -R ubuntu $REPOSITORY/data # chown을 다시 하는 이유는 사용자가 바뀔 수 있으니
# ubuntu로 설정해줌


docker-compose down -v > $REPOSITORY/nohup.out # docker-compose down -v는 볼륨도 없애면서 down
# 이거에 대한 로그를 nohup.out에 찍으라는 의미
nohup docker-compose up --build >> $REPOSITORY/nohup.out 2>&1 &
# nohup으로 로그 찍으며 docker-compose up --build하면서 
# 그리고 이전거를 지우지 말고 쓰라는 뜻
# 에러가 생기면 표준 출력으로 redirect하고 백그라운드에서 돌리라는 의미
  • docker-compose.yml
  • nginx-app.conf
  • nginx-release.conf
  • AWS:
    • IAM 사용자 추가
    • 역할 설정
    • S3 생성 및 권한 수정
    • EC2에 code-deploy 에이전트 설치
반응형