Kubernetes (المعروف أيضًا باسم k8s) هو نظام تنسيق مفتوح المصدر. يتيح للمستخدمين نشر التطبيقات المعبأة في حاويات وتوسيع نطاقها وإدارتها بأقل وقت توقف. في هذا البرنامج التعليمي، ستتعلم كيفية نشر تطبيق PHP على عنقود Kubernetes.
يعمل Nginx كوكيل لـ PHP-FPM أثناء تشغيل تطبيق PHP. تعد إدارة هاتين الخدمتين في حاوية واحدة عملية صعبة. يساعدنا Kubernetes في إدارتهما في حاويتين مختلفتين ويقلل من المتاعب. كما يتيح للمستخدمين إعادة استخدام الحاويات وعدم القلق بشأن بناء صورة الحاوية الخاصة بهم لكل إصدار جديد من PHP/Nginx.
ستقوم بتشغيل تطبيقك وخدمة الوكيل في حاويتين منفصلتين. سيوفر البرنامج التعليمي أيضًا نظرة ثاقبة حول كيفية استخدام التخزين المحلي لإنشاء حجم تخزين دائم (PV) وطلب حجم تخزين دائم (PVC). ستستخدم بعد ذلك هذا الـ PVC للاحتفاظ بملفات التكوين والتعليمات البرمجية الخاصة بك خارج صور الحاوية. بعد الانتهاء من هذا البرنامج التعليمي، ستتمكن من إعادة استخدام صورة Nginx الخاصة بك للتطبيقات الأخرى التي تتطلب خادم وكيل. يمكنك تحقيق ذلك عن طريق تمرير تكوين، بدلاً من إعادة بناء الصورة له.
المتطلبات الأساسية
- فهم أساسي لـ Kubernetes (k8s) وكائناته. راجع هذا الدليل للحصول على نظرة عامة مفصلة على نظام Kubernetes البيئي.
- عنقود Kubernetes يعمل وجاهز على Ubuntu 18.04. اتبع هذا البرنامج التعليمي لـ إنشاء عنقود Kubernetes الخاص بك باستخدام kubeadm.
- بالإضافة إلى ذلك، تحتاج إلى استضافة كود تطبيقك على عنوان URL عام، على سبيل المثال، GitHub.
الخطوة 1: إنشاء خدمات PHP-FPM و Nginx
ستساعدك هذه الخطوة في إنشاء خدمات PHP-FPM و Nginx. توفر أي خدمة إمكانية الوصول إلى مجموعة من الـ pods داخل العنقود. يمكن لجميع الخدمات الموجودة في العنقود الاتصال ببعضها البعض بأسمائها، دون عناوين IP. ستوفر خدمة PHP-FPM وخدمة Nginx إمكانية الوصول إلى pods الخاصة بـ PHP-FPM و Nginx، على التوالي.
ستحتاج إلى إخبار خدمة PHP-FPM بكيفية العثور على pods الخاصة بـ Nginx لأنها ستعمل كوكيل لـ pods الخاصة بـ PHP-FPM. لهذا، ستستفيد من الاكتشاف التلقائي للخدمات في Kubernetes’ وتستخدم أسماء سهلة القراءة لتوجيه الطلب إلى الخدمة المعنية.
من أجل إنشاء أي خدمة، ستحتاج إلى إنشاء ملف YAML يحتوي على تعريف الكائن. يحتوي ملف YAML هذا على الأقل على العلامات التالية:
apiVersion: إصدار Kubernetes API الذي ينتمي إليه التعريف.kind: نوع كائن Kubernetes الذي ينشئه ملف YAML هذا. على سبيل المثال:service، أوjob، أوpod.metadata: يتم تعريف اسم الكائن والـlabelsالمختلفة التي قد يرغب المستخدم في تطبيقها على هذا الكائن تحت هذه العلامة.spec: تحتوي هذه العلامة على مواصفات الكائن الخاص بك، مثل متغيرات البيئة (ENVs)، وصورة الحاوية المراد استخدامها، والمنافذ التي ستكون خدمة الحاوية متاحة من خلالها.
إنشاء خدمة PHP-FPM
للبدء، يجب عليك إنشاء دليل للاحتفاظ بتعريف كائن Kubernetes الخاص بك. قم بتسجيل الدخول إلى العقدة الرئيسية (master node) الخاصة بك وأنشئ دليلاً باسم “definitions:”
|
1 |
mkdir definitions |
قم بتغيير الدليل إلى دليل definitions:
|
1 |
cd definitions |
بعد ذلك، قم بإنشاء ملف خدمة PHP-FPM كملف php_service.yaml :
|
1 |
nano php_fpm_service.yaml |
بعد ذلك، قم بتعيين apiVersion و kind في ملف php_fpm_service.yaml :
|
1 2 |
apiVersion: v1 kind: Service |
قم بتسمية خدمتك باسم php أو php-fpm لأنها ستوفر إمكانية الوصول إلى تطبيق PHP-FPM الخاص بك:
|
1 2 3 |
… Metadata: name: php |
قم بتسمية خدمة php الخاصة بك بـ tier: backend حيث سيتم تشغيل تطبيق PHP خلف هذه الخدمة:
|
1 2 3 |
… labels: tier: backend |
تستخدم الخدمة تسميات selector لتحديد الـ pods التي سيتم الوصول إليها. يتم تقديم الخدمة لأي pod يطابق هذه التسميات، بغض النظر عن وقت إنشاء الـ pod. ستتعلم كيفية إضافة تسميات إلى الـ pods الخاصة بك لاحقًا في هذا البرنامج التعليمي.
قم بتضمين tier: backend الذي يخصص الـ pod الخاص بك إلى طبقة backend، بالإضافة إلى تسمية app: php-fpm للإشارة إلى أن الـ pod يقوم بتشغيل تطبيق PHP-FPM. يجب عليك إضافة هذه التسميات بعد قسم metadata :
|
1 2 3 4 5 |
… spec: selector: app: php-fpm tier: backend |
بعد ذلك، تحتاج إلى الإعلان عن المنفذ للوصول إلى خدمة php-fpm هذه تحت spec. يمكنك إضافة أي منفذ من اختيارك، ولكننا سنستخدم المنفذ 9000 في هذا البرنامج التعليمي:
|
1 2 3 4 |
... ports: - protocol: TCP port: 9000 |
بمجرد الانتهاء من الخطوات المذكورة أعلاه، سيبدو ملف php_fpm_service.yaml الخاص بك كما يلي:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
apiVersion: v1 kind: Service metadata: name: php labels: tier: backend spec: selector: app: php tier: backend ports: - protocol: TCP port: 9000 |
اضغط على Ctrl + O لحفظ الملف، ثم اضغط على Ctrl + X للخروج من nano.
تطبيق أمر kubectl لإنشاء خدمة PHP
بمجرد إنشاء تعريف الكائن لخدمتك، قم بتشغيل الأمر kubectl apply مع المعامل -f من خلال تحديد ملف php_fpm_service.yaml الخاص بك:
|
1 |
kubectl apply -f php_fpm_service.yaml |
يجب أن تكون مخرجات الأمر أعلاه كما يلي:
|
1 |
service/php created |
قم بتشغيل الأمر أدناه للتحقق من أن خدمة php-fpm قيد التشغيل:
|
1 |
$ kubectl get svc |
ستتمكن من رؤية خدمة php-fpm قيد التشغيل:
|
1 2 3 |
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m php ClusterIP 10.100.59.238 <none> 9000/TCP 5m |
إنشاء خدمة Nginx
بما أن خدمة PHP-FPM جاهزة الآن، فقد حان الوقت لإنشاء خدمة Nginx أيضًا. قم بإنشاء وفتح ملف YAML جديد لهذه الخدمة باسم nginx_service.yaml في المحرر:
|
1 |
$ nano nginx_service.yaml |
قم بتسمية هذه الخدمة باسم nginx لأنها ستستهدف pods الخاصة بـ Nginx. تنتمي هذه الخدمة أيضًا إلى الـ backend، لذا يجب عليك إضافة التسمية tier: backend إليها:
|
1 2 3 4 5 6 |
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend |
كما فعلنا في خدمة php-fpm، أضف تسميات المحدد app: nginx و tier: backend لاستهداف الـ pods. أضف منفذ HTTP الافتراضي 80 للوصول إلى هذه الخدمة:
|
1 2 3 4 5 6 7 8 |
... spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80 |
يمكن الوصول إلى خدمة Nginx بشكل عام على الإنترنت من عنوان IP العام. يمكنك إضافة عنوان IP الخاص بـ worker node’s كـ your_public_ip. أضف الأسطر أدناه تحت spec.externalIPs:
|
1 2 3 4 5 |
... spec: externalIPs: - your_public_ip |
يجب أن يبدو ملف nginx_service.yaml الخاص بك مثل الملف أدناه بمجرد إكمال جميع الخطوات المذكورة أعلاه:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
apiVersion: v1 kind: Service metadata: name: nginx labels: tier: backend spec: selector: app: nginx tier: backend ports: - protocol: TCP port: 80 externalIPs: - your_public_ip |
احفظ الملف وأغلقه بعد إضافة جميع المعلمات المطلوبة أعلاه.
تطبيق أمر kubectl لإنشاء خدمة Nginx
|
1 |
kubectl apply -f nginx_service.yaml |
|
1 |
service/nginx تم إنشاؤه |
|
1 |
$ kubectl get svc |
|
1 2 3 4 |
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 50s php ClusterIP 10.100.59.238 <none> 9000/TCP 8m |
|
1 |
$ kubectl delete svc/service_name |
الخطوة 2: إنشاء مساحة تخزين محلية وحجم تخزين دائم (Persistent Volume)
يوفر Kubernetes العديد من المكونات الإضافية للتخزين (storage plug-ins) التي تساعدك على إنشاء مساحة تخزين لبيئتك. سيرشدك هذا الجزء إلى كيفية إنشاء StorageClass وكيف يمكن استخدام فئة التخزين (Storage Class) هذه لاحقًا لإنشاء حجم تخزين دائم (Persistent Volume).
إنشاء مساحة تخزين محلية
أنشئ ملفًا، وليكن باسم storageClass.yaml، في المحرر الخاص بك:
|
1 |
$nano storageClass.yaml |
أضف kind كـ "storageClass" و apiVersion كـ "storage.k8s.io/v1" كما يلي:
|
1 2 |
kind: StorageClass apiVersion: storage.k8s.io/v1 |
قم بتسمية StorageClass هذه باسم "my-local-storage" وأضف provisioner و volumeBindingMode كما يلي:
|
1 2 3 4 5 |
… metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: Immediate |
احفظ الملف واخرج منه، ويجب أن يبدو ملف storageClass.yaml النهائي كما يلي:
|
1 2 3 4 5 6 |
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: my-local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer |
الآن، قم بإنشاء StorageClass عن طريق تشغيل الأمر kubectl create، كما يلي:
|
1 |
$ kubectl create -f storageClass.yaml |
بعد تشغيل الأمر أعلاه، يجب أن تحصل على المخرجات أدناه:
|
1 |
storageclass.storage.k8s.io/my-local-storage تم إنشاؤه |
إنشاء حجم تخزين دائم محلي (Persistent Volume)
بعد إنشاء مساحة التخزين المحلية، يمكنك إنشاء حجم التخزين الدائم المحلي الخاص بك. حجم التخزين الدائم، المعروف أيضًا باسم PV، هو مساحة تخزين مخصصة الحجم ومستقلة عن دورة حياة الـ pod. حجم التخزين الدائم المحلي ليس سوى قرص محلي أو دليل متاح على عقدة cluster الخاصة بـ Kubernetes. يتيح حجم التخزين الدائم المحلي هذا لمستخدميه الوصول إلى التخزين المحلي باستخدام طلب حجم تخزين دائم محلي (Persistent Volume Claim) بطريقة بسيطة للغاية وسهلة النقل. يمكنك إنشاء حجم التخزين الدائم المحلي هذا باستخدام فئة التخزين التي أنشأناها للتو. افتح ملفًا، وليكن باسم persistentVolume.yaml، في المحرر الخاص بك:
|
1 |
$ nano persistentVolume.yaml |
امنح حجم التخزين الدائم هذا اسمًا، وليكن "my-local-pv":
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv |
يمكنك إضافة سعة التخزين وفقًا لاستخدامك أثناء إنشاء حجم تخزين دائم محلي. في هذا البرنامج التعليمي، سنستخدم 5 Gi للتخزين:
|
1 2 3 4 |
… spec: capacity: storage: 5Gi |
أضف accessModes و persistentVolumeReclaimPolicy، ووفر نفس الـ storageClassName المستخدم في storageClass.yaml:
|
1 2 3 4 5 |
… accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage |
أضف local.path لـ Persistent Volume الخاص بك كما يلي:
|
1 2 3 |
… local: path: /mnt/disk/vol |
بعد إضافة جميع الحقول المطلوبة، يجب أن يبدو ملف persistentVolume.yaml الخاص بك كما يلي:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-storage local: path: /mnt/disk/vol nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - worker |
تحضير وحدة التخزين المحلية (Local Volume)
الآن، نحتاج إلى تحضير وحدة تخزين محلية على عقدة “worker” كما أضفنا في ملف persistentVolume.yaml الخاص بك. قم بتشغيل الأوامر أدناه على العقدة التي قمت بتكوينها في persistentVolume. في هذه الحالة، هي عقدة “worker”:
|
1 2 3 |
$ DIRNAME="vol" $ mkdir -p /mnt/disk/$DIRNAME $ chmod 777 /mnt/disk/$DIRNAME |
قم بتشغيل الأمر أدناه على العقدة الرئيسية (master node) حيث يوجد ملف persistentVolume.yaml الخاص بك:
|
1 |
kubectl create -f persistentVolume.yaml |
يجب أن تحصل على المخرجات أدناه:
|
1 |
persistentvolume/my-local-pv created |
بما أنك قمت بإنشاء التخزين المحلي و Persistent Volume بنجاح، يمكنك الآن المضي قدمًا وإنشاء Persistent Volume Claim للاحتفاظ بكود تطبيقك وملفات التكوين.
الخطوة 3: إنشاء Persistent Volume
يجب الحفاظ على أمان كود تطبيقك أثناء إدارة الـ pods أو تحديثها. لهذا الغرض، ستستخدم Persistent Volume، الذي تم إنشاؤه في الخطوة السابقة، والذي يتم الوصول إليه باستخدام PersistentVolumeClaim، أو PVC. يقوم PVC هذا بتركيب (mount) الـ PV في المسار المطلوب.
افتح ملفًا، لنقل code_volume.yaml، في المحرر الخاص بك:
|
1 |
$ nano code_volume.yaml |
قم بتسمية PVC الخاص بك باسم code عن طريق إضافة المعلمات والقيم أدناه إلى ملفك:
|
1 2 3 4 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code |
يحتوي قسم spec الخاص بـ PVC على العناصر التالية:
- accessModes: هناك قيم مختلفة محتملة لهذا الحقل كما يلي:
- ReadWriteOnce – يقوم بتركيب وحدة التخزين لعقدة واحدة مع أذونات القراءة والكتابة معًا.
- ReadOnlyMany – يقوم بتركيب وحدة التخزين للعديد من العقد مع إذن القراءة فقط.
- ReadWriteMany – يقوم بتركيب وحدة التخزين للعديد من العقد مع أذونات القراءة والكتابة معًا.
- resources: يحدد مساحة التخزين المطلوبة.
بما أن وحدة التخزين المحلية يتم تثبيتها على عقدة واحدة فقط، فستحتاج إلى تعيين accessMode على ReadWriteOnce. في هذا البرنامج التعليمي، ستضيف جزءًا صغيرًا فقط من كود التطبيق، وبالتالي ستكون مساحة تخزين تبلغ 1 جيجابايت كافية هنا. ومع ذلك، إذا كنت ترغب في تخزين كمية أكبر من البيانات أو الكود، يمكنك تعديل معلمة التخزين وفقًا لمتطلباتك. لاحظ أنه بمجرد إنشاء وحدة التخزين، ستتمكن من زيادة حجم التخزين. ومع ذلك، فإن تقليله غير مدعوم:
|
1 2 3 4 5 6 7 |
... spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi |
الآن، قم بالتصريح عن فئة التخزين التي سيستخدمها تجميع Kubernetes لتخصيصها لوحدات التخزين. استخدم فئة التخزين my-local-storage، التي تم إنشاؤها في الخطوة السابقة، هنا لـ storageClassName الخاص بك:
|
1 2 |
... storageClassName: my-local-storage |
بعد إكمال الخطوات المذكورة أعلاه، يجب أن يبدو ملف code_volume.yaml الخاص بك كما يلي:
|
1 2 3 4 5 6 7 8 9 10 11 |
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: my-local-storage |
الآن احفظ الملف واخرج منه.
إنشاء PVC
قم بإنشاء PVC الخاص بالكود عن طريق تشغيل الأمر kubectl apply:
|
1 |
$ kubectl apply -f code_volume.yaml |
يجب أن تحصل على المخرجات التالية التي تشير إلى أنه تم إنشاء الكائن بنجاح وأنه جاهز لتتمكن من تثبيت PVC الخاص بك بحجم 1 جيجابايت كوحدة تخزين:
|
1 |
persistentvolumeclaim/code created |
يمكنك تنفيذ الأمر التالي للتحقق من وحدة التخزين الدائمة (PV) المتاحة:
|
1 |
$ kubectl get pv |
يجب أن تكون مخرجات الأمر أعلاه كما يلي:
|
1 2 |
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13 1Gi RWO Delete Bound default/code do-block-storage 2m |
جميع الحقول المذكورة أعلاه، باستثناء Reclaim Policy و Status، هي نظرة عامة على ملف التكوين الخاص بك. تحدد Reclaim Policy ما يحدث لـ PV بمجرد حذف PVC الذي يصل إليها. تؤدي القيمة Delete إلى إزالة PV من تجميع Kubernetes وكذلك من البنية التحتية للتخزين. يمكنك الرجوع إلى وثائق Kubernetes PV للحصول على فهم واضح لـ Reclaim Policy و Status.
يمكنك الآن إنشاء وحدات الـ pod الخاصة بك باستخدام Deployment بعد أن قمت بإنشاء وحدة التخزين الدائمة (Persistent Volume) بنجاح باستخدام التخزين المحلي.
الخطوة 4: إنشاء Deployment لتطبيق PHP-FPM الخاص بك
ستساعدك هذه الخطوة في إنشاء pod الخاص بـ PHP-FPM باستخدام Deployment. تستخدم Deployment الـ ReplicaSets لتوفير طريقة مستقرة لإنشاء وتحديث وإدارة الـ pods الخاصة بك. تقوم Deployment تلقائيًا بالتراجع عن الـ pods الخاصة بها إلى صورة سابقة.
المفتاح spec.selector في Deployment يسرد جميع تسميات الـ pods التي يديرها. كما أنه يستخدم مفتاح template لإنشاء الـ pods المطلوبة.
في هذه الخطوة، سنقدم أيضًا تطبيق Init Containers. تقوم Init Containers بتشغيل بعض الأوامر قبل الحاويات العادية المحددة تحت قالب الـ pod’s. هنا، ستستخدم Init Container موقع GitHub Gist (https://gist.github.com/) للحصول على ملف index.php نموذجي. محتويات الملف النموذجي هي:
|
1 2 |
<?php echo phpinfo(); |
إنشاء PHP Deployment
افتح ملفًا جديدًا باسم php_deployment.yaml في المحرر الخاص بك لإنشاء Deployment الخاص بك:
|
1 |
$ nano php_deployment.yaml |
الآن، قم بتسمية كائن Deployment باسم PHP لأن هذا الـ Deployment سيدير كبسولات (pods) PHP-FPM الخاصة بك. أضف التسمية (label) tier: backend لأن الكبسولة (pod) ستنتمي إلى طبقة الـ backend:
|
1 2 3 4 5 6 |
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend |
باستخدام معامل replica، حدد عدد النسخ التي يجب إنشاؤها من هذه الكبسولة (pod). قد يختلف عدد النسخ المتطابقة (replicas) بناءً على متطلباتك والموارد المتاحة. في هذا البرنامج التعليمي، ستقوم بإنشاء نسخة متطابقة واحدة فقط من الكبسولة الخاصة بك:
|
1 2 3 4 |
... spec: replicas: 1 |
أضف app: php و tier:backend من التسميات (labels) تحت مفتاح selector الذي يشير إلى أن هذا الـ Deployment سيدير الكبسولات (pods) التي تطابق هاتين التسميتين:
|
1 2 3 4 5 |
... selector: matchLabels: app: php tier: backend |
الآن، يحتاج تعريف كائن الـ pod’s الخاص بك إلى قالب (template) تحت مواصفات الـ Deployment (spec). يحدد هذا القالب المواصفات المطلوبة لإنشاء الكبسولة الخاصة بك. للبدء، أضف التسميات (labels) التي تم تحديدها لـ php service selector و matchLabels الخاصة بالـ Deployment. ثم أضف app:php و tier:backend تحت template.metadata.labels:
|
1 2 3 4 5 6 7 |
... template: metadata: labels: app: php tier: backend |
أولاً، تحتاج إلى تحديد جميع وحدات التخزين (volumes) التي ستصل إليها حاوياتك. قم بتسمية وحدة التخزين هذه باسم code لأنك قمت بإنشاء PVC باسم code للاحتفاظ ببرمجية تطبيقك:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
بعد ذلك، حدد اسم الحاوية (container) بالإضافة إلى الصورة (image) التي تريد تشغيلها داخل الكبسولة (pod). تتوفر صور متنوعة في متجر Docker (https://hub.docker.com/explore/)، ولكن في هذا البرنامج التعليمي، سنستخدم php:7-fpm صورة:
|
1 2 3 4 |
... containers: - name: php image: php:7-fpm |
الآن، قم بتثبيت وحدات التخزين (volumes) التي تحتاج الحاوية إلى الوصول إليها. نظرًا لأن هذه الحاوية ستقوم بتشغيل برمجية php الخاصة بك، فستحتاج إلى الوصول إلى وحدة التخزين code التي تم إنشاؤها في الخطوة السابقة. في هذه الخطوة، ستتعلم أيضًا كيفية نسخ برمجية تطبيقك باستخدام Init Container.
لتنزيل البرمجية، سيرشدك هذا البرنامج التعليمي إلى كيفية استخدام Init Container واحد مع busybox. إن busybox عبارة عن حاوية صغيرة تحتوي على أداة wget التي ستستخدمها لتحقيق ذلك.
أولاً، أضف الـ initContainer الخاص بك تحت spec.template.spec وحدد صورة busybox:
|
1 2 3 4 |
... initContainers: - name: install image: busybox |
بعد ذلك، لتنزيل البرمجية في وحدة التخزين code، سيحتاج الـ Init Container الخاص بك إلى الوصول إليها. قم بتثبيت وحدة التخزين code في المسار /code تحت spec.template.spec.initContainers:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
يتطلب كل Init Container تشغيل أمر. سيستخدم هذا الـ Init Container أداة wget لتنزيل code من Github إلى المجلد /code . يمكنك تمرير الخيار -O لتسمية هذا الملف الذي تم تنزيله، ويمكنك تسمية هذا الملف index.php.
بالإضافة إلى ذلك، أضف السطور أدناه تحت حاوية التثبيت في spec.template.spec.initContainers:
|
1 2 3 4 5 6 |
... command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php |
بعد إكمال كل هذه الخطوات، يجب أن يبدو ملف php_deployment.yaml الخاص بك كما يلي:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
apiVersion: apps/v1 kind: Deployment metadata: name: php labels: tier: backend spec: replicas: 1 selector: matchLabels: app: php tier: backend template: metadata: labels: app: php tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code containers: - name: php image: php:7-fpm volumeMounts: - name: code mountPath: /code initContainers: - name: install image: busybox volumeMounts: - name: code mountPath: /code command: - wget - "-O" - "/code/index.php" - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php |
يمكنك الآن حفظ الملف والخروج. بعد ذلك، قم بإنشاء Deployment لـ PHP-FPM باستخدام kubectl apply أمر:
|
1 |
$ kubectl apply -f php_deployment.yaml |
يجب أن يمنحك الإنشاء الناجح لـ Deployment المخرجات أدناه:
|
1 |
deployment.apps/php created |
يبدأ هذا الـ Deployment بتنزيل الصور المحددة، ثم سيطلب PersistentVolume من PersistentVolumeClaim الخاصة بك، ثم يقوم بتشغيل initContainers. بمجرد الانتهاء من هذه الخطوة، ستعمل الحاويات وتقوم بتركيب وحدات التخزين في نقطة التركيب المحددة. بعد إكمال كل هذه الخطوات، سيكون الـ pod الخاص بك قيد التشغيل.
يمكنك تشغيل الأمر أدناه لعرض الـ Deployment الخاص بك:
|
1 |
$ kubectl get deployments |
بعد تشغيل الأمر أعلاه، يجب أن تحصل على المخرجات أدناه:
|
1 2 |
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s |
يمكنك فهم الحالة الحالية لـ Deployment بمساعدة هذه المخرجات. الـ Deployment هو وحدة تحكم تحافظ على الحالة المطلوبة. يحدد حقل DESIRED أنه يحتوي على نسخة متطابقة واحدة من الـ pod المسمى php. ويشير حقل CURRENT إلى عدد النسخ المتطابقة من الحالة DESIRED التي تعمل في الوقت الحالي. بالنسبة لـ pod سليم، يجب أن يتطابق هذا مع الحالة DESIRED. يمكنك معرفة المزيد حول الحقول المتبقية في وثائق Kubernetes Deployments الوثائق.
بعد ذلك، للتحقق من حالة الـ pod قيد التشغيل، يمكنك تشغيل الأمر أدناه:
|
1 |
$ kubectl get pods |
يمكن أن تختلف مخرجات هذا الأمر اعتمادًا على الوقت الذي مضى منذ إنشاء الـ Deployment الخاص بك. إذا تم تشغيله بعد وقت قصير من إنشاء الـ Deployment، فستكون المخرجات مشابهة لـ:
|
1 2 |
NAME READY STATUS RESTARTS AGE php-5d8f6bbf7f-56df2 0/1 Init:0/1 0 9s |
Explanation:
تمثل هذه الأعمدة المعلومات على النحو التالي:
- Ready: عدد النسخ المتطابقة الحالية/المطلوبة التي تشغل هذا الـ pod.
- الحالة: حالة الـ pod الخاص بك. تشير Init:0/1 إلى أن حاويات البدء (Init Containers) قيد التشغيل وأن 0 من أصل 1 من حاويات البدء قد انتهت من العمل.
- إعادات التشغيل: يشير هذا إلى عدد المرات التي تمت فيها إعادة تشغيل هذه العملية لبدء الـ pod.
قد يستغرق الـ pod الخاص بك بضع دقائق لتتغير الحالة إلى podInitializing اعتمادًا على مدى تعقيد البرامج النصية لبدء التشغيل لديك:
|
1 2 |
الاسم جاهز الحالة إعادات التشغيل العمر php-5d8f6bbf7f-56df2 0/1 podInitializing 0 39s |
يشير هذا إلى أن حاويات البدء (Init Containers) قد تم تشغيلها بنجاح، والآن، يجري تهيئة الحاويات:
|
1 2 |
الاسم جاهز الحالة إعادات التشغيل العمر php-5d8f6bbf7f-56df2 1/1 قيد التشغيل 0 4m10s |
كما ترى الآن، فإن الـ pod الخاص بك يعمل بشكل صحيح. ومع ذلك، في حال لم يبدأ الـ pod الخاص بك، يمكنك تشغيل الأوامر أدناه لأغراض تصحيح الأخطاء:
1. لعرض معلومات مفصلة عن الـ pod:
|
1 |
$ kubectl describe pods pod-name |
2. لعرض سجلات الـ pod:
|
1 |
$ kubectl logs pod-name |
3. لعرض سجلات حاوية معينة في الـ pod:
|
1 |
$ kubectl logs pod-name container-name |
تهانينا! لقد قمت بتركيب كود التطبيق بنجاح وأصبحت خدمة PHP-FPM جاهزة للتعامل مع الاتصالات. وبالمثل، يمكنك إنشاء نشر Nginx الخاص بك.
الخطوة 5: إنشاء نشر Nginx الخاص بك
ستوجهك هذه الخطوة إلى كيفية تكوين Nginx باستخدام ConfigMap. يحتفظ الـ ConfigMap بجميع التكوينات المطلوبة بتنسيق مفتاح-قيمة والذي سيتم استخدامه في تعريفات كائنات Kubernetes الأخرى. باستخدام هذا النهج، ستتمتع بالمرونة لإعادة استخدام صورة Nginx أو استبدالها بإصدار مختلف، عند الحاجة. يمكنك تحديث الـ ConfigMap وسيقوم تلقائيًا بتكرار تلك التغييرات في أي pod يقوم بتركيب هذا الـ ConfigMap.
للبدء، افتح ملف nginx_configmap.yaml في المحرر الخاص بك:
|
1 |
$ nano nginx_configMap.yaml |
الآن، قم بتسمية هذا الـ ConfigMap باسم nginx-config وأضفه إلى الخدمة المصغرة tier: backend :
|
1 2 3 4 5 6 |
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend |
بالإضافة إلى ذلك، يمكنك إضافة البيانات إلى ConfigMap. أضف مفتاحًا باسم config وأضف جميع محتويات ملف تكوين Nginx كقيمة.
نظرًا لأنه من الممكن لـ Kubernetes توجيه الطلبات إلى المضيفين المعنيين لخدمة ما، يمكنك إدخال اسم خدمة PHP-FPM الخاصة بك تحت المعلمة fastcgi_pass بدلاً من عنوان IP الخاص بها. أضف أسطر الكود التالية إلى ملف nginx_configMap.yaml الخاص بك:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
... data: config : | server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /code; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } } |
بمجرد الانتهاء، فإن ملف nginx_configMap.yaml الخاص بك سيبدو كالتالي:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
apiVersion: v1 kind: ConfigMap metadata: name: nginx-config labels: tier: backend data: config : | server { index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /code; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } } |
يمكنك الآن حفظ الملف والخروج من المحرر. الآن قم بتنفيذ kubectl apply الأمر لإنشاء ConfigMap:
|
1 |
$ kubectl apply -f nginx_configMap.yaml |
بعد ذلك، يجب أن ترى المخرجات التالية على شاشتك:
|
1 |
configmap/nginx-config created |
لقد قمت بإنشاء Nginx Configmap بنجاح. الآن يمكنك إنشاء Nginx Deployment الخاص بك.
إنشاء Nginx Deployment
للبدء، يمكنك إنشاء ملف جديد باسم nginx_deployment.yaml في المحرر:
|
1 |
$ nano nginx_deployment.yaml |
قم بتسمية هذا الـ Deployment بـ nginx وأضف علامة tier: backend إليه:
|
1 2 3 4 5 6 7 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend |
بعد ذلك، حدد عدد النسخ المتطابقة بإضافة حقل replica في مواصفات (spec) الـ Deployment وأضف علامتي app: nginx و tier: backend إليه:
|
1 2 3 4 5 6 7 |
... spec: replicas: 1 selector: matchLabels: app: nginx tier: backend |
وبالمثل، أضف قالب الـ pod. تأكد من إضافة نفس العلامات التي أضفتها في الـ selector.matchLabels الخاص بالـ Deployment’s. يمكنك إضافة ما يلي:
|
1 2 3 4 5 6 |
... template: metadata: labels: app: nginx tier: backend |
امنح Nginx حق الوصول إلى PVC الخاص بالكود الذي تم إنشاؤه مسبقًا عن طريق إضافة المعلمات التالية تحت spec.template.spec.volumes:
|
1 2 3 4 5 6 |
... spec: volumes: - name: code persistentVolumeClaim: claimName: code |
|
1 2 3 4 5 6 7 |
... - name: config configMap: name: nginx-config items: - key: config path: site.conf |
تحذير: ستستبدل محتويات المفتاح الـ mountPath الخاص بالـ volume’s إذا لم يتم تحديد ملف. بمعنى آخر، ستفقد جميع المحتويات في المجلد الوجهة إذا لم يتم تحديد مسار بشكل صريح.
الآن، حدد الاسم والصورة (image) والمنفذ (port) الذي تريد استخدامه في الـ pod الخاص بك. هنا، سنستخدم صورة nginx:1.7.9 والمنفذ 80. أضفهم تحت spec.template.spec قسم:
|
1 2 3 4 5 6 |
... containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 |
أيضًا، قم بتركيب وحدة تخزين الكود في /code حيث سيحتاج كل من Nginx و PHP-FPM إلى الوصول إلى الملف في نفس المسار:
|
1 2 3 4 |
... volumeMounts: - name: code mountPath: /code |
إن صورة nginx-1.7.9 تقوم تلقائيًا بتحميل أي ملف تكوين ضمن المجلد /etc/nginx/conf.d. الآن، إذا قمنا بتركيب وحدة تخزين التكوين في هذا الدليل، فسيتم إنشاء /etc/nginx/conf.d/site.conf. أضف ما يلي أسفل قسم volumeMount:
|
1 2 3 |
... - name: config mountPath: /etc/nginx/conf.d |
بعد إكمال جميع الخطوات المذكورة أعلاه، يجب أن يبدو ملف nginx_deployment.yaml الخاص بك كما يلي:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: tier: backend spec: replicas: 1 selector: matchLabels: app: nginx tier: backend template: metadata: labels: app: nginx tier: backend spec: volumes: - name: code persistentVolumeClaim: claimName: code - name: config configMap: name: nginx-config items: - key: config path: site.conf containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: - name: code mountPath: /code - name: config mountPath: /etc/nginx/conf.d |
يمكنك الآن حفظ الملف والخروج منه وإنشاء Nginx Deployment عن طريق تشغيل الأمر التالي:
|
1 |
$ kubectl apply -f nginx_deployment.yaml |
عند تنفيذ الأمر بنجاح، يجب أن تشاهد المخرجات التالية:
|
1 |
deployment.apps/nginx created |
يمكنك سرد جميع عمليات النشر (Deployments) الخاصة بك عن طريق تنفيذ الأوامر أدناه:
|
1 |
$ kubectl get deployments |
يجب أن تشاهد الآن كلاً من عمليات نشر Nginx و PHP-FPM:
علاوة على ذلك، يمكنك تشغيل الأمر التالي لسرد الـ pods التي تتم إدارتها بواسطة كلا الـ Deployments المذكورة أعلاه:
|
1 |
$ kubectl get pods |
سترى أن كلا الـ pods لديك يعملان بشكل صحيح على النحو التالي:
بما أن جميع كائنات Kubernetes الخاصة بك نشطة في هذه المرحلة، يمكنك الآن الوصول إلى خدمة Nginx على متصفحك.
قم بتشغيل الأمر التالي لسرد الخدمات:
|
1 |
$ kubectl get services -o wide |
قم بتدوين الـ External IP الخاص بخدمة Nginx لديك:
الآن، باستخدام الـ External IP هذا لخدمة Nginx، يمكنك زيارة خادمك عن طريق كتابة http://your_public_ip على متصفحك. يجب أن تكون قادرًا على رؤية مخرجات php_info() التي تؤكد أن خدمات Kubernetes الخاصة بك تعمل بشكل صحيح.
خاتمة
في هذا البرنامج التعليمي، لإدارة خدمات PHP-FPM و Nginx بشكل مستقل، قمت بوضع الخدمتين في حاويات. من خلال القيام بذلك، لن تقوم فقط بتحسين قابلية التوسع لمشروعك، بل ستستخدم أيضًا مواردك بكفاءة. لقد تعلمت أيضًا كيفية إنشاء مساحة تخزين محلية و Persistent Volume لتخزين كود تطبيقك على وحدة تخزين والقدرة على تحديث خدماتك بسهولة في المستقبل. من خلال القيام بذلك، قمت بتحسين قابلية الاستخدام والصيانة لكودك.
علاوة على ذلك، ألقِ نظرة على برامجنا التعليمية الأخرى التي تركز على Docker و Kubernetes والتي يمكنك العثور عليها في مدونتنا:
- التعرف على Kubernetes
- كيفية إنشاء عنقود Kubernetes باستخدام Kubeadm على Ubuntu 18.04
- تنظيف موارد Docker – الصور، الحاويات، ووحدات التخزين
- نشر Laravel و Nginx و MySQL باستخدام Docker Compose
- كيفية تثبيت & تشغيل Docker على Ubuntu في السحابة العامة
حوسبة سعيدة!


التعليقات
لا توجد تعليقات بعد. كن أول من يعلق.