عند إنشائك لتطبيقات حديثة عديمة الحالة (stateless)، فإن عملية إعداد الحاويات لمكونات التطبيق ستكون هي الخطوة الأولى في النشر والتوسيع على الأنظمة الأساسية الموزعة. إذا كنت قد استخدمت Docker Compose في التطوير، فسوف تعمل على تحديث التطبيق وحاوياته بما يلي:
- استخراج معلومات التكوين اللازمة من شيفرتك.
- إلغاء تحميل حالة تطبيقك.
- تحزيم تطبيقك من أجل الاستخدام المتكرر.
سيكون لديك أيضًا تعريفات خدمة مكتوبة تحدّد كيف ستشتغل صور حاوياتك.
لتشغيل خدماتك على نظام أساسي موزّع مثل Kubernetes، ستحتاج إلى ترجمة تعريفات خدمة Compose إلى كائنات Kubernetes. سيسمح لك ذلك بتوسيع نطاق تطبيقك بنوع من المرونة. وتعدّ kompose إحدى الأدوات التي يمكن أن تسرع عملية الترجمة إلى Kubernetes، وهي أداة تحويل تساعد المطورين على نقل سير عمل Compose إلى منسّق للحاويات مثل Kubernetes أو OpenShift.
سوف تعمل في هذا البرنامج التعليمي على ترجمة خدمات Compose إلى كائنات Kubernetes باستخدام kompose. ستستخدم تعريفات الكائنات التي توفرها kompose كنقطة بداية، كما ستجري تعديلات للتأكد من أن إعداداتك ستستخدم الأسرار (secrets) والخدمات (services) وطلبات وحدة التخزين الثابتة (PersistentVolumeClaims) على النحو المتوقّع في Kubernetes. عند نهاية الدرس، سيكون لديك تطبيق Node.js بنسخة واحدة لقاعدة بيانات MongoDB تعمل على نظام Kubernetes. سيعكس هذا الإعداد وظائف الشيفرة الموضحة في كيفية إعداد تطبيق node.js لسير عملٍ يعتمد على الحاويات باستخدام Docker Compose وسيكون نقطة انطلاق جيدة لإنشاء حلّ جاهز للإنتاج يتناسب مع احتياجاتك.
المتطلبات الأساسية
- عنقود Kubernetes 1.10+ مع تفعيل التحكم في الوصول المستند إلى الدور role-based access control (RBAC). سيستخدم هذا الإعداد عنقود DigitalOcean Kubernetes، لكن تبقى لك حرية الاختيار في إنشاء عنقود باستخدام طريقة أخرى.
- أداة سطر الأوامر kubectl المثبتة على جهازك المحلي أو خادم التطوير وإعدادها للاتصال بعنقودك. يمكنك قراءة المزيد حول تثبيت kubectl في التوثيق الرسمي.
- Docker مثبت على جهازك المحلي أو خادم التطوير. إذا كنت تعمل على نظام أوبونتو 18.04، اتبع الخطوتين 1 و 2 لكيفية تثبيت واستخدام Docker على أوبونتو 18.04؛ خلاف ذلك، اتبع التوثيق الرسمي للحصول على معلومات حول التثبيت على أنظمة التشغيل الأخرى. تأكد من إضافة مستخدمك غير الجذري إلى مجموعة Docker، كما هو موضح في الخطوة 2 من البرنامج التعليمي المرتبط.
- حساب Docker Hub. للحصول على نظرة عامة حول كيفية إعداده، راجع هذه المقدمة إلى Docker Hub.
الخطوة الأولى: تثبيت kompose
للبدء في استخدام kompose، انتقل إلى صفحة إصدارات GitHub للمشروع، وانسخ الرابط إلى الإصدار الحالي. الصق هذا الرابط في الأمر curl التالي لتنزيل أحدث إصدار من kompose:
curl -L https://github.com/kubernetes/kompose/releases/download/v1.18.0/kompose-linux-amd64 -o kompose
للحصول على تفاصيل حول التثبيت على أنظمة غير تابعة لنظام لينكس، يرجى الرجوع إلى إرشادات التثبيت.
أنشئ الملف التنفيذي (binary):
chmod +x kompose
انقله إلى مسارك PATH
:
sudo mv ./kompose /usr/local/bin/kompose
ثم تحقق من تثبيته بشكل صحيح. يمكنك إجراء فحص للإصدار:
kompose version
إذا كان التثبيت ناجحًا، فسيظهر لك الإخراج التالي:
Output 1.18.0 (06a2e56)
بعد تثبيت kompose وجاهزيته للاستخدام، يمكنك الآن استنساخ شيفرة المشروع Node.js
الذي سيُترجَم إلى Kubernetes
.
الخطوة الثانية: استنساخ وتحزيم التطبيق
لاستخدام تطبيقنا على Kubernetes، سنحتاج إلى استنساخ شيفرة المشروع وتحزيم التطبيق حتى تتمكن خدمة kubelet من سحب الصورة.
ستكون خطوتنا الأولى هي استنساخ مستودع node-mongo-docker-dev من حسابDigitalOcean Community GitHub. يتضمن هذا المستودع شيفرة الإعداد الموضح في كيفية إعداد تطبيق node.js لسير عملٍ يعتمد على الحاويات باستخدام Docker Compose، والذي يستخدم تطبيق Node.js لشرح كيفية إعداد بيئة تطوير باستخدام Docker Compose. يمكنك العثور على مزيد من المعلومات حول التطبيق نفسه في سلسلة من الحاويات إلى Kubernetes باستخدام Node.js.
استنسخ المستودع في مجلّد يسمى node_project:
git clone https://github.com/do-community/node-mongo-docker-dev.git node_project
انتقل إلى المجلّد node_project:
cd node_project
يحتوي مجلّد node_project على ملفات ومجلدات لتطبيق معلومات سمك القرش الذي يعمل على مدخلات المستخدم. لقد حُدِّث للعمل على الحاويات وأزيلت منه معلومات التكوين الحساسة والمحددة في شيفرة التطبيق وأُعيد تشكيلها من أجل حقنها عند تنفيذ التطبيق، كما أُلغيَ تحميل حالة التطبيق إلى قاعدة بيانات MongoDB.
لمزيد من المعلومات حول تصميم التطبيقات الحديثة عديمة الحالة، يرجى الاطلاع على هيكلة التطبيقات ل Kubernetes وتحديث التطبيقات لKubernetes.
يتضمن مجلّد المشروع ملفّا Dockerfile بتعليمات لبناء صورة التطبيق. دعنا نبني الصورة الآن على النحو الذي يتيح رفعها إلى حسابك Docker Hub واستخدامها في إعداداتك Kubernetes.
استخدم الأمر docker build
لبناء الصورة باستخدام الراية t-، والتي تتيح لك تعليمها باسم لا يُنسى. في هذه الحالة، علّم الصورة باسم مستخدمك Docker Hub وسمّها node kubernetes
أو أيّ اسم من اختيارك:
docker build -t your_dockerhub_username/node-kubernetes .
تحدد النقطة .
في الأمر أن سياق البناء هو المجلّد الحالي.
سوف يستغرق الأمر دقيقة أو دقيقتين لبناء الصورة. بمجرد اكتماله، تحقق من صورك:
docker images
سيظهر لك الإخراج التالي:
Output REPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/node-kubernetes latest 9c6f897e1fbc 3 seconds ago 90MB node 10-alpine 94f3c8956482 12 days ago 71MB
بعد ذلك، سجّل الدخول إلى حساب Docker Hub الذي أنشأته في المتطلبات الأساسية:
docker login -u your_dockerhub_username
أدخل كلمة مرور حساب Docker Hub عندما يُطلب منك ذلك. سيؤدي التسجيل بهذه الطريقة إلى إنشاء ملف ~/.docker/config.json في المجلّد الرئيسي للمستخدم الخاص بك باستخدام بيانات اعتماد. Docker Hub
ارفع صورة التطبيق إلى Docker Hub باستخدام الأمر docker push. ولا تنس أن تعوّض yourdockerhubusername باسم مستخدمك Docker Hub:
docker push your_dockerhub_username/node-kubernetes
لديك الآن صورة للتطبيق يمكنك سحبها لتشغيل تطبيقك على Kubernetes
. ستكون الخطوة التالية هي ترجمة تعريفات خدمة التطبيق إلى كائنات .Kubernetes
الخطوة الثالثة: ترجمة الخدمات إلى كائنات Kubernetes باستخدام kompose
يحدّد ملف Docker Compose، المسمى هنا docker-compose.yaml، التعريفات التي ستعمل على تشغيل خدماتنا على Compose. الخدمة في "Compose" هي عبارة عن حاوية قيد التشغيل، وتحتوي تعريفات الخدمة على معلومات حول كيفية تشغيل صورة كل حاوية. في هذه الخطوة، سوف نترجم هذه التعريفات إلى كائنات Kubernetes باستخدام kompose لإنشاء ملفات .yaml سوف تحتوي هذه الملفات على خصائص كائنات Kubernetes التي تصف الحالة التي نريدها عليها.
سوف نستخدم هذه الملفات لإنشاء أنواع مختلفة من الكائنات: أوّلها الخدمات، والتي ستضمن بقاء العُلَب (pods) التي تشغّل حاوياتنا متاحةً. ثانيها عمليّات النشر، والتي سوف تحتوي على معلومات حول الحالة التي نريد عليها العلب. ثالثها PersistentVolumeClaim لتوفير تخزين لقاعدة البيانات. رابعها خريطة الإعداد ConfigMap لمتغيرات البيئة التي تُحقَن في وقت التشغيل. وآخرها سرٌّ (secret) لمستخدم قاعدة بيانات التطبيق وكلمة المرور. ستكون بعض هذه التعريفات في الملفات التي سينشئها لناkompose ، والبعض الآخر سوف نحتاج إلى إنشائه بأنفسنا.
سنحتاج بدايةّ إلى تعديل بعض التعاريف في ملف docker-compose.yaml
للعمل على Kubernetes. سنُضمّن إشارة إلى صورة التطبيق التي بُنيت حديثًا في تعريف خدمتنا nodejs
، كما سنحذف الروابط bind mounts
والحجوم والأوامر الإضافية التي استخدمناها لتشغيل حاوية التطبيق قيد التطوير باستخدام Compose. بالإضافة إلى ذلك، سنعيد تحديد سياسات إعادة تشغيل كلتا الحاويتين بحيث تتوافق مع السلوك الذي المتوقع في Kubernetes.
افتح الملف باستخدام nano أو المحرر المفضل لديك:
nano docker-compose.yaml
يبدو التعريف الحالي لخدمة تطبيق nodejs كما يلي:
... services: nodejs: build: context: . dockerfile: Dockerfile image: nodejs container_name: nodejs restart: unless-stopped env_file: .env environment: - MONGO_USERNAME=$MONGO_USERNAME - MONGO_PASSWORD=$MONGO_PASSWORD - MONGO_HOSTNAME=db - MONGO_PORT=$MONGO_PORT - MONGO_DB=$MONGO_DB ports: - "80:8080" volumes: - .:/home/node/app - node_modules:/home/node/app/node_modules networks: - app-network command: ./wait-for.sh db:27017 -- /home/node/app/node_modules/.bin/nodemon app.js ...
بعدها أَجرِ التعديلات التالية على تعريف الخدمة:
- استخدم صورة node-kubernetes بدلاً من ملف Dockerfile المحلي.
- عدّل سياسة إعادة تشغيل الحاوية restart من unless-stopped إلى always.
- احذف قائمة الحجوم volumes وتعليمات الأوامر command.
سيبدو تعريف الخدمة النهائية الآن كما يلي:
... services: nodejs: image: your_dockerhub_username/node-kubernetes container_name: nodejs restart: always env_file: .env environment: - MONGO_USERNAME=$MONGO_USERNAME - MONGO_PASSWORD=$MONGO_PASSWORD - MONGO_HOSTNAME=db - MONGO_PORT=$MONGO_PORT - MONGO_DB=$MONGO_DB ports: - "80:8080" networks: - app-network …
بعد ذلك، انزل إلى تعريف الخدمة db
. ثم أجر التعديلات التالية:
-
غيّر سياسة إعادة التشغيل restart للخدمة always.
-
احذف ملف env. فبدلاً من استخدام قيمٍ من ملف env.، سنمرّر القيم الخاصة بـ MONGO_INITDB_ROOT_USERNAME و MONGO_INITDB_ROOT_PASSWORD إلى حاوية قاعدة البيانات باستخدام السّر Secret الذي سننشئه في الخطوة الرابعة.
سيبدو تعريف خدمة db الآن كما يلي:
... db: image: mongo:4.1.8-xenial container_name: db restart: always environment: - MONGO_INITDB_ROOT_USERNAME=$MONGO_USERNAME - MONGO_INITDB_ROOT_PASSWORD=$MONGO_PASSWORD volumes: - dbdata:/data/db networks: - app-network ...
أخيرًا، في الجزء السفلي من الملف، احذف الحجوم node_modules من مفتاح المستوى الأعلى volumes. وسيبدو المفتاح عندها كما يلي:
... volumes: dbdata:
احفظ الملف وأغلقه عند الانتهاء من التحرير.
سنحتاج، قبل ترجمة تعريفاتنا للخدمة، إلى كتابة ملف env. الذي سيستخدمه kompose لإنشاء خريطة الإعداد ConfigMap بمعلوماتنا غير الحساسة. الرجاء مراجعة الخطوة الثانية من كيفية إعداد تطبيق node.js لسير عملٍ يعتمد على الحاويات باستخدام Docker Compose للمزيد من التوضيح حول هذا الملف.
في ذلك الدرس، أضفنا env.
إلى ملفنا gitignore.
للتأكد من عدم نسخه إلى التحكم في الإصدار. هذا يعني أنه لم يُنسَخ عندما استنسخنا مستودع node-mongo-docker-dev
في الخطوة الثانية من هذا الدرس. لذلك سوف نحتاج إلى إعادة إنشائه الآن.
أنشئ هذا الملف إذًا:
nano .env
سوف يستخدم kompose
هذا الملف لإنشاء خريطة إعداد ConfigMap لتطبيقنا. ومع ذلك، بدلاً من تعيين كافة المتغيرات من تعريف خدمة nodejs في ملفنا Compose، سنضيف فقط اسم قاعدة البيانات MONGO_DB
و MONGO_PORT
. سنعيّن اسم المستخدم وكلمة المرور لقاعدة البيانات بشكل منفصل عندما ننشئ يدويًا كائنًا Secret في الخطوة الرابعة.
أضف معلومات المنفذ واسم قاعدة البيانات التالية إلى ملف env.
. لا تتردد في إعادة تسمية قاعدة بياناتك إذا كنت ترغب في ذلك:
MONGO_PORT=27017 MONGO_DB=sharkinfo
احفظ الملف وأغلقه عند الانتهاء من التحرير.
أنت الآن مستعدّ لإنشاء الملفات اعتمادًا على خصائص كائنك. ويقدم لك kompose خيارات متعددة لترجمة مواردك. إذ تستطيع:
- إنشاء ملفات yaml بناءً على تعريفات الخدمة في ملفك docker-compose.yaml باستخدام kompose convert.
- إنشاء كائنات Kubernetes مباشرة باستخدام kompose up.
- إنشاء مخطط Helm باستخدام kompose convert -c.
في الوقت الحالي، سنحوّل تعريفاتنا للخدمة إلى ملفات yaml ثم نضيف الملفات التي ينشئها kompose وننقّحها. استخدام الأمر التالي لتحويل تعريفات الخدمة إلى ملفات yaml:
kompose convert
يمكنك أيضًا تسمية ملفات تكوين محددة أو متعددة باستخدام الراية f-
. بعد تنفيذ هذا الأمر، سيُخرِج kompose معلوماتٍ حول الملفات التي أنشأتها:
INFO Kubernetes file "nodejs-service.yaml" created INFO Kubernetes file "db-deployment.yaml" created INFO Kubernetes file "dbdata-persistentvolumeclaim.yaml" created INFO Kubernetes file "nodejs-deployment.yaml" created INFO Kubernetes file "nodejs-env-configmap.yaml" created
يتضمّن هذا الإخراج الملفات yaml مع خصائص خدمة ونشر وخريطة إعداد تطبيق Node، وكذلك طلب وحدة التخزين الثابتة ل dbdata ونشر قاعدة بيانات MongoDB.
تعدّ هذه الملفات نقطة انطلاق جيدة، ولكن لكي تتطابق وظائف تطبيقنا مع الإعداد الموضح في كيفية إعداد تطبيق node.js لسير عملٍ يعتمد على الحاويات باستخدام Docker Compose، سنحتاج إلى إجراء بعض الإضافات والتغييرات على الملفات التي أنشأها kompose.
الخطوة الرابعة: إنشاء أسرار Kubernetes
لكي يعمل تطبيقنا بالطريقة التي نتوقعها، سنحتاج إلى إجراء بعض التعديلات على الملفات التي أنشأها kompose. أول هذه التغييرات هو إنشاء سرٍّ لمستخدم قاعدة البيانات وكلمة المرور وإضافتها إلى عمليات نشر التطبيق وقاعدة البيانات. ويقدّم Kubernetes طريقتين للعمل بمتغيرات البيئة: ConfigMap وSecret. وقد أنشأ kompose بالفعل خريطة إعداد ConfigMap بالمعلومات غير السرية التي ضمّنناها في ملفنا env.، لذلك سننشئ الآن سرًّا بمعلوماتنا السرية: اسم المستخدم وكلمة المرور لقاعدة البيانات.
ستكون الخطوة الأولى في إنشاء السّرِّ يدويًا هي تحويل اسم المستخدم وكلمة المرور إلى base64، وهو نظام ترميز يسمح لك بنقل البيانات بشكل موحد، بما في ذلك البيانات الثنائية.
حوّل أولا اسم مستخدم قاعدة بياناتك:
echo -n 'your_database_username' | base64
دوّن القيمة التي تظهر لك في الإخراج. بعد ذلك، حوّل كلمة مرورك:
echo -n 'your_database_password' | base64
دوّن القيمة الظاهرة في الإخراج هنا أيضا. افتح ملف السّر:
nano secret.yaml
ملاحظة: تُحدّد كائنات Kubernetes عادة باستخدام YAML الذي يمنع بصرامةٍ علامات التبويب ويتطلب مسافتين للمسافة البادئة. إذا كنت ترغب في التحقق من تنسيق أيٍّ من ملفاتك yaml ، فيمكنك استخدام linter أو اختبار صياغة (syntax) تركيبك باستخدام kubectl create
مع الرايتين dry-run--
و validate--
:
kubectl create -f your_yaml_file.yaml --dry-run --validate=true
يُستحسن بشكل عام التحقق من صحة الصياغة قبل إنشاء الموارد باستخدام kubectl.
أضف الشيفرة التالية إلى الملف لإنشاء سرٍّ يحدّد MONGO_USERNAME و MONGO_PASSWORD باستخدام القيم المشفرة التي أنشأتها للتو. تأكد من تعويض القيم الوهمية هنا باسم المستخدم وكلمة المرور المشفرة:
-
الملف
~/node_project/secret.yaml
:
apiVersion: v1 kind: Secret metadata: name: mongo-secret data: MONGO_USERNAME: your_encoded_username MONGO_PASSWORD: your_encoded_password
لقد سمّينا كائن السرّ mongo-secret، ولكن يمكنك تسميته كما تشاء.
احفظ هذا الملف وأغلقه عند الانتهاء من التحرير. وكما فعلت مع ملفك env. ، تأكد من إضافة secret.yaml إلى ملفك gitignore. لإبقائه خارج نطاق التحكم في الإصدار.
بعد تحرير secret.yaml، ستكون خطوتنا التالية هي ضمان استخدام عُلَب كلّ من التطبيق وقاعدة البيانات للقيم التي أضفناها إلى الملف. لنبدأ بإضافة إشارات مرجعية إلى السّرّ Secret في نشر التطبيق.
افتح الملف المسمى nodejs-publish.yaml:
nano nodejs-deployment.yaml
تتضمن مواصفات حاوية الملف متغيرات البيئة التالية المحددة تحت مفتاح env:
apiVersion: extensions/v1beta1 kind: Deployment ... spec: containers: - env: - name: MONGO_DB valueFrom: configMapKeyRef: key: MONGO_DB name: nodejs-env - name: MONGO_HOSTNAME value: db - name: MONGO_PASSWORD - name: MONGO_PORT valueFrom: configMapKeyRef: key: MONGO_PORT name: nodejs-env - name: MONGO_USERNAME
سنحتاج إلى إضافة إشارات مرجعية إلى السرّ في متغيرات MONGO_USERNAME و MONGO_PASSWORD المدرجة هنا، حتى يتمكن تطبيقنا من الوصول إلى تلك القيم. وبدلاً من تضمين مفتاح configMapKeyRef للإشارة إلى خريطة الإعداد لnodejs-env ، كما هو الحال مع قيم MONGO_DB و MONGO_PORT،، سنُضمِّن مفتاح secretKeyRef للإشارة إلى القيم الموجودة في السرّ secret.
أضف إشارات السرّ المرجعية التالية إلى المتغيرين MONGO_USERNAME
و MONGO_PASSWORD
:
apiVersion: extensions/v1beta1 kind: Deployment ... spec: containers: - env: - name: MONGO_DB valueFrom: configMapKeyRef: key: MONGO_DB name: nodejs-env - name: MONGO_HOSTNAME value: db - name: MONGO_PASSWORD valueFrom: secretKeyRef: name: mongo-secret key: MONGO_PASSWORD - name: MONGO_PORT valueFrom: configMapKeyRef: key: MONGO_PORT name: nodejs-env - name: MONGO_USERNAME valueFrom: secretKeyRef: name: mongo-secret key: MONGO_USERNAME
احفظ الملف وأغلقه عند الانتهاء من التحرير. بعد ذلك ، سنضيف القيم نفسها إلى ملف db-publish.yaml. افتح الملف للتحرير:
nano db-deployment.yaml
سنضيف في هذا الملف إشارات مرجعية إلى السرّ في مفاتيح المتغيرات التالية: MONGO_INITDB_ROOT_USERNAME و MONGO_INITDB_ROOT_PASSWORD. تجعل صورة mongo هذه المتغيرات متاحة لتتمكّن من تعديل تهيئة نسخة قاعدة بياناتك.
ينشئ MONGO_INITDB_ROOT_USERNAME وMONGO_INITDB_ROOT_PASSWORD معًا مستخدمًا جذرًا في قاعدة بيانات المشرف admin مع التأكد من تفعيل التصديق على الهوية عند بدء تشغيل حاوية قاعدة البيانات.
يضمن استخدام القيم التي حدّدناها في السرّ أن يكون لدينا مستخدم للتطبيق يتمتع بأذونات الجذر root في نسخة قاعدة البيانات، مع إمكانية الوصول إلى جميع الأذونات الإدارية والتشغيلية لهذا الدور. عند العمل في الإنتاج، سترغب في إنشاء مستخدم تطبيق مخصّص ذي صلاحيات محددة النطاق.
أضف أسفل متغيرات MONGO_INITDB_ROOT_USERNAME وMONGO_INITDB_ROOT_PASSWORD إشارات مرجعية إلى قيم السرّ Secret:
apiVersion: extensions/v1beta1 kind: Deployment ... spec: containers: - env: - name: MONGO_INITDB_ROOT_PASSWORD valueFrom: secretKeyRef: name: mongo-secret key: MONGO_PASSWORD - name: MONGO_INITDB_ROOT_USERNAME valueFrom: secretKeyRef: name: mongo-secret key: MONGO_USERNAME image: mongo:4.1.8-xenial …
احفظ الملف وأغلقه عند الانتهاء من التحرير.
بعد إعداد السر الخاص بك، يمكنك الانتقال إلى إنشاء خدمة قاعدة بياناتك والتأكد من أن حاوية التطبيق تحاول فقط الاتصال بقاعدة البيانات بمجرد إعدادها وتهيئتها بالكامل.
الخطوة الخامسة: إنشاء خدمة قاعدة البيانات وحاوية التطبيق الأولية
الآن بعد أن أعددنا السرّ، يمكننا الانتقال إلى إنشاء خدمة قاعدة البيانات وحاوية أولية مهمّتها استطلاع هذه الخدمة للتأكد من أن تطبيقنا يحاول فقط الاتصال بقاعدة البيانات بمجرد اكتمال إجراءات بدء تشغيل قاعدة البيانات، بما في ذلك إنشاء مستخدم وكلمة مرور MONGO_INITDB.
للمزيد حول كيفية تنفيذ هذه الوظيفة في Compose، يرجى الاطلاع على الخطوة الرابعة من إعداد تطبيق node.js لسير عملٍ يعتمد على الحاويات باستخدام Docker Compose.
افتح ملفًا لتحديد مواصفات خدمة قاعدة البيانات:
nano db-service.yaml
أضف الشيفرة التالية إلى الملف لتعريف الخدمة:
-
الملف
~/node_project/db-service.yaml
:
apiVersion: v1 kind: Service metadata: annotations: kompose.cmd: kompose convert kompose.version: 1.18.0 (06a2e56) creationTimestamp: null labels: io.kompose.service: db name: db spec: ports: - port: 27017 targetPort: 27017 selector: io.kompose.service: db status: loadBalancer: {}
سيُطابِق المحدد selector الذي أدرجناه هنا كائن الخدمة هذا مع علب (Pods) قاعدة بياناتنا، والتي عُرِّفت بالتسمية io.kompose.service: db
بواسطة kompose في ملف .db-publish.yaml لقد سمّينا أيضًا هذه الخدمة db.
احفظ الملف وأغلقه عند الانتهاء من التحرير.
بعد ذلك، دعنا نضيف حقلًا لحاوية أولية إلى المصفوفة containers في nodejs-deployment.yaml سيؤدي هذا إلى إنشاء حاوية أوّلية يمكننا استخدامها لتأخير حاوية تطبيقنا عن الاشتغال حتى إنشاء خدمة db ذات علبة يمكن الوصول إليها. وهذا هو أحد الاستخدامات المحتملة للحاويات الأولية. لمعرفة المزيد عن حالات الاستخدام الأخرى، يرجى الاطلاع على التوثيق الرسمي.
افتح الآن الملف nodejs-publish.yaml:
nano nodejs-deployment.yaml
داخل العلبة Pod وبجانب المصفوفة containers، سنضيف حقلًا initContainers بحاوية مهمتها استقصاء الخدمة db.
أضف الشيفرة التالية أسفل الحقلين ports وresources وفوق restartPolicy في مصفوفة nodejs containers:
-
الملف
~/node_project/nodejs-deployment.yaml
:
apiVersion: extensions/v1beta1 kind: Deployment ... spec: containers: ... name: nodejs ports: - containerPort: 8080 resources: {} initContainers: - name: init-db image: busybox command: ['sh', '-c', 'until nc -z db:27017; do echo waiting for db; sleep 2; done;'] restartPolicy: Always ...
تستخدم هذه الحاوية الأولية صورة BusyBox، وهي صورة خفيفة الوزن تتضمن العديد من أدوات UNIX. في هذه الحالة، سنستخدم الأداة netcat لاستقصاء هل تقبل العلبة المرتبطة بالخدمة db الاتصالات TCP على المنفذ 27017.
يكرّر أمر الحاوية command هذا وظيفة السكربت wait-for الذي حذفناه من الملف docker-compose.yaml في الخطوة الثالثة. لمزيد من التوضيح حول كيفية وعلّة استخدام تطبيقنا للسكربت wait-for ، يرجى الاطلاع على الخطوة الرابعة من كيفية إعداد تطبيق node.js لسير عملٍ يعتمد على الحاويات باستخدام Docker Compose.
تشتغل الحاويات الأولية وفق نظام run to completion. هذا يعني في حالتنا هذه أن حاوية التطبيق Node لن تبدأ في الاشتغال حتى تبدأ حاوية قاعدة البيانات في الاشتغال وقبول الاتصالات على المنفذ 27017. يسمح لنا تعريف الخدمة db بضمان هذه الوظيفة بغض النظر عن الموقع المحدّد لحاوية قاعدة البيانات، والذي يمكنه أن يتغيّر.
احفظ الملف وأغلقه عند الانتهاء من التحرير.
بعد إنشائك لخدمة قاعدة البيانات ووضعك لحاوياتك الأولية للتحكم في ترتيب اشتغال الحاويات، يمكنك الانتقال إلى التحقق من متطلبات التخزين في PersistentVolumeClaim وعرض خدمة تطبيقك باستخدام LoadBalancer.
الخطوة السّادسة: تعديل PersistentVolumeClaim وعرض الواجهة الأمامية للتطبيق
قبل تشغيل التطبيق، سنجري تغييرين أخيرين لضمان توفير تخزين قاعدة البيانات بشكل صحيح، وأنّنا نستطيع عرض الواجهة الأمامية لتطبيقنا باستخدام LoadBalancer.
دعنا نعدل أولاً مورد التخزين storage resource المحدد في PersistentVolumeClaim الذي أنشأناه. تتيح لنا هذه المطالبة (claim) توفير مساحة تخزين ديناميكية لإدارة حالة التطبيق.
للعمل ب PersistentVolumeClaims، يجب أن يكون لديك صنف تخزين StorageClass أنشأته وأعددته لتوفير موارد التخزين. في حالتنا هذه، ونظرًا لأننا نعمل على DigitalOcean Kubernetes، يعيّن صنف التخزين provisioner الافتراضي على dobs.csi.digitalocean.com.
يمكننا التحقق من ذلك عبر كتابة ما يلي:
kubectl get storageclass
إذا كنت تعمل مع مجموعة DigitalOcean، فسترى الإخراج التالي:
NAME PROVISIONER AGE do-block-storage (default) dobs.csi.digitalocean.com 76m
إذا كنت لا تعمل على عنقود DigitalOcean، فستحتاج إلى إنشاء StorageClass وإعداد مزوّد من اختيارك. للحصول على تفاصيل حول كيفية القيام بذلك، يرجى الاطلاع على التوثيق الرسمي.
عندما ينشئ kompose الملف dbdata-persistentvolumeclaim.yaml، فإنه يعيّن مورد التخزين storage resource على سعةٍ لا تلبي الحدّ المطلوب في مزوّد الخدمة لدينا. لذلك، سنحتاج إلى تعديل PersistentVolumeClaim الخاص بنا لاستخدام السعة الدنيا القابلة للتطبيق لوحدة تخزين DigitalOcean Block المحدّدة في 1 جيجابايت. ويمكنك تعديل هذه القيمة لتلبية متطلبات التخزين الخاصة بك.
افتح الملفّ dbdata-persistentvolumeclaim.yaml:
nano dbdata-persistentvolumeclaim.yaml
عوّض قيمة التخزين storage بـ 1Gi:
-
الملف
~/node_project/dbdata-persistentvolumeclaim.yaml
:
apiVersion: v1 kind: PersistentVolumeClaim metadata: creationTimestamp: null labels: io.kompose.service: dbdata name: dbdata spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi status: {}
لاحظ أيضًا أنّ accessMode: ReadWriteOnce يعني أن الحجم المتوفّر كنتيجة لهذه الطلب سيكون للقراءة والكتابة من خلال عقدة واحدة فقط. يرجى الاطلاع على التوثيق لمزيد من المعلومات حول أوضاع الوصول المختلفة.
احفظ الملف وأغلقه عند الانتهاء. بعد ذلك، افتح nodejs-service.yaml:
nano nodejs-service.yaml
سنعمل على الكشف عن هذه الخدمة خارجيًا باستخدام .DigitalOcean Load Balancer
إذا كنت لا تستخدم عنقود DigitalOcean، فيرجى الرجوع إلى التوثيق ذا الصلة من مزوّد الخدمة السحابية للحصول على معلومات حول موازِنات الحمل الخاصة به. بدلاً من ذلك، يمكنك اتباع توثيق Kubernetes الرسمية الخاصة بإعداد عنقود عالي التوفّر باستخدام kubeadm، لكن في هذه الحالة لن تتمكن من استخدام PersistentVolumeClaims لتوفير التخزين.
حدّد ضمن مواصفات الخدمة، LoadBalancer في الحقل type الخاصّ بالخدمة:
-
الملف
~/node_project/nodejs-service.yaml
:
apiVersion: v1 kind: Service ... spec: type: LoadBalancer ports: ...
عندما ننشئ خدمة nodejs، سيُنشَأ مُوازِن للتحميل تلقائيًا، مما يوفر لنا عنوانًا خارجيًا IP يمكِّننا من الوصول إلى تطبيقنا.
احفظ الملف وأغلقه عند الانتهاء من التحرير. بوجود جميع ملفاتنا في مكانها الصحيح، نكون على استعداد لبدء واختبار التطبيق.
الخطوة السابعة: بدء التطبيق والوصول إليه
لقد حان الوقت لإنشاء كائنات Kubernetes واختبار عمل التطبيق على النحو المتوقع.
لإنشاء الكائنات التي حددناها، سنستخدم kubectl create مع الراية f-، والتي سوف تتيح لنا تحديد الملفات التي أنشأها لنا Compose، بالإضافة إلى الملفات التي حرّرناها. نفّذ الأمر التالي لإنشاء تطبيق Node وخدمات قاعدة بيانات MongoDB وعمليات النشر، مع Secret وConfigMap وPersistentVolumeClaim:
kubectl create -f nodejs-service.yaml,nodejs-deployment.yaml,nodejs-env-configmap.yaml,db-service.yaml,db-deployment.yaml,dbdata-persistentvolumeclaim.yaml,secret.yaml
سيظهر لك الإخراج التالي مشيرًا إلى إنشاء الكائنات:
Output service/nodejs created deployment.extensions/nodejs created configmap/nodejs-env created service/db created deployment.extensions/db created persistentvolumeclaim/dbdata created secret/mongo-secret created
للتحقق من اشتغال العلب Pods، اكتب ما يلي:
kubectl get pods
لا تحتاج إلى تحديد فضاء اسم (namespace) هنا، لأننا أنشأنا كائناتنا في مساحة اسمية الافتراضية. إذا كنت تعمل على مساحات اسمية متعددة، فتأكد من تضمين الراية n-
عند تنفيذ هذا الأمر، بالإضافة إلى اسم مساحتك الاسمية.
سيظهر لك الإخراج التالي أثناء بدء تشغيل الحاوية db وحاوية تطبيقك الأولية:
Output NAME READY STATUS RESTARTS AGE db-679d658576-kfpsl 0/1 ContainerCreating 0 10s nodejs-6b9585dc8b-pnsws 0/1 Init:0/1 0 10s
بمجرد تشغيل تلك الحاوية وبدء تشغيل حاويات التطبيق وقاعدة البيانات، سيظهر لك هذا الإخراج:
Output NAME READY STATUS RESTARTS AGE db-679d658576-kfpsl 1/1 Running 0 54s nodejs-6b9585dc8b-pnsws 1/1 Running 0 54s
يشير Running STATUS إلى أن العلب الخاصة بك مرتبطة بالعُقَد وأن الحاويات المرتبطة بتلك العلب تعمل. ويشير READY إلى عدد الحاويات الموجودة في العلبة. لمزيد من المعلومات، يرجى الرجوع إلى توثيق دورة حياة العلبة.
ملحوظة: إذا رأيت مراحل غير متوقعة في العمود STATUS، تذكر أنه يمكنك استكشاف الأخطاء وإصلاحها باستخدام الأوامر التالية:
kubectl describe pods your_pod kubectl logs your_pod
بعد تشغيل حاوياتك، يمكنك الآن الوصول إلى التطبيق. للحصول على العنوان IP الخاص بـ LoadBalancer، اكتب:
kubectl get svc
سيظهر لك الإخراج التالي:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE db ClusterIP 10.245.189.250 <none> 27017/TCP 93s kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 25m12s nodejs LoadBalancer 10.245.15.56 your_lb_ip 80:30729/TCP 93s
العنوان EXTERNAL_IP المرتبط بخدمة nodejs هو عنوان IP يمكّنك من الوصول إلى التطبيق. إذا رأيت حالة <pending>
في عمود EXTERNAL_IP،، فهذا يعني أن مُوازِن التحميل لا يزال قيد الإنشاء.
بمجرد رؤية عنوان IP في هذا العمود، انتقل إليه في متصفحك: http://your_lb_ip. ينبغي أن تظهر لك صفحة الهبوط التالية:
انقر على زر الحصول على معلومات القرش. ستظهر صفحةّ فيها نموذج إدخال حيث يمكنك إدخال اسم سمك القرش ووصف لسلوكه العام:
أضف في النموذج سمكة قرش من اختيارك. للتوضيح، سنضيف Megalodon Shark إلى حقل Shark Name، وAncient لحقل Shark Character:
انقر على زر الإرسال. ستظهر صفحة بها معلومات القرش معروضة لك:
لديك الآن إعداد نسخة واحدة لتطبيق Node.js بقاعدة بيانات MongoDB تعمل على عنقود Kubernetes.
خاتمة
تعدّ الملفات التي أنشأتها في هذا الدرس نقطة انطلاق جيدة للبناء عليها أثناء تقدمك نحو الإنتاج. ويمكنك العمل أثناء تطوير تطبيقك على تنفيذ ما يلي:
-
تسجيل الدّخول والمراقبة بشكل مركزي. يرجى الاطلاع على المناقشة ذات الصلة على موقع ديجيتال أوشن حول تحديث تطبيقات Kubernetes للحصول على نظرة أشمل. يمكنك أيضًا الاطلاع على كيفية إعداد حزمة تسجيل دخول Elasticsearch، و Fluentd و Kibana (EFK) على Kubernetes على موقع ديجيتال أوشن. راجع أيضًا مقال مقدمة لشبكات الخدمة للحصول على معلومات حول كيفية تنفيذ شبكات الخدمات مثل Istio لهذه الوظيفة.
-
موارد الولوج لتوجيه حركة المرور إلى عنقودك. يعد هذا بديلاً جيدًا لموزع الحمل LoadBalancer في الحالات التي تشغّل فيها خدمات متعددة، والتي تتطلب كل منها موازِنًا LoadBalancer خاصًّا بها، أو عندما ترغب في تنفيذ استراتيجيات توجيه على مستوى التطبيق (اختبارات A/B & canary، على سبيل المثال). لمزيد من المعلومات، تحقّق من مقال كيفية إعداد Nginx Ingress مع Cert-Manager على DigitalOcean Kubernetes والمناقشة ذات الصلة على ديجيتال أوشن بالتوجيه في سياق شبكة الخدمة في مقدمة لشبكات الخدمة.
-
استراتيجيات النسخ الاحتياطي لكائناتك Kubernetes. للحصول على إرشادات حول تنفيذ النسخ الاحتياطية باستخدام Velero (سابقًا Heptio Ark) مع منتج Kubernetes الخاص بـ DigitalOcean، يرجى الاطلاع على مقال كيفية عمل نسخة احتياطية واستعادة عنقود Kubernetes على DigitalOcean باستخدام Heptio Ark.
ترجمة -وبتصرف- للمقال How To Migrate a Docker Compose Workflow to Kubernetes لصاحبته Kathleen Juell
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.