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
التحقّق
بعد إنشاء المجموعات، يمكننا التأكّد من أنّها تعمل باستخدام 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
إثبات الملكية
تأكَّد من أنّ 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
التحقّق
لنتحقّق من الحاويات:
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، انقر على رمز "المعاينة على الويب"
واختر "المعاينة على المنفذ 8080".

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

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

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:

أدخِل مسار الملف /tmp/kaniko-secret.json وانقر على "تنزيل".
بالعودة إلى صفحة Jenkins، انقر على بيانات الاعتماد في اللوحة على يمين الصفحة، ثم على النظام.


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


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

المتغيرات البيئية
هناك بعض متغيرات البيئة التي يجب تحديدها في 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:

ثم ضبط النظام:

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

انقر على زر حفظ في أسفل الصفحة لتطبيق التغييرات.
7. إعداد مسار التعلّم
في Jenkins، انقر على "عنصر جديد":

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

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

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

باستخدام أمر 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".


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