Continuous Delivery with Jenkins in Kubernetes Engine
Continuous Delivery with Jenkins in Kubernetes Engine
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-down의 Google 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
'대외활동 > Google Cloud Study Jam' 카테고리의 다른 글
[Kubernetes 입문] Managing Deployments Using Kubernetes Engine (0) | 2022.07.29 |
---|---|
[Kubernetes 입문] Orchestrating the Cloud with Kubernetes (0) | 2022.07.26 |
[Kubernetes 입문] Kubernetes Engine: Qwik Start (0) | 2022.07.25 |
[Kubernetes 입문] Introduction to Docker (0) | 2022.07.24 |
[Kubernetes 입문] Kubernetes in Google Cloud (0) | 2022.07.24 |