1. 總覽
Jenkins 是目前最受歡迎的持續整合解決方案之一。這項工具可用於自動化軟體開發流程中非人為介入的必要部分。我們將 Jenkins 部署至 Google Cloud 上的 Kubernetes 並使用 GKE 外掛程式,就能視需要快速且自動地調度建構執行器。搭配使用 Cloud Storage,我們就能輕鬆建構及測試應用程式。
執行步驟
- 將 Jenkins 部署至 Kubernetes 叢集
- 部署並設定 Jenkins GKE 外掛程式,讓 Jenkins 能夠建立及刪除 Pod 做為執行緒節點
- 建構及測試範例 SpringBoot 應用程式
- 建構並發布至 Google Container Registry 的容器
- 將範例應用程式部署至測試和實際工作 GKE 環境
軟硬體需求
- 已設定帳單的 Google Cloud 專案。如果沒有,請建立。
2. 開始設定
這個程式碼研究室可以完全在 Google Cloud Platform 上執行,無須在本機安裝或設定任何內容。
Cloud Shell
在本程式碼研究室中,我們將透過 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 叢集
建立叢集
接下來,我們將建立 GKE 叢集,用於代管 Jenkins 系統,包括要以工作節點形式調派的 Pod。--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
我們會使用 Helm (Kubernetes 的應用程式套件管理工具) 在叢集上安裝 Jenkins。如要開始使用,請下載包含 Kubernetes 資訊清單的專案,我們會用這些資訊清單部署 Jenkins:
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git ~/continuous-deployment-on-kubernetes
將目前的工作目錄變更為專案目錄:
cd ~/continuous-deployment-on-kubernetes/
建立叢集角色繫結,授予自己叢集管理員角色權限:
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}
並將 Helm 二進位檔下載至 Cloud 控制台:
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 是 Helm 的伺服器端,會在 Kubernetes 叢集中執行。我們來建立名為 tiller
的服務帳戶:
kubectl create serviceaccount tiller \ --namespace kube-system
並將其繫結至 cluster-admin
叢集角色,以便進行變更:
kubectl create clusterrolebinding tiller-admin-binding \ --clusterrole=cluster-admin \ --serviceaccount=kube-system:tiller
我們現在可以初始化 Helm 並更新 Repo:
./helm init --service-account=tiller && \ ./helm repo update
驗證
確認 Helm 可搭配 ./helm version
使用 - 這應該會傳回用戶端和伺服器的版本號碼:
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
驗證
我們來看看 Pod 的狀態:
kubectl get pods
輸出結果應顯示 Jenkins Pod 的狀態為 RUNNING:
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
和先前步驟中傳回的密碼:
按一下「Sign in」後,系統應會將我們導向 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
是 Terraform 設定檔,可建立具有受限權限的自訂 GCP IAM 角色,以及要授予該角色的 GCP 服務帳戶。這個檔案需要專案、區域和服務帳戶名稱變數的值。我們會先宣告下列環境變數,再提供這些值:
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」。輸入「kaniko-role」做為名稱,然後上傳先前步驟中建立的 JSON 金鑰,然後按一下「OK」。
環境變數
在建立多分支管道之前,我們需要定義一些環境變數。這 3 個子類型如下:
- 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」:
然後點選「Configure System」:
畫面上會顯示「Global properties」部分,勾選「Environment variables」方塊後,畫面上會顯示「Add」按鈕,點選這個按鈕即可將上述變數新增為鍵/值組合:
按一下頁面底部的「儲存」按鈕,套用變更。
7. 設定管道
在 Jenkins 中按一下「New Item」:
輸入名稱「jenkins-integration-sample」,選取「Multibranch Pipeline」做為專案類型,然後按一下「OK」:
系統會將您重新導向至管道設定頁面。在「Branch Sources」下方,輸入「https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git」https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git做為「Project Repository」。在「Build Configuration」下方,輸入「gke/Jenkinsfile」做為「Script Path」。
按一下「儲存」套用這些設定。儲存後,Jenkins 就會開始掃描存放區,並為每個分支版本執行後續建構作業。在建構過程中,您會在 Kubernetes Workloads 頁面上看到 Pod 的建立、執行和刪除情形。
建構作業完成後,您會在 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 主控台中,前往「Cloud Resource Manager」頁面:
在專案清單中選取我們正在使用的專案,然後按一下「刪除」。系統會提示您輸入專案 ID。輸入專案 ID 後,按一下「Shut Down」。
或者,您也可以使用 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
- 我們安裝並設定 GKE 外掛程式,讓 Jenkins 將建構構件部署到 Kubernetes 叢集
- 我們設定 Jenkins 來設定多分支管道,將工作分派至 GKE 叢集