1. 개요
Jenkins는 가장 널리 사용되는 지속적 통합 솔루션 중 하나입니다. 소프트웨어 개발 프로세스의 사람이 아닌 필수 부분을 자동화하는 데 사용됩니다. Google Cloud의 Kubernetes에 Jenkins를 배포하고 GKE 플러그인을 활용하면 필요에 따라 빌드 실행자를 빠르고 자동으로 확장할 수 있습니다. Cloud Storage와 결합하면 최소한의 노력으로 애플리케이션을 빌드하고 테스트할 수 있습니다.
실행할 작업
- Kubernetes 클러스터에 Jenkins 배포
- Jenkins가 포드를 실행자 노드로 만들고 삭제할 수 있도록 Jenkins GKE 플러그인을 배포하고 구성합니다.
- 샘플 SpringBoot 애플리케이션 빌드 및 테스트
- 컨테이너를 빌드하고 Google Container Registry에 게시
- 스테이징 및 프로덕션 GKE 환경에 샘플 애플리케이션 배포
필요한 항목
- 결제가 설정된 Google Cloud 프로젝트 계정이 없는 경우 계정을 만드세요.
2. 설정
이 Codelab은 로컬 설치나 구성 없이 Google Cloud Platform에서 완전히 실행할 수 있습니다.
Cloud Shell
이 Codelab에서는 Cloud Shell을 통해 명령줄을 사용하여 다양한 클라우드 리소스와 서비스를 프로비저닝하고 관리합니다.
API 사용 설정
다음은 프로젝트에서 사용 설정해야 하는 API입니다.
- Compute Engine API - 가상 머신을 만들고 실행합니다.
- Kubernetes Engine API: 컨테이너 기반 애플리케이션을 빌드하고 관리합니다.
- Cloud Build API - Google Cloud의 지속적 통합 및 지속적 배포 플랫폼
- Service Management API: 서비스 생산자가 Google Cloud Platform에 서비스를 게시할 수 있도록 허용
- Cloud Resource Manager API: Google Cloud 리소스 컨테이너의 메타데이터를 만들고, 읽고, 업데이트합니다.
다음 gcloud 명령어를 사용하여 필수 API를 사용 설정합니다.
gcloud services enable compute.googleapis.com \ container.googleapis.com \ cloudbuild.googleapis.com \ servicemanagement.googleapis.com \ cloudresourcemanager.googleapis.com \ --project ${GOOGLE_CLOUD_PROJECT}
GCS 버킷 만들기
테스트 작업을 업로드하려면 GCS 버킷이 필요합니다. 이름에 프로젝트 ID를 사용하여 고유성을 보장하는 버킷을 만들어 보겠습니다.
gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/
3. Kubernetes 클러스터 만들기
클러스터 만들기
다음으로 워커 노드로 전달될 포드를 포함하여 Jenkins 시스템을 호스팅할 GKE 클러스터를 만듭니다. --scopes
플래그로 표시된 추가 범위를 사용하면 Jenkins가 Cloud Source Repositories 및 Container Registry에 액세스할 수 있습니다. Cloud 콘솔에서 다음을 실행합니다.
gcloud container clusters create jenkins-cd \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --scopes "https://www.googleapis.com/auth/source.read_write,cloud-platform" \ --cluster-version latest
샘플 애플리케이션의 스테이징 및 프로덕션 빌드를 호스팅할 클러스터를 2개 배포해 보겠습니다.
gcloud container clusters create staging \ --machine-type n1-standard-2 --num-nodes 1 \ --zone us-east1-d \ --cluster-version latest
gcloud container clusters create prod \ --machine-type n1-standard-2 --num-nodes 2 \ --zone us-east1-d \ --cluster-version latest
확인
클러스터가 생성되면 gcloud container clusters list
로 실행 중인지 확인할 수 있습니다.
출력의 STATUS
열에 RUNNING
가 있어야 합니다.
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS jenkins-cd us-east1-d 1.15.9-gke.9 34.74.77.124 n1-standard-2 1.15.9-gke.9 2 RUNNING prod us-east1-d 1.15.9-gke.9 35.229.98.12 n1-standard-2 1.15.9-gke.9 2 RUNNING staging us-east1-d 1.15.9-gke.9 34.73.92.228 n1-standard-2 1.15.9-gke.9 2 RUNNING
4. Helm을 사용하여 Jenkins 배포
Helm 설치
Kubernetes용 애플리케이션 패키지 관리자인 Helm을 사용하여 클러스터에 Jenkins를 설치합니다. 시작하려면 Jenkins를 배포하는 데 사용할 Kubernetes 매니페스트가 포함된 프로젝트를 다운로드합니다.
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
현재 작업 디렉터리를 프로젝트 디렉터리로 변경합니다.
cd ~/continuous-deployment-on-kubernetes/
클러스터 역할 바인딩을 만들어 cluster-admin 역할 권한을 부여합니다.
kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
사용자 인증 정보를 가져와 jenkins 클러스터에 연결합니다.
gcloud container clusters get-credentials jenkins-cd --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
다음과 같이 Cloud 콘솔에 Helm 바이너리를 다운로드합니다.
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.14.1-linux-amd64.tar.gz
파일의 압축을 풀고 포함된 helm 파일을 현재 작업 디렉터리에 복사합니다.
tar zxfv helm-v2.14.1-linux-amd64.tar.gz && \ cp linux-amd64/helm .
Tiller는 Kubernetes 클러스터에서 실행되는 Helm의 서버 측입니다. tiller
라는 서비스 계정을 만들어 보겠습니다.
kubectl create serviceaccount tiller \ --namespace kube-system
변경할 수 있도록 cluster-admin
클러스터 역할에 바인딩합니다.
kubectl create clusterrolebinding tiller-admin-binding \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
이제 Helm을 초기화하고 저장소를 업데이트할 수 있습니다.
./helm init --service-account=tiller && \ ./helm repo update
인증
./helm version
를 사용하여 Helm이 제대로 작동하는지 확인합니다. 클라이언트와 서버의 버전 번호가 반환됩니다.
Client: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.14.1", GitCommit:"5270352a09c7e8b6e8c9593002a73535276507c0", GitTreeState:"clean"}
Jenkins 설치
이제 클러스터에 Helm이 설치되었으므로 Jenkins를 설치할 준비가 되었습니다.
./helm install stable/jenkins -n cd \ -f jenkins/values.yaml \ --version 1.2.2 --wait
확인
포드를 확인해 보겠습니다.
kubectl get pods
출력에 RUNNING 상태의 Jenkins Pod가 표시됩니다.
NAME READY STATUS RESTARTS AGE cd-jenkins-7c786475dd-vbhg4 1/1 Running 0 1m
Jenkins 서비스가 올바르게 생성되었는지 확인합니다.
kubectl get svc
출력은 다음과 같이 표시됩니다.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE cd-jenkins ClusterIP 10.35.241.170 <none> 8080/TCP 2m27s cd-jenkins-agent ClusterIP 10.35.250.57 <none> 50000/TCP 2m27s kubernetes ClusterIP 10.35.240.1 <none> 443/TCP 75m
Jenkins 설치는 Kubernetes 플러그인을 사용하여 빌더 에이전트를 만듭니다. Jenkins 마스터에 의해 필요에 따라 자동으로 시작됩니다. 해당 작업이 완료되면 자동으로 종료되고 리소스가 클러스터의 리소스 풀에 다시 추가됩니다.
Jenkins에 연결
Jenkins가 클러스터에서 실행되고 있지만 UI에 액세스하려면 Cloud Shell에서 포트 전달을 설정하겠습니다.
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 &
설치 중에 관리자 비밀번호가 생성되었습니다. 가져오려면 다음 단계를 따르세요.
printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
Cloud Shell 상단에서 웹 미리보기 아이콘 을 클릭하고 '포트 8080에서 미리보기'를 선택합니다.
Jenkins의 로그인 화면이 표시되며 여기에서 사용자 이름으로 admin
를 입력하고 이전 단계에서 반환된 비밀번호를 입력할 수 있습니다.
로그인을 클릭하면 Jenkins의 기본 페이지로 이동합니다.
5. GKE 플러그인 설치 및 구성
Google Kubernetes Engine 플러그인을 사용하면 Jenkins 내에서 빌드된 배포를 GKE 내에서 실행되는 Kubernetes 클러스터에 게시할 수 있습니다. 프로젝트에서 IAM 권한으로 실행해야 하는 구성이 있습니다. Terraform을 사용하여 이 구성을 배포합니다.
먼저 GKE 플러그인 프로젝트를 다운로드합니다.
git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin
자동화된 IAM 권한 구성
현재 작업 디렉터리를 이전에 클론한 GKE 프로젝트의 rbac 디렉터리로 변경합니다.
cd ~/google-kubernetes-engine-plugin/docs/rbac/
gcp-sa-setup.tf
는 제한된 권한이 있는 커스텀 GCP IAM 역할과 이 역할을 부여할 GCP 서비스 계정을 만드는 Terraform 구성 파일입니다. 이 파일에는 프로젝트, 리전, 서비스 계정 이름 변수의 값이 필요합니다. 먼저 다음 환경 변수를 선언하여 이러한 값을 제공합니다.
export TF_VAR_project=${GOOGLE_CLOUD_PROJECT} export TF_VAR_region=us-east1-d export TF_VAR_sa_name=kaniko-role
Terraform을 초기화하고 계획을 생성한 후 적용합니다.
terraform init terraform plan -out /tmp/tf.plan terraform apply /tmp/tf.plan && rm /tmp/tf.plan
서비스 계정이 Cloud Storage 버킷에 저장하려면 스토리지 관리자 권한이 필요합니다.
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com \ --role 'roles/storage.admin'
또한 파이프라인의 배포 단계에 대한 컨테이너 권한도 필요합니다.
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} --member \ serviceAccount:kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com --role 'roles/container.developer'
이제 Helm을 사용하여 gke 로봇 배포 도구를 사용하여 GKE 플러그인의 클러스터 권한을 설정할 수 있습니다. 작업 디렉터리를 GKE 프로젝트의 Helm 디렉터리로 변경합니다.
cd ~/google-kubernetes-engine-plugin/docs/helm/
제공된 Helm 차트를 사용하여 설치합니다.
export TARGET_NAMESPACE=kube-system && \ envsubst < gke-robot-deployer/values.yaml | helm install ./gke-robot-deployer --name gke-robot-deployer -f -
6. Jenkins 구성
서비스 계정 키
서비스 계정이 제대로 작동하려면 비공개 키 파일을 생성하고 이를 Kubernetes 보안 비밀로 추가해야 합니다. 먼저 다음 gcloud 명령어를 사용하여 파일을 생성합니다.
gcloud iam service-accounts keys create /tmp/kaniko-secret.json --iam-account kaniko-role@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
이 파일을 사용하여 Kubernetes 보안 비밀 저장소에 보안 비밀 키를 만듭니다.
kubectl create secret generic jenkins-int-samples-kaniko-secret --from-file=/tmp/kaniko-secret.json
Cloud Shell의 점 3개 메뉴에서 파일 다운로드 항목에 액세스하여 json 파일을 로컬 디스크에 다운로드합니다.
파일 경로 /tmp/kaniko-secret.json
를 입력하고 '다운로드'를 클릭합니다.
Jenkins 페이지로 돌아가 왼쪽 창에서 사용자 인증 정보와 시스템을 차례로 클릭합니다.
페이지의 시스템 섹션에서 왼쪽의 글로벌 사용자 인증 정보와 사용자 인증 정보 추가를 차례로 클릭합니다.
Kind(종류) 드롭다운에서 Google Service Account from private key(비공개 키의 Google 서비스 계정)를 선택합니다. 이름으로 'kaniko-role'을 입력한 후 이전 단계에서 만든 JSON 키를 업로드하고 '확인'을 클릭합니다.
환경 변수
다중 브랜치 파이프라인을 만들기 전에 Jenkins에서 정의해야 하는 몇 가지 환경 변수가 있습니다. 각 필터는 다음과 같습니다.
- JENK_INT_IT_ZONE: Kubernetes 클러스터의 영역입니다. 여기서는
us-east1-d
입니다. - JENK_INT_IT_PROJECT_ID - 이 Jenkins 인스턴스를 호스팅하는 GCP 프로젝트 ID를 나타냅니다.
- JENK_INT_IT_STAGING - '스테이징' 클러스터 이름입니다. 데모 목적으로는
staging
입니다. - JENK_INT_IT_PROD - 'prod' 클러스터 이름입니다. 데모 목적으로
prod
입니다. - JENK_INT_IT_BUCKET: 이전 단계에서 만든 Google Cloud Storage 버킷
- JENK_INT_IT_CRED_ID: 이전 단계에서 JSON을 사용하여 만든 사용자 인증 정보를 나타냅니다. 값은 지정한 이름인
kaniko-role
과 일치해야 합니다.
이를 추가하려면 Manage Jenkins(Jenkins 관리)로 이동합니다.
그런 다음 시스템 구성:
전역 속성이라는 섹션이 표시되고 환경 변수 체크박스를 선택하면 추가 버튼이 표시됩니다. 이 버튼을 클릭하여 위의 변수를 키-값 쌍으로 추가합니다.
페이지 하단의 저장 버튼을 클릭하여 변경사항을 적용합니다.
7. 파이프라인 설정
Jenkins에서 '새 항목'을 클릭합니다.
이름으로 'jenkins-integration-sample'을 입력하고 프로젝트 유형으로 'Multibranch Pipeline'을 선택한 다음 'OK'를 클릭합니다.
파이프라인 구성 페이지로 리디렉션됩니다. 브랜치 소스에서 프로젝트 저장소로 https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git을 입력합니다. 빌드 구성에서 스크립트 경로로 'gke/Jenkinsfile'을 입력합니다.
저장을 클릭하여 설정을 적용합니다. 저장하면 Jenkins에서 저장소 스캔을 시작하고 각 브랜치에 대해 후속 빌드를 시작합니다. 빌드가 진행되면 Kubernetes 워크로드 페이지에서 빌드가 진행됨에 따라 포드가 생성, 실행, 삭제되는 것을 볼 수 있습니다.
빌드가 완료되면 Kubernetes 워크로드 페이지에 각각 프로덕션 또는 테스트 클러스터에 해당하는 jenkins-integration-samples-gke라는 두 가지 항목이 표시됩니다. 상태는 'OK'로 표시됩니다.
다음 gcloud 명령어를 사용하면 파이프라인에 해당하는 컨테이너 이미지가 Google Container Registry에 업로드된 것을 확인할 수 있습니다.
gcloud container images list
브라우저에서 워크로드를 보려면 프로덕션 클러스터의 사용자 인증 정보를 가져옵니다.
gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}
다음을 실행하여 셸의 포트 8081에서 워크로드의 포트 8080으로 포트 전달을 설정합니다.
export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") && kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &
Cloud Shell 상단에서 웹 미리보기 아이콘을 클릭하고 '포트 8081에서 미리보기'를 선택합니다.
8. 삭제
Kubernetes에 Jenkins와 샘플 다중 브랜치 파이프라인을 배포하는 방법을 알아봤습니다. 이제 프로젝트에서 생성된 리소스를 정리해 보겠습니다.
프로젝트 삭제하기
원하는 경우 전체 프로젝트를 삭제할 수 있습니다. GCP Console에서 Cloud Resource Manager 페이지로 이동합니다.
프로젝트 목록에서 작업 중인 프로젝트를 선택하고 삭제를 클릭합니다. 프로젝트 ID를 입력하라는 메시지가 표시됩니다. 프로젝트 ID를 입력하고 종료를 클릭합니다.
또는 gcloud를 사용하여 Cloud Shell에서 바로 전체 프로젝트를 삭제할 수도 있습니다.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
다양한 청구 가능 구성요소를 하나씩 삭제하려면 다음 섹션으로 진행하세요.
Kubernetes 클러스터
gcloud를 사용하여 전체 Kubernetes 클러스터를 삭제합니다.
gcloud container clusters delete jenkins-cd --zone=us-east1-d
스토리지 버킷
업로드된 모든 파일을 삭제하고 gsutil을 사용하여 버킷을 삭제합니다.
gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket
Google Container Registry 이미지
이미지 다이제스트를 사용하여 Google Container Registry 이미지를 삭제합니다. 먼저 다음 명령어를 사용하여 다이제스트를 가져옵니다.
gcloud container images list-tags gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke --format="value(digest)"
그런 다음 반환된 각 다이제스트에 대해 다음을 실행합니다.
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/jenkins-integration-samples-gke@sha256:<DIGEST>
9. 축하합니다.
오호! 잘 하셨습니다. GKE에 Jenkins를 배포하고 Kubernetes 클러스터에 작업을 전달하는 방법을 알아봤습니다.
학습한 내용
- Kubernetes 클러스터를 배포하고 Helm을 사용하여 Jenkins를 설치했습니다.
- Jenkins가 Kubernetes 클러스터에 빌드 아티팩트를 배포할 수 있도록 GKE 플러그인을 설치하고 구성했습니다.
- GKE 클러스터에 작업을 전달하는 멀티브랜치 파이프라인을 설정하도록 Jenkins를 구성했습니다.