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

1. نظرة عامة

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

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

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

المتطلبات

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

2. الإعداد

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

Cloud Shell

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

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

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

  • ‫Compute Engine API: لإنشاء الأجهزة الافتراضية وتشغيلها
  • Kubernetes Engine API: لإنشاء تطبيقات مستندة إلى الحاويات وإدارتها
  • واجهة برمجة التطبيقات Cloud Build: منصة الدمج المتواصل والتسليم المتواصل من Google Cloud
  • واجهة برمجة التطبيقات Service Management API: تتيح لمقدّمي الخدمات نشر الخدمات على Google Cloud Platform
  • واجهة برمجة تطبيقات Cloud Resource Manager: لإنشاء البيانات الوصفية لحاويات موارد 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، بما في ذلك وحدات Pod التي سيتم إرسالها كعُقد عاملة. سيسمح النطاق الإضافي الذي تشير إليه العلامة --scopes لـ Jenkins بالوصول إلى Cloud Source Repositories وContainer Registry. في 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 التحقّق

لنتحقّق من الحاويات:

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

الربط بـ 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 بأذونات محدودة، بالإضافة إلى حساب خدمة على 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 إلى القرص المحلي من خلال الوصول إلى العنصر "تنزيل الملف" (Download File) من قائمة النقاط الثلاث في Cloud Shell:

c40378e72013b843.png

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

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

6c140f7e6bb82f8.png

3b874912cdc8019b.png

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

4350c0e68561119b.png

3d3526551cdae8b.png

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

b0502213408e730e.png

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

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

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

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

5135bd6b0374508c.png

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

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

bdec6b1753d1ba07.png

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

gcloud container images list

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

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

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