اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'kubernetes'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 5 نتائج

  1. هذا المقال هو الثالث من سلسلة تعليمية تتضمن ثلاث مقالات عن الانتقال من الحاويات إلى كوبيرنتس Kubernetes باستخدام جانغو Django إطار العمل الخاص بتسريع تطوير تطبيقات الويب المبنية بلغة بايثون، في المقال الأول تعلمنا تعديل عينة تجريبية من تطبيق جانغو (تسمى التطبيق Polls) وفق منهجية Twelve-Factor الخاصة بتطوير تطبيقات ويب سحابية قابلة للتوسع والعمل ضمن الحاويات، وفي المقال الثاني تعرفنا على طرق توسيع هذا التطبيق (المعدّل المغلف في حاوية دوكر) توسيعًا أفقيًا وتأمينه بتشغيل وكيل عكسي أمامه هو خادم Nginx مع استخدام شهادات TLS مصدقة من Let's Encrypt، أما اليوم نشارككم كيفية نشر التطبيق المعدّل نفسه باستعمال عنقود كوبيرنتس Kubernetes Cluster. كوبيرنتس kubernetes هو حل مفتوح المصدر لإدارة الحاويات، ميزته الأساسية أتمتة عمليات نشر وتوسيع وإدارة تطبيقات الويب المغلفة ضمن حاويات، وذلك من خلال مجموعة من الكائنات الخاصة مثل خرائط الإعدادات ConfigMaps والأسرار Secrets التي تسمح بتهيئة مركزية للبيئة من خارج الحاويات، ووحدات التحكم مثل النشر Deployments المسؤولة عن إعادة تشغيل الحاويات تلقائيًا في حال حدوث أي خلل وعن التوسعة التلقائية بتشغيل حاويات إضافية مماثلة لحاوية التطبيق عند ازدياد الطلب عليه، وأيضًا كائن الإدخال ingress أو المُدخل (تترجم أحيانًا إلى كائن الولوج واعتمدنا هنا كائن الإدخال والمُدخل حسب سياق الجملة) المسؤول عن توجيه حركة البيانات HTTP أو HTTPS المشفرة بشهادات TLS من المصادر الخارجية إلى خدمات كوبيرنتس الداخلية عبر قواعد وصول محددة مع وحدة التحكم مفتوحة المصدر ingress-nginx، أما التجديد الدوري للشهادات وتصديقها من Let's Encrypt تنجزه الوظيفة الإضافية مدير الشهادات cert-manager. هذا المقال جزء من سلسلة قصيرة حول احتواء تطبيقات جانغو بحاويات وإدارتها وإليك فهرس السلسلة: بناء تطبيق جانغو بخادم Gunicorn ووضعه ضمن حاوية دوكر توسيع تطبيق جانغو وتأمينه عبر حاوية دوكر وخادم Nginx وخدمة Let's Encrypt نشر تطبيق جانغو آمن وقابل للتوسيع باستخدام كوبيرنتس متطلبات بيئة العمل ستحتاج المتطلبات التالية لتتمكن من التطبيق العملي لهذا المقال: عنقود كوبيرنتس بإصدار 1.15 أو أعلى، مع تفعيل خاصية التحكم بالوصول المستند على الدور Role-based access control (RBAC)، استخدمنا في المقال عنقود خدمة DigitalOcean، لكنك لست ملزمًا بذلك يمكنك إعداده بنفسك بالطريقة التي تناسبك. تثبيت أداة سطر الأوامر kubectl على جهازك المحلي وإعدادها للاتصال بالعنقود، يمكنك معرفة المزيد عن تثبيت kubectl بالاطلاع على توثيقات كوبيرنتس الرسمية. أما إن اعتمدت DigitalOcean فاستعن بالمقال إعداد الاتصال مع عنقود كوبيرنتس في DigitalOcean. حجز اسم نطاق لتطبيقك، سنعتمد في مقالنا على الاسم your_domain.com، مع العلم بإمكانية حصولك على اسم نطاق مجاني من Freenom. تثبيت وحدة التحكم ingress-nginx ومدير الشهادات cert-manager وضبط الإعدادات اللازمة للتحقق من الشهادات، يمكنك الاطلاع على كيفية إعداد Nginx Ingress ومدير الشهادات على كوبيرنتس. ربط اسم النطاق بعنوان IP العام لمُدخل موازن الحمل عبر إضافة سجل DNS من النوع A، يمكنك الحصول على تفاصيل إضافية حول DNS بالاطلاع على القسم الخاص بخدمة اسم النطاق DNS على أكاديمية حسوب. خدمة تخزين كائني متوافقة مع S3 ومع إضافة django-storages مثل DigitalOcean Space وظيفتها تأمين المساحة التخزينية اللازمة لملفات تطبيق جانغو الساكنة، مع مجموعة مفاتيح الوصول الخاصة بإدارة هذه المساحة، استرشد بكيفية إعداد مساحة على DigitalOcean Space وعدّل بما يلائم خدمة التخزين التي اخترتها. نظام إدارة قواعد بيانات متوافق مع جانغو مع إنشاء قاعدة بيانات ومستخدم خاص بالتطبيق، نحن اخترنا خادم PostgreSQL، اهتم بالتفاصيل التالية أثناء إنجازك لهذه النقطة لتتمكن من متابعة خطوات المقال: استخدم الاسم polls لقاعدة البيانات والاسم sammy لمستخدم قاعدة البيانات (هذه الأسماء ليست ملزمة ولكننا استخدمناها في المقال واستخدامك لها سيسهل عليك المتابعة)، لمزيد من التفاصيل حول الإنشاء استرشد بالخطوة /1/ من مقالنا السابق [بناء تطبيق جانغو بخادم Gunicorn ووضعه ضمن حاوية دوكر]()، مع العلم أن هذه المهمة يمكن إنجازها من أي خادم من الخوادم الثلاثة لبيئة العمل. اعتمدنا في المقال على نظام إدارة قواعد البيانات من نوع Managed PostgreSQL cluster الذي توفره DigitalOcean. لكن يمكنك تثبيت PostgreSQL وتشغيله وإعداده بنفسك مع الاستعانة بالفيديو التعليمي تثبيت وإعداد قاعدة بيانات PostgreSQL. حساب على Docker Hub، استرشد بتوثيقات دوكر الخاصة بالمستودعات لإنشائه. تثبيت دوكر على جهازك المحلي، استعن لذلك بمقال كيفية تثبيت دوكر واستخدامه على دبيان. الخطوة 1: استنساخ التطبيق وضبط إعداداته تتلخص هذه الخطوة باستنساخ كود التطبيق من مستودع GitHub بالإضافة إلى ضبط محددات الاتصال مع خادم قاعدة البيانات والمفاتيح الخاصة بخدمة التخزين الكائني المستخدمة. سنحصل على كود التطبيق والملف Dockerfile من القسم polls-docker من مستودع GitHub الذي يتضمن نسخًا تجريبية من التطبيق المسمى Polls وهذه النسخ تتناسب مع أغراض جانغو التعليمية، بالإضافة لكونها مغلفة ومعدّلة بكل ما يلزم لتعمل بفعالية داخل الحاوية وتتكيف مع متغيرات بيئة التشغيل وفق ما تعلمنا في المقال الأول من هذه السلسلة. اكتب الأمر التالي للاستنساخ: git clone --single-branch --branch polls-docker https://github.com/do-community/django-polls.git توجه للمجلد django-polls عبر الأمر: cd django-polls يتضمن هذا المجلد كود التطبيق والملف Dockerfile الذي سيستخدمه دوكر لبناء صورة الحاوية، بالإضافة إلى الملف env الذي يتضمن متغيرات البيئة التي ستمرر للحاوية من بيئة التشغيل المحيطة. استعرض الملف Dockerfile عبر تعليمة لينكس cat: cat Dockerfile وستحصل على الخرج التالي: FROM python:3.7.4-alpine3.10 ADD django-polls/requirements.txt /app/requirements.txt RUN set -ex \ && apk add --no-cache --virtual .build-deps postgresql-dev build-base \ && python -m venv /env \ && /env/bin/pip install --upgrade pip \ && /env/bin/pip install --no-cache-dir -r /app/requirements.txt \ && runDeps="$(scanelf --needed --nobanner --recursive /env \ | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ | sort -u \ | xargs -r apk info --installed \ | sort -u)" \ && apk add --virtual rundeps $runDeps \ && apk del .build-deps ADD django-polls /app WORKDIR /app ENV VIRTUAL_ENV /env ENV PATH /env/bin:$PATH EXPOSE 8000 CMD ["gunicorn", "--bind", ":8000", "--workers", "3", "mysite.wsgi"] وفقًا للخرج السابق، فإن Dockerfile سيستخدم صورة دوكر بإصدار بايثون 3.7.4، ويثبت اعتماديات وحزم بايثون اللازمة لكل من جانغو وخادم gunicorn وفق ملف متطلبات التطبيق django-polls/requirements.txt ومن ثم يحذف الملفات غير اللازمة بعد انتهاء التثبيت، وينسخ بعد ذلك كود التطبيق إلى الصورة ويسند قيمة المتغير PATH، وأخيرًا سيحدد البوابة أو المنفذ 8000 لاستقبال حركة البيانات الواردة إلى الحاوية، ويشغل gunicorn مع عمال workers عدد /3/ عبر المنفذ 8000. لتعرف المزيد عن كل مرحلة ضمن Dockerfile راجع مقالنا الأول السابق من السلسلة. لنبني صورة الحاوية باستخدام docker build: docker build -t polls . سميّنا الصورة باسم polls باستخدام الراية t- ومررنا المسار الحالي . كمسار context للتعليمة build فهو يتضمن كافة الملفات اللازمة لعملية البناء. بعد انتهاء عملية البناء استخدم الأمر docker images لاستعراض الصور المتاحة: docker images وستحصل على الخرج التالي: REPOSITORY TAG IMAGE ID CREATED SIZE polls latest 80ec4f33aae1 2 weeks ago 197MB python 3.7.4-alpine3.10 f309434dea3a 8 months ago 98.7MB لنضبط متغيرات البيئة تمهيدًا لعملية التشغيل docker run، وذلك بتعديل الملف env باستعمال محرر النصوص: nano env سيظهر أمامك الملف env بالشكل التالي: DJANGO_SECRET_KEY= DEBUG=True DJANGO_ALLOWED_HOSTS= DATABASE_ENGINE=postgresql_psycopg2 DATABASE_NAME=polls DATABASE_USERNAME= DATABASE_PASSWORD= DATABASE_HOST= DATABASE_PORT= STATIC_ACCESS_KEY_ID= STATIC_SECRET_KEY= STATIC_BUCKET_NAME= STATIC_ENDPOINT_URL= DJANGO_LOGLEVEL=info كما ترى فبعض محددات الملف قيمها موجودة والبعض الآخر يحتاج إلى ضبط بما يناسب بيئتك، سنذكر المحددات التي تحتاج إلى ضبط بالترتيب: المفتاح السري DJANGO_SECRET_KEY اختر له قيمة فريدة صعبة التخمين كما توصي توثيقات Docker نقدم لك في الخطوة /5/ من مقال كيفية إعداد تطبيق جانغو عبر DigitalOcean Managed Databases and Spaces إحدى طرق جانغو لتوليد المفاتيح. أما DJANGO_ALLOWED_HOSTS فأسند له اسم النطاق الخاص بك your_domain.com، أو يمكنك وضع الرمز * لأغراض الاختبار فقط وليس ضمن بيئة العمل الفعلية فهذا الرمز يسمح لأي عنوان IP بالوصول، يحميك هذا المحدد من الهجمات المعتمدة على حقن ترويسة HTTP وفي حال أردت المزيد من المعلومات اطلع على توثيقات جانغو الخاصة بهذا المحدد ضمن Core Settings DATABASE_USERNAME ضع اسم مستخدم قاعدة البيانات PostgreSQL الذي أنشأته أثناء إعدادك لمتطلبات العمل. DATABASE_NAME ضع القيمة polls أو الاسم الذي اخترته لقاعدة البيانات أثناء إعدادك لمتطلبات العمل. كذلك الأمر لكلمة المرور DATABASE_PASSWORD. ضع اسم مضيف قاعدة البيانات DATABASE_HOST ورقم بوابة الاتصال معها DATABASE_PORT. أما المحددات STATIC_ACCESS_KEY_ID و STATIC_SECRET_KEY و STATIC_BUCKET_NAME و STATIC_ENDPOINT_URL فهي تتعلق بخدمة التخزين الكائني الخارجية، اضبطها بما يتناسب مع الخدمة التي تستخدمها. احفظ التغيرات على الملف env بعد الانتهاء وأغلقه، ولننتقل للخطوة التالية. الخطوة 2: إنشاء مخطط قاعدة البيانات ورفع ملفات التطبيق إلى وحدة التخزين الكائني شغل صورة الحاوية polls:latest عبر الأمر التالي: docker run --env-file env polls sh -c "python manage.py makemigrations && python manage.py migrate" وبموجبه الأمر سيجري تجاوز الأمر الافتراضي عند بدء التشغيل المحدد بتعليمة CMD ضمن الملف Dockerfile وتنشئ أثناء التشغيل مخطط قاعدة بيانات التطبيق وهو الأمر الفرعي: sh -c "python manage.py makemigrations && python manage.py migrate" إن كنت تنفذ الأمر docker run للمرة الأولى فستحصل على الخرج التالي الذي يبين نجاح إنشاء مخطط قاعدة البيانات: No changes detected Operations to perform: Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying polls.0001_initial... OK Applying sessions.0001_initial... OK مع العلم أن جانغو لن يجري أي عملية عندما تنفذ migrate في المرات القادمة طالما لم يطرأ أي تغيير على مخطط قاعدة بيانات التطبيق. نفذ بعدها أمر تشغيل جديد للحاوية مع استدعاء سطر الأوامر الخاص بالصدفة Shell كما يلي: docker run -i -t --env-file env polls sh تظهر بنتيجة هذا الأمر نافذة الصدفة shell ضمن الحاوية اكتب فيها تعليمة إنشاء المستخدم الخاص بتطبيق جانغو: python manage.py createsuperuser استكمل بياناته وهي اسم المستخدم وكلمة المرور والبريد الإلكتروني، واضغط بعدها على الاختصار Ctrl+D للخروج من الحاوية وإنهاء عملها. أما العملية الأخيرة فهي جمع الملفات الساكنة الخاصة بالتطبيق collectstatic ورفعها على خدمة التخزين الكائني وتتم وفق الأمر التالي علمًا أنها قد تستغرق بعض الوقت: docker run --env-file env polls sh -c "python manage.py collectstatic --noinput" يظهر بعدها الخرج التالي: 121 static files copied. يمكنك الآن تشغيل التطبيق: docker run --env-file env -p 80:8000 polls ستحصل على الخرج: [2019-10-17 21:23:36 +0000] [1] [INFO] Starting gunicorn 19.9.0 [2019-10-17 21:23:36 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1) [2019-10-17 21:23:36 +0000] [1] [INFO] Using worker: sync [2019-10-17 21:23:36 +0000] [7] [INFO] Booting worker with pid: 7 [2019-10-17 21:23:36 +0000] [8] [INFO] Booting worker with pid: 8 [2019-10-17 21:23:36 +0000] [9] [INFO] Booting worker with pid: 9 مع العلم أن التشغيل هذه المرة وفق الإعدادات الافتراضية المنصوص عليها في ملف Dockerfile وهي: gunicorn --bind :8000 --workers 3 mysite.wsgi:application وأن البوابة 8000 للحاوية فُتحت لتستقبل حركة البيانات القادمة من البوابة 80 للخادم أوبونتو. يمكنك الآن كتابة عنوان URL الخاص بالتطبيق polls بمتصفح الإنترنت واستعراضه، لاحظ أنك ستحصل على الخطأ 404 (لم يتم العثور على الصفحة) في حال اكتفيت بالعنوان: http://APP_SERVER_1_IP/ بسبب عدم وجود بيانات للتطبيق تحت الجذر / لذا اكتب العنوان التالي لتحصل على واجهة polls: http://APP_SERVER_1_IP/polls اكتب الرابط التالي: http://APP_SERVER_1_ip/admin وستتمكن من الوصول إلى واجهة الدخول للوحة التحكم الخاصة بالتطبيق: أدخل بيانات المستخدم مدير التطبيق المنشأ سابقًا باستخدام الأمر createsuperuser وستظهر أمامك واجهة الإدارة والتحكم الخاصة بالتطبيق. تذكر أن تسليم المكونات الساكنة للتطبيق admin و polls يتم من خدمة التخزين الكائني ويمكنك اتباع هذه الخطوات لاختبار جودته وأيضًا التأكد من صحة إحضار الملفات. بعد أن تنتهي من اختبار عمل التطبيق اضغط على الاختصار Ctrl+c في نافذة كتابة الأوامر السطرية التي تشغل حاوية دوكر لتنهي عمل الحاوية. والآن بعد إتمام بناء صورة دوكر للتطبيق، وبناء مخطط قاعدة البيانات وتحميل مكونات التطبيق الساكنة إلى وحدة التخزين الكائني، وأخيرًا اختبار عمل الحاوية والتطبيق، يمكننا رفع الصورة إلى سجل صور مثل Docker Hub وهو موضوع خطوتنا التالية. الخطوة 3: رفع صورة جانغو إلى Docker Hub لتستخدم تطبيقك ضمن عنقود كوبيرنتس، ستحتاج أولًا رفع صورة التطبيق إلى سجل صور عام أو خاص مثل Docker Hub حتى تتمكن خدمة كوبيرنتس من سحب الصورة ونشر التطبيق. علمًا أن لسجلات الصور نوعان عام وخاص، السجل العام مجاني إلاّ أنه يجعل صورك في متناول جميع المستخدمين ويمكّنهم من سحبها، أما الخاص فيعطي خصوصية أكبر إذا يسمح لك بمشاركة الصور مع مجموعة محددة من المستخدمين مثل زملاء عملك، وتقدم بعض الشركات -مثل سجل حاويات DigitalOcean على سبيل المثال لا الحصر- عروضًا مجانية لإنشاء سجلات خاصة محدودة، أما Docker Hub فيدعم النوعين العام والخاص. سنقدم في مثالنا طريقة سحب الصور من سجل Docker Hub عام ويمكنك الاطلاع على توثيقات كوبيرنتس لمعرفة طريقة العمل مع السجلات الخاصة. لنبدأ بتسجيل الدخول إلى Docker Hub وفق الحساب الذي ذكرناه في متطلبات العمل: docker login سيُطلب منك إدخال اسم المستخدم وكلمة المرور لحسابك وفق التالي: Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: تحمل صورة التطبيق في بيئتنا الوسم polls:latest أعطها وسمًا جديدًا يتضمن اسم حسابك على Docker Hub واسم مستودعك باستخدام tag وفق التالي: docker tag polls:latest your_dockerhub_username/your_dockerhub_repo_name:latest استعملنا في مثالنا الاسم sammy للحساب و sammy-django للمستودع وبذلك يصبح الأمر على الشكل التالي: docker push sammy/sammy-django:latest ستحصل على خرج يتضمن تفاصيل عملية الرفع، وبعد إتمام العملية ستصبح الصورة متاحة أمام كوبيرنتس على Docker Hub. الخطوة 4: إعداد خريطة الإعدادات ConfigMap خريطة الإعدادات ConfigMap هي كائن كوبيرنتس المسؤول عن تمرير متغيرات بيئة التشغيل العامة إلى العنقود مثل إعدادات التطبيق، ويشاركه المهمة كائن آخر يدعى السرّ Secret إلاّ أنه يُعنى بالمتغيرات الحساسة مثل البيانات الخاصة بواجهات التخاطب API أو بقاعدة البيانات ولذا فهو يخضع لقواعد خاصة لحمايته والتحكم بوصول المستخدمين إليه مثل تفعيل خاصية encryption at rest، وبناءً على هذا الاختلاف في طبيعة بيانات الكائنين فإن بيانات ConfigMap تخزن بشكل نصي صريح ومقروء للمستخدم، بينما تخزن بيانات Secret معماة بأسلوب base64. تتشابه هذه الآلية في الواقع مع تمرير متغيرات البيئة لحاوية دوكر بالملف env الذي يلقم هذه المعلومات لأمر تشغيل الحاوية docker-run. لنبدأ بإعداد ConfigMap، والخطوة الأولى هي إنشاء مجلد يدعى yaml سنخزن ضمنه وثائق كوبرنيتس الأساسية: mkdir yaml cd ومن ثم أنشئ ضمن المجلد ملف نصي باسم polls-configmap.yaml يتضمن خريطة الإعدادات وفق التالي: nano polls-configmap.yaml وهذا يعني أننا بصدد إنشاء كائن كوبرنتس من نوع ConfigMap يحمل الاسم polls-config. الآن لننتقي من الملف env (الذي عملنا عليه في الخطوة /1/) البيانات العامة للتطبيق التي لا تتمتع بحساسية خاصة ونكتبها في الملف polls-configmap.yaml وذلك وفق الصيغة التالية: apiVersion: v1 kind: ConfigMap metadata: name: polls-config data: DJANGO_ALLOWED_HOSTS: "*" STATIC_ENDPOINT_URL: "https://your_space_name.space_region.digitaloceanspaces.com" STATIC_BUCKET_NAME: "your_space_name" DJANGO_LOGLEVEL: "info" DEBUG: "True" DATABASE_ENGINE: "postgresql_psycopg2" بالطبع مع وضع نفس القيم الموجودة في env وبخصوص المحدد DJANGO_ALLOWED_HOSTS نعطيه القيمة * كوننا نعمل في بيئة تجريبية. نحفظ بعدها التغييرات ونغلق الملف تمهيدًا لإنشاء الكائن ConfigMap بالأمر الأمر التالي: kubectl apply -f polls-configmap.yaml وسنحصل على الخرج التالي الذي يبين نجاح العملية: configmap/polls-config created الخطوة 5: إعداد السر Secret بيانات الكائن من نوع سرّ secret هي بيانات حساسة ومهمة كما ذكرنا سابقًا لذا فهي تُعمَّى بالأساس64، ولتحقيق ذلك لديك طريقتين إما ترميز البيانات خارجيًا من ثم كتابتها معماة ضمن الملف الذي سنعدّه للكائن، أو استخدام الأمر kubectl create مع الراية from-env-file-- وهي الطريقة التي استعملناها هنا. نعود للملف env استخدمنا متغيراته العامة في إنشاء الكائن Configmap والآن سنستخدم بقية المتغيرات التي تعد بيانات حساسة لإعداد الكائن secret. لننتقل للتطبيق العملي، انسخ الملف env إلى المجلد yaml وسمي النسخة polls-secrets وفق التالي: cp ../env ./polls-secrets افتح الملف polls-secrets باستعمال محرر النصوص: nano polls-secrets ستحصل على بيانات الملف env المنسوخ كاملةً: DJANGO_SECRET_KEY= DEBUG=True DJANGO_ALLOWED_HOSTS= DATABASE_ENGINE=postgresql_psycopg2 DATABASE_NAME=polls DATABASE_USERNAME= DATABASE_PASSWORD= DATABASE_HOST= DATABASE_PORT= STATIC_ACCESS_KEY_ID= STATIC_SECRET_KEY= STATIC_BUCKET_NAME= STATIC_ENDPOINT_URL= DJANGO_LOGLEVEL=info الآن احذف منه المتغيرات التي كتبناها ضمن ConfigMap في الخطوة السابقة، وستبقى المتغيرات التالية ضمنه: DJANGO_SECRET_KEY=your_secret_key DATABASE_NAME=polls DATABASE_USERNAME=your_django_db_user DATABASE_PASSWORD=your_django_db_user_password DATABASE_HOST=your_db_host DATABASE_PORT=your_db_port STATIC_ACCESS_KEY_ID=your_space_access_key STATIC_SECRET_KEY=your_space_access_key_secret ضع القيم الخاصة بتطبيقك نفسها التي ضبطناها في الخطوة /1/ من المقال (مثل محددات قاعدة البيانات والمفتاح الخاص وغيرها)، واحفظ التغييرات على الملف polls-secrets وأغلقه. أنشئ الآن الكائن من نوع secret والذي يحمل الاسم polls-secret من خلال الأمر التالي مع تمرير المتغيرات اللازمة للعنقود عبر الملف polls-secrets الذي أغلقته توًا: kubectl create secret generic polls-secret --from-env-file=poll-secrets وستحصل على الخرج الذي يبين نجاح الإنشاء: secret/polls-secret created استعرض بعدها وصف الكائن باستخدام kubectl describe: kubectl describe secret polls-secret لاحظ القيم المرمزة في الخرج: Name: polls-secret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== DATABASE_PASSWORD: 8 bytes DATABASE_PORT: 5 bytes DATABASE_USERNAME: 5 bytes DJANGO_SECRET_KEY: 14 bytes STATIC_ACCESS_KEY_ID: 20 bytes STATIC_SECRET_KEY: 43 bytes DATABASE_HOST: 47 bytes DATABASE_NAME: 5 bytes مررنا بذلك إعدادات التطبيق جانغو إلى داخل عنقود كوبيرنتس وتم تخزينها باستخدام كائنات من نوع Secret و ConfigMap، وأصبحت بيئتنا جاهزة لنشر التطبيق ضمن العنقود. الخطوة 6: نشر التطبيق باستخدام وحدة تحكم النشر وحدة النشر Deployment هي إحدى وحدات تحكم عنقود كوبيرنتس، تتولى إدارة التطبيقات عديمة الحالة stateless applications التي تعمل ضمن العنقود. إذ أنها تدير أعباء العمل صعودًا ونزولًا فتُدخل العناصر بالخدمة أو تخرجها تبعًا لضغط العمل، بالإضافة إلى إعطائها أوامر إعادة التشغيل للحاويات التي تفشل أثناء الإقلاع. تتحكم وحدة النشر Deployment بواحد أو أكثر من كائنات Pod، أما Pod فهي أصغر عناصر عنقود كوبيرنتس وكل واحدة منها يمكن أن تتضمن حاوية أو أكثر، لمعرفة المزيد يمكنك الاطلاع على تعلم أساسيات Kubernetes على أكاديمية حسوب. افتح ملفًا جديدًا يحمل الاسم polls-deployment.yaml عبر أي محرر تفضله وليكن عبر nano مثلًا: nano polls-deployment.yaml والصق ضمنه التعليمات التالية: apiVersion: apps/v1 kind: Deployment metadata: name: polls-app labels: app: polls spec: replicas: 2 selector: matchLabels: app: polls template: metadata: labels: app: polls spec: containers: - image: your_dockerhub_username/app_repo_name:latest name: polls envFrom: - secretRef: name: polls-secret - configMapRef: name: polls-config ports: - containerPort: 8000 name: gunicorn أكتب اسم الصورة التي بنيناها في الخطوة /2/ ولا تنسَ الإشارة للاسم الذي رفعنا به الصورة على Docker Hub. لنشرح التعليمات السابقة بالترتيب. أطلقنا على وحدة التحكم الاسم polls-app وميّزناها بعنوان label ذا القيمة المزدوجة app: polls، وضبطنا عدد نسخ Pods المطلوب تشغيلها بنسختين وفق replicas: 2 أما إعدادات هذه Pods فتُحددها المواصفات المكتوبة تحت template. أما configMapRef و secretRef المستخدمين بعد envFrom فيحددان على الترتيب قيم المتغيرات التي عرفناها من خلال كائن خريطة الإعدادات واسمه polls-config والكائن سرّ واسمه polls-secret، وفي نهاية الملف عرفنا بوابة الحاوية containerPort وهي تحمل الرقم 8000 والاسم gunicorn. يمكنك تعلم المزيد عن وحدة تحكم النشر من خلال توثيقات كوبيرنتس. أغلق الملف بعد حفظ التغييرات، لنباشر بإنشاء وحدة تحكم النشر عبر الأمر التالي: kubectl apply -f polls-deployment.yaml تحصل على الخرج الذي يؤكد نجاح العملية: deployment.apps/polls-app created يمكنك أيضًا التأكد من الإنشاء عبر الأمر: kubectl get deploy polls-app الذي يعطي النتيجة: NAME READY UP-TO-DATE AVAILABLE AGE polls-app 2/2 2 2 6m38s في حال واجهت أي خطأ في عمل وحدة التحكم وأردت التأكد من حالتها استخدم الأمر: kubectl describe deploy أما لفحص الـ Pods وحالتها فاستخدم: kubectl get pod وستحصل على الخرج التالي: NAME READY STATUS RESTARTS AGE polls-app-847f8ccbf4-2stf7 1/1 Running 0 6m42s polls-app-847f8ccbf4-tqpwm 1/1 Running 0 6m57s الخطوة 7: السماح للمصادر الخارجية بالوصول إلى الخدمة سننشئ في هذه الخطوة خدمة كوبيرنتس خاصة بتطبيقنا، والخدمات في كوبيرنتس عبارة عن مفهوم مجرد يعرّف مجموعة من كائنات Pod لتظهر أمام المصادر الخارجية كخدمة شبكة واحدة أي كطرف واحد endpoint بغض النظر عن توقف أي Pod أو تشغيلها، والمصادر الخارجية في مثالنا هي حركة البيانات باتجاه التطبيق، وبالتالي من يطلب التطبيق جانغو سيطلب خدمة كوبيرنتس واحدة مستقرة ولن يتأثر بتوقف أو إضافة أي Pod داخلية. تتعدد أنواع خدمات كوبيرنتس، مثل خدمة ClusterIP التي تعتمد على عنوان IP الداخلي للعنقود، وخدمة NodePort التي تعرض الخدمة على بوابة محددة من كل عقدة، وخدمة LoadBalancer التي توفر موازنة حمل سحابية لحركة مرور البيانات القادمة من المصادر الخارجية إلى Pods داخل العنقود وذلك عبر خدمات NodePorts الخاصة بكل عقدة، والتي يتم إنشاؤها تلقائيًا في هذه الحالة. يمكنك تعلم المزيد عن هذه الخدمات من خلال توثيقات كوبيرنتس. لنبدأ بإنشاء الخدمة الخاصة بتطبيق جانغو وسنعتمد النوع NodePort. أنشئ ملفًا باسم polls-svc.yaml باستعمال محرر النصوص الذي تفضله وليكن باستعمال نانو nano: nano polls-svc.yaml والصق ضمنه التعليمات التالية: apiVersion: v1 kind: Service metadata: name: polls labels: app: polls spec: type: NodePort selector: app: polls ports: - port: 8000 targetPort: 8000 ``` لاحظ التعليمات السابقة، نوع الخدمة هو NodePort، اسمها polls وهي مميزة بالعنوان app: polls، وحددنا من خلال مُحدِّد selector الربط مع Pods الواجهات الخلفية بالعنوان app: polls و البوابة 8000. أغلق الملف بعد حفظ التغييرات، ومن ثم أنشئ الخدمة بالأمر kubectl apply: kubectl apply -f polls-svc.yaml ونحصل على ما يؤكد الإنشاء وفق الخرج التالي: service/polls created استعرض الخدمة وتأكد من إنشائها عبر kubectl get svc: kubectl get svc polls وسيظهر لك الخرج التالي، الذي يتضمن عنوان IP الداخلي للعنقود وبوابة العقدة NodePort وهي في حالتنا 32654: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls NodePort 10.245.197.189 <none> 8000:32654/TCP 59s حصلنا على رقم البوابة، ونحتاج إلى عنوان IP الخارجي للخدمة للاتصال مع التطبيق، وسنحصل عليه بالأمر التالي: kubectl get node -o wide الذي يعطينا الخرج: NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME pool-7no0qd9e0-364fd Ready <none> 27h v1.18.8 10.118.0.5 203.0.113.1 Debian GNU/Linux 10 (buster) 4.19.0-10-cloud-amd64 docker://18.9.9 pool-7no0qd9e0-364fi Ready <none> 27h v1.18.8 10.118.0.4 203.0.113.2 Debian GNU/Linux 10 (buster) 4.19.0-10-cloud-amd64 docker://18.9.9 pool-7no0qd9e0-364fv Ready <none> 27h v1.18.8 10.118.0.3 203.0.113.3 Debian GNU/Linux 10 (buster) 4.19.0-10-cloud-amd64 docker://18.9.9 أصبحت معلوماتنا كاملة لنستعرض التطبيق بكتابة العنوان التالي في المتصفح: http://203.0.113.1:32654/polls من المفترض حصولك على واجهة التطبيق نفسها التي استعرضتها محليًا في الخطوة /1/: تصفح أيضًا واجهة إدارة التطبيق admin/ للتأكد أكثر: http://203.0.113.1:32654/admin إذًا تطبيق جانغو الآن يستخدم حاويتين متماثلتين ويمكن الوصول له من خارج العنقود عبر خدمة كوبيرنتس مستقرة من نوع NodePort، والخطوة الأخيرة المتبقية لنا هي تأمين هذا الوصول ليتم عبر HTTPS وذلك بالاستفادة من وحدة التحكم ingress-nginx (وهي من متطلبات بيئة العمل المفترض تحضيرها) وبإنشاء كائن إدخال يوجه الحركة الخارجية إلى الخدمة polls. الخطوة 8: إعداد HTTPS باستخدام Nginx Ingress ومدير الشهادات توجه موارد كوبيرنتس من نوع المدخلات Ingresses حركة البيانات HTTP و HTTPS بمرونة إلى داخل العنقود، وذلك من خلال كائنات الإدخال التي تحدد قواعد التوجيه من المصادر الخارجية إلى خدمات كوبيرنتس الموجودة داخل عنقودك، ووحدات تحكم الإدخال التي تنفذ هذه القواعد عبر موازنة الحمل وتوجيه الطلبات إلى خدمات الواجهات الخلفية الأنسب. لابد أنك جهزت المتطلبات الواردة في بداية المقال وأنت تحضر بيئة العمل، ومنها تثبيت وحدة التحكم Ingress-nginx والوظيفة الإضافية cert-manager الخاصة بأتمتة شهادات TLS، مع ما يلزم لتصديق النطاق من Let’s Encrypt، وفي أثناء العملية أنشأت كائن إدخال لاختبار صلاحية الشهادة والتشفير TLS مع اثنين من خدمات الواجهات الخلفية الوهمية المنشأة لهذا الغرض، لذا سنبدأ بحذف echo-ingress الذي أنشأته خلال التحضير وفق التالي: kubectl delete ingress echo-ingress يمكنك أيضًا حذف الخدمات الوهمية المنشأة أثناء التحضير عبر التعليمتين kubectl delete svc kubectl delete deploy لكنه ليس أمرًا ملزمًا في حالتنا. لديك أيضًا (من متطلبات بيئة العمل) سجل DNS من النوع A يربط اسم لنطاقك بعنوان الـ IP العام لمُدخل موازن الحمل، فيمكنك إذًا إنشاء مُدخل لنطاقك your_domain.com والخدمة polls. أنشئ ملف polls-ingress.yaml باستخدام محرر النصوص: nano polls-ingress.yaml والصق ضمنه التعليمات التالية: [polls-ingress.yaml] apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: polls-ingress annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: "letsencrypt-staging" spec: tls: - hosts: - your_domain.com secretName: polls-tls rules: - host: your_domain.com http: paths: - backend: serviceName: polls servicePort: 8000 بموجب التعليمات السابقة، وصّفنا كائن إدخال يدعى polls-ingress ليستخدم وحدة التحكم ingress-nginx ووظيفة مدير الشهادات cert-manager مع ضبط ClusterIssuer الخاص بها على خيار staging، كما فعّلنا الشهادات TLS لترتبط باسم النطاق الخاص بنا your_domain.com أما ملف الشهادة والمفتاح الخاص تم تخزينهم في كائن من نوع سرّ يدعى polls-tls، وأخيرًا وجهّنا حركة البيانات التي تطلب النطاق your_domain.com لتمر عبر البوابة 8000 من الخدمة polls. احفظ الملف الآن وأغلقه، لننشئ الكائن بالاعتماد عليه، باستعمال الأمر التالي: kubectl apply -f polls-ingress.yaml سنحصل بعدها على الخرج: ingress.networking.k8s.io/polls-ingress created يمكنك استعراض وصف الكائن وتتبع حالته باستخدام kubectl describe: kubectl describe ingress polls-ingress التي تعطي الخرج: Name: polls-ingress Namespace: default Address: workaround.your_domain.com Default backend: default-http-backend:80 (<error: endpoints "default-http-backend" not found>) TLS: polls-tls terminates your_domain.com Rules: Host Path Backends ---- ---- -------- your_domain.com polls:8000 (10.244.0.207:8000,10.244.0.53:8000) Annotations: cert-manager.io/cluster-issuer: letsencrypt-staging kubernetes.io/ingress.class: nginx Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 51s nginx-ingress-controller Ingress default/polls-ingress Normal CreateCertificate 51s cert-manager Successfully created Certificate "polls-tls" Normal UPDATE 25s nginx-ingress-controller Ingress default/polls-ingress وبنفس الطريقة تستطيع استعراض وصف polls-tls للتأكد من صحته: kubectl describe certificate polls-tls وستظهر لك حالة الشهادة في الخرج: . . . Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Issuing 3m33s cert-manager Issuing certificate as Secret does not exist Normal Generated 3m32s cert-manager Stored new private key in temporary Secret resource "polls-tls-v9lv9" Normal Requested 3m32s cert-manager Created new CertificateRequest resource "polls-tls-drx9c" Normal Issuing 2m58s cert-manager The certificate has been successfully issued بذلك نكون قد وجّهنا الطلبات الواردة إلى التطبيق لتصبح HTTPS مشفرة، ولكن Clusterissuer في وضع staging ما يعني أن شهادتنا التجريبية المزيفة من Let's Encrypt لن تحظى بثقة معظم متصفحات الويب، أكتب الطلب التالي لنطاقك في نافذة سطر الأوامر: wget -O - http://your_domain.com/polls ولاحظ التحذير الظاهر في الخرج بسبب هذه الشهادة: . . . ERROR: cannot verify your_domain.com's certificate, issued by ‘CN=Fake LE Intermediate X1’: Unable to locally verify the issuer's authority. To connect to your_domain.com insecurely, use `--no-check-certificate'. سنتبع المقترح الوارد في الخرج أعلاه ونستخدم الراية no-check-certificate-- مع الطلب wget لتجاوز التحذير الخاص بالشهادة وفق التالي: wget --no-check-certificate -q -O - http://your_domain.com/polls ستحصل عندها على الخرج المبين أدناه والذي يظهر صفحة HTML المقابلة للواجهة polls/ وأيضًا مسار التخزين الكائني الذي أُحضرت منه الصفحة: <link rel="stylesheet" type="text/css" href="https://your_space.nyc3.digitaloceanspaces.com/django-polls/static/polls/style.css"> <p>No polls are available.</p> وهذا دليل على نجاح طلب النطاق، ما يعني أن بإمكاننا الآن تبديل Clusterissuer إلى وضع المنتج production عوضًا عن staging عبر فتح الملف polls-ingress.yaml: nano polls-ingress.yaml وتعديل قيمة cluster-issuer كما ذكرنا: [polls-ingress.yaml] apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: polls-ingress annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: tls: - hosts: - your_domain.com secretName: polls-tls rules: - host: your_domain.com http: paths: - backend: serviceName: polls servicePort: 8000 احفظ التغييرات على الملف وأغلقه، ولكن انتبه فهي لن تصبح نافذة حتى تُحدّث الكائن polls-ingress باستخدام التعليمة kubectl apply: kubectl apply -f polls-ingress.yaml سيشير الخرج إلى نجاح العملية: ingress.networking.k8s.io/polls-ingress configured شاهد التغير الذي طرأ على حالة الشهادات باستخدام: kubectl describe certificate polls-tls أو kubectl describe ingress polls-ingress وستحصل على الخرج التالي الذي يبين نجاح التحقق من الشهادات الجديدة وكونها مخزنة في السرّ polls-tls: . . . Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal CREATE 23m nginx-ingress-controller Ingress default/polls-ingress Normal CreateCertificate 23m cert-manager Successfully created Certificate "polls-tls" Normal UPDATE 76s (x2 over 22m) nginx-ingress-controller Ingress default/polls-ingress Normal UpdateCertificate 76s cert-manager Successfully updated Certificate "polls-tls" استعرض الآن تطبيقك your_domain.com/polls ولاحظ تفعيل HTTPS وعدم وجود أي تحذير بخصوص صلاحية الشهادة ويمكنك استعراض تفاصيل الشهادة وسلطة التصديق بالضغط على رمز القفل قرب الشريط المخصص لكتابة عنوان URL في متصفحك: ننصحك بإجراء اختياري أخير هو تعديل نوع الخدمة polls من NodePort إلى ClusterIP إذ إن هذا النوع يقبل فقط الحركة القادمة من عنوان IP الداخلي للعنقود ما يمنح تطبيقك مزيدًا من الأمان: افتح الملف polls-svc.yaml باستخدام المحرر: nano polls-svc.yaml بدل قيمة المحدد type من NodePort إلى ClusterIP: apiVersion: v1 kind: Service metadata: name: polls labels: app: polls spec: type: ClusterIP selector: app: polls ports: - port: 8000 targetPort: 8000 احفظ التغييرات على الملف وأغلقه، وحدّث بعدها الخدمة عبر الأمر: kubectl apply -f polls-svc.yaml --force سيؤكد لك الخرج التالي نجاح تعديل الخدمة: service/polls configured تحقق من حالة الخدمة المحدثة باستخدام: kubectl get svc polls ولاحظ معلومات الخرج: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE polls ClusterIP 10.245.203.186 <none> 8000/TCP 22s وبذلك قيدّت الوصول لتطبيقك ليكون حصرًا من خلال اسم النطاق والمُدخل المنشأ في هذه الخطوة. خاتمة تعلمنا في هذا المقال طريقة نشر تطبيق جانغو قابل للتوسيع ومؤمن ببروتوكول HTTPS باستخدام عنقود كوبيرنتس، مع تسليم ملفات التطبيق الساكنة من وحدة تخزين كائني خارجية، وتوفير المرونة التامة لزيادة أو إنقاص عدد Pods التي تُخدم التطبيق بسرعة وبسهولة عبر المحدد replicas من ملف الإعدادات الخاص بوحدة تحكم النشر Deployment والتي أسميناها polls-app، ونذكرك بإمكانية تسريع التسليم باستخدام شبكة توصيل المحتوى CDN كإجراء اختياري. ترجمة -وبتصرف- للمقال How To Deploy a Scalable and Secure Django Application with Kubernetes لصاحبه Hanif Jetha. اقرأ أيضًا ما الفرق بين دوكر Docker وكوبيرنيتيس Kubernetes؟ مدخل إلى Helm: مدير حزم Kubernetes البدء مع إطار العمل جانغو لإنشاء تطبيق ويب
  2. يعرّف هذا المقال منصَّة Kubernetes، نتناول فيه ثلاث نقاط مهمة، وهي: ما Kubernetes؟ كائنات Kubernetes Objects مرحبا Miniku ما Kubernetes؟ هذا الجزء عبارة عن نظرة عامة على Kubernetes، نتناول فيه ما يلي: نظرة على نشر التطبيقات قبل وجود Kubernetes. لماذا نحتاج Kubernetes وما الذي يمكنه فعله؟ الحالات التي لا ينفع فيها Kubernetes. Kubernetes هو منصة مفتوحة المصدر قابلة للنقل والتوسيع لإدارة أعباء العمل والخدمات الموجودة في حاويات، والتي تُسهِّل كلًا من الضبط التصريحي (Declarative) والأتمتة (Automation). تتوفّر منصة Kubernates على نظام بيئي غني وسريع النمو، كما أن دعم المنصة، وخدماتها، وأدواتها مُتاحة على نطاقٍ واسع. تنحدر كلمة Kubernetes من اليونانية، وتعني قائد الدّفة أو الطيار. جعلت غوغل مشروع Kubernetes مفتوح المصدر عام 2014. تستند Kubernetes على عقد ونصف من الخبرة التي تتمتع بها Google في تشغيل أعباء الإنتاج على نطاق واسع، جنبًا إلى جنب مع أفضل الأفكار والممارسات التي يقترحها المجتمع. نظرة على نشر التطبيقات قبل وجود Kubernetes دعنا نلق نظرة على الماضي لنفهم السبب الذي يجعل Kubernetes مفيدًا جدا. عصر النشر التقليدي في البداية، كانت المؤسسات تشغّل التطبيقات على خوادم فعلية (Physical Servers). لم تكن هناك طريقة لتعريف حدود على موارد التطبيقات في الخادم الفعلي، وقد تسبب ذلك في مشكلات تخصيص الموارد. على سبيل المثال، إذا شُغّلت تطبيقات متعددة على خادم فعلي، فقد تكون هناك حالات يستهلك فيها تطبيق واحد معظم الموارد، ونتيجة لذلك، يتراجع أداء التطبيقات الأخرى. قد يكون الحل لتلك المشكلة هو تشغيل كل تطبيق على خادم فعلي مختلف، إلّا ذلك لم يُحدِث فارقًا، إذ كانت الموارد غير مستغلة، وكان مكلفًا للمؤسسات استخدام الكثير من الخوادم الفعلية. عصر النشر الافتراضي قُدّمت الحوسبة الافتراضية (Virtualization) كحل يتيح لك تشغيل العديد من الأجهزة الافتراضية (Virtual machines، أو VM اختصارا) على وحدة المعالجة المركزية (CPU) لخادم فعلي واحد. تسمح المحاكاة الافتراضية بتقسيم التطبيقات بين الأجهزة الافتراضية وتوفِّر مستوى من الأمان إذ لا يمكن الوصول إلى معلومات أحد التطبيقات من خلال تطبيق آخر. تتيح المحاكاة الافتراضية استغلالًا أفضل للموارد في الخادم الفعلي وتتيح قابلية تطوير أفضل لأنه يمكن إضافة تطبيق أو تحديثه بسهولة، ويقلل من تكاليف العتاد (Hardware)، وأكثر من ذلك بكثير. يمكنك من خلال الحوسبة الافتراضية تقديم مجموعة من الموارد المادية على شكل مجموعة من الأجهزة الافتراضية القابلة للتدوير. كل آلة افتراضية عبارة عن آلة كاملة تقوم بتشغيل جميع المكونات، بما في ذلك نظام التشغيل الخاص بها، على الآلات الافتراضية. عصر النشر على الحاويات (Containers) تتشابه الحاويات مع الآلات الافتراضية، لكن لها خصائص عزل مريحة لمشاركة نظام التشغيل (OS) بين التطبيقات. لذلك، تعدّ الحاويات خفيفة. تحتوي الحاوية، على غرار الآلة الافتراضية ، على نظام ملفات (File System) خاص بها، ووحدة معالجة مركزية (CPU)، وذاكرة حية (Memory)، وفضاء معالجة (Process Space)، والمزيد. يمكن نقل الحاويات بين سحابات (Clouds) وتوزيعات نظم تشغيل مختلفة، نظرًا لكونها غير مقترنة بالبنية التحتية التي تعمل عليها. أصبحت "الحاويات" شائعة لأنها توفر فوائد إضافية، مثل: إنشاء ونشر تطبيقات مرنة (Agile Applications): سهولة وكفاءة إنشاء صور الحاويات مقارنة باستخدام صور الآلات الافتراضية. التطوير المستمر والتكامل والنشر (CD/CI): يُوفَّر بنية تحتية لبناء صور موثوقة ومتكررة للحاويات ونشرها مع إمكانية التراجع السريع والسهل (بسبب ثبات الصورة). فصل الاهتمامات بين التطوير وإدارة العمليات: إنشاء صور الحاويات عند إنشاء التطبيق أو أثناء إصداربدلاً من إنشائها عند نشر التطبيق، وبالتالي فصل التطبيقات عن البنية التحتية. سهولة الملاحظة: لا تقتصر الملاحظات على المعلومات والمقاييس على مستوى نظام التشغيل، بل تتعذّاه إلى سلامة التطبيق وإشارات أخرى. الاتساق البيئي عبر التطوير والاختبار والإنتاج: يعمل بنفس الطريقة على الحاسوب المحمول كما هو الحال في السحابة. قابلية التوزيع بغض النظر عن السحابة ونظام التشغيل: تعمل على أوبونتو، ردهات (RHEL)، CoreOS، لدى العميل أو على السحابات العامة الرئيسية، وفي أي مكان آخر. إدارة تتمحور حول التطبيقات: ترفع مستوى التجريد من تشغيل نظام تشغيل على آلات افتراضية إلى تشغيل تطبيق على نظام تشغيل باستخدام الموارد المنطقية. خدمات صغيرة (Micro services) موزعة، ومرنة، ومتحررة وذات اقتران محدود: تُقسَّم التطبيقات إلى قطع أصغرومستقلة يمكن نشرها وإدارتها ديناميكيًا، وليس مكدسًا (Stack) متجانسًا يعمل على آللة واحدة كبيرة أحادية الغرض. عزل الموارد: إمكانية التنبؤ بأداء التطبيقات. استغلال الموارد: كفاءة وكثافة عالية. لماذا تحتاج Kubernetes ومالذي يمكن أن يفعله تُعَد الحاويات طريقة جيدة لتجميع التطبيقات وتشغيلها. في بيئة الإنتاج، تحتاج إلى إدارة الحاويات التي تشغّل التطبيقات والتأكد من عدم وجود وقت تعطل. على سبيل المثال، في حالة تعطل الحاوية، يجب أن تبدأ حاوية أخرى. ألن يكون أسهل إذا كان النظام هو ما يتعامل مع هذا السلوك؟ هنا يأتي دور منصة Kubernates. يوفر لك Kubernetes إطار عمل لتشغيل أنظمة موزعة متكيّفة، ويعتني بتحجيم (Scaling) التطبيقات، وتجاوز إخفاقها (Failover)، ويوفر أنماطًا لنشرها، وأمور أخرى. على سبيل المثال، يمكن لمنصة Kubernetes إدارة نشر الكناري (ِCanary deployment)، وهو طريقة لنشر الإصدارات إلى مجموعة فرعية من المستخدمين أو الخوادم واختبارها أولًا ثم طرحها على بقية الخوادم، لنظامك بسهولة. يوفر لك Kubernetes ما يلي: اكتشاف الخدمات وموازنة الحِمل (Load balancing): يمكن لـ Kubernetes كشف حاوية باستخدام اسم نطاق أو باستخدام عنوان IP الخاص بها، كما يمكنه موازنة الحِمل إذا كانت حركة البيانات إلى الحاوية عالية، وتوزيع حركة البيانات عبرالشبكة لكي يكون النشر مستقرا. تنسيق التخزين (Storage orchestration): يسمح لك Kubernetes بتركيب نظام تخزين من اختيارك تلقائيًا، مثل المخازن المحلية، وموفري السحابة العامة والمزيد. أتمتة طرح الحاويات (Rollout) واستردادها (Rollback) : يمكنك وصف الحالة المرغوبة للحاويات التي تُنشَر باستخدام Kubernetes، ويمكنك تغيير الحالة الراهنة إلى الحالة المرغوبة بمعدل يُتحكّم فيه. على سبيل المثال، يمكنك إعداد Kubernetes لإنشاء حاويات جديدة للنشر آليًا، وإزالة الحاويات الموجودة وإسناد جميع مواردها في الحاوية الجديدة. التعبئة التلقائية للحاويات: تزوّد Kubernetes بمجموعة من العقد (الأجهزة) التي يمكن استخدامها لتشغيل المهام في حاويات، وتخبر المنصة بما تحتاجه كل حاوية من قدرة معالجة وذاكرة حية. يستطيع Kubernetes وضع الحاويات على العقد الخاصة بك لتحقيق أقصى استفادة من مواردك. التعالج الذاتي: يعيد Kubernetes تشغيل الحاويات التي أخفقت، ويستبدل الحاويات، ويوقف الحاويات التي لا تستجيب لمعايير التحقق التي يحددها المستخدم، ولا يعلن عن الحاويات للعملاء إلا إذا كانت جاهزة للخدمة. الإدارة السرية والتكوين: يتيح لك Kubernetes تخزين المعلومات الحساسة وإدارتها، مثل كلمات المرور ورموز OAuth ومفاتيح SSH. يمكنك نشر وتحديث هذه المعلومات الحساسة، وبناء التطبيق دون إعادة إنشاء صور الحاوية، وبدون الكشف عن الأسرار في تكوين المكدس (Stack) الخاص بك. الحالات التي لا ينفع فيها Kubernetes Kubernetes ليس نظامًا تقليديًّا وشاملًا لتقديم المنصات بصيغة خدمة (PaaS - Platform as a Service). نظرًا لأن Kubernetes يعمل على مستوى الحاوية بدلاً من مستوى الأجهزة، فإنه يوفر بعض الميزات القابلة للتطبيق عمومًا والشائع وجودها في المنصات المُقدّمة بصيغة خدمة، مثل النشر، والتحجيم، وموازنة الحِمل، والتسجيل، والمراقبة. ومع ذلك، فإن Kubernetes غير متجانس، وهذه الحلول الافتراضية اختيارية وقابلة للتوصيل بالمنصة. يوفر Kubernetes اللبنات الأساسية لبناء منصات للمطورين، ولكنه يحافظ على اختيار المستخدم والمرونة حيث يكون ذلك مهما. إنَّ Kubernetes: لا يحد من أنواع التطبيقات المدعومة. يهدف Kubernetes إلى دعم مجموعة متنوعة للغاية من أعباء العمل، بما في ذلك أعباء العمل عديمة الحالة (Stateless)، وذات الحالة (Stetful)، والتي تعالج البيانات. إذا كان يمكن تشغيل تطبيق في حاوية، فبالتأكيد سيعمل على نحو رائع على Kubernetes. لا ينشر الشفرة المصدرية ولا يبني تطبيقك. يُحدَّد سير عمل آليّات التكامل والتسليم والنشر المستمر (CI/CD) من خلال ثقافات المؤسسة وتفضيلاتها، بالإضافة إلى المتطلبات التقنية. لا يوفر خدمات على مستوى التطبيق، مثل البرامج الوسيطة (على سبيل المثال، قنوات الرسائل)، وأطر معالجة البيانات (Spark مثلًَا)، وقواعد البيانات (MySQL مثلًا)، وذاكرة التخزين المؤقت، وأنظمة التخزين العقدية (Ceph مثلًا) لا يقدّمها كخدمات مدمجة. يمكن تشغيل هذه المكونات على Kubernetes، مع الوصول إليها - أو عدمه - عن طريق التطبيقات التي تعمل على Kubernetes من خلال آليات محمولة، مثل Open Service Broker. لا يفرض حلول التسجيل أو المراقبة أو التنبيه. يوفر إرشادات إلى عمليات التكامل، وآليات جمع المقاييس وتصديرها. لا يوفر ولا يفرض لغة أو نظامًا للضبط (Jsonnet مثلا). يوفر واجهة تطبيقات برمجية تصريحية يمكن استهدافها من خلال أشكال عشوائية من المواصفات التصريحية. لا يوفر ولا يعتمد أي أنظمة ضبط أو صيانة أو إدارة أو معالجة ذاتية شاملة للأنظمة. بالإضافة إلى ذلك، Kubernetes ليس مجرد نظام تنسيق. في الواقع، يلغي Kubernetes الحاجة إلى التنسيق. التعريف الفني للتنسيق هو تنفيذ سير عمل محدد: أولاً قم بـ أ، ثم ب، ثم ج. على النقيض من ذلك، يشتمل Kubernetes على مجموعة من عمليات تحكم مستقلة قابلة للتوليف تدفع باستمرار الحالة الحالية نحو الحالة المطلوبة المقدمة. لا يهم كيف تنتقل من أ إلى ج. التحكم المركزي ليس مطلوبًا أيضًا. ينتج عن ذلك نظام أسهل استخدامًا، وأكثر قوة وصلابة وقابلية للتكيّف والتوسع. فهم كائنات Kubernetes يشرح هذا الجزء كيفية تمثيل الكائنات في واجهة برمجة تطبيقات Kubernetes ‏(Kubernetes API)، وكيف يمكنك التعبير عنها بتنسيق yaml. ونتناول به ما يلي: شرح كائنات Kubernetes. مواصفات الكائن وحالته وصف كائن Kubernetes الحقول المطلوبة شرح كائنات Kubernetes الكائنات (Kubernetes objects) هي كيانات مستديمة (Persistent) في نظام Kubernetes. تُستخدم هذه الكيانات لتمثيل حالة العنقود (Cluster) الخاصة بك. على وجه التحديد، يمكن للكائنات وصف: التطبيقات المُحتواة (Containerized) المشغَّلة الآن (وعلى أي عقدة Node). الموارد المتاحة لتلك التطبيقات. السياسات المتعلقة بكيفية تصرف هذه التطبيقات، مثل سياسات إعادة التشغيل، والتحديثات، والتسامح مع الأخطاء (Fualt tolerance). كائن Kubernetes هو "سجل نيات". بمجرد أن تُنشئ الكائن، سيعمل نظام Kubernetes باستمرار للتأكد من وجوده. من خلال إنشاء كائن، فأنت تخبر نظام Kubernetes عمليَّا بالكيفية التي تريد أن يبدو عليها عبء عمل العنقود. هذه هي الحالة المرغوبة (Desired state) للعنقود. للعمل مع كائنات Kubernetes، سواء لإنشائها أو تعديلها أو حذفها، ستحتاج إلى استخدام واجهة برمجة تطبيقات Kubernetes. عند استخدام واجهة سطر الأوامر، kubectl على سبيل المثال، تستدعي واجهة سطر الأوامر واجهةَ برمجة تطبيقات Kubernetes الضرورية. يمكنك أيضًا استخدام واجهة التطبيقات البرمجية مباشرة في برامجك الخاصة باستخدام إحدى المكتبات العميلة. مواصفات الكائن وحالته يحتوي كل كائن Kubernetes تقريبًا على حقلين مضمَّنيْن في الكائن يتحكمان في تكوينه، وهما مواصفات الكائن spec وحالتهstatus. بالنسبة للكائنات التي لها مواصفات (الحقل spec)، يجب عليك تعيين الحقل عند إنشاء الكائن، مع تقديم وصف للخصائص التي يجب توافرها في المورد: الحالة المرغوبة. يصف حقل status الحالة الراهنة للكائن. يتولّى Kubernetes ومكوّناته تبديل الحالة الراهنة للكائن وتحديثها. يدير مستوى التحكم (Controle plane) في Kubernetes باستمرار ونشاط، الحالة الفعلية لكل كائن لمطابقتها مع الحالة المرغوبة التي حدّدتها. على سبيل المثال: في Kubernetes ، النشر (Deployment) هو كائن يمكن أن يمثل تطبيقًا يعمل على عنقودك. عند إنشاء النشر، يمكنك تعيين مواصفات النشر spec لتحديد أنك تريد تشغيل ثلاث نسخ متماثلة من التطبيق. يقرأ نظام Kubernetes مواصفات النشر ويبدأ ثلاث نظائر من التطبيق المطلوب، مع تحديث الحالة لتتوافق مع المواصفات الخاصة بك. في حالة تعطّل واحدة من تلك النظائر (تغيير الحالة)، يستجيب نظام Kubernetes لوجود فرق بين المواصفات spec والحالة statusعن طريق إجراء تصحيح، في هذه الحالة، بدء نسخة بديلة من التطبيق. راجع اتفاقيّات واجهة برمجة تطبيقات Kubernetes ‏(Kubernetes API Conventions) لمزيد من المعلومات حول مواصفات الكائن وحالته والبيانات الوصفية. وصف كائن Kubernetes عندما تنشئ كائنًا في Kubernetes، يجب عليك تقديم مواصفات الكائن التي تصف حالته المرغوبة، بالإضافة إلى بعض المعلومات الأساسية حول الكائن (مثل الاسم). عند استخدام واجهة برمجة تطبيقات Kubernetes لإنشاء الكائن (إما مباشرة أو عبر kubectl)، يجب أن يتضمن طلب واجهة برمجة التطبيقات (API request) تلك المعلومات على أنها JSON في متن الطلب (Request body). في معظم الأحيان، تُقدَّم المعلومات إلى kubectl في ملف yaml. و يحوِّل kubectl المعلومات إلى JSON عند تقديم طلب واجهة برمجة التطبيقات. ها هو مثال لملف yaml. يعرض الحقول المطلوبة ومواصفات كائن نشر Kubernetes: الملف application/deployment.yaml apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 # tells deployment to run 2 pods matching the template template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 تتمثل إحدى طرق إنشاء النشر باستخدام ملف yaml.، مثل الملف أعلاه، في استخدام الأمر kubectl apply في واجهة سطر أوامر kubectl، وتمرير ملف yaml. كوسيط. إليك مثال: kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record الناتج مشابه لهذا: deployment.apps/nginx-deployment created الحقول المطلوبة ستحتاج إلى تعيين قيم للحقول التالية في ملف yaml. لكائن Kubernetes الذي تريد إنشاءه: apiVersion: إصدار واجهة برمجة تطبيقات Kubernetes التي تستخدمها لإنشاء هذا الكائن. kind: نوع الكائن الذي تريد إنشاءه. metadata: البيانات الوصفية التي تساعد على تحديد الكائن على نحو فريد، بما في ذلك سلسلة محارف (String) الاسم (الحقل name)، والمعرّف الفريد (UID)، و فضاء أسماء (namespace) اختياري. spec: الحالة المرغوبة للكائن. تختلف الصيغة الدقيقة للمواصفات حسب كائنات Kubernetes، وتحتوي على حقول متداخلة خاصة بكل كائن. يمكن أن يساعدك مرجع واجهة برمجة تطبيقات Kubentes ‏(The Kubernetes API Reference) في العثور على صيغة المواصفات لجميع الكائنات التي يمكنك إنشاؤها باستخدام Kubernetes. على سبيل المثال، يمكن العثور على صيغة مواصفات الكائنات (الحقل spec) من نوع Pod على الرابط التالي. PodSpec v1 core، ويمكن العثور على صيغة المواصفات spec لكائن نشر (Deployment) هنا. مرحبا Minikube تشرح الفقرات التالية من الدرس كيفية تشغيل برنامج "مرحبا بالعالم!" بسيط في بيئة Node.js على منصة Kubernetes باستخدام Minikube و Katacoda الذي يوفر بيئة Kubernetes مجانية في المتصفح. ملحوظة: تصلح التعليمات المذكورة هنا في بيئات Kubernetes المثبَّتة محلّيا. سنتناول ما يلي: الأهداف المتطلبات إنشاء عنقود Minikube إنشاء كائن نشر إنشاء خدمة تمكين الإضافات تنظيف المخلفات الأهداف نشر برنامج "مرحبا بالعالم!" على MiniKube. تشغيل التطبيق. عرض سجلات التطبيق. المتطلبات يوفر هذا الدرس صورة حاوية أنشئت من الملفات التالية: الملف minikube/server.js var http = require('http'); var handleRequest = function(request, response) { console.log('Received request for URL: ' + request.url); response.writeHead(200); response.end('Hello World!'); }; var www = http.createServer(handleRequest); www.listen(8080); الملف minikube/Dockerfile FROM node:6.14.2 EXPOSE 8080 COPY server.js . CMD [ "node", "server.js" ] راجع توثيق Docker للمزيد من المعلومات عن أمر docker build. إنشاء عنقود Minikube اضغط على Launch Terminal. افتح لوحة معلومات Kubernetes في متصفح: minikube dashboard بالنسبة لمستخدمي بيئة Katacoda فقط: في الجزء العلوي من لوجة الطرفية، اضغط على علامة الجمع (+)، ثم اضغط على Select port to view on Host 1. بالنسبة لمستخدمي بيئة Katacoda فقط: اكتب 30000، ثم اضغط على Display Port. إنشاء كائن نشر (Deployment) كائنات Pod في Kubernetes عبارة عن حاوية واحدة أو مجموعة من الحاويات مرتبطة ببعضها البعض لأغراض الإدارة والتواصل. تحتوي كائنات Pod في هذا الدرس على حاوية واحدة فقط. يتحقق كائن النشر (Deployment) في Kubernetes من صحة Pod الخاص بك ويعيد تشغيل حاوية Pod إنْ توقفت عن العمل. عمليات النشر هي الطريقة الموصى بها لإدارة إنشاء وتحجيم مجموعات الحاويات المسمّاة Pods. استخدم الأمر create kubectl لإنشاء كائن نشر يدير Pod. يقوم Pod بتشغيل الحاوية بناءً على صورة Docker المتوفرة. kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node عرض كائن النشر: kubectl get deployments الناتج مشابه لما يلي: NAME READY UP-TO-DATE AVAILABLE AGE hello-node 1/1 1 1 1m عرض Pod: kubectl get pods الناتج مشابه لما يلي: NAME READY STATUS RESTARTS AGE hello-node-5f76cf6ccf-br9b5 1/1 Running 0 1m عرض أحداث العنقود (Cluster Events): kubectl get events عرض إعدادات kubectl: kubectl config view إنشاء خدمة لا يمكن الوصول إلى كائن Pod افتراضيَّا إلا من خلال عنوان IP الداخلي الخاص به ضمن عنقود Kubernetes. لإتاحة الوصول إلى حاوية hello-node من خارج شبكة Kubernetes الافتراضية، يجب عليك عرض كائن Pod بصيغة خدمة Kubernetes. استخدم الأمر kubectl expose لعرض كائن Pod للعموم: kubectl expose deployment hello-node --type=LoadBalancer --port=8080 يشير الخيار type=LoadBalancer-- إلى أنك تريد إتاحة الخدمة للوصول إليها من خارج العنقود. اعرض الخدمة التي أنشأتها للتو: kubectl get services الناتج مشابه لما يلي: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-node LoadBalancer 10.108.144.78 <pending> 8080:30369/TCP 21s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23m بالنسبة لمزوّدي السحابة الذين يدعمون موازنة الحمل، فسيتوفّر عنوان IP خارجي للوصول إلى الخدمة. في بيئة Minikube، يتيح النوع LoadBalancer الوصول إلى الخدمة من خلال الأمر minikube service. نفّذ الأمر التالي: minikube service hello-node بالنسبة لمستخدمي بيئة Katacoda: اضغط على علامة الجمع (+)، ثم اضغط على Select port to view on Host 1. بالنسبة لمستخدمي بيئة Katacoda: لاحظ رقم المنفذ المكون من 5 أرقام المعروض مقابل 8080 في مُخرجات الخدمات (Services Output). يُولّد رقم المنفذ هذا عشوائيًّا ويمكن أن يكون مختلفًا بالنسبة لك. اكتب رقمك في مربع نص رقم المنفذ، ثم اضغط على Display Port. باستخدام المثال السابق ، يمكنك كتابة 30369 يؤدي ذلك إلى فتح نافذة متصفح تخدم تطبيقك وتظهر رسالة "Hello World". تمكين الإضافات يحتوي Minikube على مجموعة من الإضافات المدمجة، وهي موارد تضيف وظائف جديدة إلى Kubernetes. يمكن تمكين الإضافات وتعطيلها وفتحها في بيئة Kubernetes المحلية. أظهر قائمة بالإضافات المدعومة حاليّا: minikube addons list الناتج مشابه لما يلي: addon-manager: enabled dashboard: enabled default-storageclass: enabled efk: disabled freshpod: disabled gvisor: disabled helm-tiller: disabled ingress: disabled ingress-dns: disabled logviewer: disabled metrics-server: disabled nvidia-driver-installer: disabled nvidia-gpu-device-plugin: disabled registry: disabled registry-creds: disabled storage-provisioner: enabled storage-provisioner-gluster: disabled تمكين إضافة، على سبيل المثال، metrics-server: minikube addons enable metrics-server الناتج مشابه لما يلي: metrics-server was successfully enabled عرض Pod والخدمة التي أنشأتها للتو: kubectl get pod,svc -n kube-system الناتج مشابه لما يلي: NAME READY STATUS RESTARTS AGE pod/coredns-5644d7b6d9-mh9ll 1/1 Running 0 34m pod/coredns-5644d7b6d9-pqd2t 1/1 Running 0 34m pod/metrics-server-67fb648c5 1/1 Running 0 26s pod/etcd-minikube 1/1 Running 0 34m pod/influxdb-grafana-b29w8 2/2 Running 0 26s pod/kube-addon-manager-minikube 1/1 Running 0 34m pod/kube-apiserver-minikube 1/1 Running 0 34m pod/kube-controller-manager-minikube 1/1 Running 0 34m pod/kube-proxy-rnlps 1/1 Running 0 34m pod/kube-scheduler-minikube 1/1 Running 0 34m pod/storage-provisioner 1/1 Running 0 34m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/metrics-server ClusterIP 10.96.241.45 <none> 80/TCP 26s service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 34m service/monitoring-grafana NodePort 10.99.24.54 <none> 80:30002/TCP 26s service/monitoring-influxdb ClusterIP 10.111.169.94 <none> 8083/TCP,8086/TCP 26s تعطيل metrics-server: minikube addons disable metrics-server والناتج مشابه لما يلي: metrics-server was successfully disabled التخلّص من الموارد يمكنك الآن التخلص من الموارد التي أنشأتها في العنقود: kubectl delete service hello-node kubectl delete deployment hello-node يوجد خيار آخر يتمثّل في إيقاف آلة Minikube الافتراضية: minikube stop كما يمكن حذف Minikube: minikube delete ترجمة وبتصرُّف للمقالات التالية: What is Kubernetes Understanding Kubernetes Objects Hello Minikube
  3. يمكن أن يكون نشر التطبيقات في Kubernetes، نظام تنسيق الحاويات القوي والشائع، أمرًا معقدا. قد يتضمن إعداد تطبيق واحد إنشاء التعامل مع موارد Kubernetes المترابطة، مثل كائنات Pod، والخدمات وعمليات النشر والنسخ المتماثلة، يتطلب كل منها كتابة ملف YAML مفصل. Helm هو مدير حزم يسمح للمطورين والمشغلين بتحزيم التطبيقات والخدمات وإعدادها ونشرها على عناقيد Kubernetes بسهولة أكبر؛ وهو الآن مشروع رسمي من مشاريع منصة Kubernetes الرسمية، ويمثّل جزءًا من مؤسسة الحوسبة السحابية الأصيلة (Cloud Native Computing Foundation)، وهي مؤسسة غير ربحية تدعم المشاريع مفتوحة المصدر التي تشكّل جزءًا من النظام البيئي لمنصة Kubernetes، والمشاريع التي تدور حولها. سنقدم في هذ المقال نظرة عامة على Helm والتجريدات المختلفة التي يستخدمها لتبسيط نشر التطبيقات في Kubernetes. إذا كنت جديدًا على Kubernetes، فقد يكون من المفيد قراءة مقدمة عن Kubernetes أولاً للتعرف على المفاهيم الأساسية. نظرة عامة على Helm تحوي غالبية لغات البرمجة وأنظمة التشغيل على مدير حزم خاص بها للمساعدة في تثبيت البرامج وصيانتها. يقدّم Helm مجموعة الميزات الأساسية نفسها التي يقدّمها الكثير من مديري الحزم المشهورين مثل apt في توزيعة دبيان و pip في بيئة تطوير بايثون. يستطيع Helm: تثبيت البرامج. تثبيت اعتماديّات البرامج تلقائيا. ترقية البرامج. إعداد عمليات نشر البرامج. إحضار حزم البرامج من المستودعات. يوفر Helm هذه الوظائف من خلال المكونات التالية: أداة سطر الأوامر، helm، التي توفر واجهة مستخدم لجميع وظائف Helm. مكوّن مرافق للخادم، tiller، يعمل على عنقود Kubernetes الخاصة بك، ويستمع إلى الأوامر من helm، ويتعامل مع إعدادات إصدارات البرامج وعمليّات نشرها على عنقود Kubernetes. صيغة تحزيم خاصّة بمدير الحزم Helm، وتسمى charts. مستودع رسمي لحزم Charts، مع حزم جاهزة لمشاريع برمجية مفتوحة المصدر شائعة. سنحقق في تنسيق الحزم بمزيد من التفاصيل بعد ذلك. سنفصّل في ما يلي حول صيغة التحزيم Charts. صيغة التحزيم Charts يُطلَق على حزم Helm اسم Charts، وتتكون من عدد قليل من ملفات الإعداد المكتوبة بلغة YAML وبعض القوالب التي تُصيَّر (Rendered) ضمن ملف التبيان (Manifest file) في Kubernetes. في ما يلي البنية القاعدية لمجلّد حزمة بصيغة Chart: package-name/ charts/ templates/ Chart.yaml LICENSE README.md requirements.yaml values.yaml هذه المجلدات والملفات لها الوظائف التالية: /charts: يمكن وضع اعتماديّات الحزم المُدارة يدويًا في هذا المجلد، على الرغم من أنه من الأفضل عادةً استخدام requirements.yaml لربط الاعتماديّات بالحزمة ديناميكيّا. /templates: يحتوي هذا المجلد على ملفات القوالب التي تُدمَج مع قيم الإعداد (من ملف values.yaml وسطر الأوامر) وتُصيّر ضمن ملفّات تبيان Kubernetes. تستخدم القوالب تنسيق القوالب في لغة برمجة Go. Chart.yaml: ملف YAML يحتوي على بيانات وصفية حول الحزم، مثل اسم الحزمة وإصدارها، ومعلومات المشرف، وموقع الويب ذي الصلة، والكلمات الرئيسية للبحث. LICENSE: ترخيص نص عادي للحزمة. README.md: ملف تمهيدي يحتوي على معلومات لمستخدمي الحزمة. requirements.yaml: ملف YAML يسرد اعتماديّات الحزمة. values.yaml: ملف YAML بقيم الإعدادات الافتراضية للحزمة. يمكن للأمر helm تثبيت حزمة من مُجلد محلي، أو من مجلّد بالبنية أعلاه مضغوط ضمن ملف tar.gz.. يمكن أيضًا تنزيل هذه الحزم وتثبيتها تلقائيًا من مستودعات حزم Helm. سنلقي في ما يلي نظرة على مستودعات حزم Helm. مستودعات الحزم يتمثّل مستودع حزم Helm في موقع ويب بسيط يقدّم ملفّ index.yaml وحزمة Helm مضغوطة في ملفtar.gz. . يحتوي الأمر helm على خيارات متاحة للمساعدة في التحزيم بصيغة Helm وإنشاء ملف index.yaml المطلوب. يمكن تقديم هذه الملفات بواسطة أي خادم ويب أو خدمة تخزين أو مضيف مواقع ثابتة مثل صفحات GitHub. يأتي Helm مهيأ مسبقًا بمستودع حزم مبدئي، يوصف بأنه مستقر (stable). يشير هذا المستودع إلى مجموعة تخزين Google على الرابط https://kubernetes-charts.storage.googleapis.com. يمكن العثور على مصدر المستودع المستقر على مستودع Git التالي. يمكن إضافة مستودعات بديلة باستخدام الأمر helm repo add. في ما يلي مستودعات بديلة شائعة: مستودع incubator الرسمي الذي يحتوي على حزم غير جاهزة بعد لتكون ضمن المستودع المستقر. يمكن العثور على تعليمات استخدام Incubator في صفحة Github التالية. مستودع Bitnami الذي يوفر حزمًا غير متوفّرة في المستودع الرسمي المستقر. سواء كنت تثبّت حزمة طوّرتها محليًا، أو حصلت عليها من مستودع، فستحتاج إلى تهيئتها لإعداداتك الخاصة، وهو ما سننظر فيه الفقرة التالية إعداد حزم Helm عادةً ما تأتي حزم Helm بقيم الإعدادات الافتراضية في ملف values.yaml. قد تكون بعض التطبيقات قابلة للنشر كاملةً باستخدام القيم الافتراضية، ولكن ستحتاج عادةً إلى إعادة تعيين قيم لتلبية احتياجاتك. يحدّد مطوّر الحزمة القيم التي تمكن إعادة تعيينها. تُستخدم بعض القيم لإعداد وظائف Kubernetes، في حين تُمرَّر أخرى عبر الحاويّة لإعداد التطبيق نفسه. فيما يلي مقتطف من مثال لملف قيم: service: type: ClusterIP port: 3306 هذه خيارات لإعداد مورد خدمة Kubernetes. يمكنك استخدام helm inspect values chart-name لتفريغ كل قيم الإعداد المتاحة للحزمة. يمكن تجاوز هذه القيم عن طريق كتابة ملف YAML خاص بك واستخدامه عند تشغيل الأمر helm install، أو من خلال تعيين الخيارات فرديًّا في سطر الأوامر مع الخيار set--. ما عليك سوى تحديد تلك القيم التي تريد تغييرها من الإعدادات الافتراضية. تُسمى حزم Helm المنشورة بإعداد معين بالإصدار (release). الإصدارات أثناء تثبيت الحزمة، يجمع Helm بين القوالب والإعدادات المُخصّصة من طرف المستخدم والقيم الافتراضية في value.yaml. تُحوّل تلك الإعدادات إلى ملف Manifest في Kubernetes تُنشَر بعد ذلك عبر واجهة تطبيقات Kubernetes. ينتج عن ذلك إنشاء إصدار، وهو إعداد ونشر محدّديْن لحزمة معينة. مفهوم الإصدارات هذا مهم، لأنك قد ترغب في نشر التطبيق نفسه أكثر من مرة على عنقود. على سبيل المثال، قد تحتاج إلى عدة خوادم MySQL بإعدادات مختلفة. قد ترغب أيضًا في ترقية نظائر مختلفة من الحزمة فرديّا. ربما يكون تطبيق جاهزًا لخادم MySQL مُحدَّث ولكن تطبيقًا آخر ليس كذلك. باستخدام Helm، يمكنك ترقية كل إصدار على حدة. يمكنك ترقية إصدار لأن الحزمة الخاصة به مُحدّثة، أو لأنك ترغب في تحديث إعدادات الإصدار. في كلتا الحالتين، ستُنشئ كل ترقية مراجعة جديدة للإصدار، وسيسمح لك Helm بالعودة بسهولة إلى المراجعات السابقة في حالة وجود مشكلة. إنشاء الحزم إذا لم تتمكن من العثور على حزمة موجود للبرنامج الذي تنشره، فقد ترغب في إنشاء الحزمة الخاص بك. يمكن لمدير الحزم Helm إنشاء بنية جاهزة لمجلد الحزمة باستخدام الأمر helm create chart-name. سيؤدي هذا إلى إنشاء مجلد يحتوي على الملفات والمجلدات التي ناقشناها في قسم ضيغة التحزيم أعلاه. من هناك، ستحتاج إلى ملء البيانات الوصفية للحزمة الخاصة بك في Chart.yaml ووضع ملفات تبيان Kubernetes في مجلد templates. ستحتاج بعد ذلك إلى استخلاص متغيرات الإعداد المناسبة من ملفات التبيان إلى ملف القيم values.yaml، ثم تضمينها مرة أخرى في ملفات التبيان باستخدام نظام القوالب. يحتوي الأمر helm على العديد من الخيارات المتاحة لمساعدتك في إنشاء حزم Helm واختبارها وتقديمها. لمزيد من المعلومات، يرجى قراءة وثائق Helm الرسمية حول تطوير الحزم. خاتمة في هذا المقال استعرضنا Helm، مدير حزم Kubernetes. ألقينا نظرة عامة على هندسة Helm، ومكوناته helm و tiller، وفصّلنا صيغة حزم Helm، وألقينا نظرة على مستودعات الحزم. تطرّقنا كذلك إلى كيفية إعداد حزم Helm، وكيف تُدمَج الإعدادات والحزم وتُنشَر كإصدارات على عناقيد Kubernetes. أخيرًا، تطرقنا إلى أساسيات إنشاء حزمة في حالة عدم توفر حزمة مناسب بالفعل. لمزيد من المعلومات حول Helm ، ألق نظرة على وثائق Helm الرسمية. تحقق من مستودع helm/charts على Github للعثور على الحزم الرسمية. ترجمة - وبتصرّف - للمقال An Introduction to Helm, the Package Manager for Kubernetes لصاحبه Brian Boucheron.
  4. عند تشغيل خدمات وتطبيقات متعددة على عنقود Kubernetes، يمكن أن يساعدك مكدس سجلات مركزي على مستوى العنقود على فرز الحجم الكبير لبيانات السجلات التي تنتجها كائنات Pod، وتحليل تلك السجلّات بسرعة. أحد حلول التسجيل المركزية الشائعة هو مكدس EFK الذي يضم التطبيقات الثلاث Elasticsearch، وFluentd وKibana. Elasticsearch هو محرك بحث فوري ومُوزّع وقابل للتحجيم يسمح بالبحث في النصوص والبيانات المنظَّمة وكذلك التحليلات. يُستخدم Elasticsearch عادةً لفهرسة كميات كبيرة من بيانات السجلّات والبحث فيها، ولكن يمكن استخدامه أيضًا للبحث في العديد من أنواع المستندات المختلفة. يُنشَر Elasticsearch عادة جنبًا إلى جنب مع Kibana، وهي واجهة أمامية ولوحة تحكم فعّالة لعرض البيانات. تتيح Kibana استكشاف بيانات سجل Elasticsearch الخاص بك من خلال واجهة ويب، وإنشاء لوحات تحكم واستعلامات للإجابة بسرعة على الأسئلة والحصول على نظرة مفصَّلة عن تطبيقات Kubernetes. سنستخدم في هذا الدرس Fluentd لجمع بيانات السجل وتحويلها وشحنها إلى سند Elasticsearch الخلفي. Fluentd هو مُجمِّع بيانات شائع الاستخدام، ومفتوح المصدر، سنعدّه على عُقد Kubernetes لتتبّع ملفات سجلّات الحاوية، وتصفية وتحويل بيانات السجل، وتسليمها إلى عنقود Elasticsearch، حيث تُفهرَس وتُخزَّن. سنبدأ بإعداد وتشغيل عنقود Elasticearch قابل للتحجيم، ثم ننشئ خدمة Kibana وعمليّة النشر الخاصّة بها على Kubernetes. في الختام، سنعدّ Fluentd بصيغة متحكّم DaemonSet حتى يُشغَّل على كل عقدة عاملة على Kubernetes. المتطلبات الأساسية قبل أن تبدأ بهذا الدليل، تأكد من توفر ما يلي لك: عنقود Kubernetes، الإصدار 1.10 فما فوق، مع تفعيل التحكّم في الوصول اعتمادًا على الدور (Role-Based Accedd Control, RBAC). تأكّد أن العنقود لديه موارد كافية لتشغيل مكدس EFK، وإن لم يكن، زد حجم العنقود بإضافة عقَد عاملة جديدة. سننشر Elasticsearch على ثلاث كائنات Pod (يمكنك تقليل العدد إلى 1 إنْ لزم الأمر)، بالإضافة إلى كائن Pod واحد لبيئة Kibana. ستشغّل كل عقدة عاملة كائن Pod لتطبيق Fluentd. يتكون العنقود في هذا الدليل من ثلاث عقد عاملة ومستوى تحكم مُدبَّر (Managed control plane) واحد. أداة سطر الأوامر kubectl مُثبّتة على جهازك المحلي، مُعدَّة للاتصال بالعنقود. يمكنك قراءة المزيد حول تثبيت kubectl في التوثيق الرسمي. بمجرد الانتهاء من إعداد هذه المكونات، تكون جاهزًا للبدء بهذا الدليل. الخطوة الأولى: إنشاء فضاء أسماء (Namespace) قبل إطلاق عنقود Elasticsearch، سنُنشئ أولاً فضاء أسماء نثبّت فيه جميع أدوات التسجيل الخاصة بنا. يتيح لك Kubernetes فصل الكائنات التي تعمل في العنقود باستخدام تجريد ينشئ "عنقودَا افتراضيًّا" يُسمّى فضاء الأسماء. سننشئ في هذا الدليل فضاء أسماء نطلق عليه kube-logging نثبّت فيه مكونات مكدس EFK. علاوةً على ذلك، سيسمح لنا فضاء الأسماء هذا بتنظيف مكدس EFK وإزالته بسرعة دون فقدان وظائف أخرى في عنقود Kubernetes. للبدء، تَحقَّق أولاً من فضاءات الأسماء الموجودة في العنقود باستخدام kubectl: $ kubectl get namespaces يجب أن ترى فضاءات الأسماء الثلاثة المبدئية التالية، والتي تأتي مُثبَّتة مسبقًا مع عنقود Kubernetes: NAME STATUS AGE default Active 5m kube-system Active 5m kube-public Active 5m يحتوي فضاء الأسماء default على كائنات أنشئت بدون تحديد فضاء أسماء لها. يحتوي فضاء الأسماء kube-system على كائنات أنشأها واستخدمها نظام Kubernetes، مثلkube-dns، kube-proxy، وkubernetes-dashboard. من الجيد الحفاظ على نظافة فضاءات الأسماء هذه وعدم تلويثها بأحمال عمل التطبيقات والأدوات الأخرى. فضاء الأسماء kube-public هو الآخرأنشئ تلقائيًا ويمكن استخدامه لتخزين الكائنات التي تريد لها أن تكون قابلة للقراءة ويمكن الوصول إليها عبر العنقود بأكمله، حتى للمستخدمين الذين لم تستوثق منهم (Unauthenticated users). لإنشاء فضاء الأسماء kube-logging، أولًا افتح ملفًّا يُسمى kube-logging.yaml باستخدام المحرر المفضل لديك، مثل nano: $ nano kube-logging.yaml داخل المحرر، الصق كائن فضاء الأسماء التالي المكتوب بصيغة YAML: kind: Namespace apiVersion: v1 metadata: name: kube-logging ثم احفظ الملف وأغلقه. هنا، نحدد نوع كائن Kubernetes بأنه فضاء أسماء. لمعرفة المزيد حول كائنات فضاء الأسماء، راجع إرشادات فاضاءات الأسماء في توثيق Kubernetes. نحدد أيضًا إصدار واجهة تطبيقات Kubernetes المستخدم لإنشاء الكائن (v1)، ونعيّن قيمة الحقل name (الاسم) لتكون kube-logging. أنشئ فضاء أسماء باستخدام الأمر kubectl create مع خيار اسم الملف f-، مباشرة بعد تحرير ملف كائن فضاء الأسماء kube-logging.yaml، وذلك على النحو التالي: $kubectl create -f kube-logging.yaml تظهر المُخرجات كالتالي: namespace/kube-logging created يمكنك بعد ذلك التأكد من إنشاء فضاء الأسماء بنجاح: $ kubectl get namespaces عند هذه النقطة، من المُفترض أن ترى فضاء الأسماء الجديد kube-logging : NAME STATUS AGE default Active 23m kube-logging Active 1m kube-public Active 23m kube-system Active 23m يمكننا الآن نشر عنقود Elasticsearch في فضاء الأسماء المعزول الخاص بالتسجيل. الخطوة 2 - إنشاء Elasticsearch StatefulSet الآن بعد أن أنشأنا فضاء أسماء لاستيعاب مكدس السجلّات، يمكننا البدء في طرح مكوناته المختلفة. سنبدأ أولاً بنشر عنقود Elasticsearch من ثلاث عُقد. في هذا الدليل نستخدم ثلاث كائنات Pod ليعمل عليها عنقود Elasticsearch، والهدف هو تجنب مشكلة "الدماغ المنصدع" (Split-brain)، التي قد تحدث في العنقود متعدّد العقد. تحدث مشكلة "الدماغ المنصدع" عندما يتعذر على عُقدة (أو عدة عقد) التواصل مع العقد الأخرى، فتُختار عدة عقد لتلعب دور القبطان (Master). مع ثلاث عقد، إذا انفصلت عقدة عن العنقود يمكن للعقدتين الأخريين انتخاب قبطان جديد ويمكن للعنقود أن يستمر في العمل بينما تحاول العقدة الضائعة الالتحاق. راجع المقالين A new era for cluster coordination in Elasticsearch وVoting configurations لمعرفة المزيد عن المشكلة المذكورة. إنشاء خدمة مجهولة العنوان (Headless Service) للبدء، سننشئ خدمة Kubernetes مجهولة العنوان تسمى elasticsearch تعرّف اسم نطاق لكائنات Pod الثلاثة الموجودة في عنقود Elasticsearch. لا توازن الخدمة مجهولة العنوان الحمل وليس لديها عنوان IP ثابت. راجع توثيق Kubernetes للمزيد عن هذه الخدمات. افتح الملف elasticsearch_svc.yaml بمحرّر النصوص المفضل لديك: $ nano elasticsearch_svc.yaml الصق فيه خدمة Kubernetes التالية (بصيغة YAML): elasticsearch_svc.yaml kind: Service apiVersion: v1 metadata: name: elasticsearch namespace: kube-logging labels: app: elasticsearch spec: selector: app: elasticsearch clusterIP: None ports: - port: 9200 name: rest - port: 9300 name: inter-node ثم احفظ الملف وأغلقه. نعيّن خدمة (service) تسمى elasticearch في فضاء الأسماء kube-logging ، ونعطيها اللصيقة app: elasticsearch. ثم نعيّن القيمة app: elasticsearch للحقل spec.selector. لكي تختار لخدمة كائن Pod عن طريق اللصيقة app: elasticsearch. عندما نربط متحكّم StatefulSet في عنقود Elasticsearch الخاص بنا مع هذه الخدمة، سترجع الخدمة سجل DNS من النوع A يشير إلى كائنات Pod ذات اللصيقة app: elasticsearch في عنقود Elasticsearch. ثم نعيّن الحقل clusterIP لتكون قيمته None، ممّا يجعل الخدمة مجهولة العنوان. أخيرًا، نُحدد المنافذ 9200 و9300 التي تُستخدَم على التوالي للتفاعل مع واجهة التطبيقات من النوع، وللتواصل الداخلي بين العقد. أنشئ الخدمة باستخدام kubectl: $ kubectl create -f elasticsearch_svc.yaml يجدر أن تظهر مُخرجات كالتالي: service/elasticsearch created أخيرًا، تحقق جيدًا من إنشاء الخدمة بنجاح باستخدام kubectl get: kubectl get services --namespace=kube-logging يجب أن ترى ما يلي: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 26s الآن بعد أن أعددنا خدمتنا المستقرة مجهولة العنوان والنطاق elasticsearch.kube-logging.svc.cluster.local. لكائنات Pod الخاصة بنا، يمكننا المضي قدمًا وإنشاء متحكّم المجموعة ذات الحالة (StatefulSet). إنشاء مجموعة ذات حالة (StatefulSet) من كائنات Pod يسمح لك كائن StatefulSet في Kubernetes بتعيين هوية ثابتة لكائنات Pod ومنحها تخزينًا مستقرًّا ودائما. يحتاج Elasticsearch لتخزين مستقر لضمان ديمومة البيانات عند إعادة جدولة كائنات Pod وإعادة تشغيلها. راجع التوثيق الرسمي للمزيد حول كائنات StatefulSet. افتح الملف المُسمّى elasticsearch_statefulset.yaml في المُحرر المفضل لديك: $ nano elasticsearch_statefulset.yaml سنمرّ خطوة خطوة على تعريف كائن StatefulSet من خلال لصق أجزاء من التعريف في الملف المذكور. نبدأ بنسخ ثم لصق الجزء التالي: apiVersion: apps/v1 kind: StatefulSet metadata: name: es-cluster namespace: kube-logging spec: serviceName: elasticsearch replicas: 3 selector: matchLabels: app: elasticsearch template: metadata: labels: app: elasticsearch نعرّف في الجزء أعلاه كائن StatefulSet باسم es-cluster في فضاء الأسماء kube-logging. ثم نربطه بخدمة elasticsearch التي أنشئت مسبقًا باستخدام حقل serviceName، ممّا يضمن إمكانية الوصول إلى كل كائن Pod في المجموعة باستخدام النطاق التالي: es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local، حيث [0,1,2] يُشير إلى العدد الترتيبي لكائن Pod. نحدد ثلاث نسخ متطابقة (كائنات Pod) بتعيين القيمة 3 للحقل replicas، ونعيّن القيمة app: elasticseach للمُحدِّد matchLabels، ونكرّر الأمر مع الحقل spec.template.metadata.. يجب أن تتطابق قيمتا الحقلين .spec.selector.matchLabels و .spec.template.metadata.labels. يمكننا الآن الانتقال إلى مواصفات الكائن. ألصق الجزء التعريفي التالي، المكتوب بصيغة YAML، أسفل الجزء السابق: . . . spec: containers: - name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0 resources: limits: cpu: 1000m requests: cpu: 100m ports: - containerPort: 9200 name: rest protocol: TCP - containerPort: 9300 name: inter-node protocol: TCP volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data env: - name: cluster.name value: k8s-logs - name: node.name valueFrom: fieldRef: fieldPath: metadata.name - name: discovery.seed_hosts value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch" - name: cluster.initial_master_nodes value: "es-cluster-0,es-cluster-1,es-cluster-2" - name: ES_JAVA_OPTS value: "-Xms512m -Xmx512m" هنا نحدد كائنات Pod في المجموعة ذات الحالة (StatefulSet). نسمّي الحاويات elasticsearch ونختار صورة Docker من الرابط docker.elastic.co/elasticsearch/elasticsearch:7.2.0. في هذه المرحلة، يمكنك تعديل وسم الصورة هذا ليتوافق مع صورة Elasticsearch الداخلية الخاصة بك، أو مع إصدار مختلف. لاحظ أنه لأغراض هذا الدليل، اقتصر الااختبارعلى الإصدار 7.2.0 من Elasticsearch. ثم نستخدم الحقل resources لتحديد أن الحاوية تحتاج على الأقل لضمان 10% من وحدة المعالجة المركزية الافتراضية ( 0.1vCPU)، ويمكن أن يزيد الاستخدام ليصل إلى وحدة معالجة كاملة (1vCPU)، أي أننا نعيّن الحد الأقصى لاستهلاك المورد في حالات مثل استقبال كائن Pod لكمية أولية كبيرة من البيانات أو في أوقات الذروة). يجب تعديل هذه القيم اعتمادًا على الحمل المتوقع والموارد المتاحة. راجع توثيق Kubernetes للمزيد عن الطلبات على الموارد وحدوها. ثم نفتح المنفذين 9200 و 9300، مع تسميتهما، بغرض الاتصال بواجهة تطبيقات REST والاتصال الداخلي، على التوالي. نحدد نقطة لتركيب تجزئات التخزين (الحقل volumeMount) ونسمّيها data. وظيفة نقطة التركيب تلك هي تحميل التجزئة المستقرّة (كائن من النوع PersistentVolume) المُسماة data الموجودة ضمن الحاوية على المسار usr/share/elasticsearch/data/. سنحدد مطالب الحجم (VolumeClaims) لهذه المجموعة في جزء لاحق من التعريف. أخيرًا، نعيّن بعض متغيرات البيئة في الحاوية: cluster.name: اسم عنقود Elasticsearch، والذي في هذا الدليل هو k8s-logs. node.name: اسم العقدة، الذي عيّناه للحقل metadata.name. باستخدام valueFrom. ستُترجم هذه القيمة إلى [es-cluster-[0,1,2، اعتمادًا على العدد الترتيبي المعيّن للعقدة. discovery.seed_hosts: يعين هذا الحقل قائمة بالعقد المؤهلة لتؤدّي دور القبطان في العنقود الذي سيؤسس لعملية استكشاف العقد. في هذا الدليل، وبفضل الخدمة مجهولة العنوان التي أعددناها سابقًا، تأخذ كائنات Pod نطاقات بالصيغة es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local، لذلك عيّنا هذا المتغير وفقًا لذلك. يمكننا تقصير النطاق إلى es-cluster-[0,1,2].elasticsearch باستخدام ترجمة أسماء النطاقات الداخلية في Kubernetes. راجع توثيق Elasticsearch للمزيد عن الاستكشاف في Elasticsearch. cluster.initial_master_nodes: يحدد هذا الحقل أيضًا قائمة عقد مؤهلة لتؤدّي دور القبطان في العنقود ستشارك في عملية انتخاب القبطان. لاحظ أنه في هذا الحقل، يجب تحديد العقد من خلال node.name وليس أسماء المضيفين. ES_JAVA_OPTS: ضبطنا المتغيّر على القيم Xms512m -Xmx512m- لإخبار آلة جافا الافتراضية (JVM) برغبتنا في استخدام 512 ميجابايت لتكون الحد الأدنى والحد الأقصى لحجم كومة الذاكرة المؤقتة. يجب ضبط هذه المعاملات بناءً على توفر الموارد للعنقود واحتياجاته. راجع المقال التالي للمزيد من التفاصيل. يظهر الجزء الموالي من التعريف على النحو التالي: . . . initContainers: - name: fix-permissions image: busybox command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"] securityContext: privileged: true volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data - name: increase-vm-max-map image: busybox command: ["sysctl", "-w", "vm.max_map_count=262144"] securityContext: privileged: true - name: increase-fd-ulimit image: busybox command: ["sh", "-c", "ulimit -n 65536"] securityContext: privileged: true في هذه الجزء، نحدد العديد من الحاويات الأولية التي تُشغَّب قبل حاوية تطبيق elasticearch الرئيسية. تُشغَّل هذه الحاويات الأولية (Init Containers) حتى إكمال عملها بالترتيب المحدد. راجع التوثيق الرسمي لمعرفة المزيد عن الحاويات الأولية. تنفّذ الحاوية الأولى، المُسمّاة fix-permissions، أمر chown لتغيير الحساب والمجموعة المالكيْن لمجلّد بيانات دليل Elasticsearch ليصبحا 1000: 1000، وهما معرّفا (UID) مستخدم ومجموعة Elasticsearch. يركّب Kubernetes مجلّد البيانات بالحساب الجذر (root)، مما يجعل وصول Elasticsearch إليه غير ممكن. راجع توثيق Elasticsearch لمزيد من المعلومات حول هذه الخطوة. تنفّذ الحاوية الثانية، المسمّاة increase-fd-ulimit، أمرًا لزيادة حدود استدعاءات mmap التي يمكن لنظام التشغيل إجراؤها، والتي قد يكون عددها افتراضيًا منخفضًا جدًا، مما ينتج عنه أخطاء في الذاكرة. راجع توثيق Elasticsearch لمزيد من المعلومات حول هذه الخطوة. الحاوية الأوليّة التالية هي increase-fd-ulimit والتي تنفّذ الأمر ulimit لزيادة الحد الأقصى لعدد واصفات الملفات المفتوحة (File descriptor). راجع توثيق Elasticsearch لمزيد من المعلومات حول هذه الخطوة. الآن بعد أن حددنا حاوية التطبيق الرئيسية والحاويات الأوليّة التي تُشغَّل قبلها لضبط نظام تشغيل الحاوية، يمكننا إضافة الجزء الأخير إلى ملف تعريف كائن StatefulSet، وهو الجزء المتعلّق بقوالب مطالب الحجم (volumeClaimTemplates). ألصق الجزء التالي المتعلّق بتعريف volumeClaimTemplate: . . . volumeClaimTemplates: - metadata: name: data labels: app: elasticsearch spec: accessModes: [ "ReadWriteOnce" ] storageClassName: do-block-storage resources: requests: storage: 100Gi في هذا الجزء، نحدد المجلد VolumeClaimTemplates الخاص بكائن StatefulSet. سيستخدم Kubernetes هذا المجلّد لإنشاء تجزئات دائمة (PersistentVolumes) لكائنات Pod. في التعريف أعلاه، نسميها data (وهو الاسم الذي نشير إليه في وحدة التخزين التي تم تعريفها سابقًا)، ونعطيها نفس اللصيقة (app: elasticsearch) اللتي أعطيناها لكائن StatefulSet سابقا. ثم نحدد وضع الوصول إلى التجزئات ليكون ReadWriteOnce، مما يعني أنه لا تمكن القراءة والكتابة منها إلّا بواسطة عُقدة واحدة. نحدد الصنف do-block-storage ليكون صنف التخزين إذ أننا نستخدم عنقود Kubernetes من DigitalOcean لأغراض الشرح. يجب تغيير هذه القيمة اعتمادًا على أين تشغّل عنقود Kubernetes الخاص بك. راجع توثيق Kubernetes للمزيد عن التخزين الدائم. أخيرًا، نحدد حجم كل مجلد دائم (PersistentVolume) ليكون 100 غيغابايت. يجب تعديل هذه القيمة حسب احتياجات بيئة الإنتاج الخاصة بك. تبدو المواصفات الكاملة لكائن StatefulSet كالتالي: apiVersion: apps/v1 kind: StatefulSet metadata: name: es-cluster namespace: kube-logging spec: serviceName: elasticsearch replicas: 3 selector: matchLabels: app: elasticsearch template: metadata: labels: app: elasticsearch spec: containers: - name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0 resources: limits: cpu: 1000m requests: cpu: 100m ports: - containerPort: 9200 name: rest protocol: TCP - containerPort: 9300 name: inter-node protocol: TCP volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data env: - name: cluster.name value: k8s-logs - name: node.name valueFrom: fieldRef: fieldPath: metadata.name - name: discovery.seed_hosts value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch" - name: cluster.initial_master_nodes value: "es-cluster-0,es-cluster-1,es-cluster-2" - name: ES_JAVA_OPTS value: "-Xms512m -Xmx512m" initContainers: - name: fix-permissions image: busybox command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"] securityContext: privileged: true volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data - name: increase-vm-max-map image: busybox command: ["sysctl", "-w", "vm.max_map_count=262144"] securityContext: privileged: true - name: increase-fd-ulimit image: busybox command: ["sh", "-c", "ulimit -n 65536"] securityContext: privileged: true volumeClaimTemplates: - metadata: name: data labels: app: elasticsearch spec: accessModes: [ "ReadWriteOnce" ] storageClassName: do-block-storage resources: requests: storage: 100Gi احفظ الملف ثم أغلقه بعد التأكد من محتواه. الآن، انشر ملف StatefulSet باستخدام kubectl: $ kubectl create -f elasticsearch_statefulset.yaml يجب أن تشاهد المُخرجات التالية: statefulset.apps/es-cluster created يمكنك مراقبة حالة StatefulSet أثناء إطلاقه باستخدام kubectl rollout status: $ kubectl rollout status sts/es-cluster --namespace=kube-logging يجب أن ترى المخرجات التالية أثناء إطلاق العنقود: Waiting for 3 pods to be ready... Waiting for 2 pods to be ready... Waiting for 1 pods to be ready... partitioned roll out complete: 3 new pods have been updated... بمجرد نشر كل كائنات Pod، يمكنك التحقق من أن عنقود Elasticsearch الخاص بك يعمل من خلال إرسال طلب إلى واجهة تطبيقات REST. لذا، أعد توجيه المنفذ المحلي 9200 إلى المنفذ 9200 على إحدى عُقد Elasticsearch وهي (es-cluster-0)، باستخدام kubectl port-forward: $ kubectl port-forward es-cluster-0 9200:9200 --namespace=kube-logging ثم، في نافذة طرفية منفصلة، نفذ طلب curl باتجاه واجهة REST: $ curl http://localhost:9200/_cluster/state?pretty يجب أن تظهر المخرجات التالية: { "cluster_name" : "k8s-logs", "compressed_size_in_bytes" : 348, "cluster_uuid" : "QD06dK7CQgids-GQZooNVw", "version" : 3, "state_uuid" : "mjNIWXAzQVuxNNOQ7xR-qg", "master_node" : "IdM5B7cUQWqFgIHXBp0JDg", "blocks" : { }, "nodes" : { "u7DoTpMmSCixOoictzHItA" : { "name" : "es-cluster-1", "ephemeral_id" : "ZlBflnXKRMC4RvEACHIVdg", "transport_address" : "10.244.8.2:9300", "attributes" : { } }, "IdM5B7cUQWqFgIHXBp0JDg" : { "name" : "es-cluster-0", "ephemeral_id" : "JTk1FDdFQuWbSFAtBxdxAQ", "transport_address" : "10.244.44.3:9300", "attributes" : { } }, "R8E7xcSUSbGbgrhAdyAKmQ" : { "name" : "es-cluster-2", "ephemeral_id" : "9wv6ke71Qqy9vk2LgJTqaA", "transport_address" : "10.244.40.4:9300", "attributes" : { } } }, ... تشير المخرجات إلى أنّ العنقود k8s-logs المكوَّن من ثلاث عقد ( es-cluster-1، es-cluster-0 وes-cluster-2.) قد أنشئ بنجاح. العقدة التي تؤدي دور القبطان هي حاليًّا es-cluster-0. الآن بعد أن أصبح عنقود Elasticsearch جاهزًا يمكنك الانتقال إلى إعداد واجهة Kibana الأمامية. الخطوة 3: إنشاء خدمة ونشر كيبانا لإطلاق Kibana على Kubernetes، سننشئ خدمة تسمى kibana، وننشئ أيضًا عملية نشر (Deployment) تتكوّن من كائن Pod واحد. يمكنك تحديد عدد النسخ التي تحتاجها بناءً على احتياجات بيئة الإنتاج الخاصة بك، وتحديد النوع LoadBalancer لتوزيع عبء بين كائنات Pod. هذه المرة ، سننشئ الخدمة والنشر في الملف نفسه. افتح ملفًا يسمى kibana.yaml في محررك المفضل: $ nano kibana.yaml ألصق المواصفات التالية للخدمة: apiVersion: v1 kind: Service metadata: name: kibana namespace: kube-logging labels: app: kibana spec: ports: - port: 5601 selector: app: kibana --- apiVersion: apps/v1 kind: Deployment metadata: name: kibana namespace: kube-logging labels: app: kibana spec: replicas: 1 selector: matchLabels: app: kibana template: metadata: labels: app: kibana spec: containers: - name: kibana image: docker.elastic.co/kibana/kibana:7.2.0 resources: limits: cpu: 1000m requests: cpu: 100m env: - name: ELASTICSEARCH_URL value: http://elasticsearch:9200 ports: - containerPort: 5601 ثم احفظ الملف وأغلقه. في هذه المواصفات، حددنا خدمة تسمى kibana في فضاء الأسماء kube-logging، وأعطيناها اللصيقة app: kibana. حددنا أيضًا أنه يجب الوصول إليها على المنفذ 5601 واستخدمنا اللصيقة app: kibana لتحديد كائنات Pod المُستهدَفة بالخدمة. في مواصفات النشر Deployment، نحدد عملية نشر تُسمى kibana ونحدد أننا نريد كائن Pod واحدا. نستخدم صورة Kibana من الرابط docker.elastic.co/kibana/kibana:7.2.0. عند هذه النقطة يمكنك وضع صورة كيبانا الخاصة أو العامة التي تودّ استخدامها. نحدد أن الحاوية تحتاج على الأقل لضمان 10% من وحدة المعالجة المركزية الافتراضية ( 0.1vCPU)، ويمكن أن يزيد الاستخدام ليصل إلى وحدة معالجة كاملة (1vCPU)، أي أننا نعيّن الحد الأقصى لاستهلاك المورد. يمكنك تغيير هذه المعاملات اعتمادًا على الحمل المتوقع والموارد المتاحة. بعد ذلك ، نستخدم متغير البيئة ELASTICSEARCH_URL لتعيين نقطة النهاية والمنفذ لعنقود Elasticsearch. باستخدام نطاقات Kubernetes نجد أن نقطة النهاية تتوافق مع اسم الخدمة الخاص بها elasticsearch. سيُترجم اسم النطاق إلى قائمة عناوين IP الخاصة بكائنات Pod الثلاث. راجع توثيق Kubernetes للمزيد عن إدارة أسماء النطاقات في Kubernetes. أخيرًا، عيّنا 5601 ليكون منفذ حاويات Kibana، حيث ستعيد خدمة Kibana توجيه الطلبات إليه. يمكنك - بعد التأكّد من إعدادات Kibana - إطلاق الخدمة وتشغيل عملية النشر باستخدام kubectl: $ kubectl create -f kibana.yaml يجب أن تشاهد المخرجات التالية: service/kibana created deployment.apps/kibana created يمكنك التحقق من نجاح إطلاق الخدمة عن طريق تشغيل الأمر التالي: $ kubectl rollout status deployment/kibana --namespace=kube-logging يجب أن تشاهد المخرجات التالية: deployment "kibana" successfully rolled out للوصول إلى واجهة Kibana، سنعيد توجيه منفذ محلي مرة أخرى إلى عُقدة Kubernetes التي تشغّل Kibana. احصل على تفاصيل كائن Pod الخاص بعقدة Kibana باستخدام kubectl get: $ kubectl get pods --namespace=kube-logging المخرجات: NAME READY STATUS RESTARTS AGE es-cluster-0 1/1 Running 0 55m es-cluster-1 1/1 Running 0 54m es-cluster-2 1/1 Running 0 54m kibana-6c9fb4b5b7-plbg2 1/1 Running 0 4m27s هنا نلاحظ أن كائن Pod الخاص بعقدة Kibana يُسمّى kibana-6c9fb4b5b7-plbg2. أعد توجيه المنفذ المحلي 5601 إلى المنفذ 5601 على ذلك الكائن: $ kubectl port-forward kibana-6c9fb4b5b7-plbg2 5601:5601 --namespace=kube-logging يجب أن تظهر المخرجات التالية: Forwarding from 127.0.0.1:5601 -> 5601 Forwarding from [::1]:5601 -> 5601 الآن، زر رابط URL التالي: http://localhost:5601 إذا رأيت صفحة ترحيب Kibana التالية، فقد نجحت في نشر Kibana في عنقود Kubernetes: يمكنك الآن الانتقال إلى إطلاق المكون النهائي لمكدس EFK وهو مُجمِّع السجلات Fluentd. الخطوة 4: إنشاء Fluentd DaemonSet في هذا الدليل، سنعدّ Fluentd بصيغة DaemonSet، وهو نوع من أعباء العمل في Kubernetes يشغّل نسخة من كائن Pod على كل عقدة في عنقود Kubernetes. باستخدام وحدة تحكم DaemonSet هذه، سنطلق وكيل تسجيل Fluentd عبارة عن كائن Pod على كل عقدة من العنقود. راجع هذا المقال من توثيق Kubernetes الرسمي لمعرفة المزيد حول بنية التسجيل هذه. تُلتَقط سجّلات المُخرجات والأخطاء المعيارية (stdout و stderr على التوالي) للتطبيقات العاملة ضمن حاويّات ويُعاد توجيهها إلى ملفات JSON على العقد. سيتتبّع وكيل Fluentd ملفّات السجلّات تلك، ويفرز الأحداث الموجودة فيها، ويحوّل بيانات السجلّات وفي الأخير يشحنها إلى السند الخلفي لحفظ السجلّات على Elasticsearch الذي نشرناه في الخطوة الثانية من هذا الدليل. بالإضافة إلى سجلات الحاوية، يتتبّع وكيل Fluentd سجلات مكونات نظام Kubernetes مثل سجلات kubelet وkube-proxy وDocker. راجع ملف kubernetes.conf المستخدم لإعداد وكيل التسجيل للاطلاع على قائمة كاملة بالمصادر التي يتتبعها وكيل تسجيل Fluentd. راجع توثيق Kubernetes لمعرفة المزيد حول تسجيل الأحداث على مستوى عقد Kubernetes. ابدأ بفتح الملف fluentd.yaml في محرر النصوص المفضل لديك: $ nano fluentd.yaml مرة أخرى ، سنلصق تعريفات الكائن جزءًا جزءًا، مع شرح سياق التعريفات في كل جزء. نستند في هذا الدليل على مواصفات متحكّم Fluentd DaemonSet التي يوفرها فريق صيانة Fluentd. مورد مفيد آخر يقدمه مشرفو Fluentd هو مقالات Flunetd ضمن توثيق Kuberentes. أولاً، الصق في تعريف ServiceAccount التالي: apiVersion: v1 kind: ServiceAccount metadata: name: fluentd namespace: kube-logging labels: app: fluentd هنا، قمنا بإنشاء حساب خدمة باسم flentd ستستخدمه كائنات Pod التابعة لخدمة Fluentd في الوصول إلى واجهة تطبيقات Kubernetes. ننشئ الحساب في فضاء الأسماء kube-logging ونعطيه مرة أخرى اللصيقة app: fluentd. راجع توثيق Kubernetes للمزيد عن حسابات الخدمة في Kubernetes. بعد ذلك، الصق الجزء التالي الذي يعرّف الكائن ClusterRole : . . . --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluentd labels: app: fluentd rules: - apiGroups: - "" resources: - pods - namespaces verbs: - get - list - watch هنا نحدد ClusterRole يسمى fluentd نمنحه صلاحيات get،وlist و watch على كائنات Pod وفضاءات الأسماء. تسمح الكائنات من النوع ClusterRoles بمنح الوصول إلى موارد Kubernetes في نطاق العنقود مثل العقَد. راجع [فصل استخدام تراخيص RBAC]() ضمن توثيق Kubernetes، للمزيد عن التحكم في الوصول المعتمد على الأدوار (RBAC). الآن، الصق الجزء التعريفي التالي المتعلق بكائن ClusterRoleBinding: . . . --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd roleRef: kind: ClusterRole name: fluentd apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: fluentd namespace: kube-logging نعرّف كائنًا من النوع ClusterRoleBinding ونسمّيهfluentd. وظيفة هذا الكائن هي الربط بين الكائن من النوع ClusterRole وحساب خدمة fluentd، ممّا يمنح الخدمة الصلاحيّات المدرجة في الكائن من النوع ClusterRole الذي أسميناهfluentd . عند هذه النقطة يمكننا البدء بلصق التعريفات ضمن المواصفات الفعليّة لمتحكّم DaemonSet: . . . --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd namespace: kube-logging labels: app: fluentd هنا، نحدد متحكّم DaemonSet يُسمى fluentd في فضاء أسماء kube-logging ونعطيها اللصيقة app: fluentd. بعد ذلك، الصق الجزء التعريفي التالي: . . . spec: selector: matchLabels: app: fluentd template: metadata: labels: app: fluentd spec: serviceAccount: fluentd serviceAccountName: fluentd tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1 env: - name: FLUENT_ELASTICSEARCH_HOST value: "elasticsearch.kube-logging.svc.cluster.local" - name: FLUENT_ELASTICSEARCH_PORT value: "9200" - name: FLUENT_ELASTICSEARCH_SCHEME value: "http" - name: FLUENTD_SYSTEMD_CONF value: disable هنا، نطابق اللصيقة app: fluentd المُعرَّفة في metadata.labels.، ثم نعيّن متحكّم DaemonSet لحساب خدمة fluentd. نختار أيضًا كائنات Pod التي تطابق المحدّد app: fluentd ليتولّى المتحكّم DaemonSet إدارتها. بعد ذلك، نحدد تسهيلاً بلا جدول زمني (NoSchedule toleration) لمطابقة الشائبة (Taint) المكافئة على عقد Kubernetes الرئيسية (القبطان). نضمن بذلك أنّ المتحكّم DaemonSet سيُطلَق أيضًا على العقد الرئيسيى في على سادة Kubernetes. أزل هذا التسهيل إذا كنت لا ترغب في تشغيل كائن Pod لتطبيق Fluentd على العقد الرئيسية الخاصة بك. راجع هذا الفصل في توثيق Kubernetes للمزيد عن التسهيلات والشوائب. بعد ذلك، نبدأ في تحديد حاوية كائن Pod، والتي نسميها fluentd. يستخدم هذا الدليل صورة رسمية من توزيعة دبيان يوفّرها فريق صيانة Fluentd. عدّل وسم image في مواصفات الحاوية إذا كنت ترغب في استخدام صورة Fluentd خاصة أو عامة، أو استخدام صورة بإصدار مختلف. يتوفر ملف Dockerfile ومحتويات هذه الصورة في مستودع fluentd-kubernetes-daemonset على Github. بعد ذلك، نضبط Fluentd باستخدام بعض متغيرات البيئة: FLUENT_ELASTICSEARCH_HOST: نعيّن قيمة هذا المتغيّر لتكون اسم نطاق خدمة Elasticsearch مجهولة العنوان المُحدَّد سابقًا elasticsearch.kube-logging.svc.cluster.local. يُترجم اسم النطاق هذا إلى قائمة عناوين IP لكائنات Pod الثلاث الخاصة بتطبيق Elasticsearch. من المُرجَّح أن يكون عنوان مضيف Elasticsearch الحالي هو عنوان IP الأول في القائمة المُرجَعة. لتوزيع السجلات على العنقود، ستحتاج إلى تعديل إعدادات مُلحَق Fluentd الخاص بمُخرجات Elasticsearch. راجع توثيق Fluentd للمزيد حول هذا الملحق. FLUENT_ELASTICSEARCH_PORT: نحدّد قيمة المتغيّر لتكون المنفذ الذي عيّناه سابقًا، 9200. FLUENT_ELASTICSEARCH_SCHEME: نعيّن القيمة http. FLUENTD_SYSTEMD_CONF: نعيّن القيمة disable لحذف مُخرجات systemd غير المضبوطة في الحاوية. أخيرًا، نلصق الجزء التالي من التعريف: . . . resources: limits: memory: 512Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers هنا نحدد القيمة 512 ميجابايت لتكون الحد الأقصى للذاكرة على كائن Pod الخاص بتطبيق Fluentd الذي نضمن له 0.1 من المعالج الافتراضي (0.1vCPU) و 200 ميجابايت من الذاكرة. يمكنك تدقيق حدود الموارد والطلبات بناءً على حجم السجلّات المتوقعة والموارد المتاحة. بعد ذلك، نقوم نركّب مسارات المضيف var/log/ و var/lib/docker/containers/ في الحاوية باستخدام نقطتيْ التركيب (volumeMounts) المذكورتيْن varlog و varlibdockercontainers . تُعرَّف التجزئات (volumes) في نهاية الجزء السابق. الوسيط الأخير الذي نعرّفه هو terminationGracePeriodSeconds، والذي يمنح 30 ثانية لإيقاف Fluentd بأمان عند استقبال إشارة SIGTERM. بعد 30 ثانية، تُرسَل إلى الحاويات إشارة SIGKILL. القيمة الافتراضية للوسيط terminationGracePeriodSeconds هي 30 ثانية، لذلك في معظم الحالات يمكن إغفال هذا الوسيط. راجع هذا المقال من غوغل عن أفضل الممارسات لإيقاف أعباء العمل على Kubernetes. يجب أن تبدو المواصفات الكاملة لتطبيق Fluentd كما يلي: apiVersion: v1 kind: ServiceAccount metadata: name: fluentd namespace: kube-logging labels: app: fluentd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluentd labels: app: fluentd rules: - apiGroups: - "" resources: - pods - namespaces verbs: - get - list - watch --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd roleRef: kind: ClusterRole name: fluentd apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: fluentd namespace: kube-logging --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd namespace: kube-logging labels: app: fluentd spec: selector: matchLabels: app: fluentd template: metadata: labels: app: fluentd spec: serviceAccount: fluentd serviceAccountName: fluentd tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1 env: - name: FLUENT_ELASTICSEARCH_HOST value: "elasticsearch.kube-logging.svc.cluster.local" - name: FLUENT_ELASTICSEARCH_PORT value: "9200" - name: FLUENT_ELASTICSEARCH_SCHEME value: "http" - name: FLUENTD_SYSTEMD_CONF value: disable resources: limits: memory: 512Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers احفظ الملف وأغلقه بعد ضبط إعداد المتحكّم DaemonSet لتطبيق Fluentd. الآن، أطلق DaemonSet باستخدام kubectl: $ kubectl create -f fluentd.yaml يجب أن تشاهد الناتج التالي: serviceaccount/fluentd created clusterrole.rbac.authorization.k8s.io/fluentd created clusterrolebinding.rbac.authorization.k8s.io/fluentd created daemonset.extensions/fluentd created تحقق من نجاح إطلاق DaemonSet باستخدام kubectl: $ kubectl get ds --namespace=kube-logging يجب أن ترى الحالة الظاهرة في المُخرجات التالية: NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE fluentd 3 3 3 3 3 <none> 58s تشير النتيجة أعلاه إلى وجود ثلاث كائنات Pod قيد التشغيل ويعمل عليها المتحكّم fluentd. يتوافق هذا العدد مع عقد Kubernetes. يمكننا الآن النظر في Kibana للتحقق من أن بيانات السجلّات تُجمَع وتُشحَن كما نريد إلى Elasticsearch. استخدم المتصفّح لفتح العنوان التالي http://localhost:5601، مع استمرار تنفيذ الأمرkubectl port-forward. اضغط على زر Discover (اكتشف) في قائمة التنقل اليسرى: يجب أن تظهر نافذة الإعدادات التالية: تتيح لك هذه النافذة تحديد مؤشرات Elasticsearch التي ترغب في استكشافها في Kibana. لمعرفة المزيد، راجع المقال التالي في توثيق Kibana للمزيد عن أنماط الفهرسة في Kibana. في الوقت الحالي، سنستخدم نمط محارف البدل logstash-* لالتقاط جميع بيانات السجلّات في عنقود Elasticsearch الخاص بنا. اكتبlogstash-* في مربع النص ثم انقر على Next (التالي). ستنتقل بعد ذلك إلى الصفحة التالية. تسمح هذه النفاذة بإعداد الحقل الذي سيستخدمه Kibana لتصفية بيانات السجل حسب الوقت. في القائمة المنسدلة، حدد حقلtimestamp@، واضغط على Create index pattern (إنشاء نمط فهرس). الآن، اضغط على Discover (اكتشف) في قائمة التنقل اليسرى. يجب أن تشاهد مخطّطًا بيانيّا وبعض المُدخلات الأخيرة في السجلّات. بالوصول إلى هذه النقطة تكون قد نجحت في إعداد حزمة EFK وإطلاقها على عنقود Kubernetes. راجع دليل مستخدم Kibana لمعرفة كيفية استخدام Kibana لتحليل بيانات السجل. في القسم الاختياري التالي، سننشر كائن Pod لعدّاد بسيط يطبع أعدادًا على وحدة الإخراج المعيارية (stdout)، ونعثر على سجلاته في Kibana. الخطوة 5 (اختياري) - اختبار تسجيل الحاويات لتوضيح حالة بسيطة لاستخدام Kibana لاستكشاف أحدث السجلات على كائن Pod معيّن، سننشر كائن Pod محدود الإمكانيّات يطبع أعدادًا متسلسلة على وحدة stdout. لنبدأ بإنشاء كائن Pod. افتح ملفًا يسمى counter.yaml في محررك المفضل: $ nano counter.yaml ثم الصق مواصفات التالية لكائن Pod: apiVersion: v1 kind: Pod metadata: name: counter spec: containers: - name: count image: busybox args: [/bin/sh, -c, 'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done'] احفظ الملف ثم أغلقه. تعرّف المواصفات كائن Pod محدود يُسمى counter ينفّذ حلقة while تكرارية تطبع أعدادًا تسلسلية. ننشر counter باستخدامkubectl: $ kubectl create -f counter.yaml بمجرد إنشاء كائن Pod وتشغيله، انتقل مرة أخرى إلى لوحة معلومات Kibana. أدخل العبارة kubernetes.pod_name: counter في شريط البحث ضمن صفحة Discover (اكتشف). تصفّي العبارة السابقة بيانات السجلّات لعرض البيانات القادمة من كائن Pod المسمَّىcounter دون غيره. يمكنك النقر على أي من مُدخلات السجل لعرض بيانات وصفية إضافية مثل اسم الحاوية، وعقدة Kubernetes، وفضاء الأسماء، والمزيد. خاتمة أوضحنا في هذا الدليل كيفية إعداد وتهيئة Elasticsearch و Fluentd و Kibana على عنقود Kubernetes. استخدمنا الحد الأدنى لإنشاء بنية تسجيل تتكون من وكيل تسجيل واحد يعمل على كل عقدة Kubernetes عاملة. قبل نشر مكدس التسجيل هذا على عنقود Kubernetes ضمن بيئة إنتاج، من الأفضل ضبط متطلبات الموارد وحدودها كما هو موضح في هذا الدليل. قد تحتاج أيضًا إلى إعدادX-Pacl لتمكين ميزات المراقبة والأمان المضمنة. تتكون بنية التسجيل التي استخدمناها هنا من ثلاث كائنات Pod لتطبيق Elasticsearch، وكائن Pod واحد لتطبيق Kibana (بدون موازنة الحِمل)، ومجموعة من كائنات Pod لتطبيق Fluentd تُشغَّل على أنها متحكّمات DaemonSet. قد ترغب في تحجيم هذا الإعداد وفقًا لحالة استخدام بيئة الإنتاج الخاصة بك. راجع هذا المقال للمزيد عن حجيم Elasticsearch و Kibana. يسمح Kubernetes أيضًا ببُنى أكثر تغقيدًا لوكلاء التسجيل ممّا قد يتناسب أكثر مع استخداماتك. راجع هذا المقال على توثيق Kubernetes للمزيد عن بنية السجلّات في Kubernetes. ترجمة - وبتصرّف - للمقال How To Set Up an Elasticsearch, Fluentd and Kibana (EFK) Logging Stack on Kubernetes لصاحبه Hanif Jetha.
  5. يوفر هذا الدرس نظرة عامة على أساسيات نظام تنسيق العناقيد (Cluster orchestration) في Kubernetes. تحتوي كل وحدة على معلومات أساسية عن ميزات ومفاهيم Kubernetes الرئيسية، وتتضمن برنامجًا تعليميًا تفاعليًا عبر الإنترنت. تتيح لك هذه الدروس التفاعلية إدارة عنقود بسيط والتطبيقات العاملة على حاويّات فيه. باستخدام الدروس التفاعلية، يمكنك تعلم ما يلي: نشر تطبيق يعمل ضمن حاوية على عنقود. تحجيم النشر. تحديث التطبيق العامل ضمن حاوية بإصدار جديد من البرنامج. تنقيح التطبيقات العاملة ضمن حاويات. تستخدم البرامج التعليمية منصَّة Katacoda لتشغيل طرفية افتراضية في متصفح الويب يشغّل Minikube، وهو بيئة نشر Kubernetes محلية محدودة الحجم يمكن تشغيلها في أي مكان. لا داعي لتثبيت أي برنامج أو ضبط أي شيء؛ يعمل كل درس تفاعلي مباشرة من متصفح الويب. ما الذي يمكن أن يقدمه لك Kubernetes؟ مع خدمات الويب الحديثة، يتوقع المستخدمون أن تكون التطبيقات متاحة على مدار الساعة طوال أيام الأسبوع، ويتوقع المطورون نشر إصدارات جديدة من هذه التطبيقات عدة مرات في اليوم. يُساعد مفهوم "الحاويات" على تحزيم البرامج لخدمة هذه الأهداف، مما يتيح إصدار التطبيقات وتحديثها بطريقة سهلة وسريعة دون توقف. يساعدك Kubernetes على التأكد من تشغيل هذه التطبيقات الحاوية أينما ومتى تريد، ويساعد في العثور على الموارد والأدوات التي تحتاجها تلك الحاويّات للعمل. Kubernetes هي منصّة مفتوحة المصدر، جاهزة للإنتاج ومصممة بخبرة Google المتراكمة في تنسيق الحاويات، جنبًا إلى جنب مع أفضل الأفكار والممارسات التي يقترحها المجتمع. سننتقل الآن إلى التحدث عن وحدات Kubernetes الأساسية: إنشاء عنقود Kubernetes نشر التطبيق استكشاف التطبيق الإعلان عن التطبيق تحجيم التطبيق تحديث التطبيق 1. استخدام Minikube لإنشاء عنقود Kubernetes عناقيد Kubernetes تنسق Kubernetes عناقيد من الحواسيب عالية التوفّر المتصلة في ما بينها للعمل كوحدة منفردة. تسمح لك التجريدات (Abstractions) في Kubernetes بنشر تطبيقات تعمل ضمن حاويات على عنقود دون ربط الحاويّات بأجهزة مخصوصة. للاستفادة من هذا النموذج الجديد للنشر، يجب تحزيم التطبيقات بطريقة تفصلها عن المضيفات الفردية، أي أنه يجب وضعها في حاويات. التطبيقات العاملة ضمن حاويات أكثر مرونة وتوفّرًا مما كانت عليه في نماذج النشر السابقة، إذ كانت التطبيقات تثبّت مباشرة على أجهزة معينة بصيغة حزم مدمجة شديدة الارتباط بالمضيف. يؤتمت Kubernetes عمليات توزيع حاويّات التطبيقات وجدولتها على عنقود من المضيفات بطريقة أكثر كفاءة. Kubernetes هي منصة مفتوحة المصدر وجاهزة للإنتاج. يتكون عنقود Kubernetes من نوعين من الموارد: القبطان (The Master) الذي ينسق عمل العنقود. العُقَد (Nodes) وهي الموارد العاملة على تشغيل التطبيق. مخطط عنقود القبطان هو المسؤول عن إدارة الدفة. ينسّق القبطان جميع الأنشطة في العنقود، مثل جدولة التطبيقات، والحفاظ على الحالة المرغوبة، وتحجيم التطبيقات، وطرح تحديثات جديدة. العقدة هي آلة افتراضية (VM) أو حاسوب فيزيائي يُستخدم كآلة عاملة في عنقود Kubernetes. تحتوي كل عقدة على Kubelet، وهو وكيل لإدارة العقدة والتواصل مع القبطان. يجب أن تحتوي العقدة أيضًا على أدوات للتعامل مع عمليات الحاوية، مثل Docker أو rkt. يجب أن يحتوي عنقود Kubernetes الذي يتعامل مع حركة البيانات في بيئة إنتاج على ثلاث عقد على الأقل. عندما تنشر تطبيقات على Kubernetes، فأنت تطلب من القبطان تشغيل حاويات التطبيقات. يجدول القبطان الحاويات لتعمل على عقد العنقود. **تتواصل العُقَد مع القبطان باستخدام واجهة تطبيقات Kubernetes التي يبرزها القبطان. يمكن للمستخدمين النهائيين أيضًا استخدام واجهة تطبيقات Kubernetes مباشرةً للتفاعل مع العنقود. يمكن نشر عنقود Kubernetes على الأجهزة الفيزيائية أو الافتراضية على حد السواء. يمكنك بدء التطوير على Kubernetes باستخدام Minikube، وهو إصدار مخفّف من Kubernetes ينشئ آلة افتراضية على جهازك المحلي وينشر عنقودًا بسيطًا يحتوي على عقدة واحدة فقط. يتوفر Minikube لأنظمة لينكس و ماك وويندوز. توفّر طرفية Minikube عمليات التمهيد الأساسية للعمل مع العناقيد، بما في ذلك البدء (Start) والإيقاف (Stop) والحالة (Status) والحذف (Delete). توجد على هذه الصفحة طرفية جاهزة للاستخدام يُثبّت عليها Minikube مسبقا. 2. نشر تطبيق باستخدام kubectl عمليات النشر في Kubernetes يمكن نشر تطبيقات تعمل على حاويّات ضمن منصة Kubernetes بمجرّد توفر عنقود قيد التشغيل. لذا أنشئ إعدادات نشر (Deployment). يوجِّه كائن النشر Kubernetes إلى كيفية إنشاء نظائر (Instances) للتطبيق وتحديثها. يجدول قبطان Kubernetes، بعد إعداد كائن النشر، نظائر التطبيق للعمل على عقد العنقود. تراقب وحدة تحكم (Controller) باستمرار عمل النظائر بعد إنشائها. إنْ تعطلت عقدة مضيفة أو حذفت، فإن وحدة التحكم تستبدلها بعقدة أخرى من العنقود ليعمل عليها التطبيق، ممّا يوفّر آلية للإصلاح الذاتي لمعالجة إخفاق الآلة أو لصيانتها. في عالم ما قبل التنسيق، غالبًا ما كان تُشتخدَم سكربتات تثبيت لبدء التطبيقات، لكن لم توفر الحلول حينئذٍ لاستعادة عمل التطبيق عند إخفاق الآلة. من خلال إنشاء نظائر لتطبيقك والحفاظ على تشغيلها عبر العُقَد، توفر عمليات النشر في Kubernetes نهجًا مختلفًا جذريًا لإدارة التطبيقات. نشر تطبيقك الأول على Kubernetes يمكنك إنشاء عملية نشر وإدارتها باستخدام واجهة سطر أوامر Kubernetes ‏(Kubectl). يستخدم Kubectl واجهة برمجة تطبيقات Kubernetes للتفاعل مع العنقود. في هذا الجزء، ستتعلم أوامر Kubectl الأكثر شيوعًا اللازمة لإنشاء عمليات النشر التي تشغّل تطبيقاتك على عنقود Kubernetes. عندما تنشئ عملية نشر، ستحتاج إلى تحديد صورة حاوية التطبيق وعدد النظائر التي تريد تشغيلها. يمكنك تغيير هذه المعلومات لاحقًا عن طريق تحديث النشر. تناقش النقطتان 5 و 6 من هذا الدرس كيفية تحجيم عمليات النشر وتحديثها. بالنسبة إلى عملية النشر الأولى، ستستخدم تطبيق Node.js معبَّأ في حاوية Docker. (إذا لم تكن قد حاولت بالفعل إنشاء تطبيق Node.js ونشره باستخدام حاوية، فيمكنك القيام بذلك أولاً باتباع الإرشادات من مقال مدخل إلى Kubernetes. 3. استكشاف التطبيق: عرض العناقيد والعُقد الكائنات من نوع Pod عندما أنشأت عملية نشر في الجزء 2 أعلاه، أنشأ Kubernetes كائنًا من نوع Pod لاستضافة نظير من التطبيق. كائنات Pod هي تجريد Kubernetes لتمثيل مجموعة واحدة أو أكثر من حاويات التطبيقات (مثل Docker أو rkt)، إضافة إلى موارد مشتركة بين تلك الحاويات. تشمل تلك الموارد: التخزين المشترك، بصيغة تجزئات (Partitions). الشبكات، مثل عنوان IP فريد لكل عنقود. معلومات حول كيفية تشغيل كل حاوية، مثل إصدار صورة الحاوية أو منافذ معينة لاستخدامها. يصمّم كائن Pod "مضيفًا منطقيًّا" خاصًّا بالتطبيق، ويمكن أن يحتوي على حاويات تطبيق مختلفة مقترنة في ما بينها بإحكام نسبيًا. على سبيل المثال، قد يحتوي الكائن على حاوية تطبيق Node.js بالإضافة إلى حاوية أخرى تغذي البيانات التي سينشرها خادم الويب Node.js الذي يعمل في الحاوية الأولى. تشترك الحاويات الموجودة في كائن واحد عنوانَ IP وفضاء منافذ (Port Space)، كما أنها تشترك دائمًا العقدة والجدولة، وتعمل في سياق مشترك على العقدة نفسها. كائنات Pod هي أصغر وحدة على منصة Kubernetes. عندما تنشئ عملية نشر فإن هذا النشر ينشئ كائنات Pod مع حاويات بداخل الكائن (بدلًا من إنشاء حاويات مباشرة). يرتبط كل كائن Pod بالعقدة التي جُدولت عليها، وتظل هناك حتى الإنهاء (وفقًا لسياسة إعادة التشغيل) أو الحذف. في حالة إخفاق العقدة، تُجدول كائنات Pod متطابقة على العقد الأخرى المتاحة في العنقود. نظرة عامة على كائنات Pod عقد Kubernetes تُشَغَّل كائنات Pod دائمًا على عقدة. العقدة هي آلة عاملة في Kubernetes وقد تكون إما آلة افتراضية أو فيزيائية، حسب العنقود. يدير القبطان كل العُقد. يمكن أن تحتوي العُقدة على عدة كائنات Pod. يتولّى القبطان في Kubernetes جدولة كائنات Pod تلقائيًا على عقد العنقود. تأخذ الجدولة التلقائية من طرف القبطان في الاعتبار الموارد المتاحة لكل عقدة. تُشغِّل كل عقدة Kubernetes على الأقل: Kubelet، عملية مسؤولة عن التواصل بين القبطان و العُقدة؛ تُدير كائنات Pod والحاويات التي تعمل على الجهاز. بيئة تشغيل حاويات (مثل Docker وrkt) مسؤولة عن سحب صورة الحاوية من تقييد (Registry)، فك ضغط الحاوية، وتشغيل التطبيق. نظرة عامة على العقد استكشاف الأخطاء وإصلاحها باستخدام kubectl تحدّثنا في الجزء 2 أعلاه عن واجهة سطر الأوامر kubectl. سنستمر في الحديث عنه في هذا الجزء للحصول على معلومات حول التطبيقات المنشورة وبيئاتها. يمكن تنفيذ العمليات الأكثر شيوعًا باستخدام أوامر kubectl التالية: kubectl get - سرد الموارد. kubectl describe - عرض معلومات تفصيلية حول مورد. kubectl logs - طباعة السجلات من حاوية في كائن Pod. kubectl exec - تنفيذ أمر على حاوية في كائن Pod. يمكنك استخدام هذه الأوامر لمعرفة متى نُشرت التطبيقات، وما حالاتها الراهنة، وأين تعمل وما إعداداتها. الآن بعد أن عرفنا المزيد عن مكونات المجموعة لدينا وسطر الأوامر، دعنا نستكشف تطبيقنا. توجد على هذا الرابط بيئة تفاعلية لعرض العناقيد والعقد واستكشاف أوامر kubectl. 4. الإعلان عن التطبيق للعموم استخدام خدمة للإعلان عن التطبيق الخاص بك نظرة عامة على خدمات Kubernetes كائنات Pod في Kubernetes فانية. وهي في الواقع لها دورة حياة. عند توقّف عقدة عاملة تفقد كل كائنات Pod التي تعمل كانت تعمل على العقدة. قد تعيد وحدة التحكم ReplicaSet بعد ذلك العنقود ديناميكيًّا إلى الحالة المرغوبة من خلال إنشاء كائنات Pod جديدة للحفاظ على تشغيل التطبيق الخاص بك. مثال آخر، فلنفترض سندًا (Backend) لمعالجة الصور مع ثلاث حاويّات متماثلة. هذه النسخ المتماثلة قابلة للاستبدال؛ يجب ألا يهتم نظام الواجهة الأمامية بالنسخ المتماثلة للسند أو حتى في حالة فقد كائن Pod وإعادة إنشائه. ومع ذلك، فإن كل كائن Pod في عنقود Kubernetes له عنوان IP فريد، حتى الكائنات على العقدة نفسها. لذا يجب أن تكون هناك طريقة للتوفيق بين التغييرات تلقائيًا بين كائنات Pod حتى تستمر تطبيقاتك في العمل. الخدمة في Kubernetes عبارة عن تجريد يعرّف مجموعة منطقية من كائنات Pod وسياسة للوصول إليها. تتيح الخدمات اقترانًا فضفاضًا بين كائنات Pod المترابطة في ما بينها. تُعرّف الخدمة باستخدام YAML (وهي الوسيلة المفضّلة) أو JSON، مثل جميع كائنات Kubernetes. عادةً ما تُحدّذ مجموعة كائنات Pod التي تستهدفها الخدمة بواسطة كائن من النوع LabelSelector (انظر أدناه لمعرفة الحالات التي قد تدعوك لإنشاء خدمة بطريقة مغايرة). على الرغم من أن كل كائن Pod لديه عنوان IP فريد، إلّا أنّ تلك العناوين لا تُعرَض خارج العنقود بدون خدمة. تسمح الخدمات لتطبيقاتك بتلقي حركة المرور. يمكن الإعلان عن الخدمات بطرق مختلفة عن طريق تحديد النوع type في ServiceSpec: ClusterIP (قيمة افتراضية): يعرض الخدمة على عنوان IP داخلي في العنقود. يجعل هذا النوع الوصول للخدمة متاحًا فقط من داخل العنقود. NodePort: يعرض الخدمة على نفس المنفذ لكل عقدة محددة في العنقود باستخدام ترجمة عناوين الشبكة (NAT). يتيح الوصول إلى خدمة من خارج العنقود باستخدام عنوان IP العنقود ورقم المنفذ (<NodeIP>:<NodePort>). امتداد للطريقة السابقة (ClusterIP). LoadBalancer : ينشئ موازن حِمْل خارجي في السحابة الحالية (إذا كانت تدعم ذلك) ويعين عنوان IP ثابتًا خارجيًا للخدمة. امتداد للطريقة السابقة (NodePort). ExternalName: يُعلن عن الخدمة باستخدام اسم عشوائي (محدد بواسطة القيمة externalName في المواصفات spec) عن طريق إرجاع سجل CNAME يتضمّن الاسم. لا يُستخدَم أي وكيل (Proxy). يتطلب هذا النوع الإصدار v1.7 أو أعلى من حزمة kube-dns. يمكن العثور على مزيد من المعلومات حول الأنواع المختلفة من الخدمات في الدرس التالي، وأيضًا من خلال هذا المقال. بالإضافة إلى ذلك، يُرجى ملاحظة أن هناك حالات استخدام لا تتضمن فيها الخدمات تحديد حقل selector في المواصفات (spec). لن تنشئ الخدمة في تلك الحالة الكائن الطرفي (Endpoint object) المقابل، وهو ما يسمح للمستخدمين بالتعيين اليدوي للنقاط الطرفية للخدمة. توجد إمكانية أخرى لعدم وجود حقل selector وهي أنك تستخدم النوع ExternalName. الخدمات واللصائق (Labels) توجّه الخدمة البيانات عبر مجموعة من كائنات Pod. الخدمات هي طبقة تجريد تسمح بزوال كائنات Pod وتكرارها دون التأثير على عمل التطبيق في بيئة Kubernetes. تتولّى خدمات Kubernetes اكتشاف كائنات Pod المترابطة (مثل تطبيق يتكوّن من سند وواجهة أمامية) والتوجيه بينها. تتعرّف الخدمات على كائنات Pod المترابطة من خلال المحدّدات واللصائق (Selectors and Labels). المحدّدات هي دوال للتجميع تسمح بإجراء عمليات منطقية على كائنات Kubernetes، أمّا اللصائق فهي أزواج مفاتيح وقيم (Key/Value) مرفقة بالكائنات، ويمكن استخدامها بأي واحدة من الطرق التالية: تعيين كائنات للتطوير والاختبار والإنتاج، تضمين وسوم الإصدار، تصنيف كائن حسب الوسوم. يمكن إرفاق التسميات أو اللصائق (label) بالكائنات في وقت الإنشاء أو لاحقا. يمكن تعديلها في أي وقت. تجربة تفاعلية لعرض التطبيق للعموم باستخدام خدمات Kubernetes. 5. تحجيم التطبيق تشغيل نُسَخ متعددة للتطبيق رأينا أعلاه كيفية إنشاء عملية نشر (Deplyment)، ثم كيفية الإعلان عنها للعموم عبر خدمة. أنشأت عملية النشر كائن Pod واحدًا لتشغيل التطبيق. عندما تزداد حركة البيانات، سنحتاج إلى تحجيم (Scaling) التطبيق لمواكبة طلب المستخدم. يتحقّق التحجيم عن طريق تغيير عدد النظائر المنشورة. نظرة عامة على التحجيم سيضمن تحجيم النشر إنشاء كائنات Pod جديدة وجدولتها على العقد ذات الموارد المتاحة. سيؤدي التحجيم إلى زيادة عدد كائنات Pod إلى الحالة المرغوبة الجديدة. يدعم Kubernetes أيضًا التحجيم التلقائي Autoscaling لكائنات Pod، ولكنّ ذلك خارج نطاق هذا الدرس. التحجيم باتجاه الصفر ممكن أيضًا، وسيؤدي إلى إنهاء جميع كائنات Pod في عملية النشر المحددة. يتطلب تشغيل نسخ متعددة من تطبيق ما طريقة لتوزيع حركة البيانات عليها جميعا. تتضمّن الخدمات موازِن حِمل متكامل من شأنه أن يوزِّع البيانات المارة في الشبكة على جميع كائنات Pod الموجود ضمن نشر متاح للعموم. تراقب الخدماتُ كائنات Pod العاملة باستمرار باستخدام النقاط الطرفية لضمان إرسال البيانات إلى كائنات Pod المتاحة فقط. بمجرد أن يكون لديك نُسَخ متعددة للتطبيق قيد التشغيل، ستتمكن من دحرجة التحديثات دون توقف. سنغطي ذلك في الأجزاء التالية، وهو ما سنراه في الجزء اللاحق. يمكنك تجربة تحجيم التطبيق (بتوسيعه أو تقليصه) عبر هذه الطرفية التفاعلية. 6. تحديث التطبيق التحديث المتدحرج (Rolling update) يتوقع المستخدمون أن تكون التطبيقات متاحة طوال الوقت، ويُنتظر من المطورين أن ينشروا إصدارات جديدة منها عدة مرات في اليوم. في Kubernetes يتم ذلك عن طريق التحديثات المتدحرجة. تسمح التحديثات المتدحرجة بتحديث عمليات النشر دون توقف عن طريق التحديث التدريجي بإحلال كائنات Pod جديدة تدريجيًّا مكان الكائنات الحالية. تُجدول كائنات Pod الجديدة على العُقد التي لديها موارد متاحة. تحدّثنا في الجزء السابق عن تحجيم التطبيق لتشغيل نُسَخ متعددة. هذا الأمر مطلوب لإجراء التحديثات دون التأثير على توفر التطبيق. افتراضيًّا، الحد الأقصى لعدد كائنات Pod التي يمكن أن تكون غير متاحة ولعدد كائنات Pod الجديدة التي يمكن إنشاؤها أثناء التحديث، هو واحد. يمكن ضبط كل واحد من الخيارين إما بالأرقام أو بالنسب المئوية (من كائنات Pod). تؤصدر (Versioned) التحديثات في Kubernetes، ويمكن التراجع عن أي تحديث نشر إلى إصدار سابق (مستقر). نظرة عامة على التحديثات المتدحرجة على غرار تحجيم التطبيق، إذا كان النشر متاحًا للعموم، فإن الخدمة ستوازن حركة البيانات فقط بين كائنات Pod المتاحة أثناء التحديث. كائن Pod متاح هو نظير متوفّر لمستخدمي التطبيق. تسمح التحديثات المتدحرجة بالإجراءات التالية: نقل تطبيق من بيئة إلى أخرى (عبر تحديثات صورة الحاوية). التراجع إلى إصدارات سابقة. التكامل المستمر والتوصيل المستمر للتطبيقات بدون توقف. يمكن استخدام هذه النافذة التفاعلية لاختبار تحديث تطبيق إلى إصدار جديد والتراجع عن ذلك. ترجمة - وبتصرّف - لأجزاء kubernetes basics من توثيق Kubernetes.
×
×
  • أضف...