مسار Jenkins المتعدّد الفروع على GKE

1. نظرة عامة

‫Jenkins هو أحد أكثر حلول الدمج المستمر شيوعًا. ويتم استخدامه لأتمتة الأجزاء الأساسية غير البشرية من عملية تطوير البرامج. من خلال نشر Jenkins في Kubenetes على Google Cloud واستخدام المكوّن الإضافي GKE، يمكننا توسيع نطاق مشغّلي عمليات الإنشاء بسرعة وتلقائيًا حسب الحاجة. وباستخدام Cloud Storage، يمكننا إنشاء تطبيق واختباره بأقل مجهود.

المهام التي ستنفّذها

  • نشر Jenkins في مجموعة Kubernetes
  • نشر مكوّن GKE الإضافي في Jenkins وضبطه لتفعيل Jenkins لإنشاء وحدات pod وإزالتها كنواة تنفيذ
  • إنشاء نموذج لتطبيق SpringBoot واختباره
  • إنشاء حاوية ونشرها في Google Container Registry
  • نشر نموذج التطبيق في بيئة GKE الرئيسية والاختبارية

المتطلبات

  • مشروع على Google Cloud تم إعداد الفوترة له إذا لم يكن لديك حساب، عليك إنشاء حساب.

2. الإعداد

يمكن تشغيل هذا الإصدار التجريبي من الرمز البرمجي بالكامل على Google Cloud Platform بدون أي تثبيت أو ضبط على الجهاز.

Cloud Shell

خلال هذا الدرس التطبيقي حول رموز البرامج، سنوفّر خدمات وموارد مختلفة في السحابة الإلكترونية ونديرها باستخدام سطر الأوامر من خلال Cloud Shell.

تفعيل واجهات برمجة التطبيقات

في ما يلي واجهات برمجة التطبيقات التي سنحتاج إلى تفعيلها في مشروعنا:

  • Compute Engine API: لإنشاء الأجهزة الافتراضية وتشغيلها
  • Kubernetes Engine API: لإنشاء التطبيقات المستندة إلى حاويات وإدارتها
  • Cloud Build API: منصة الدمج والتسليم المستمرَين من Google Cloud
  • Service Management API: تتيح لمطوّري الخدمات نشر الخدمات على Google Cloud Platform.
  • Cloud Resource Manager API: لإنشاء البيانات الوصفية لحاويات موارد Google Cloud وقراءتها وتعديلها

فعِّل واجهات برمجة التطبيقات المطلوبة باستخدام أمر 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/ 

3- إنشاء مجموعات Kubernetes

إنشاء المجموعة

بعد ذلك، سننشئ مجموعة GKE ستستضيف نظام Jenkins، بما في ذلك مجموعات التطبيقات التي سيتم إرسالها كنوى عامل. سيسمح النطاق الإضافي الذي يشير إليه الرمز --scopes لـ Jenkins بالوصول إلى "مستودعات مصادر Cloud" و"سجلّ الحاويات". في Cloud Console، نفِّذ ما يلي:

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.

يجب أن تحتوي النتيجة على RUNNING في عمود STATUS:

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. نشر Jenkins باستخدام Helm

تثبيت 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 Console:

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 وتعديل المستودع:

./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"}

تثبيت Jenkins

بعد تثبيت Helm على مجموعتنا، أصبحنا جاهزين لتثبيت Jenkins:

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

28b45298e1e82748.png التحقّق من الملكية

لنطّلِع على وحدات pod:

kubectl get pods

من المفترض أن يعرض الإخراج مجموعة Jenkins مع حالة "جارٍ":

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 حسب الحاجة. وعند الانتهاء من عملها، يتم إنهاء عملها تلقائيًا وتتم إضافة مواردها مرة أخرى إلى مجموعة موارد المجموعة.

الاتصال بخدمة Jenkins

يعمل Jenkins على مجموعتنا، ولكن للوصول إلى واجهة المستخدم، لنعدّ إعدادات إعادة توجيه المنفذ من 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واختَر "معاينة على المنفذ 8080".

1d614c831a621cff.png

من المفترض أن تظهر لنا شاشة تسجيل الدخول إلى Jenkins حيث يمكننا إدخال admin لاسم المستخدم وكلمة المرور التي تم عرضها في الخطوة السابقة:

9cba23e856cbc84f.png

عند النقر على تسجيل الدخول، من المفترض أن يتم توجيهنا إلى الصفحة الرئيسية لخدمة Jenkins.

9261f3e914829137.png

5- تثبيت المكوّن الإضافي لـ GKE وضبطه

يتيح لنا مكوّن Google Kubernetes Engine الإضافي نشر عمليات النشر التي تم إنشاؤها في Jenkins إلى مجموعات Kubernetes التي تعمل ضمن GKE. هناك بعض الإعدادات التي يجب إجراؤها باستخدام أذونات إدارة الهوية وإمكانية الوصول في مشروعك. سننشر هذه الإعدادات باستخدام Terraform.

أولاً، نزِّل مشروع المكوّن الإضافي لـ GKE:

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

ضبط أذونات إدارة الهوية وإمكانية الوصول التلقائية

غيِّر دليل العمل الحالي إلى دليل rbac في مشروع GKE الذي نسخناه سابقًا:

cd ~/google-kubernetes-engine-plugin/docs/rbac/

gcp-sa-setup.tf هو ملف إعدادات Terraform سينشئ دورًا مخصّصًا في "إدارة الهوية وإمكانية الوصول" في Google Cloud Platform (IAM) مع أذونات مفروض عليها قيود، بالإضافة إلى حساب خدمة على Google Cloud Platform لمنح هذا الدور. يتطلب الملف قيمًا لمتغيّرات اسم المشروع والمنطقة وحساب الخدمة. نقدّم هذه القيم من خلال تحديد متغيّرات البيئة التالية أولاً:

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. غيِّر دليل العمل إلى دليل 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 -

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 

نزِّل ملف json إلى القرص المحلي من خلال الوصول إلى عنصر "تنزيل الملف" من قائمة النقاط الثلاث في Cloud Shell:

c40378e72013b843.png

أدخِل مسار الملف /tmp/kaniko-secret.json وانقر على "تنزيل".

في صفحة Jenkins، على يمين الصفحة، انقر على الاعتمادات، ثم على النظام.

6c140f7e6bb82f8.png

3b874912cdc8019b.png

ضمن قسم الصفحة بعنوان النظام، انقر على "بيانات الاعتماد الشاملة" ثم على "إضافة بيانات اعتماد" على يمين الصفحة:

4350c0e68561119b.png

3d3526551cdae8b.png

في القائمة المنسدلة "النوع"، اختَر حساب خدمة Google من المفتاح الخاص. أدخِل "kaniko-role" كاسم، ثم حمِّل مفتاح JSON الذي تم إنشاؤه في الخطوات السابقة وانقر على "حسنًا".

b0502213408e730e.png

متغيّرات البيئة

هناك بعض متغيّرات البيئة التي سنحتاج إلى تحديدها في Jenkins قبل إنشاء مسار الإدراج المتعدّد الفروع. وهذه الأنواع الفرعية هي:

  • ‫JENK_INT_IT_ZONE: منطقة مجموعة Kubernetes. في حالتنا us-east1-d
  • ‫JENK_INT_IT_PROJECT_ID: يشير إلى رقم تعريف مشروع GCP الذي يستضيف هذا المثيل من Jenkins
  • 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.

لإضافة هذه العناصر، انتقِل إلى إدارة Jenkins:

d54f279190a07878.png

بعد ذلك، ضبط النظام:

ce79d218b2799640.png

سيظهر قسم بعنوان الخصائص الشاملة، وعند وضع علامة في المربّع بجانب متغيّرات البيئة، سيظهر زر إضافة يمكننا النقر عليه لإضافة المتغيّرات أعلاه كأزواج مفتاح/قيمة:

81aa222a2b17b2cc.png

انقر على الزر حفظ في أسفل الصفحة لتطبيق التغييرات.

7- إعداد مسار إحالة ناجحة

في Jenkins، انقر على "عنصر جديد":

8d1270ce4d7b6a8a.png

أدخِل jenkins-integration-sample للاسم واختَر Multibranch Pipeline كنوع المشروع، ثم انقر على "حسنًا":

eb071ecfbb4d775b.png

ستتم إعادة توجيهنا إلى صفحة إعدادات مسار الإحالة الناجحة. ضمن مصادر الفروع، أدخِل https://github.com/GoogleCloudPlatform/jenkins-integration-samples.git كـ مستودع المشروع. ضمن إعدادات الإصدار، أدخِل gke/Jenkinsfile كـ مسار النص البرمجي.

5135bd6b0374508c.png

انقر على حفظ لتطبيق هذه الإعدادات. عند الحفظ، سيبدأ Jenkins عملية فحص للمستودع وإنشاء لاحق لكل فرع. أثناء التقدّم، سترى وحدات pod يتم إنشاؤها وتشغيلها وإزالتها مع تقدّم عمليات الإنشاء في صفحة "أحمال Kubernetes".

عند اكتمال عمليات الإنشاء، سيظهر لك عنصران في صفحة "أحمال عمل Kubernetes" باسم jenkins-integration-samples-gke، يتوافق كل منهما مع المجموعة الاختبارية أو مجموعة الإنتاج. ستظهر الحالة "حسنًا":

bdec6b1753d1ba07.png

باستخدام الأمر gcloud التالي، سنرى أنّنا حمّلنا صورة حاوية إلى "مستودع حاويات Google" المرتبط بمسار الإرسال:

gcloud container images list

للاطّلاع على حجم العمل في المتصفّح، احصل على بيانات الاعتماد الخاصة بمجموعة الإنتاج:

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

وشغِّل ما يلي لإعداد إعادة توجيه منفذ من منفذ shell‏ 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".

1b19b5b56f1bae7.png

e80e995e71763bb2.png

8. تنظيف

لقد استكشَفنا كيفية نشر Jenkins ونموذج مسار عمل متعدد الفروع على Kubernetes. حان الآن وقت إزالة أيّ موارد أنشأناها من مشروعنا.

حذف المشروع

يمكنك أيضًا حذف المشروع بأكمله. في وحدة تحكّم Google Cloud Platform، انتقِل إلى صفحة 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

صور 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. تهانينا!

رائع! أحسنت. لقد تعلّمت كيفية نشر Jenkins على GKE وإرسال المهام إلى مجموعات Kubernetes.

المواضيع التي تناولناها

  • لقد نفّذنا مجموعة Kubernetes واستخدمنا Helm لتثبيت Jenkins.
  • لقد ثبَّتنا مكوّن GKE الإضافي وضبطناه لتفعيل Jenkins من أجل نشر عناصر الإنشاء في مجموعات Kubernetes.
  • لقد أعددنا Jenkins لإعداد مسار عمل متعدد الفروع يرسل العمل إلى مجموعات GKE.