본문 바로가기
대외활동/Google Cloud Study Jam

[Kubernetes 입문] Continuous Delivery with Jenkins in Kubernetes Engine

by 드인 2022. 7. 31.

Continuous Delivery with Jenkins in Kubernetes Engine


Continuous Delivery with Jenkins in Kubernetes Engine

 

Kubernetes Engine에서 Jenkins로 지속적 배포 | Google Cloud Skills Boost

이 실습에서는 Kubernetes 엔진에서 실행되는 Jenkins를 사용하여 지속적 배포 파이프라인을 배포하고 완전하게 구성하며 개발-배포 프로세스를 진행합니다.

www.cloudskillsboost.google

1. 개요

 - 목표: Kubernetes 엔진에서 Jenkins으로 continuous delivery 파이프라인을 설정

 - Jenkins: 공유 저장소에 코드를 자주 통합하는 개발자를 위한 자동화 서버

 - 구축 솔루션

1) 쿠버네티스 엔진

 - 쿠버네티스의 Google Cloud 호스팅 버전 → 컨테이너를 위한 강력한 클러스터 관리자 및 조정 시스템

 - 노트북에서 고가용성 다중 노드 클러스터에 이르기까지 다양한 환경에서 실행할 수 있는 오픈 소스 프로젝트

 

2) 젠킨스

 - 빌드, 테스트 및 배포 파이프라인을 유연하게 오케스트레이션할 수 있는 오픈 소스 자동화 서버

 - 개발자가 지속적 배포에서 발생할 수 있는 오버헤드 문제와 상관없이 프로젝트를 빠르게 반복 가능

 

3) 지속적 전달 / 지속적 배포(Continuous Delivery / Continuous Deployment)

 - CD(지속적 전달) 파이프라인을 설정하면, Kubernetes Engine에 Jenkins를 배포할 때 표준 VM 기반 배포보다 유리

 - 빌드 프로세스에서 컨테이너를 사용하는 경우 하나의 가상 호스트가 여러 운영 체제에서 작업을 실행

  •  Kubernetes Engine의 ephemeral build executors는 빌드가 활발하게 실행 중일 때만 활용되며 일괄 처리 작업과 같은 다른 클러스터 작업을 위한 리소스를 남겨둠

  - Kubernetes Engine에는 Google의 글로벌 로드 밸런서가 사전 장착되어 있어 인스턴스로의 웹 트래픽 라우팅을 자동화하는 데 사용 가능

  •  로드 밸런서는 SSL 종료를 처리하고 웹 프런트와 결합된 Google의 백본 네트워크로 구성된 전역 IP 주소를 활용
  •  로드 밸런서는 항상 사용자에게 애플리케이션 인스턴스에 대한 가능한 가장 빠른 경로를 설정

 

2. 설정 및 요구 사항

 - Google Cloud Platform(GCP) 환경 설정


3. Task 1. Download the source code

1) 영역 설정

gcloud config set compute/zone

 

2) 샘플 코드 복사

gsutil cp gs://spls/gsp051/continuous-deployment-on-kubernetes.zip .
unzip continuous-deployment-on-kubernetes.zip

 

3) 디렉토리 변경

cd continuous-deployment-on-kubernetes

 

4. Task 2. Provisioning Jenkins

1) Kubernetes 클러스터 만들기

 (1) Kubernetes 클러스터 프로비저닝

gcloud container clusters create jenkins-cd \
--num-nodes 2 \
--machine-type n1-standard-2 \
--scopes "https://www.googleapis.com/auth/source.read_write,cloud-platform"

 

 (2) 클러스터 실행 확인

gcloud container clusters list

 

 (3)  클러스터 자격 증명

gcloud container clusters get-credentials jenkins-cd

 

 (4) 클러스터에 연결 가능한지 확인

kubectl cluster-info

  - Kubernetes Engine은 이러한 자격 증명을 사용하여 새로 프로비저닝된 클러스터에 액세스


5. Task 3. Setup Helm

- Helm: Kubernetes 애플리케이션을 쉽게 구성하고 배포할 수 있게 해주는 패키지 관리자 

1) Helm의 안정적인 차트 저장소 추가

helm repo add jenkins https://charts.jenkins.io

 

2)  리포지토리가 최신 상태 확인

helm repo update


6. Task 4. Configure and Install Jenkins

- Jenkins 설치 시 values파일을 템플릿으로 사용하여 설정에 필요한 값을 제공할 수 있음

- 사용자 지정 values파일을 사용하여 Kubernetes 클라우드를 자동으로 구성하고 다음 필수 플러그인을 추가

  • Kubernetes:1.29.4
  • Workflow-multibranch:latest
  • Git:4.7.1
  • Configuration-as-code:1.51
  • Google-oauth-plugin:latest
  • Google-source-plugin:latest
  • Google-storage-plugin:latest

1) 사용자 지정 values파일 다운로드

gsutil cp gs://spls/gsp330/values.yaml jenkins/values.yaml

 

2) Helm CLI를 사용하여 구성 설정으로 차트 배포

helm install cd jenkins/jenkins -f jenkins/values.yaml --wait

 

3) Jenkins 포드가 Running상태로 전환되고 컨테이너가 READY 상태인지 확인

kubectl get pods

 

4) 클러스터에 배포할 수 있도록 Jenkins 서비스 계정 구성

kubectl create clusterrolebinding jenkins-deploy --clusterrole=cluster-admin --serviceaccount=default:cd-jenkins

 

5) Jenkins UI로 포트 전달 설정

export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/component=jenkins-master" -l "app.kubernetes.io/instance=cd" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 8080:8080 >> /dev/null &

 

6) Jenkins 서비스 생성 확인

kubectl get svc

- Jenkins 마스터가 요청할 때 빌더 노드가 필요에 따라 자동으로 시작되도록 Kubernetes 플러그인 사용

- 작업이 완료되면 자동으로 종료되고 리소스가 클러스터 리소스 풀에 다시 추가


7. Task 5. Connect to Jenkins

1) Jenkins 차트가 자동으로 관리자 암호를 생성했는지 확인

printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo

 

2) Jenkins 사용자 인터페이스로 이동

 - Cloud Shell에서 웹 미리보기 버튼을 클릭한 다음 포트 8080에서 미리보기 를 클릭 

 

3) 사용자 이름 admin과 자동 생성된 비밀번호로 로그인


8. Task 6. Understanding the Application

- 연속 배포 파이프라인에서 샘플 애플리케이션 gceme를 배포

  • 애플리케이션은 Go 언어로 작성됨
  • repo의 sample-app 디렉토리에 존재
  • Compute Engine 인스턴스에서 gceme 바이너리를 실행하면 앱이 정보 카드에 인스턴스의 메타데이터를 표시

- 애플리케이션은 두 가지 작동 모드를 지원하여 마이크로서비스를 모방

  • 백엔드 모드 : gceme는 포트 8080에서 수신 대기하고 Compute Engine 인스턴스 메타데이터를 JSON 형식으로 반환
  • 프론트엔드 모드 에서 : gceme는 백엔드 gceme 서비스를 쿼리하고 사용자 인터페이스에서 결과 JSON을 렌더링


9. Task 7. Deploying the Application

- 애플리케이션을 두 가지 다른 환경에 배포

  • 프로덕션 : 사용자가 액세스하는 라이브 사이트
  • 카나리아 : 사용자 트래픽의 일정 비율만 수신하는 소규모 사이트. 이 환경을 사용하여 모든 사용자에게 릴리스되기 전에 라이브 트래픽으로 소프트웨어를 검증

1) 샘플 애플리케이션 디렉터리로 이동

cd sample-app

 

2) 배포를 논리적으로 격리하기 위해 Kubernetes 네임스페이스 생성

kubectl create ns production

 

3) 프로덕션 및 카나리아 배포와 서비스 생성

kubectl apply -f k8s/production -n production
kubectl apply -f k8s/canary -n production
kubectl apply -f k8s/services -n production

 - 프론트엔드의 복제본은 하나만 배포됨 

 

4) 프로덕션 환경 프론트엔드 확장

kubectl scale deployment gceme-frontend-production -n production --replicas 4

 

5) 프론트엔드용으로 5개의 포드, 프로덕션 트래픽용으로 4개, 카나리아 릴리스용으로 1개가 실행 중인지 확인

kubectl get pods -n production -l app=gceme -l role=frontend

  - 카나리아 릴리스에 대한 변경 사항은 사용자 5명 중 1명(20%)에게만 영향을 미침

 

6) 백엔드용 포드 2개(프로덕션용 1개, 카나리아용 1개)가 있는지 확인

kubectl get pods -n production -l app=gceme -l role=backend

 

7) 프로덕션 서비스에 대한 외부 IP 검색

kubectl get service gceme-frontend -n production

 - 외부 IP 를 브라우저에 붙여 넣으면 카드에 표시된 정보 카드를 볼 수 있음

 

8) 프론트엔드 서비스 로드 밸런서 IP를 나중에 사용할 수 있도록 환경 변수에 저장

export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)

 

9) 브라우저에서 프런트엔드 외부 IP 주소를 열어 두 서비스가 모두 작동하는지 확인

 

10) 서비스의 버전 출력을 확인

curl http://$FRONTEND_SERVICE_IP/version

 - 1.0.0


10. Task 8. Creating the Jenkins Pipeline

1) 샘플 앱 소스 코드를 호스팅할 리포지토리 만들기

 (1) gceme 샘플 앱 의 사본 을 만들어 Cloud Source Repository 에 푸시

gcloud source repos create default
git init

 

 (2) sample-app 디렉토리를 자체 Git 리포지토리로 초기화

git config credential.helper gcloud.sh
git remote add origin https://source.developers.google.com/p/$DEVSHELL_PROJECT_ID/r/default

 

 (3) Git 커밋에 대한 사용자 이름과 이메일 주소 설정

git config --global user.email "[EMAIL_ADDRESS]"
git config --global user.name "[USERNAME]"

 

 (4) 파일을 추가, 커밋 및 푸시

git add .
git commit -m "Initial commit"
git push origin master

 

2) 서비스 계정 자격 증명 추가

 - Jenkins가 코드 리포지토리에 액세스할 수 있도록 자격 증명을 구성

 - Jenkins는 Cloud Source Repositories에서 코드를 다운로드하기 위해 클러스터의 서비스 계정 자격 증명을 사용

 

 (1) Jenkins 사용자 인터페이스 의 왼쪽 탐색에서 Jenkins 관리 를 클릭한 다음 자격 증명 관리 를 클릭

 (2) Jenkins를 클릭

 (3) Global credentials (unrestricted)을 클릭

 (4) 왼쪽 탐색 메뉴에서 Add Credentials를 클릭

 (5) Kind drop-downGoogle Service Account from metadata을 선택하고 확인 을 클릭 

  - 글로벌 자격 증명이 추가됨

  - 자격 증명 이름은 CONNECTION DETAILS 랩 섹션 Project ID에서 찾을 수 있음

 

3) Jenkins 작업 만들기

 (1) 왼쪽 패널에서 Dashboard > New Item을 클릭

 (2) 프로젝트 이름을 sample-app으로 지정한 다음 Multibranch Pipeline 옵션을 선택하고 확인을 클릭

 (3) 다음 페이지의 Branch Sources 섹션에서 Add Source를 클릭하고 git을 선택

 (4) Cloud Source Repositories에 있는 샘플 앱 저장소의 HTTPS 복제 URL을 Project Repository 필드에 붙여넣음

https://source.developers.google.com/p/[PROJECT_ID]/r/default

 (5) Credentials drop-down에서 이전 단계에서 서비스 계정을 추가할 때 생성한 자격 증명의 이름 선택

 (6) Scan Multibranch Pipeline Triggers 섹션에서, Periodically if not otherwise run 확인란을 선택하고 Interval 값 1분으로 설정

 (7) 작업 구성

 (8) 다른 모든 옵션은 기본값으로 두고 저장 클릭

 - 완료하면 Branch indexing이라는 작업이 실행됨

 - 메타 작업은 저장소의 분기를 식별하고 기존 분기에서 변경 사항이 발생하지 않았는지 확인

 - 왼쪽 상단의 sample-app을 클릭하면 master작업이 표시됨


11. Task 9. Creating the development environment

 - 개발 branches는 개발자가 라이브 사이트에 통합하기 위해 제출하기 전에 코드 변경 사항을 테스트하는 데 사용하는 환경 세트

 - 환경은 애플리케이션의 축소 버전이지만 실제 환경과 동일한 메커니즘을 사용하여 배포해야 함

 

1) 개발 branch 생성

 - 기능 branch에서 개발 환경을 만들려면 branch를 Git 서버로 푸시하고 Jenkins가 환경을 배포하도록 할 수 있음

 - 개발 branch를 만들고 Git 서버에 푸시

git checkout -b new-feature

 

2) 파이프라인 정의 수정

 - 해당 Jenkinsfile 파이프라인을 정의하는 것은 Jenkins Pipeline Groovy 구문 을 사용하여 작성

 - Jenkinsfile를 사용하면 전체 빌드 파이프라인을 소스 코드와 함께 있는 단일 파일로 표현할 수 있음

 - 파이프라인은 병렬화와 같은 강력한 기능을 지원하며 수동 사용자 승인이 필요

 - 파이프라인이 예상대로 작동하려면 Jenkinsfile프로젝트 ID를 설정하도록 수정해야 함

 

 (1) Jenkinsfile 열기

vi Jenkinsfile

 

 (2) REPLACE_WITH_YOUR_PROJECT_ID값에  PROJECT_ID를 추가

 

 (3) 설정한 기본 compute/zone으로 CLUSTER_ZONE 변경 

PROJECT = "REPLACE_WITH_YOUR_PROJECT_ID"
APP_NAME = "gceme"
FE_SVC_NAME = "${APP_NAME}-frontend"
CLUSTER = "jenkins-cd"
CLUSTER_ZONE = ""
IMAGE_TAG = "gcr.io/${PROJECT}/${APP_NAME}:${env.BRANCH_NAME}.${env.BUILD_NUMBER}"
JENKINS_CRED = "${PROJECT}"

 

 (4) 파일 저장

 

3) 사이트 수정

 - 애플리케이션 변경을 시연하기 위해 gceme 카드를 파란색 에서 주황색 으로 변경

 (1) html.go 열기

vi html.go

 

 (2) <div class="card blue">의 두 인스턴스를 변경

 

 (3) 파일 저장

 

 (4) main.go 열기

vi main.go

 

 (5) 버전 업데이트

const version string = "2.0.0"

 

 (6) 파일 저장 


12. Task 10. Kick off Deployment

 1) 변경 사항을 커밋하고 푸시

git add Jenkinsfile html.go main.go
git commit -m "Version 2.0.0"
git push origin new-feature

 - 개발 환경 빌드가 시작

 - 변경 사항을 Git 리포지토리로 푸시한 후 Jenkins 사용자 인터페이스로 이동하여 new-feature branch에 대한 빌드가 시작되었음을 확인할 수 있음

 

2) 빌드가 실행되면 왼쪽 탐색에서 build 옆에 있는 아래쪽 화살표를 클릭하고 Console output을 선택

 

3) 몇 분 동안 빌드 출력을 추적하고 kubectl --namespace=new-feature apply...메시지가 시작되는지 확인

 - 새 기능 분기가 클러스터에 배포됨

 - Jenkins homepage > sample app으로 이동합니다. new-feature 파이프라인이 생성되었는지 확인

 

4) 백그라운드에서 프록시를 시작

kubectl proxy &

 

5) 멈추면 Ctrl + C 를 눌러 종료. localhost로 요청을 보내고 kubectl 프록시가 이를 서비스로 전달하도록 하여 애플리케이션에 액세스할 수 있는지 확인

curl \
http://localhost:8001/api/v1/namespaces/new-feature/services/gceme-frontend:80/proxy/version


13. Task 11. Deploying a canary release

1) Canary branch를 만들고 Git 서버에 푸시

git checkout -b canary
git push origin canary

 

2) Jenkins에서 카나리아 파이프라인 시작 확인 가능

export FRONTEND_SERVICE_IP=$(kubectl get -o \
jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1; done

 - 완료되면 서비스 URL을 확인하여 일부 트래픽이 새 버전에서 제공되고 있는지 확인할 수 있음

 - 요청 5개 중 1개(특정 순서 없이)가 version 2.0.0을 반환하는 것을 볼 수 있음


14. Task 12. Deploying to production

1) Canary branch를 만들고 Git 서버에 푸시 

git checkout master
git merge canary
git push origin master

 - Jenkins에서 마스터 파이프라인이 시작된 것을 볼 수 있음 

 

2) 서비스 URL을 확인하여 모든 트래픽이 새 버전 2.0.0에서 제공되고 있는지 확인

export FRONTEND_SERVICE_IP=$(kubectl get -o \
jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1; done

 - gceme 애플리케이션이 정보 카드를 표시하는 사이트로 이동할 수도 있음

 - 카드 색상이 파란색에서 주황색으로 변경됨

 

3) 외부 IP 주소 확인

kubectl get service gceme-frontend -n production