본문 바로가기
프로젝트 (Project)

[CI/CD] SSH into my VM - Using git action & docker-compose

by moveho 2023. 5. 1.

시나리오 Flow 및 사용 기술 Stack

CI/CD 지속적으로 새로운 코드 변경 사항이 있거나 빌드 및 테스트 되어 GIT REPO에 통합되어 관리되는 것과 그것을 CD , Production Level 까지도 자동으로 Deploy 되는 과정을 시나리오 형태로 본 프로젝트에서는 담아보고자 합니다.

 

다음 사례는 직접 필자가 겪은 일을 토대로 프로젝트를 진행하도록 하겠습니다.

[사례]

항공권을 예매를 하는데 Application에서 마지막 결제하기 버튼이 아무리 눌러도 눌리지 않는 상황을 마주한적 있습니다. 아무래도 결제하기 버튼의 Request 처리가 제대로 동작하지 않는 것이라 생각이 들었습니다. OO 항공사가 이 사실을 모르고 있는 것 같아 직접 고객센터에 전화하여 APP에 문제가 있는 것 같다고 결제하기 위치를 알려주며 확인해 보라고 하였습니다. 만약 알려주지 않았다면 항공사가 입은 손해는 얼마나 될까? 라는 생각을 하며 항공사는 이 문제를 해결하기 위해 어떤 Flow로 문제를 해결하고 정상적인 Application으로 복구 해서 제공 했을 지 필자가 생각한 다음과 같은 단계를 예로 들어 진행해 보도록 하겠습니다.

 

1.    Bug 탐지 및 발견

2.    DevOps engineer: 잘 작동하던 안정적인 이미지를 개발자에게 제공

3.    Dev: 에러코드 수정

4.    Dev: 에러 해결 후 새로운 버전 제공 및 지속적 통합 서버에 제공

5.    배포 서버 인스턴스에 배포하여 Bug 해결

 

[오류를 가정한 템플릿]

현재 에러가 발생하여 pay 버튼을 클릭했을 때 아무런 반응이 없습니다. 이를 정상적으로 만들어봅시다.

 

[정상적인 템플릿]

[템플릿 코드]

https://github.com/MachDn/payment-error-cicd

https://hub.docker.com/repository/docker/moveho/payment/general

 

[사용 서버 및 네트워크 설정]

Oracle VM (Ubuntu 20.04) // 192.168.56.111 <1>

네트워크 어댑터 1: NAT // 네트워크 어댑터 2: 호스트 전용 어댑터

 

1.[프로젝트 환경 구성]

1.  본인의 Git HubGit repo에 등록해줍니다.

2.  git clone 명령어로 본인의 VM에 제공 소스 코드를 복사해 옵니다.

git clone https://github.com/MachDn/payment-error-cicd.git
cd payment-error-cicd

1.  본인의 git repo에 소스 코드를 push 해줍니다.

 

git init .
git config --global user.email "you@example.com"
git config --global user.name "Your Name"

git add .
git commit -m “test”

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

git push

Username for 'https://github.com': 본인의 깃허브 닉네임
Password for 'https://MachDn@github.com': 깃허브 토큰 값

git add .
commit -m "test push"
[master db5ccaf] test push
 1 file changed, 1 insertion(+), 1 deletion(-)
git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 286 bytes | 286.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:MachDn/payment-error-cicd.git
   e3d1be7..db5ccaf  master -> master

다음과 같이 소스 코드들이 잘 push 된 모습을 볼 수 있습니다.

 

2.[git action Workflow 생성]

1.   git repo 상단의 Action을 클릭합니다.

2.   Set up a workflow yourself 클릭합니다.

3.   다음과 같이 workflow 작성 후 Commit changes 를 클릭합니다. (workflow 내용은 하단 3. 참조)

 

4. Commit changes 버튼을 클릭합니다

5. 확인

Workflow를 등록하게 되면 다음과 같이Workflow가 생성된 모습을 볼 수 있습니다.

 

3. git action Workflow 작성 참조

name: Update Docker container on VM

on:
  push:
    branches: [ master ]

jobs:
  build-and-deploy:
    runs-on: self-hosted          # git runner를 설정해서 self-hosted 기반 서버
    timeout-minutes: 20           # timeout 옵션을 넣어서 충분한 시간 제공
    steps:
    - name: Checkout
      uses: actions/checkout@v2
      
    - name: Login to Docker Hub               # Docker Hub 로그인
      uses: docker/login-action@v1
      with:
        username: ${{ secrets.DOCKER_HUB_USERNAME }}
        password: ${{ secrets.DOCKER_HUB_PASSWORD }}
    - name: Build and push Docker image       # Docker push 이미지 최신화
      uses: docker/build-push-action@v2
      with:
        push: true
        tags: moveho/payment:latest

    - name: SSH into VM and update Docker container  # SSH로 VM 접근하여 sh 실행
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SSH_HOST }}
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.SSH_PRIVATE_KEY }}
        port: ${{ secrets.SSH_PORT }}
        script: |
          cd /home/kevin/payment-error-cicd     # VM에서 실행할 스크립트 작성
          sh cicd.sh				# 프로젝트 디렉터리로 들어와 설정해둔 sh 실행 
        timeout: 1m

Cicd.sh 파일 docker compose down 으로 컨테이너 종료 후 최신 도커 이미지를 받아 다시 컨테이너 실행하는 스크립트.

 

4.[Secret 생성]

 

Git repo -> Settings -> Secrets and variables -> actions 경로에 생성 가능

${{ secrets.DOCKER_HUB_USERNAME }}   # 도커허브 로그인 아이디
${{ secrets.DOCKER_HUB_PASSWORD }}   # 도커허브 비밀번호
${{ secrets.SSH_HOST }}                   # VM의 IP 주소
${{ secrets.SSH_USERNAME }}             # VM의 Username
${{ secrets.SSH_PRIVATE_KEY }}          # VM에서 발급 받은 RSA KEY (하단 설명 참조)
${{ secrets.SSH_PORT }}                   # 사용하는 SSH PORT 보통 22 사용

다음과 같은 형태로 Name KEY SecretValue 형태로 넣어주면 됩니다.

PRIVATE_KEY 값에는 id_RSA 키 값을 넣어주면 됩니다 (하단 설명 참조)

 

다음과 같은 형태로 필요한 Secret 값을 모두 생성해줍니다.

 

5.[.SSH RSA KEY PAIR 생성]

ssh-keygen -t rsa -b 4096 -C “[git hub 이메일 주소]”       # 키 생성 이후 Enter
chmod 700 .ssh
cat $HOME/id_rsa.pub >> $HOME/.ssh/authorized_keys
cat $HOME/id_rsa >> $HOME/.ssh/authorized_keys

키값을 Secret 값에 등록할 때,

 

-----BEGIN OPENSSH PRIVATE KEY-----
여기 안에 들어간것만 넣어주는게 아니라 위 아래 --- 까지 다 넣어야 됩니다.
-----END OPENSSH PRIVATE KEY-----

 

 

6.[docker-compose up로 컨테이너 실행]

cd payment-error-cicd
docker-compose up -d     #docker compose 데몬으로 실행
docker ps -a               #docker ps 확인

Error 가 발생한 page 가 나타납니다.  Pay error 버튼에 눌러도 아무런 반응이 없습니다.

 

 

7.[GitHub Action Runner 설정]

https://github.com/MachDn/payment-error-cicd/settings/actions/runners/new?arch=x64&os=linux

Runner 설정 url 참조 Download 진행하면 됩니다.

 

mkdir actions-runner && cd actions-runner

curl -o actions-runner-linux-x64-2.303.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.303.0/actions-runner-linux-x64-2.303.0.tar.gz

echo "e4a9fb7269c1a156eb5d5369232d0cd62e06bec2fd2b321600e85ac914a9cc73  actions-runner-linux-x64-2.303.0.tar.gz" | shasum -a 256 -c

tar xzf ./actions-runner-linux-x64-2.303.0.tar.gz

./config.sh --url https://github.com/MachDn/payment-error-cicd --token [토큰값]

./run.sh

다음과 같은 창을 만날수 있습니다. ./run.sh 를 실행 시킨 상태에서 수정 및 push를 진행 하겠습니다.

 

8.[CI/CDerror 수정 및 배포]

Index.html 파일

cd /payment-error-cicd
vi index.html

56 번째 줄 코드 button 이름 pay error è pay로 수정

60번째줄 코드 const successMessage = document.getElementById(“success-message”); 추가

 

수정 =>  git push => 설정해둔 git action 확인

 

git add .
git commit -m “good work page”
git push

36초 정도 소요되며 정상적으로 수정사항이 배포되어 적용되었는지 확인.

 

다음과 같이 github runner log로도 ci/cd가 잘 완료 되었는지 확인할 수 있다.

 

SSH VM에 정상적으로 접근하여 설정해둔 sh 셸스크립트가 작동한 모습..

 

 

 

Localhost로 접속 후 새로고침 하면 수정사항이 바뀌어 배포 된 것을 확인할 수 있음. 버튼 이름과, 버튼을 클릭 했을 때 정삭적으로 완료되었다는 문구가 나오는 것을 확인 할 수 있습니다.

 

만약 이 상황이 실제였다면 현재 진행한 프로젝트에서는 load-balancer 없이 한 개의 container로만 진행 하다보니 업데이트 중간에 서비스가 실행되지 않는 공백시간이 발생했습니다. 하지만 이를 kubernetespodcontainer로서 운영 한다면 이런 Update 또한 중단없이 무중단업데이트 rolling update를 진행할 수 있겠다라는 생각을 했습니다. Ci/CD Git action을 통해 진행하면서 secret keypair, 네트워크 등 관련 내용들도 많이 배울수 있었습니다. 추후에는 k8s 를 통해 cicd를 무중단으로 업데이트 하는 프로젝트로 만나뵙겠습니다. 감사합니다.

댓글