사이드 프로젝트를 하면서 CI/CD를 적용해야 할 필요성을 느꼈고 어떤 방식으로 할지 고민했다.
이전 프로젝트에서는 github action으로 CI를 하고 jenkins로 CD를 진행했었는데 이번에는 github action과 도커와 쿠버네티스를 적용해볼 생각이였다.
도커와 쿠버네티스를 이용하는 이유는 이식성과 자가 치유, 오토스케일링, 로드밸런싱을 손쉽게 적용할 수 있기 때문이다.
Cloud 환경은 gcp를 택했다. aws 프리 티어에서는 할 수 있는 것이 많지 않아 gcp에서 주는 300달러 무료 크레딧을 가지고 활용하기로 했다.
서비스 계정에는 Docker image를 Artifact Registry에 푸시하고, GKE에서 Deployment를 만들고,
파드 컨테이너 내에서 이미지를 가져오는 데 필요한 모든 권한이 있다.
새 서비스 계정을 생성하려면 앞서 언급했던 작업을 수행할 수 있도록 역할을 할당해야 한다.
일단은 이 서비스 계정에 대한 JSON 키를 생성하는 것이다. 이 키는 github action에서 gcp에 대한 인증을 위해 사용된다.
IAM 및 관리자 -> 서비스 계정 -> 키 관리로 이동한다.
아래의 이미지와 같이 새키 만들기를 눌러준다.
Json을 선택하고 만들기를 누른다. 해당 파일을 안전하게 저장
위에 언급했듯이 이 키는 github action에서 gcp에 대한 인증을 위해 사용된다.
키에 대한 준비가 끝났다면 이제는 쿠버네티스 클러스터를 생성해준다.
클러스터가 생성되었다면 1차적인 준비는 끝이 났다.
github action cd과정에 대한 yml파일은 아래와 같다.
name: cd for click-service
on:
push:
branches: [ main ]
paths:
- click-service/**
- .github/**
env:
PROJECT_ID: ${{ secrets.PROJECT_ID }}
DOCKER_REPO: ${{ secrets.DOCKER_REPO }} #Artifact registry
REGION: ${{ secrets.REGION }}
WORKSTATION_IMAGE: click-service
VERSION: '1.0.1'
IMAGE: ${{ secrets.REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/${{ secrets.DOCKER_REPO }}/click-service
REDIS_HOST: ${{secrets.REDIS_HOST}}
REDIS_PORT: ${{secrets.REDIS_PORT}}
DATASOURCE_URL: ${{secrets.DB_URL}}
DATASOURCE_USERNAME: ${{secrets.DB_USERNAME}}
DATASOURCE_PASSWORD: ${{secrets.DB_PASSWORD}}
jobs:
build:
runs-on: ubuntu-22.04
steps:
- name: Check out Repository
uses: actions/checkout@v3
- name: Cache Gradle caches
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ github.job}}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-gradle-${{ github.job }}
- name: Cache Jib layers
uses: actions/cache@v3
with:
path: ./click-service/build/jib-cache
key: ${{ runner.os }}-jib-${{ github.job }}-${{ hashFiles('**/build.gradle') }}
restore-keys: ${{ runner.os }}-jib-${{ github.job }}
- name: Set up google auth
id: 'auth'
uses: google-github-actions/auth@v1
with:
credentials_json: ${{ secrets.GCE_SA_KEY }}
- id: 'get-credentials'
uses: google-github-actions/get-gke-credentials@v1
with:
cluster_name: autopilot-cluster-2
location: ${{ env.REGION }}
- name: Docker auth
run: |-
gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev --quiet
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Docker Build
run: ./gradlew :click-service:jib
- name: Deploy
run: |
sed "s,\${image},${{ env.IMAGE }},g" ./click-service/resources.yaml > deployment.yaml
kubectl apply -f ./deployment.yaml
kubectl apply -f ./click-service/hpa.yaml
과정을 살펴보면 cd과정을 빠르게 하려고 gradle cache와 jib cache가 있다. jib에 대한 부분은 이 게시글을 살펴보는게 좋다.
Set up google auth
는 gcp에 대한 권한을 가져오는 부분이고
Docker auth
는 docker에 대한 권한을 설정하는 부분이다.
그 이후에는 docker 이미지를 빌드한 후 쿠버네티스에 배포하는 과정이다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: click-service # 이 Deployment의 이름을 지정
spec: # Deployment의 동작을 제어하는 설정
selector: # 이 Deployment가 관리할 파드를 선택하는 레이블 셀렉터를 지정
matchLabels:
app: click-service # app 레이블의 값이 'click-service'인 파드를 선택
strategy:
rollingUpdate: # 롤링 업데이트 전략을 설정
maxSurge: 25% # 업데이트 도중에 추가로 생성할 수 있는 파드의 최대 비율을 지정
maxUnavailable: 25% # 업데이트 도중에 사용할 수 없게 될 수 있는 파드의 최대 비율
replicas: 1 # 이 Deployment에서 유지할 파드의 개수를 지정
template:
metadata:
labels:
app: click-service
spec:
containers:
- name: click-service # 컨테이너의 이름을 지정
image: ${image}:latest # 사용할 도커 이미지를 지정, ${image}는 실제 이미지 이름으로 대체해야함
imagePullPolicy: Always # 항상 최신 이미지를 가져오도록 설정
ports:
- containerPort: 8080 # 컨테이너가 리스닝할 포트를 지정
protocol: TCP # 통신 프로토콜을 TCP로 설정
resources:
requests:
cpu: 500m
memory: 1000Mi
해당 파일에 대한 설명은 주석으로 달아놨으니 그 부분을 살펴보면 좋을 것 같다.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: click-service-hpa # 이 HPA의 이름을 지정
spec:
minReplicas: 1 # 파드의 최소 수를 1개로 설정
maxReplicas: 10 # 파드의 최대 수를 10개로 설정
scaleTargetRef: # HPA가 적용될 대상을 지정
apiVersion: apps/v1
kind: Deployment
name: click-service # click-service라는 이름의 Deployment에 이 HPA 설정을 적용
metrics: # HPA가 파드 수를 조정하는 기준이 되는 메트릭을 지정
- type: Resource #메트릭 유형을 리소스로 설정
resource:
name: cpu #CPU 사용률을 파드 조정의 기준으로 사용
target:
averageUtilization: 60 #평균 CPU 사용률이 60%가 넘으면 파드를 늘리고, 미달하면 줄인다.
type: Utilization # 메트릭의 타입을 사용률로 설정
이 설정은 'click-service' Deployment의 평균 CPU 사용률이 60%를 넘어가면 파드를 늘리고, 미달하면 줄이도록 한다.
그리고 파드의 수는 최소 1개에서 최대 10개까지 조절이 가능합니다.
이번 프로젝트를 통해 Docker와 Kubernetes를 활용한 CI/CD의 효율성과 강력함을 직접 경험하게 되었다.
이전에 팀 프로젝트를 진행할 때는 Docker와 Kubernetes를 사용하지 않았다. 그 때는 빌드한 파일을 일일이 VM에 옮겨 실행하는 과정을 Jenkins로 진행했다.
이 과정은 서버가 늘어나면 또 일일히 추가해주는 과정을 필요해 번거로울뿐만 아니라 문제가 발생할 때 롤백하는 스크립트도 작업해줘야 했다.
하지만 이번에 Docker와 Kubernetes를 통해 CI/CD를 구현하면서 많은 편리함을 느꼈다.
먼저, 빌드에 대한 설정파일을 yaml로 관리할 수 있고 실패한 경우 이전에 성공적으로 배포된 이미지로 롤백하는 기능은 서비스의 안정성을 크게 향상시켰습니다.
그리고 가장 인상 깊었던 것은 Kubernetes의 오토스케일링 기능이다.
이 기능 덕분에 서비스의 트래픽 변화에 따라 자동으로 스케일 아웃하거나 스케일 인할 수 있다. 이를 통해 자원을 효율적으로 활용하면서도 서비스의 안정성을 유지할 수 있었다.
구현한 내용들은 여기에서 확인이 가능하다.
Spring Batch 파티셔닝 적용후 JVM이 종료되지 않는 문제 해결 (0) | 2024.05.03 |
---|---|
Redis의 클릭 카운트 MySQL로 데이터 동기화 (2) (0) | 2023.12.22 |
Redis의 클릭 카운트 MySQL로 데이터 동기화 (1) (0) | 2023.12.15 |
Jib을 이용한 CD 최적화: Layer 캐싱 활용 (0) | 2023.11.30 |
github에서 README.md이미지 업데이트 문제: Camo와 캐싱 이슈 해결하기 (0) | 2023.10.20 |