لماذا نحتاج إلى تعبئة تطبيقات Kubernetes؟
لماذا نحتاج إلى تعبئة تطبيقات Kubernetes؟
لقد أتقنتَ البنى الأساسية لـ Kubernetes — الـ Deployments والـ Services والـ ConfigMaps والـ Ingresses والـ HorizontalPodAutoscalers. تخيّل الآن أنك طلبتَ من أحد زملائك نشر خدمة مصغّرة واحدة. يحتاج إلى: ملف Deployment، وملف Service، وملف ConfigMap، ومرجع Secret، وقاعدة Ingress، وملف PodDisruptionBudget، وملف ServiceAccount. هذه سبعة ملفات YAML — قبل أن تتطرّق إلى القيم الخاصة بكل بيئة تشغيل. اضرب هذا العدد في ثلاثين خدمة مصغّرة موزّعة عبر بيئات التطوير والاختبار والإنتاج. هذا ما يُعرف بـ تضخّم YAML.
مشكلة تضخّم YAML
في المراحل الأولى لـ Kubernetes، كانت الفرق تدير الملفات الخام داخل مجلد k8s/. ينهار هذا النهج عند أربعة مواطن ضعف رئيسية:
- التكرار. يُنسخ نفس كتلة
Deploymentلكل بيئة مع اختلافات طفيفة — وسم الصورة، عدد النسخ، حدود الموارد. تحديث مُهمَل في إحدى النسخ كفيل بإحداث حادث إنتاجي. - غياب الذرية. يُطبّق
kubectl apply -f k8s/الملفات واحداً تلو الآخر بحسب الترتيب الأبجدي. إن نجح تطبيقConfigMapوفشل تطبيقDeployment، تجد نفسك في حالة وسيطة مجهولة دون آلية تراجع مدمجة. - الإصدار ضمني في أحسن الأحوال. ما الإصدار من "التطبيق" الذي يعمل في بيئة الإنتاج؟ تربط علامات Git commits الكود بالصور، لكنها لا تُخبرك بأي مجموعة من كائنات Kubernetes تمثّل الإعداد السليم المعروف.
- إدارة المتغيرات عشوائية. تلجأ الفرق إلى
sedأوenvsubstأو سكريبتات Shell مخصّصة لحقن القيم. هذه السكريبتات هشّة وغير مختبرة ولم تُوثَّق كجزء من واجهة التطبيق.
envsubst لحقن وسم الصورة في الملفات قبل تطبيقها. ينسى مطوّر تصدير المتغير، فيستبدل envsubst العلامة المؤقتة بسلسلة فارغة، ويُطبّق kubectl apply بصمت image: "". يتعطّل الـ Pod فوراً، لكن لا أحد يفهم السبب لأن الأمر أعاد كود الخروج صفر.
انظر إلى هيكل الملفات الخام لخدمة واحدة فقط:
هذه عشرة ملفات لخدمة واحدة فقط. مع ثلاثين خدمة تُصبح لديك 300 ملف، والحفاظ على مزامنة التغييرات الأساسية عبر الـ overlays عبءٌ يدوي متواصل. حين يسأل مهندس: "ما الذي تغيّر بين نشر الإنتاج الثلاثاء الماضي وهذا الثلاثاء؟"، تتطلّب الإجابة مقارنة عشرات الملفات عبر مجلدات متعددة.
Helm: مدير حزم Kubernetes
يحلّ Helm مشكلة تضخّم YAML بنفس الطريقة التي حلّ بها apt وbrew وnpm مشكلة توزيع البرمجيات: إذ يُقدّم صيغة حزمة (تُسمّى Chart)، ونظام مستودعات لمشاركة الـ Charts، ونموذج إصدار يتتبّع ما هو مُنشَر في الكلاستر.
ثلاثة مفاهيم جوهرية عليك استيعابها من اليوم الأول:
- Chart — شجرة مجلدات تحتوي على قوالب وقيم افتراضية تصف تطبيق Kubernetes. فكّر فيها كالأرشيف المصدري.
- Release — نسخة مُسمّاة ومُرقَّمة من Chart مُثبَّتة في الكلاستر. يمكنك تثبيت نفس الـ Chart عدة مرات (مرة لكل بيئة أو لكل مستأجر) وكل تثبيت هو إصدار مستقل بسجلّه الخاص.
- Repository — خادم HTTP يستضيف Charts مُعبَّأة (أرشيفات
.tgz) وملفindex.yaml. Artifact Hub هو السجلّ العام، بينما تُستضاف المستودعات الخاصة على Nexus أو Artifactory أو سجلات OCI (ECR, GCR, ACR) أو حاويات S3 عادية.
ما الذي يفعله Helm فعلياً — دورة التثبيت والترقية
تحت الغطاء، يُنفّذ helm install وhelm upgrade الخطوات التالية بالتسلسل:
- تحميل الـ Chart ودمج القيم التي يُزوّدها المستخدم فوق القيم الافتراضية.
- تصيير جميع القوالب في
templates/عبر محرّك قوالب Go، لإنتاج مجموعة من Kubernetes manifests. - تشغيل هوكات ما قبل التثبيت/الترقية (Jobs وسكريبتات Shell — تُغطّى في الدرس السابع).
- تطبيق جميع الـ manifests على الكلاستر عبر خادم Kubernetes API.
- الانتظار حتى تصل الموارد إلى حالة الجاهزية (مع
--wait) والتراجع إن انتهت المهلة (مع--atomic). - تخزين مجموعة الـ manifests المُصيَّرة كـ release secret في الـ namespace المستهدف. هذا هو المصدر الحقيقي للمعلومات عند التراجع.
--atomic، يتراجع Helm تلقائياً إن لم تصل الترقية إلى حالة صحية خلال المهلة الزمنية. تنصّ ممارسات Google SRE على ضرورة أن يكون كل نشر قابلاً للعكس خلال دقيقة واحدة — وآلية التراجع في Helm (المدعومة بـ release secrets المخزَّنة) تجعل ذلك ممكناً تشغيلياً دون الحاجة إلى برمجة تطبيق يدوي لـ kubectl apply على لقطة manifest سابقة.
Helm في مقابل البدائل
ليس Helm الأداة الوحيدة في هذا المجال. ستصادف هذه الأدوات في قواعد الكود الإنتاجية:
- Kustomize — مدمجة في
kubectl. قائمة على التصحيح، بلا لغة قوالب. ممتازة للـ overlays البسيطة؛ تصبح عسيرة حين تحتاج منطقاً (مثل "فعّل هذا الـ sidecar في الإنتاج فقط"). - Kapp + ytt من Carvel — يُستخدمان على نطاق واسع في VMware/Tanzu. تُتيح
yttمنطقاً شبيهاً بـ Python في YAML؛ تتتبّعkappملكية الموارد كـ Helm releases لكن بلا طبقة قوالب. - Jsonnet / Tanka — مجموعة أدوات Grafana Labs. كتابة قوية وإعادة استخدام لـ monorepos الكبيرة، مع منحنى تعلّم حادّ.
- ملفات خام + سكريبتات CI — نقطة البداية الأكثر شيوعاً، والمسار الأسرع نحو مشكلة التضخّم المذكورة آنفاً.
يتفوّق Helm باتساع منظومته البيئية وأدواته التشغيلية. تعني المنظومة العامة للـ Charts (آلاف الـ Charts على Artifact Hub) إمكانية تثبيت بنية تحتية مُجرَّبة ومعتمدة (Prometheus، cert-manager، Nginx Ingress) في دقائق بدلاً من كتابة وصيانة ملفات manifest من الصفر.
تثبيت Helm
أزال Helm 3 (الإصدار الرئيسي الحالي، الصادر في نوفمبر 2019) مكوّن Tiller من جانب الخادم الذي كان يُسبّب كوارث في إعدادات RBAC في Helm 2. كل تثبيت لـ Helm 3 هو من جانب العميل فقط ويستخدم بيانات اعتماد kubeconfig المحلية مباشرةً.
بعد تثبيت Helm وإعداد kubeconfig للإشارة إلى كلاسترك، أنت مستعد للانتقال من فهم مشكلة التعبئة إلى كتابة أول Chart خاص بك في الدرس الثالث. يتناول الدرس الثاني استهلاك Charts المجتمعية الجاهزة — أسرع طريقة لبناء الحدس حول تشريح الـ Chart قبل تأليف درسك الخاص.