Helm وتغليف Kubernetes

التبعيات والـ Subcharts

18 دقيقة الدرس 6 من 28

التبعيات والـ Subcharts

نادراً ما تكون تطبيقات الإنتاج الحقيقية مكتفية بذاتها. يحتاج الـ backend API إلى قاعدة بيانات وطبقة cache وربما وسيط رسائل. يحلّ Helm هذه المشكلة من خلال نظام تبعيات متكامل: تُعلن عمّا يحتاجه الـ chart، يُحضره Helm من المستودعات، وتُثبَّت الحزمة الكاملة وتُرقَّى كوحدة ذرية واحدة. يُعلّمك هذا الدرس آلية عمل تبعيات الـ chart، وكيفية مشاركة القيم بين الـ chart الأب والـ charts الأبناء عبر القيم العامة (global values)، وكيفية تركيب مكدّس متعدد الخدمات باستخدام umbrella chart — النمط الذي تعتمده فرق المنصّات في شركات كـ Shopify وLyft لنشر بيئات كاملة بأمر helm install واحد.

إعلان التبعيات في Chart.yaml

تُعلَن التبعيات في كتلة dependencies داخل Chart.yaml. كل إدخال يحدد اسم الـ chart ونطاق الإصدار ورابط المستودع. بعد تعديل هذه الكتلة، يجب تشغيل helm dependency update — إذ يُحلّل Helm التبعيات ويُنزّلها ويُعبّئها داخل مجلد charts/ كأرشيفات .tgz، ويكتب ملف Chart.lock يُثبّت الإصدارات المُحلَّلة بدقة (يماثل package-lock.json).

# Chart.yaml لـ backend API يعتمد على PostgreSQL وRedis apiVersion: v2 name: backend-api description: Production API service with managed dependencies type: application version: 1.4.0 appVersion: "2.9.1" dependencies: - name: postgresql version: "15.3.x" # نطاق semver — يُحلّ أحدث 15.3.z repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled # يمكن تعطيله عند التثبيت - name: redis version: "19.x.x" repository: "https://charts.bitnami.com/bitnami" condition: redis.enabled - name: common version: "2.x.x" # مكتبة helpers داخلية repository: "https://charts.bitnami.com/bitnami"
# بعد تعديل Chart.yaml شغّل دائماً: helm dependency update ./backend-api # المخرجات: # Hang tight while we grab the latest from your chart repositories... # ...Successfully got an update from the "bitnami" chart repository # Update Complete. Happy Helming! # Saving 3 charts # Downloading postgresql from repo https://charts.bitnami.com/bitnami # Downloading redis from repo https://charts.bitnami.com/bitnami # Downloading common from repo https://charts.bitnami.com/bitnami # Deleting outdated charts ls backend-api/charts/ # common-2.19.1.tgz postgresql-15.3.4.tgz redis-19.6.2.tgz # يُولَّد Chart.lock — احرص على إضافته لـ git لضمان إعادة إنتاج نفس الإصدارات cat backend-api/Chart.lock
احرص دائماً على حفظ Chart.lock في git. يُثبّت Chart.lock الإصدار المُحلَّل بدقة لكل تبعية (بما في ذلك التبعيات المتداخلة). بدونه، قد يُحلّ مهندسان يُشغّلان helm dependency update في أوقات مختلفة إصدارات patches مختلفة — ما يُنتج نشرات متباينة من نفس الـ commit. عامِله كـ go.sum أو yarn.lock.

تمرير القيم إلى الـ Subcharts

بمجرد تنزيل التبعية، تُهيّئها بوضع قيمها تحت مفتاح يطابق اسم الـ chart في ملف values.yaml الأب. يُمرّر Helm تلك القيم إلى الـ subchart تلقائياً — لن يرى الـ subchart قيم الأب على المستوى الأعلى إلا إذا استخدمتَ القيم العامة (global values) التي سنتناولها لاحقاً.

# values.yaml لـ backend-api replicaCount: 3 image: repository: myregistry.io/backend tag: "2.9.1" # قيم الـ subchart: المفتاح يجب أن يطابق اسم التبعية في Chart.yaml postgresql: enabled: true auth: username: api_user password: "" # تجاوَز باستخدام --set أو sealed secret database: api_production primary: persistence: size: 50Gi storageClass: gp3 resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2 memory: 4Gi redis: enabled: true auth: enabled: true password: "" replica: replicaCount: 2 master: persistence: size: 8Gi

داخل قوالب الـ chart الأب، تستخدم اسم Service الذي يُولّده الـ subchart لربط الاتصال. النمط الأكثر أمانًا هو كشف اسم المضيف كقيمة يقرؤها تطبيقك:

# templates/deployment.yaml (الـ chart الأب) env: - name: DATABASE_HOST value: "{{ .Release.Name }}-postgresql.{{ .Release.Namespace }}.svc.cluster.local" - name: REDIS_HOST value: "{{ .Release.Name }}-redis-master.{{ .Release.Namespace }}.svc.cluster.local" - name: DATABASE_NAME value: {{ .Values.postgresql.auth.database | quote }}

القيم العامة (Global Values)

افتراضياً يكون الـ subchart معزولاً: يرى فقط القيم الموضوعة تحت مفتاحه الخاص. تكسر القيم العامة هذا العزل بشكل مقصود — أي قيمة توضع تحت مفتاح global: في الأب تصبح مرئية لكل الـ subcharts وللأب نفسه دون أي عزل. هذه هي الطريقة المعيارية لمشاركة الإعدادات المشتركة كسجل الصور واسم البيئة ومنطقة الكلاستر.

Global values flow in parent and subchart Parent Chart: backend-api global: imageRegistry: myregistry.io environment: production storageClass: gp3 clusterRegion: us-east-1 Parent Values replicaCount: 3 image.tag: 2.9.1 postgresql.auth.database: api_prod Subchart: postgresql sees global.imageRegistry sees global.storageClass sees postgresql.auth.* does NOT see replicaCount Subchart: redis sees global.imageRegistry sees global.storageClass sees redis.auth.* does NOT see replicaCount
تتدفق القيم العامة تلقائياً إلى كل الـ subcharts؛ بينما تبقى القيم المحددة للأب معزولة عن الأبناء.
# values.yaml — كتلة global تُحقَن في كل subchart global: imageRegistry: myregistry.io # تدعم charts Bitnami هذا المفتاح تلقائياً imagePullSecrets: - name: regcred storageClass: gp3 environment: production postgresql: enabled: true image: tag: "16.3.0-debian-12-r14" auth: username: api_user database: api_production existingSecret: backend-api-db-creds # مرجع إلى Secret مُدار خارجياً redis: enabled: true auth: existingSecret: backend-api-redis-creds existingSecretPasswordKey: redis-password
لا تضع كلمات المرور بنص صريح في values.yaml المحفوظ في git. استخدم existingSecret للإشارة إلى Kubernetes Secret مُدار خارج Helm (عبر Sealed Secrets أو External Secrets Operator أو AWS Secrets Manager CSI driver). يفصل هذا النمط دورة حياة السر عن دورة حياة الـ chart — حدود أمنية بالغة الأهمية حين تُخزَّن الـ charts في مستودعات عامة أو شبه عامة.

الـ Umbrella Charts

يُعدّ الـ umbrella chart (ويُسمى أيضاً "meta chart" أو "app of apps") chart غايته الوحيدة تجميع وتهيئة مجموعة من الـ subcharts. يحتوي على محتوى ضئيل أو معدوم في مجلد templates/ الخاص به — إذ يوجد فقط لإعلان التبعيات وتوفير ملف قيم واحد يُهيّئ المكدّس بأكمله. هكذا تنشر فرق المنصّات على نطاق واسع بيئات كاملة: أمر helm install platform ./umbrella واحد يُشغّل الـ API والعمال وقاعدة البيانات والـ cache والمراقبة في عملية ذرية واحدة.

# هيكل الـ umbrella chart platform-umbrella/ ├── Chart.yaml # يُعلن جميع subcharts الخدمات كتبعيات ├── Chart.lock # الإصدارات المُثبَّتة — احرص دائماً على حفظه في git ├── values.yaml # القيم الافتراضية لجميع الـ subcharts ├── values-dev.yaml # تخصيصات بيئة التطوير ├── values-prod.yaml # تخصيصات بيئة الإنتاج ├── charts/ # الـ subcharts المنزَّلة .tgz (مُدرجة في .gitignore أو محفوظة) │ ├── backend-api-1.4.0.tgz │ ├── frontend-2.1.0.tgz │ ├── worker-1.1.3.tgz │ └── postgresql-15.3.4.tgz └── templates/ # فارغ عادةً، أو يحتوي فقط على NOTES.txt └── NOTES.txt
# platform-umbrella/Chart.yaml apiVersion: v2 name: platform-umbrella description: Full platform stack for the payments product type: application version: 4.2.0 dependencies: - name: backend-api version: "1.4.x" repository: "oci://myregistry.io/helm" # مستودع OCI (ECR/GCR) condition: backend-api.enabled - name: worker version: "1.1.x" repository: "oci://myregistry.io/helm" condition: worker.enabled - name: frontend version: "2.1.x" repository: "oci://myregistry.io/helm" condition: frontend.enabled - name: postgresql version: "15.3.x" repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled - name: redis version: "19.x.x" repository: "https://charts.bitnami.com/bitnami" condition: redis.enabled - name: kube-prometheus-stack version: "58.x.x" repository: "https://prometheus-community.github.io/helm-charts" condition: monitoring.enabled
# نشر المنصّة بالكامل إلى الإنتاج بأمر واحد helm dependency update ./platform-umbrella helm upgrade --install platform ./platform-umbrella \ --namespace platform-prod \ --create-namespace \ --values platform-umbrella/values.yaml \ --values platform-umbrella/values-prod.yaml \ --set global.imageTag="${CI_COMMIT_SHA}" \ --atomic \ --timeout 10m \ --wait # تعطيل المراقبة في بيئة تطوير خفيفة: helm upgrade --install platform ./platform-umbrella \ --values platform-umbrella/values-dev.yaml \ --set monitoring.enabled=false \ --set postgresql.primary.persistence.size=5Gi

الـ Alias والـ Tags

أحياناً تحتاج إلى تثبيت نفس الـ chart مرتين كـ subcharts مختلفين — مثلاً قاعدتا بيانات PostgreSQL منفصلتان لخدمتين مختلفتين. استخدم حقل alias لإعطاء كل نسخة اسماً فريداً يصبح المفتاح الذي تستخدمه في values.yaml:

# Chart.yaml — نسختان من PostgreSQL بـ aliases dependencies: - name: postgresql alias: userdb version: "15.3.x" repository: "https://charts.bitnami.com/bitnami" - name: postgresql alias: analyticsdb version: "15.3.x" repository: "https://charts.bitnami.com/bitnami" # values.yaml — تهيئة كل alias بشكل مستقل userdb: auth: database: users username: user_service primary: persistence: size: 20Gi analyticsdb: auth: database: analytics username: analytics_service primary: persistence: size: 200Gi storageClass: io2 # تخزين عالي IOPS للتحليلات
فخ إنتاجي — قِدَم cache الـ dependency chart. يُملأ مجلد charts/ بواسطة helm dependency update. إن حفظتَ ملفات .tgz في git، قد تتباعد عن Chart.lock حين يُحدّث أحد أفراد الفريق التبعيات دون إعادة حفظ الأرشيفات. النمط الآمن في CI هو: لا تحفظ مطلقاً charts/*.tgz في git (أضفها إلى .helmignore)، وشغّل دائماً helm dependency build (أسرع من update — يستخدم Chart.lock دون إعادة الحلّ) في pipeline CI قبل helm upgrade. هذا يضمن أن كل بناء يستخدم الإصدارات المُثبَّتة بدقة.

تجميع كل شيء — نمط CI Pipeline

يبدو pipeline CI الإنتاجي لـ umbrella chart كالتالي:

# .github/workflows/deploy.yml (الخطوات ذات الصلة فقط) - name: Add Helm repos run: | helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update - name: Build dependencies (يستخدم Chart.lock، بلا حلّ شبكي) run: helm dependency build ./platform-umbrella - name: Lint chart run: helm lint ./platform-umbrella --values values-prod.yaml - name: Dry-run render (اكتشاف أخطاء القالب قبل لمس الكلاستر) run: | helm upgrade --install platform ./platform-umbrella \ --values values-prod.yaml \ --set global.imageTag="${{ github.sha }}" \ --dry-run --debug \ --namespace platform-prod \ 2>&1 | tee helm-dry-run.log - name: Deploy run: | helm upgrade --install platform ./platform-umbrella \ --values values-prod.yaml \ --set global.imageTag="${{ github.sha }}" \ --atomic --timeout 10m \ --namespace platform-prod
استخدم helm dependency build في CI، وليس helm dependency update. يقرأ build ملف Chart.lock وينزّل تلك الإصدارات بدقة دون الاتصال بخوادم المستودعات لإعادة الحلّ. هذا أسرع وحتمي ويمنع رفع إصدار مفاجئ إن أصدر أحد الـ charts الخارجية patch جديداً بين عمليتَي CI.

بإتقان التبعيات والقيم العامة والـ umbrella charts، أصبح بحوزتك مجموعة الأدوات التركيبية الكاملة لإدارة مكدّسات الإنتاج المعقّدة. يتناول الدرس التالي الـ hooks والـ tests — كيفية تشغيل migrations قواعد البيانات واختبارات الدخان وفحوصات الاستعداد كجزء لا يتجزأ من دورة حياة إصدار Helm.