Git hub

[GIT] github-action으로 빌드, 쿠버네티스 클러스터에 배포하기 (with Naver Cloud Platform)

코끼리 개발자 2024. 3. 22. 16:19
728x90
SMALL

 

 

 

github action을 통해 소스코드 커밋 혹은 머지 시 빌드와 테스트 하고,

NCP Container Registry로 이미지 push 후 다시 pull 받아 쿠버네티스 클러스터에 Rolling Update 배포 전략을 사용하여 배포하는 방법에 대해 정리해보았다.

 

NCP kubernetes 환경 구축 방법은 아래 포스팅을 참고하면 된다.

 

- [NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편

 

[NCP] Ncloud Kubernetes Service 사용하기(+ Container Registry 사용 까지) - 1편

프로젝트를 진행하면서, 롤링 업데이트 배포 전략을 사용하기 위해 F-Lab을 통해 네이버 클라우드 플랫폼 에서 사용할 수 있는 크레딧을 제공 받아NCP에서 제공해주는 쿠버네티스를 이용해 보았

elephant-dev.tistory.com

 

 

- [NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편

 

[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편

1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는

elephant-dev.tistory.com

github-action을 통해 내가 얻고 싶은 결과물은 위의 그림과 같다

 

1. 개발자가 소스코드를 GitHub에 커밋 시 (main으로)

2. 소스코드 빌드 수행

3. 단위 테스트 수행

4. Docker Image 생성

5. Image를 NCP Container Registry에 업로드

6. NCP Container Registry에서 이미지를 pull받아 쿠버네티스 클러스터에 롤링업데이트 배포

7. 실패 시 롤백

 

 

우선 처음부터 차근차근 gihub action 사용을 위한 방법을 알아가보자

 


1. github-action workflow 생성

 

github에서 github-action을 만들고 싶은 프로젝트에 들어가 상단 카테고리 중 Actions를 클릭한다.

그러면 아래와 같이 여러 종류의 템플릿이 나온다.

자신의 프로젝트에 맞게 선택해주면 되는데, 나의 경우 java with gradle을 선택했다.

 

 Configure 버튼을 누르면 다음과 같이 내 프로젝트에 .github/workflows/gradle.yml 파일을 편집하고 저장할 수 있는 창이 

열리게 된다.

 

 

여기에서 윗 부분만 기본적으로 설명하자면 아래와 같다

참고로 yml 파일은 공백을 따라 인식하니 주의해서 작성, 수정 해야한다.

name: Java CI with Gradle # CI 이름

on:  # 언제 시작할건가
  push: # push 될 때
    branches: [ "main" ] # main branch에
  pull_request: # pull_request가 열릴 때
    branches: [ "main" ]  # main branc로
    
runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 17 
      uses: actions/setup-java@v4
      with:
        java-version: '17' ## java 버전에 맞게 수정
        distribution: 'temurin'

 

 

그다음은 빌드에 필요한 것들이 있다면 부가적으로 설정 가능하다,

gradlew 권한 부여와 서버에 필요한 key.properties를 만들도록 추가할 수 있다.

 - name: Create keys.properties file
        run: | 
          echo url=${{ secrets.DATABASE_URL }} > src/main/resources/keys.properties
          echo username=${{ secrets.DATABASE_USERNAME }} >> src/main/resources/keys.properties
          echo password=${{ secrets.DATABASE_PASSWORD }} >> src/main/resources/keys.properties

- name: Grant Execute Permission to Gradlew
       run: chmod +x ./gradlew

 

중요한 정보들은 GitHub의 secrets를 이용할 수 있다. 

프로젝트의 상단 카테고리 중 settings를 누르고 들어가 등록해주면 된다.

 

이제부터 github-action에서 쓰일 비밀번호나 키와 같은 가려져야하는 항목들은 이곳에 등록해서 사용하면 된다.

앞으로 나올 모든 secrets.xxx는 다 이곳에 등록된 키 값들이다.

 

다음은 빌드와 유닛 테스트 설정이다.

빌드와 동시에 test를 실행하고 싶다면 ./gradlew build로 두면 되고, test와 build를 분리하고 싶다면 아래와 같이 

분리하면 된다.

 

테스트와 빌드를 분리하는 것은 정확히 어떤 스텝에서 문제가 생겼는지 판단 할 때 유용하게 쓰인다.

그리고  빌드와 테스트가 완료된다면 도커 이미지로 빌드하고 NCP Container Registry에 이미지를 업로드 하도록 했다.

태그는 고유값을 가지도록 github.sha를 이용했다.

- name: Setup Gradle
  uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

- name: Build with Gradle Wrapper
  run: ./gradlew build -x test

- name: Run Unit Tests
  run: ./gradlew test

- name: NCP Container Registry push
   run: |
      echo "${{ secrets.API_PASSWORD }}" | docker login ${{ secrets.NCP_CONTAINER_URL }} --username ${{ secrets.API_KEY_ID }} --password-stdin
      docker build -t ${{ secrets.NCP_CONTAINER_URL }}/melody-market:${{ github.sha }} .
      docker push ${{ secrets.NCP_CONTAINER_URL }}/melody-market:${{ github.sha }}

 

 

 

여기에 필요한 키 값들은 

 

[NCP] Ncloud Kubernetes Service 사용하기(kubectl 사용하여 pod 생성하기) - 2편

1편에 이어 2편에서는 cluster와 상호작용하기 위해 서버에 접속하여 pod를 생성하는 작업을 진행해보려고 한다. *pod 내부에서 외부로 접속되지 않는 현상으로 인해 문제가 있었고 이를 해결하는

elephant-dev.tistory.com

위 포스트에 아래 부분을 확인하면 된다!

 

 

이 부분은 그래프로 표현하는 부분이니 수정하지 않도록 하겠다.

 dependency-submission:

    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      # Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies.
      # See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md
      - name: Generate and submit dependency graph
        uses: gradle/actions/dependency-submission@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

 

 

다음은 정말 오류가 많이 나서 힘들었었던.. deploy 부분이다

 

deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
        - name: SSH and Deploy to Kubernetes
          uses: appleboy/ssh-action@master
          with:
            host: ${{ secrets.SERVER_HOST }}
            username: ${{ secrets.SERVER_USERNAME }}
            key: ${{ secrets.NCP_KEYFILE }}
            script: |
              echo "${{ secrets.API_PASSWORD }}" | docker login ${{ secrets.NCP_CONTAINER_URL }} --username ${{ secrets.API_KEY_ID }} --password-stdin
              # Kubernetes 배포 명령 실행
              export NCLOUD_ACCESS_KEY=${{ secrets.NCLOUD_ACCESS_KEY }}
              export NCLOUD_SECRET_KEY=${{ secrets.NCLOUD_SECRET_KEY }}
              export NCLOUD_API_GW=https://ncloud.apigw.ntruss.com
              export NCLOUD_PROFILE=project
              export PATH=$PATH:$HOME/bin
              kubectl --kubeconfig="/root/kubeconfig.yml" set image deployment/melody-deployment melody=melody.kr.ncr.ntruss.com/melody-market:${{ github.sha }} --record
              # 배포 상태 확인 및 롤백 처리
              if ! kubectl --kubeconfig="/root/kubeconfig.yml" rollout status deployment/melody-deployment --timeout=60s; then
                echo "Deployment failed, starting rollback..."
                kubectl --kubeconfig="/root/kubeconfig.yml" rollout undo deployment/melody-deployment
                echo "Rollback completed."
              else
                echo "Deployment succeeded."
              fi

 

잘못 설정 시 문제가 생길 여지가 많은 부분이므로 하나씩 설명하겠다

 

ssh로 kubectl이 설치된 서버에 접속해서 deploy 하도록 하는 스크립트이다.

 

먼저 with절을 보면 접속할 서버의 IP와 Username과 Keyfile을 제공해야한다.

만일 클래식을 사용하고있는 사람들이라면 서버 접속 전용 IP와 port를 제공해야하며,

VPC 사용자라면 public IP로 포트 없이 접속하면 된다 ssh 접속 포트인 22번을 사용하게되기 때문이다.

          with:
            host: ${{ secrets.SERVER_HOST }}
            username: ${{ secrets.SERVER_USERNAME }}
            key: ${{ secrets.NCP_KEYFILE }}

 

여기서 NCP_KEYFILE이란? 서버에서 ssh 접속 가능하도록 설정해주어야한다. 

 

 

우선 eploy를 실행하려는 NCP 서버에 접속해야한다.

그 다음 아래와 같은 명령어를 수행한다.

openssl genrsa -out ssh_key.pem 4096
chmod 600 ssh_key.pem
mkdir .ssh
ssh-keygen -y -f ssh_key.pem > .ssh/authorized_keys
chmod 700 .ssh
chmod 600 .ssh/authorized_keys
systemctl restart sshd

모든 작업은 root로 수행 했고, root로 접속해서 deploy할것이라 다른 계정에 대한 내용은 없으니 주의하여야 한다.

다른 계정으로 수행하는 경우 해당 계정에서 수행해 주어야 한다.

 

그 다음 ssh_key.pem을 vi로 열어 내용을 복사해서 github secret에 넣어주면 된다.

그 내용이 위에 key: ${{ secrets.NCP_KEYFILE }}에 해당 된다.

 

다음은 서버에 접속해서 수행할 deploy script 작성 부분이다.

 script: |
              echo "${{ secrets.API_PASSWORD }}" | docker login ${{ secrets.NCP_CONTAINER_URL }} --username ${{ secrets.API_KEY_ID }} --password-stdin
              # Kubernetes 배포 명령 실행
              export NCLOUD_ACCESS_KEY=${{ secrets.NCLOUD_ACCESS_KEY }}
              export NCLOUD_SECRET_KEY=${{ secrets.NCLOUD_SECRET_KEY }}
              export NCLOUD_API_GW=https://ncloud.apigw.ntruss.com
              export NCLOUD_PROFILE=project
              export PATH=$PATH:$HOME/bin
              kubectl --kubeconfig="/root/kubeconfig.yml" set image deployment/melody-deployment melody=melody.kr.ncr.ntruss.com/melody-market:${{ github.sha }} --record
              # 배포 상태 확인 및 롤백 처리
              if ! kubectl --kubeconfig="/root/kubeconfig.yml" rollout status deployment/melody-deployment --timeout=60s; then
                echo "Deployment failed, starting rollback..."
                kubectl --kubeconfig="/root/kubeconfig.yml" rollout undo deployment/melody-deployment
                echo "Rollback completed."
              else
                echo "Deployment succeeded."
              fi

 

 

참고로 내가 작성한 포스트를 따라 여기까지 왔다면 위의 설정값이 모두 맞을지 모르지만 그게 아니라면 

자신의 환경에 맞게 수정해주어야 한다.

 

bash에 작성된 환경 설정들이 ssh 접속 시 반영되지 않기 때문에 꼭 필요한 것들을 다 export 해주고 시작해야 에러 없이 
잘 진행되므로 위와 같이 자신에 환경에 필요한 export를 해주어야 한다.

저 부분을 설정해주지 않아 여러가지 에러가 발생해서 고생했었다..

 

 

이 방법외에 NCP에서 제공하는 sourceBuild와 sourceDeploy를 활용해서 배포가 가능하긴 하지만 비용적인 절약을 위해

직접 ssh로 붙어 빌드된 image를 배포하는 형태를 채택하였다.

728x90
LIST