DevOps

Github Actions를 이용해 CI/CD를 구축해보자(ssh 연결)

SH_Roh 2023. 2. 15. 00:59
반응형

배포 자동화를 해놓지 않았을 때

  1. 인스턴스 접속
  2. git pull
  3. 백엔드 폴더에서 yarn install -> 배포
  4. 프론트 폴더에서 yarn install -> yarn build -> 배포

배포 자동화를 해놓지 않았을 때는 위 과정의 반복이었다. 조그마한 변경이 있어도 매번 이렇게 해야해 너무 번거로웠다.

그래서 Github Actions를 이용해 CI/CD를 구축해보기로 했다.

 

CI/CD를 처음 시도해봤기 때문에 어디서부터 어떻게 해야할지 참 막막했다. 현재 오라클 클라우드를 사용 중인데 오라클에서 제공하는 OCI DevOps는 유료 서비스여서 시도해보지 못했고, OCI 블로그에 나와있는 방법이나 OCI CLI를 이용하는 방법을 모두 시도해보았으나 실패했다.

그래서 평소대로 ssh로 연결한 후 배포가 진행되도록 해보았다.

 


 

ssh 연결해서 인스턴스에 접속하기

Github Actions에서 ssh로 접속하기 위해서는 SSH Remote Commands라는 action을 사용해주면 된다.

 

ppk 파일을 rsa로 변경하기

ssh-action을 사용하기 위해서는 putty로 생성했던 ppk 파일을 rsa 형식으로 변경해주어야 한다.

PuTTYgen을 실행해서 기존의 ppk 키 파일을 불러온다.

 

Conversions - Export OpenSSH key를 누르고 원하는 곳에 저장을 해주면 된다.

 

secret 설정

본격적으로 yaml 파일을 작성하기 전에, Github Actions에서 사용할 환경 변수를 설정해주어야 한다.

Settings 클릭
Secrets and variables - Actions 클릭

레포지토리의 Settings - Secrets and variables - Actions에서 New repository secret을 눌러 설정해줄 수 있다.

이런 식으로 설정해주면 되고, 포트 번호 외에도 host, key, passphrase, username을 추가적으로 등록해주었다. (key에는 아까 만들었던 rsa 키 파일의 내용을 BEGIN과 END라인까지 포함해서 넣어주면 된다.)

 

ssh 접속

secret까지 다 등록해주었다면 아래처럼 ssh 연결을 할 수 있다. 연결 후 할 동작들을 script에 쭉 적어주면 된다.

.github/workflows/deploy.yml

name: deploy
on:
  push:
    branches: ['master']
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3.3.0

      - name: execute remote ssh
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_SSH_HOST }}
          username: ${{ secrets.REMOTE_SSH_USERNAME }}
          key: ${{ secrets.REMOTE_SSH_KEY }}
          passphrase: ${{ secrets.REMOTE_SSH_PASSPHRASE }}
          port: ${{ secrets.REMOTE_SSH_PORT }}
          script: |
            whoami

 


 

Workflow 작성

특정 브랜치에 대해서만 Github Actions가 trigger되도록 하기

master 브랜치에 push되었을 때만 실행될 수 있도록 하자.

name: deploy
on:
  push:
    branches: ['master']

 

백엔드 서버 배포

.github/workflows/deploy.yml

name: deploy
on:
  push:
    branches: ['master']
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3.3.0
 
      - name: execute remote ssh & deploy backend server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_SSH_HOST }}
          username: ${{ secrets.REMOTE_SSH_USERNAME }}
          key: ${{ secrets.REMOTE_SSH_KEY }}
          passphrase: ${{ secrets.REMOTE_SSH_PASSPHRASE }}
          port: ${{ secrets.REMOTE_SSH_PORT }}
          script: |
            whoami
            cd ../../usr/KORrection/back
            sudo git pull origin master
            export NVM_DIR=~/.nvm
            source ~/.nvm/nvm.sh
            yarn install
            pm2 restart back-server

ssh로 성공적으로 연결했다면 배포에 필요한 작업들을 script에 적어주면 된다. 위의 내용은 백엔드 서버를 배포하는 스크립트이다.

백엔드 폴더로 이동 후 git pull을 받아오고, 배포 작업을 진행한다.

이 때 주의할 점은 nvm.sh를 실행해주어야 한다는 것이다. 이렇게 하지 않으면 yarn이나 pm2에 대해 command not found 에러가 발생할 수 있다.

 

프론트엔드 배포

name: frontend CD
on:
  push:
    branches: ['master']
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: execute remote ssh & deploy frontend server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_SSH_HOST }}
          username: ${{ secrets.REMOTE_SSH_USERNAME }}
          key: ${{ secrets.REMOTE_SSH_KEY }}
          passphrase: ${{ secrets.REMOTE_SSH_PASSPHRASE }}
          port: ${{ secrets.REMOTE_SSH_PORT }}
          script: |
            whoami
            cd ../../usr/KORrection/front
            sudo git pull origin master
            export NVM_DIR=~/.nvm
            source ~/.nvm/nvm.sh
            yarn install
            yarn build
            sudo systemctl reload nginx

비슷한 과정으로 프론트 배포도 해줄 수 있다.

 

특정 폴더에 대해서만 Github Actions가 trigger되도록 하기

back 폴더에서 변화가 생겼을 때는 백엔드 코드만, front 폴더 내에서 변화가 생겼을 때는 프론트엔드 코드만 배포되도록 하고 싶었다.

그래서 back.yml, front.yml로 파일을 따로 작성해주고, paths를 지정해주었었다. 의도대로 동작하지 않아 찾아보니 paths는 같은 워크플로우에서 여러 path를 지정해줄 때 쓰는 것이었다.

 

https://stackoverflow.com/questions/67941070/github-action-trigger-on-multiple-on-push-paths

path-filter라는 액션을 사용해주면 내가 의도한대로 할 수 있었다.

 

.github/workflows/deploy.yml

name: deploy
on:
  push:
    paths:
      - 'back/**'
      - 'front/**'
    branches: ['master']
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3.3.0
      
      - uses: dorny/paths-filter@v2.11.1
        id: changes
        with:
          filters: |
            back:
              - 'back/**'
            front:
              - 'front/**'
              
      - name: execute remote ssh & deploy backend server
        if: steps.changes.outputs.back == 'true'
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_SSH_HOST }}
          username: ${{ secrets.REMOTE_SSH_USERNAME }}
          key: ${{ secrets.REMOTE_SSH_KEY }}
          passphrase: ${{ secrets.REMOTE_SSH_PASSPHRASE }}
          port: ${{ secrets.REMOTE_SSH_PORT }}
          script: |
            whoami
            cd ../../usr/KORrection/back
            sudo git pull origin master
            export NVM_DIR=~/.nvm
            source ~/.nvm/nvm.sh
            yarn install
            pm2 restart back-server
            
      - name: execute remote ssh & deploy frontend server
        if: steps.changes.outputs.front == 'true'
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_SSH_HOST }}
          username: ${{ secrets.REMOTE_SSH_USERNAME }}
          key: ${{ secrets.REMOTE_SSH_KEY }}
          passphrase: ${{ secrets.REMOTE_SSH_PASSPHRASE }}
          port: ${{ secrets.REMOTE_SSH_PORT }}
          script: |
            whoami
            cd ../../usr/KORrection/front
            sudo git pull origin master
            export NVM_DIR=~/.nvm
            source ~/.nvm/nvm.sh
            yarn install
            yarn build
            sudo systemctl reload nginx

한 파일에 모든 내용을 써주고, paths filter를 통해 변경이 일어난 부분이 back인지 front인지를 확인해주고 if를 사용해 조건에 맞을 때만 실행될 수 있도록 해주면 된다.

 

 

이렇게 작성해주면 back 폴더 내에서만 변경이 일어났을경우 아래처럼 백엔드 서버만 배포해주는 것을 확인할 수 있다.

 

References

https://github.com/marketplace/actions/ssh-remote-commands

[ssh] putty ppk 파일을 openssh 개인키로 변환하기

[Github, CI/CD] 특정 파일이나 폴더에 대해서만 Github Actions가 trigger되는 방법

Github Action PM2 배포시 pm2 command not found

https://stackoverflow.com/questions/67941070/github-action-trigger-on-multiple-on-push-paths

https://github.com/marketplace/actions/paths-changes-filter

 

반응형