خط لوله چند شاخه ای جنکینز در GKE

۱. مرور کلی

جنکینز یکی از محبوب‌ترین راه‌حل‌های ادغام مداوم موجود است. از آن برای خودکارسازی بخش‌های ضروری غیرانسانی فرآیند توسعه نرم‌افزار استفاده می‌شود. با استقرار جنکینز در Kubenetes در Google Cloud و استفاده از افزونه GKE، می‌توانیم به سرعت و به طور خودکار اجراکننده‌های ساخت را در صورت نیاز مقیاس‌بندی کنیم. با ترکیب با Cloud Storage، می‌توانیم یک برنامه را با حداقل تلاش بسازیم و آزمایش کنیم.

کاری که انجام خواهید داد

  • جنکینز را در یک کلاستر Kubernetes مستقر کنید
  • افزونه Jenkins GKE را مستقر و پیکربندی کنید تا Jenkins بتواند پادها را به عنوان گره‌های اجراکننده ایجاد و از بین ببرد.
  • ساخت و آزمایش یک برنامه SpringBoot نمونه
  • ساخت و انتشار یک کانتینر در رجیستری کانتینر گوگل
  • استقرار برنامه نمونه در محیط GKE مرحله‌بندی و تولید

آنچه نیاز دارید

  • یک پروژه گوگل کلود با تنظیمات صورتحساب. اگر ندارید، باید یکی ایجاد کنید .

۲. راه‌اندازی

این آزمایشگاه کد می‌تواند بدون هیچ گونه نصب یا پیکربندی محلی، به طور کامل روی پلتفرم ابری گوگل اجرا شود.

پوسته ابری

در طول این آزمایشگاه کد، ما منابع و سرویس‌های ابری مختلف را با استفاده از خط فرمان از طریق Cloud Shell فراهم و مدیریت خواهیم کرد.

فعال کردن APIها

APIهایی که باید در پروژه خود فعال کنیم عبارتند از:

  • رابط برنامه‌نویسی کاربردی موتور محاسبات - ایجاد و اجرای ماشین‌های مجازی
  • Kubernetes Engine API - ساخت و مدیریت برنامه‌های مبتنی بر کانتینر
  • Cloud Build API - پلتفرم ادغام مداوم و تحویل مداوم Google Cloud
  • API مدیریت خدمات - به تولیدکنندگان خدمات اجازه می‌دهد تا خدمات را در پلتفرم ابری گوگل منتشر کنند.
  • رابط برنامه‌نویسی کاربردی مدیریت منابع ابری - ایجاد، خواندن و به‌روزرسانی فراداده برای کانتینرهای منابع گوگل کلود

API های مورد نیاز را با دستور gcloud زیر فعال کنید:

gcloud services enable compute.googleapis.com \
container.googleapis.com \
cloudbuild.googleapis.com \
servicemanagement.googleapis.com \
cloudresourcemanager.googleapis.com \
--project ${GOOGLE_CLOUD_PROJECT}

یک سطل GCS ایجاد کنید

برای آپلود کار آزمایشی خود به یک سطل GCS نیاز داریم. بیایید یک سطل با استفاده از شناسه پروژه خود در نام ایجاد کنیم تا از منحصر به فرد بودن آن اطمینان حاصل شود:

gsutil mb gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket/ 

۳. ایجاد خوشه‌های Kubernetes

ایجاد خوشه

در مرحله بعد، یک کلاستر GKE ایجاد خواهیم کرد که میزبان سیستم Jenkins ما، از جمله پادهایی که به عنوان گره‌های کارگر ارسال می‌شوند، خواهد بود. محدوده اضافی که با پرچم --scopes مشخص شده است، به Jenkins اجازه می‌دهد تا به مخازن منبع ابر و رجیستری کانتینر دسترسی داشته باشد. در کنسول ابر، دستور زیر را اجرا کنید:

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

همچنین بیایید دو کلاستر را برای میزبانی نسخه‌های آزمایشی و تولیدی برنامه نمونه خود مستقر کنیم:

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

28b45298e1e82748.png تأیید

پس از ایجاد خوشه‌ها، می‌توانیم تأیید کنیم که آنها با 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

۴. جنکینز را با 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 را در کنسول ابری خود دانلود کنید:

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 .

تیلر سمت سرور 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 را مقداردهی اولیه کرده و مخزن را به‌روزرسانی کنیم:

./helm init --service-account=tiller && \
./helm repo update

28b45298e1e82748.png تأیید

تأیید کنید که 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"}

نصب جنکینز

اکنون که Helm روی کلاستر ما نصب شده است، آماده نصب Jenkins هستیم:

./helm install stable/jenkins -n cd \
-f jenkins/values.yaml \
--version 1.2.2 --wait

28b45298e1e82748.png تأیید

بیایید غلاف‌ها را بررسی کنیم:

kubectl get pods

خروجی باید غلاف Jenkins ما را با وضعیت 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 master راه‌اندازی می‌شوند. پس از اتمام کار، به طور خودکار خاتمه می‌یابند و منابع آنها به مجموعه منابع کلاستر اضافه می‌شود.

اتصال به جنکینز

جنکینز روی کلاستر ما اجرا می‌شود، اما برای دسترسی به رابط کاربری، باید پورت فورواردینگ را از 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، روی آیکون پیش‌نمایش وب کلیک کنید 7ddf5a65fd556dd6.png و گزینه «پیش‌نمایش روی پورت ۸۰۸۰» را انتخاب کنید.

۱d614c831a621cff.png

باید یک صفحه ورود به سیستم برای Jenkins ببینیم که در آن می‌توانیم admin به عنوان نام کاربری و رمز عبوری که در مرحله قبل برگردانده شده است، وارد کنیم:

9cba23e856cbc84f.png

وقتی روی ورود کلیک می‌کنیم، باید به صفحه اصلی جنکینز هدایت شویم.

۹۲۶۱f3e۹۱۴۸۲۹۱۳۷.png

۵. نصب و پیکربندی افزونه GKE

افزونه‌ی موتور کوبرنتیز گوگل به ما این امکان را می‌دهد که پیاده‌سازی‌های ساخته‌شده در جنکینز را در کلاسترهای کوبرنتیز خود که در GKE اجرا می‌شوند، منتشر کنیم. پیکربندی‌هایی وجود دارد که باید با مجوزهای IAM در پروژه شما انجام شود. ما این پیکربندی را با استفاده از Terraform پیاده‌سازی خواهیم کرد.

ابتدا، پروژه افزونه GKE را دانلود کنید:

git clone https://github.com/jenkinsci/google-kubernetes-engine-plugin.git ~/google-kubernetes-engine-plugin

پیکربندی خودکار مجوزهای IAM

دایرکتوری کاری فعلی خود را به دایرکتوری rbac پروژه GKE که قبلاً کلون کردیم تغییر دهید:

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

حساب کاربری سرویس برای ذخیره در مخزن ذخیره‌سازی ابری ما به مجوزهای ادمین ذخیره‌سازی نیاز دارد:

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 robot deployer استفاده کنیم. دایرکتوری کاری خود را به دایرکتوری helm پروژه GKE تغییر دهید:

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 -

۶. پیکربندی جنکینز

کلیدهای حساب سرویس

برای اینکه حساب کاربری سرویس به درستی کار کند، باید یک فایل کلید خصوصی ایجاد کنیم و آن را به عنوان یک راز 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، فایل json را روی دیسک محلی خود دانلود کنید:

c40378e72013b843.png

مسیر فایل /tmp/kaniko-secret.json را وارد کنید و روی دانلود کلیک کنید.

به صفحه Jenkins برگردید، در پنل سمت چپ، روی Credentials و سپس System کلیک کنید.

6c140f7e6bb82f8.png

3b874912cdc8019b.png

در زیر بخشی از صفحه با عنوان سیستم، روی اعتبارنامه‌های سراسری (Global credentials) کلیک کنید و سپس در سمت چپ، اعتبارنامه‌ها را اضافه کنید (Add credentials).

4350c0e68561119b.png

3d3526551cdae8b.png

در منوی کشویی Kind، گزینه Google Service Account را از private key انتخاب کنید. 'kaniko-role' را به عنوان نام وارد کنید، سپس کلید JSON خود را که در مراحل قبل ایجاد کرده‌اید، آپلود کنید و روی OK کلیک کنید.

b0502213408e730e.png

متغیرهای محیطی

قبل از ایجاد خط لوله چند شاخه‌ای، باید متغیرهای محیطی زیر را در Jenkins تعریف کنیم:

  • JENK_INT_IT_ZONE - منطقه‌ی کلاستر Kubernetes. در مورد ما us-east1-d
  • JENK_INT_IT_PROJECT_ID - به شناسه پروژه GCP که میزبان این نمونه از Jenkins است اشاره دارد.
  • JENK_INT_IT_STAGING - نام کلاستر «staging» ما، برای اهداف نمایشی staging است.
  • JENK_INT_IT_PROD - نام کلاستر «prod» ما. برای نمایش، این prod است.
  • JENK_INT_IT_BUCKET - باکت ذخیره‌سازی ابری گوگل که در مرحله قبل ایجاد شد
  • JENK_INT_IT_CRED_ID - به اعتبارنامه‌هایی که با استفاده از json در مرحله قبل ایجاد شده‌اند اشاره دارد. مقدار آن باید با نامی که به آن دادیم، kaniko-role مطابقت داشته باشد.

برای افزودن این موارد، به مدیریت جنکینز بروید:

d54f279190a07878.png

سپس سیستم را پیکربندی کنید:

ce79d218b2799640.png

بخشی به نام Global properties وجود خواهد داشت و وقتی کادر مربوط به Environment variables را علامت بزنیم، دکمه‌ی Add ظاهر می‌شود که با کلیک روی آن می‌توانیم متغیرهای بالا را به عنوان جفت‌های کلید-مقدار اضافه کنیم:

81aa222a2b17b2cc.png

برای اعمال تغییرات، روی دکمه ذخیره در پایین صفحه کلیک کنید.

۷. راه‌اندازی یک خط لوله

در Jenkins روی «مورد جدید» کلیک کنید:

8d1270ce4d7b6a8a.png

برای نام، عبارت 'jenkins-integration-sample' را وارد کنید و نوع پروژه را 'Multibranch Pipeline' انتخاب کنید و روی تأیید کلیک کنید:

eb071ecfbb4d775b.png

ما به صفحه پیکربندی خط لوله هدایت خواهیم شد. در قسمت منابع شاخه ، https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git را به عنوان مخزن پروژه وارد کنید. در قسمت پیکربندی ساخت، 'gke/Jenkinsfile' را به عنوان مسیر اسکریپت وارد کنید.

5135bd6b0374508c.png

برای اعمال این تنظیمات، روی ذخیره کلیک کنید. پس از ذخیره، جنکینز اسکن مخزن و ساخت بعدی برای هر شاخه را آغاز می‌کند. با پیشرفت کار، خواهید دید که پادها با پیشرفت ساخت‌ها در صفحه Kubernetes Workloads ایجاد، اجرا و از بین می‌روند.

وقتی ساخت‌ها تمام شد، دو مورد در صفحه Kubernetes Workloads با نام jenkins-integration-samples-gke خواهید یافت که هر کدام مربوط به کلاستر prod یا testing هستند. وضعیت OK خواهد بود:

bdec6b1753d1ba07.png

با استفاده از دستور gcloud زیر، خواهیم دید که یک تصویر کانتینر را در رجیستری کانتینر گوگل مربوط به pipeline خود آپلود کرده‌ایم:

gcloud container images list

برای مشاهده حجم کار در مرورگر خود، اعتبارنامه‌های مربوط به خوشه prod را دریافت کنید:

gcloud container clusters get-credentials prod --zone us-east1-d --project ${GOOGLE_CLOUD_PROJECT}

و برای تنظیم یک پورت فوروارد از پورت ۸۰۸۱ پوسته خود به پورت ۸۰۸۰ بار کاری خود، دستور زیر را اجرا کنید:

export POD_NAME=$(kubectl get pods -o jsonpath="{.items[0].metadata.name}") &&
kubectl port-forward $POD_NAME 8081:8080 >> /dev/null &

در بالای پوسته ابری، روی آیکون پیش‌نمایش وب کلیک کنید و گزینه «پیش‌نمایش روی پورت ۸۰۸۱» را انتخاب کنید.

۱b19b5b56f1bae7.png

e80e995e71763bb2.png

۸. پاکسازی

ما نحوه استقرار یک Jenkins و یک نمونه خط لوله چندشاخه‌ای روی Kubernetes را بررسی کرده‌ایم. اکنون زمان آن رسیده است که پروژه خود را از هرگونه منبعی که ایجاد کرده‌ایم، پاک کنیم.

حذف پروژه

اگر ترجیح می‌دهید، می‌توانید کل پروژه را حذف کنید. در کنسول GCP، به صفحه Cloud Resource Manager بروید:

در لیست پروژه‌ها، پروژه‌ای را که روی آن کار می‌کردیم انتخاب کرده و روی «حذف» کلیک کنید. از شما خواسته می‌شود شناسه پروژه را وارد کنید. آن را وارد کرده و روی «خاموش کردن» کلیک کنید.

از طرف دیگر، می‌توانید کل پروژه را مستقیماً از Cloud Shell با gcloud حذف کنید:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

اگر ترجیح می‌دهید اجزای مختلف قابل پرداخت را یکی یکی حذف کنید، به بخش بعدی بروید.

خوشه Kubernetes

کل خوشه Kubernetes را با gcloud حذف کنید:

gcloud container clusters delete jenkins-cd --zone=us-east1-d

سطل‌های ذخیره‌سازی

تمام فایل‌های آپلود شده را حذف کنید و باکت ما را با gsutil حذف کنید:

gsutil rm -r gs://${GOOGLE_CLOUD_PROJECT}-jenkins-test-bucket

تصاویر رجیستری کانتینر گوگل

ما تصاویر رجیستری کانتینر گوگل را با استفاده از خلاصه تصاویر حذف خواهیم کرد. ابتدا خلاصه‌ها را با دستور زیر بازیابی کنید:

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>

۹. تبریک می‌گویم!

هورا! شما موفق شدید. شما یاد گرفتید که چگونه Jenkins را روی GKE مستقر کنید و کارها را به کلاسترهای Kubernetes ارسال کنید.

آنچه ما پوشش داده‌ایم

  • ما یک Kubernetes Cluster مستقر کردیم و از Helm برای نصب Jenkins استفاده کردیم.
  • ما افزونه GKE را نصب و پیکربندی کردیم تا Jenkins بتواند مصنوعات ساخت را در خوشه‌های Kubernetes مستقر کند.
  • ما Jenkins را طوری پیکربندی کردیم که یک خط لوله چندشاخه‌ای راه‌اندازی کند که کار را به خوشه‌های GKE ارسال کند.