#15 CD(지속적인 배포) 구현

seojin's 개발블로그·2023년 9월 11일
0

영화 사이트 제작

목록 보기
15/19

이전 포스팅
이전 포스팅의 테스트이후 깃액션, 도커를 이용해 EC2 서버에 자동으로 배포를 진행하는 환경을 구성해보았다.

CD라 거창해보일수 있지만 이전에 했던 수동 배포를 workflows를 작성하여 배포과정을 자동화 해주는 단계이다

📌 배포 로직


1. 깃허브 레포지토리에서 지속적인 병합으로 검증된 서비스를 main에 병합하여줌
2. main에서 jar파일을 추출하고 도커를 이용해 이미지화 시켜줌
3. EC2에서는 이미지를 pull하여 컨테이너를 실행
4. 클라이언트에게 제공

위의 단계를 생각했으며 수동 배포로 위의 단계는 모두 성공시킨 상황이다.
프론트의 경우는 서버사이드 렌더링을 할 지 리액트를 공부하여 프론트 서버를 따로 만들지는 아직 고민중이다.

📌 배포 자동화 구현

1. workflow 작성

name: CICD with gradle and docker

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest
    
    env:
        rds_end_point : ${{secrets.RDS_END_POINT}}
        rds_secret_key : ${{secrets.RDS_SECRET_KEY}}
        rds_user_name : ${{secrets.RDS_USER_NAME}}
        storage_access_key : ${{secrets.STORAGE_ACCESS_KEY}}
        storage_name : ${{secrets.STORAGE_NAME}}
        storage_secret_key : ${{secrets.STORAGE_SECRET_KEY}}

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
        
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew

    - name: Build with Gradle
      run: ./gradlew clean build

    - name: Docker build
      run: |
          docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} -p ${{ secrets.DOCKER_HUB_PASSWORD }}
          docker build -t movie_main . 
          docker tag movie_main 7zrv/movie_main:${GITHUB_SHA::7}
          docker push 7zrv/movie_main:${GITHUB_SHA::7}
          
    - name: Deploy
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_END_POINT }}
        username: ubuntu
        key: ${{ secrets.EC2_KEY }}
        envs: GITHUB_SHA
        script: |
          docker pull 7zrv/movie_main:${GITHUB_SHA::7}
          docker tag 7zrv/movie_main:${GITHUB_SHA::7} movie_main
          docker stop server
          docker rm -f server
          docker run -d --name server -p 8080:8080 --env-file env.txt movie_main
  1. main에서 push, pull이 일어나는 시점에
  2. env: git에 설정해놓은 환경변수들
  3. 체크아웃과 환경 구성
  4. 빌드 권한 부여와 클린빌드 실행
  5. 도커를 이용해 jar파일을 이미지화 시키고 push
  6. EC2 서버로 접속하여 스크립트를 실행

CI부분에 CD를 추가한것인데 main에서 자체적으로 뭔가가 수정되는 경우가 있을수 있어 CICD로 구현을 했다. develop과 마찬가지로 문제가 발생하면 병합을 방지하는 설정도 넣어주었다

2. EC2 연결을 위한 키페어 설정

나는 서버에 접속하기 위한 열쇠(개인키)를 주는것이라고 이해를 했다.

ssh-keygen -t rsa -b 4096 -C "넣고싶은 내용" -f key이름

위의 명령어를 EC2 서버에서 입력해주면 공개키와 개인키 한쌍이 생겨나게 되는데

~/.ssh/authorized_keys

공개키는 위의 경로에 등록을 해주고
개인키의 경우에는 나는 git action의 환경변수에 넣어주었다.
위의 workflows 파일의 key: ${{ secrets.EC2_KEY }} 부분에 해당한다.
개인키와 공개키의 구분은 두 파일중 .pub가 붙은 파일이 공개키이다

3. CD 테스트



main에 push를 하니 깃액션이 실행되고 완료후 EC2에서도 업데이트된 컨테이너가 실행되는것을 확인했다.

📌 발생했던 문제들

1. git action에서 빌드시 발생하는 db연결에러

원인:

 - name: Init env variables
      run: |
        echo "rds_end_point=$rds_end_point" >> .env
        echo "rds_secret_key=$rds_secret_key" >> .env
        echo "rds_user_name=$rds_user_name" >> .env
        echo "storage_access_key=$storage_access_key" >> .env
        echo "storage_name=$storage_name" >> .env
        echo "storage_secret_key=$storage_secret_key" >> .env
      env:
        rds_end_point : ${{secrets.RDS_END_POINT}}
        rds_secret_key : ${{secrets.RDS_SECRET_KEY}}
        rds_user_name : ${{secrets.RDS_USER_NAME}}
        storage_access_key : ${{secrets.STORAGE_ACCESS_KEY}}
        storage_name : ${{secrets.STORAGE_NAME}}
        storage_secret_key : ${{secrets.STORAGE_SECRET_KEY}}

초기의 workflows에 있던 설정인데 develop의 workflow와는 달리 빌드전에 환경변수들을 설정하고 환경변수를 담은 파일을 동적으로 만들어서 배포시에 사용을 하려는 생각이었는데 파일만 만들어질뿐 환경변수를 빌드시에 이용할 수가 없었고
그래서 에러가 발생한것이었다.

해결:

이전 방법으로 되돌려서 해결했다.

jobs:
  build:

    runs-on: ubuntu-latest
    
    env:
        rds_end_point : ${{secrets.RDS_END_POINT}}
        rds_secret_key : ${{secrets.RDS_SECRET_KEY}}
        rds_user_name : ${{secrets.RDS_USER_NAME}}
        storage_access_key : ${{secrets.STORAGE_ACCESS_KEY}}
        storage_name : ${{secrets.STORAGE_NAME}}
        storage_secret_key : ${{secrets.STORAGE_SECRET_KEY}}

환경변수 파일이 아닌 환경변수 자체를 초기화해주었는데 빌드시 환경변수 파일을 이용하는 방법도 생각해보았지만 아래에 있는 에러로 인해 환경변수 파일이 필요가 없어졌기에 아예 환경변수 파일 초기화부분을 없애버렸다.

2. docker run시 환경변수 인식을 못함

원인:

깃액션에서 환경변수 파일을 동적으로 생성해 이용하겠다는 아이디어 였으나
스크립트의 경우 EC2에 접속해서 EC2 환경에서 실행하는 것이라 1번 에러코드 에서 만든 깃액션의 환경변수 파일을 인식할 수 없어서 발생하는 에러였다.

해결:

vi env.txt

수동 배포를 테스트 했을때 처럼 EC2 서버 자체에 환경변수 파일을 만들어서 이용하기로 했다. 하지만 보안을 강화할 방법도 같이 찾아야하는 방법으로 환경변수 파일의 관리법을 확실히 하기 전까진 완전한 해결이라고는 할 수 없다

3. EC2 서버와 연결이 안됨

원인:

authorized_keys 설정 실수
authorized_keys가 아닌 authorized_key2 라는 설정을 하나더 만들어서 사용했는데 keys가 아닌 key라고 적어서 키 설정 자체를 인식하지 못해서 발생한 에러였다.

.ssh 경로에 모든 파일을 설정으로 인식한다 생각했는데 파일이름으로 인식을 하는줄은 몰라서 착각으로 인해 생긴문제였다.

해결:

처음엔 키의 권한제한이 있는건가 싶어서 chmod로 권한을 풀어주었지만
그래도 해결이 되지 않았고
~/.ssh 경로로 들어가보니 authorized_keys 와 authorized_key2가 있었고
authorized_key2를 authorized_keys2라는 이름으로 새롭게 파일을 만들어주어 해결되었다.

📌 후기

학교에서 진행했던 특강때는 진도가 빨라서 제대로 이해하지 못했던 부분들을
다시 공부하는 좋은 시간이었다.

옛날에는 배포 = 어려운것 이라는 막연한 생각이 있었는데 역시 일단 헤딩을 해봐야 배우는게 많은것 같고 두려움도 없어지는것 같다.

내가 혼자 배포를 담당하겠다 했을때는 하나도 할 줄 모르는 상태였는데 몇일만에 성공하니 꽤 뿌듯하다.

프론트 부분을 제외하면 프로젝트도 막바지에 이르렀다 남은 부분도 이렇게 모르는 부분이 있더라도 도전적으로 개발해봐야겠다.

profile
개발 공부하는 블로그

0개의 댓글