앞의 포스팅을 통해 라즈베리파이의 운영체제 설치 및 쿠버네티스 클러스터 환경 세팅이 끝났다. 이제 배포 지점이 될 클러스터의 세팅을 끝내고 본격적으로 CI/CD를 구현할 차례이다. 이번 포스팅에서는 깃허브에서 제공하는 Github Actions를 쓸 예정이다.
중간에 도커라이징하는 부분이 들어가는데, Dockerfile을 작성하는 방법에 대해서는 이번 포스팅에서 다루지 않는다. 관련하여 포스팅을 작성한 부분을 참고 링크로 달아두기만 하겠다.
본론
CI/CD란?
CI/CD (Continuous Intergration/Continuous Delivery)는 애플리케이션 개발 단계를 자동화하여 애플리케이션을 더욱 짧은 주기로 고객에게 제공하는 방법을 의미한다. CI/CD의 기본 개념은 지속적인 통합, 지속적인 서비스 제공, 지속적인 배포입니다. CI/CD는 새로운 코드 통합으로 인해 개발 및 운영팀에 발생하는 문제(일명 "통합 지옥(intergration hell)")를 해결하기 위한 솔루션입니다. - Redhat
CI/CD의 정의는 위와 같은데, 하나하나씩 실제 사례를 들어 살펴보도록 하겠다. 설명이 필요하지 않은 사람들은 이 섹션을 스킵해도 좋을 것 같다
짧은 주기로 제공?
우리가 애플리케이션의 소스 코드를 수정하여 애플리케이션의 버전이 올라갔다고 치자. 이 때, 배포 지점의 컴퓨터에 ssh로 붙어서, 소스 코드를 업데이트하고, java -jar 커멘드나 node main.js 등의 명령어를 사용하는 가장 기본적인 방법은, 굉장히 번거로우며 실수가 날 수도 있다. 이러한 번거로운 과정을 자동화 시켜주는 것을 CI/CD라고 부르며, 개발자는 그저 깃허브에 코드를 올리는 것만 하면 된다.
이후의 빌드 및 테스트 등의 모든 과정을 CI/CD 파이프라인이 대신해주게 된다. 이러한 과정을 통해 짧은 주기로 빠르게 소스 코드를 업데이트하고 배포하는 과정까지 도착할 수 있게 된다.
통합 지옥?
CI/CD 파이프라인이 없다고 가정해보자. 다양한 개발자들이 달라붙어 여러 PR을 만들고 main 브랜치에 한 번에 머지하였다. 이제, 누군가 배포 서버에서 여러 PR들이 머지된 코드를 내려받고 실행시킨다고 치자. 이때, 다양한 이유로 에러가 날 가능성이 있다.
PR 여러개를 한 번에 머지하고 나서 배포하는 과정에서 에러가 났다고 생각해 보자. 이렇게 되면 하나하나씩 PR을 리버트 하면서 문제 원인을 찾아야 한다. 누군가 실수로 빌드가 되는 것을 체크하지 않았다거나, 테스트를 하지 않았다거나, 혹은 운영 파일을 업데이트 하지 않은 이유로 문제가 생기는 것이다.
이렇게 개발자가 빌드를 체크하고, 테스트하는 등의 일련의 과정을 파이프라인으로 구축한 것을 CI/CD라고 부른다. 이를 통해 매 PR마다 다양한 검수 과정을 거친 후(CI) 서비스 지점에서 배포가 된다(CD) 이것을 CI/CD 파이프라인이라고 부른다.
이번 시리즈에서 이러한 CI/CD의 구축을 할 때, CI는 Github actions를 통해 구현할 예정이고, CD는 ArgoCD를 통해서 구현할 예정이다. 이번에는 Github actions를 통해 빌드, 테스트의 과정을 자동화하여 도커 이미지로 만들어 도커 허브에 업로드하는 과정을 포스팅할 예정이다.
본론
Github Actions는 github에서 제공하는 CI 및 CD 툴이다. 사용하는 방법은 간단하다. 레포지토리의 root 디렉토리에 .github/workflow 안에 yaml 파일로 작업을 정의하면 된다. 이번에는 ruby on rails 프레임워크를 사용하는 레포지토리의 CI를 구현해 보도록 한다.
우리는 위 사진을 기준으로 Continuous Intergration & Continuous Delivery 하는 과정까지를 구현할 것이다. CI를 구현할 레포지토리에 들어가 상단에 있는 Actions 섹션을 선택한다.
Github에서 레포지토리의 상태를 파악하고 다양한 configure들을 제시해 준다. 대충 설명을 읽어보니 Docker image와 Ruby on Rails의 Configure가 필요해 보인다.
- Continuous Intergration : Ruby on Rails Configure
- Continuous Delivery : Docker image Configure
먼저 Ruby on Rails에 대한 Configure를 진행하자.
해당 yml 파일을 읽어보면 무슨 일이 일어나는지 다음과 같이 요약할 수 있다. main 브랜치에 푸시하거나 PR을 올리면 다음 순서대로 실행된다.
- ubuntu OS에서 이후의 명령어들을 실행시킬 준비
- 테스트용 postgres 11 버전을 깔아서 먼저 실행
- 환경 파일을 설정해서 테스트용 postgres 11을 연결시키는 코드 추가
- ruby on rails 레포지토리이기 때문에 실행에 필요한 Ruby와 gems를 설치 ( 이런 것들을 쓴다고 한다 )
- 데이터베이스 연결
- 테스트 ( using rake )
- lint 실행 ( using rubocop )
위 스크립트를 기본적은 스키마이기 때문에 그대로 가져다 쓰지 말고, 개인의 프로젝트에 맞게 바꿔서 써야 한다. 레일즈가 아닌 다른 프로젝트의 CI 파이프라인을 만드는 경우에는 알아서 깃허브에서 맞는 configure를 추천해 준다. 현재 이 프로젝트는 일단 데이터베이스를 붙이지 않았고, lint를 사용하지 않는다. 따라서 기존의 yml 파일을 다듬어 다음의 구조만 남기도록 한다.
- ubuntu OS에서 이후 명령어들을 실행시킬 준비
- ruby on rails 레포지토리이기 때문에 실행에 필요한 Ruby와 gems를 설치
- 테스트 ( using bin/rake )
위 과정만 실행한다고 하면 CI 파일은 다음과 같이 정의할 수 있다. 다음과 같이 yml 파일을 작성한 후 우측 상단에 있는 Commit change.. 버튼을 누르면 알아서 .github/workflows 에 CI 파일이 추가된다.
name: "Ruby on Rails CI"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install Ruby and gems
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
with:
bundler-cache: true
- name: Run tests
run: bin/rake
.github/workflows 디렉터리에 yml 파일을 만들고 나서 정의된 동작을 수행하면 ( 위 경우에서는 메인 브랜치에 푸시하거나 PR 하는 경우 ) 다음의 jobs가 실행된다. 여기까지가 아주 간략하게 만든 CI이다. 정상적으로 jobs를 통과하면 다음과 같은 녹색 체크 표시를 볼 수 있다. 이제 도커 허브에 이미지를 업로드하는 continuous delivery 과정을 만들어보자.
다시 github actions 페이지로 돌아와 깃허브에서 제안하는 docker image configure를 눌러보면 다음과 같은 스크립트를 확인할 수 있다. 다음 스크립트는 Local docker hub에 업로드하는 스크립트이기 때문에 그대로 가져다 쓸 수는 없을 것 같다. public hub에 업로드하기 위해서는 docker에 로그인하는 과정을 추가해야 한다.
다음 링크를 참고하여 docker hub에 업로드하는 job을 추가하자. 다음 링크에 따라 퍼블릭 도커 허브에 업로드하는 ci.yml은 밑에 남겨두었다.
도커 허브에 업로드하는 과정은 로그인을 필요로 하기 때문에 Settings - Secrets and variables에 DOCKER_PASSWORD 및 DOCKER_USERNAME을 업로드한다.
시크릿 값 세팅이 끝났으면 다음과 같이 CI 스크립트를 작성한다.
name: "Ruby on Rails CI"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
continuous-integration:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install Ruby and gems
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
with:
bundler-cache: true
- name: Run tests
run: bin/rake
continuous-delivery:
needs: continuous-integration
runs-on: ubuntu-latest
steps:
- name: Checkout out the repo
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ secrets.DOCKER_USERNAME }}/uos-status
- name: Build and push Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
그 후, 깃허브 액션의 동작을 살펴보면 다음과 같이 동작한다.
빌드 및 테스트, 도커 이미지 업로드 등 모든 과정에 문제가 없이 실행되면 다음과 같은 표시가 뜨고, 정상적으로 도커 허브에 도커 이미지가 업로드된다.
마치며
이번 포스팅을 통해서 Github actions를 통해서 정상적으로 도커 허브에 이미지를 업로드하는 로직을 작성했다. 이제 다음 포스팅에서는 GitOps 툴인 ArgoCD를 라즈베리파이 서버에 설치함으로써 업로드된 도커 이미지 파일을 통해 배포하는 CD(Continuous Deployment)를 구현하도록 하겠다.
'DevOps > kubernetes' 카테고리의 다른 글
ETCD Leader Election이란? (1) | 2024.12.18 |
---|---|
Kubernetes의 Ingress와 Service 차이점에 대한 고찰 (0) | 2024.12.17 |
로컬 쿠버네티스 클러스터 환경 세팅 ( feat. minikube, lens ) (1) | 2024.12.16 |
[K8s homeserver 구축 - 2] 라즈베리파이 K3s 클러스터링 (0) | 2023.11.09 |
[K8s homeserver 구축 - 1] 라즈베리파이4 기본 설정 (1) | 2023.11.08 |