توليد الأساس (Baseline) من git

يعلن الأساس (Baseline) خدماته إما مضمَّنة في spec.services أو يشير إلى مستودع في spec.source. وحين يوجد مصدر يستنسخ المشغّل المستودع. ثم يولّد (render) تعريف النشر ويستخلص منه قائمة الخدمات. وتعمل المدخلات المضمَّنة حينها تجاوزاتٍ لكل خدمة بحسب اسمها.

spec:
  application: shop
  source:
    url: https://git.acme.internal/retail/shop.git
    ref: release/2026.09        # branch, tag or commit sha
    path: deploy/chart
    kind: helm                  # helm | kustomize | manifests
    secretRef: {name: shop-git}
    helm:
      valuesFiles: [values-prod.yaml]
      values: {logLevel: info}
    pollInterval: 5m            # optional; re-resolve the ref this often
  services:
    - name: shop-postgres       # override: rendered as StatefulSet, keep it shared
      shared: true

Secret بيانات الاعتماد

المفتاح الاستخدام
token رمز وصول (token) لـ HTTPS أو كلمة مرور. username اختياري وقيمته الافتراضية nezal.
ssh-privatekey مفتاح SSH. known_hosts مطلوب. passphrase اختياري.
ca.crt حزمة PEM لجهة إصدار شهادات خاصة يستخدمها خادم git.

لا يتصل المشغّل بأي جهة سوى خادم git هذا.

الصيغ

Docker Compose ليس صيغة مدعومة. فملف compose يصف حاسوبًا محمولًا ويُغفل معظم ما يحتاجه الكلستر. وكان تحويله يعني التخمين. صِف التطبيق مخططَ Helm أو طبقة Kustomize أو ملفات manifests عادية. والأساس الذي ما زال من نوع compose يذكر ذلك في حالته ولا ينشر شيئًا جديدًا.

كيف تتحول كائنات Kubernetes إلى خدمات

كل Service يختار Deployment أو StatefulSet يصبح خدمة واحدة في نزال تحمل اسم ذلك الـ Service. وتأتي الصورة والأمر والوسائط (args) ومتغيرات البيئة من الحاوية الأولى. وكذلك الموارد وعدد النسخ (replicas) ومجلد العمل ومعرّف المستخدم الرقمي (uid). ويأتي بروتوكول المنفذ من appProtocol أو من الوسم (annotation) nezal.dev/protocol وإلا فهو http. أما منافذ قواعد البيانات المعروفة فتكون tcp افتراضيًا. والوسم nezal.dev/shared: "true" يجعل الخدمة تبعية مشتركة وكذلك كون الكائن StatefulSet.

فحوص الصحة

يُنقل فحص الجاهزية (readiness probe) الموجود في المصدر كما هو.

لا يُولَّد أي فحص بقاء (liveness probe) أبدًا. ففحص البقاء يعيد تشغيل الـ Pod. والفحص المكتوب للإنتاج أو لحاسوب محمول سيعيد تشغيل بيئة معاينة لم يكتمل بناؤها بلا نهاية. أما فحص الجاهزية فيقرر فقط هل تُرسَل حركة المرور إلى الخدمة وهذا أمر يمكن التعافي منه. وحين لا يعلن عبء العمل إلا فحص بقاء يصبح ذلك الفحص فحص الجاهزية ويشير تحذير إلى ذلك.

وحين لا يوجد أي فحص معلن يستنتج نزال فحص TCP على المنفذ الأول للخدمة. وبهذا لا يصل أول طلب بعد nezal up إلى عملية لم تبدأ الاستماع بعد.

وحدات التخزين والملفات المركَّبة

في المصدر يصبح ملاحظة
emptyDir emptyDir مؤقت. لا يبقى شيء بعد إعادة التشغيل.
configMap أو secret ملف مركَّب يجب أن يكون الكائن موجودًا مسبقًا في مساحة الأسماء.
persistentVolumeClaim emptyDir مع تحذير علّم الخدمة بأنها shared إذا كانت تملك بيانات حقيقية.

وراء هذا الجدول قاعدتان. الأولى أن بيئة المعاينة يُعاد بناؤها من المستودع. والحالة التي تبقى بعد إعادة البناء تجعل البيئة غير قابلة للاستنساخ بدقة. لذلك لا يوفّر نزال لها تخزينًا دائمًا أبدًا. والثانية أن نزال لا ينسخ أبدًا أي مادة سرية من مستودع git إلى الكلستر: فالـ Secret المركَّب هو Secret ينشئه المشرف.

ولا يُنقل ConfigMap أو Secret مركَّب مجلدًا كاملًا لأن مفاتيحه لا تُعرف إلا وقت النشر. اذكر المفاتيح تحت items في المصدر أو استخدم subPath.

لكل Pod مولَّد نظام ملفات جذري للقراءة فقط. لذلك ستفشل أي خدمة تكتب خارج مسار مؤقت معلن. أضف تركيب emptyDir في المصدر للمسارات التي تحتاج إليها.

الترتيب

لا يوجد في Kubernetes ترتيب للبدء. يبدأ كل شيء في الوقت نفسه وتُعاد الخدمة إلى التشغيل حتى تستجيب تبعياتها. ويستقر ذلك عادةً خلال ثوانٍ. أما الخدمة التي تتصل بقاعدة بياناتها مرة واحدة عند البدء ثم تخرج بدل أن تعيد المحاولة فستدخل في حلقة انهيار (crash loop). فاجعل اتصالات البدء تعيد المحاولة.

ما ينبغي النظر إليه

تُعاد محاولة الإخفاقات كل دقيقتين. ويُخزَّن ناتج التوليد مؤقتًا بحسب الإيداع. لذلك لا تؤدي إعادة تشغيل المشغّل أو إعادة تطبيق الأساس نفسه إلى توليد جديد.