القوة الحقيقية لـ Helm تكمن في نظام قوالبه. كل ملف داخل templates/ يُعالَج عبر حزمة text/template في لغة Go، مُعزَّزةً بمكتبة Sprig للدوال إضافةً إلى الدوال المدمجة في Helm. فهم هذا المحرّك بعمق يُفرّق بين من يكتب Charts هشّة ومن يكتب charts قابلة لإعادة الاستخدام وجاهزة للإنتاج. يتناول هذا الدرس نموذج التنفيذ الكامل: كيف تتدفق القيم، وكيف تُحوّلها الدوال والخطوط الأنبوبية، وكيف تُتيح التعابير الشرطية والحلقات لقالب واحد التكيّف مع كل بيئة.
سياق تنفيذ القالب
كل قالب Helm يُنفَّذ ضمن كائن جذر يُسمّى . (النقطة). هذا الكائن هو مزيج من عدة فضاءات أسماء يملؤها Helm قبل بدء التصيير:
.Values — الناتج المدمج من values.yaml بالإضافة إلى كل ملف --values وكل علامة --set، بترتيب الأولوية (الأخير يكسب).
.Chart — بيانات التعريف من Chart.yaml: .Chart.Name و.Chart.Version و.Chart.AppVersion.
.Release — حالة الإصدار عند التشغيل: .Release.Name و.Release.Namespace و.Release.IsInstall و.Release.IsUpgrade.
.Files — الوصول إلى الملفات غير القوالب المضمّنة في الـ chart (ملفات الإعداد والشهادات).
يدمج Helm جميع المدخلات في سياق جذر واحد (النقطة) ويمرّره عبر محرّك قوالب Go لإنتاج Kubernetes manifests مُصيَّرة.
تحذير تغيير النطاق: عند الدخول في حلقة range أو كتلة with، تُعاد تعيين النقطة . للعنصر أو القيمة الحالية. للوصول إلى اسم الإصدار الخارجي داخل الحلقة، استخدم $.Release.Name — فالبادئة $ تشير دائماً إلى الكائن الجذر بصرف النظر عن النطاق.
القيم — الواجهة العامة للـ Chart
values.yaml ليس مجرد ملف قيم افتراضية — إنه الواجهة الموثَّقة للـ chart. كل مفتاح فيه هو ضبطة يمكن للمشغّلين تجاوزها. صمّمه كما تُصمّم توقيع دالة برمجية: أسماء واضحة، وقيم افتراضية منطقية، ومجمّعة حسب الغرض.
الإشارة إلى القيم في القالب بسيطة: {{ .Values.replicaCount }}. وللمفاتيح المتداخلة: {{ .Values.image.repository }}. يُصيّر Helm القالب كاملاً قبل تطبيقه، لذا يؤدي خطأ مطبعي في مرجع قيمة إلى خطأ وقت التصيير — لا خطأ صامتاً عند التشغيل.
الدوال والخطوط الأنبوبية
يشحن Helm أكثر من 70 دالة من Sprig بالإضافة إلى إضافاته الخاصة. الفكرة الجوهرية هي أنها تتركّب عبر الخطوط الأنبوبية — نموذج Unix pipe مُطبَّق على بيانات القوالب. يصبح خرج دالة ما آخر وسيطة للدالة التالية.
# في ملف قالب — أنماط الدوال الشائعة
# quote: يُحيط القيمة بعلامات اقتباس مزدوجة (مطلوب لقيم env var النصية)
env:
- name: APP_ENV
value: {{ .Values.appEnv | quote }}
# default: قيمة احتياطية عندما تكون القيمة فارغة
image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
# upper / lower / title — تحويلات نصية
- name: LOG_LEVEL
value: {{ .Values.logLevel | upper | quote }}
# toYaml + nindent — أهم خط أنبوبي في Helm
# تفريغ قيمة معقدة (خريطة أو قائمة) كـ YAML مُعاق في المكان
resources:
{{ toYaml .Values.resources | nindent 10 }}
# tpl — تقييم قيمة نصية كقالب (مفيد لبناء روابط URL)
annotations:
"external-dns.alpha.kubernetes.io/hostname": {{ tpl .Values.ingress.host . | quote }}
# include + nindent (للقوالب المُسمّاة — يُغطّى في الدرس الخامس)
metadata:
labels:
{{ include "myapp.labels" . | nindent 4 }}
# sha256sum — حقن تعليق توقيعي لإعادة تشغيل الـ pods عند تغيير configmap
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
نمط إنتاجي — إعادة تشغيل الـ Pod الإجباري عند تغيير ConfigMap: لا تُعيد Kubernetes تشغيل الـ Pods عند تغيير ConfigMap. تُشفّر حيلة sha256sum محتوى ConfigMap المُصيَّر في تعليق مواصفات الـ Pod داخل الـ Deployment. أي تغيير في ConfigMap يُغيّر التجزئة، مما يُغيّر مواصفة الـ Pod، وتعامل Kubernetes ذلك كتحديث متدرّج. هذه ممارسة شبه عالمية في Charts الناضجة.
فخ شائع — الخلط بين nindent وindent: تُضيف indent N مسافة N لكل سطر من مدخلها دون إضافة سطر جديد في البداية. أما nindent N فتُضيف سطراً جديداً أولاً ثم تُعيق. في YAML، المسافات الزائدة أو الناقصة تُفسد البنية بصمت. استخدم دائماً nindent بعد مفتاح يتوقع كتلة، واستخدم toYaml | nindent X بدلاً من تنسيق القيم المتداخلة يدوياً.
التعابير الشرطية
تستخدم الشروط في Helm صيغة if / else if / else / end الخاصة بقوالب Go. الشرط كاذب في هذه الحالات: false و0 والسلسلة الفارغة وnil والقائمة الفارغة والخريطة الفارغة. كل شيء آخر صحيح.
# templates/ingress.yaml — تصيير شرطي للمورد بأكمله
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "myapp.fullname" . }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
rules:
- host: {{ .Values.ingress.host | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ include "myapp.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- if .Values.ingress.tls }}
tls:
{{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
{{- end }}
الشرطة - داخل المحدّدات ({{- و-}}) تحذف المسافات البيضاء والأسطر الجديدة من الجانب المعني. هذا أمر بالغ الأهمية: بدونها، تترك الكتل الشرطية أسطراً فارغة في YAML المُصيَّر قد تُربك المُحلّلات الصارمة أو تُنتج فروقات محيّرة في أدوات GitOps.
كتلة with هي صيغة مركّزة من if — إذ تحمي من القيم الفارغة وتُعيد تعيين . للقيمة في آن واحد، مما يُزيل التكرار:
# templates/deployment.yaml — كتلة with للتعليقات الاختيارية
metadata:
name: {{ include "myapp.fullname" . }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
# مكافئ لكن أكثر تطويلاً:
# {{- if .Values.podAnnotations }}
# annotations:
# {{- toYaml .Values.podAnnotations | nindent 4 }}
# {{- end }}
# شرط قائم على Capabilities — إنتاج HPA فقط إن كانت autoscaling API متاحة
{{- if and .Values.autoscaling.enabled (.Capabilities.APIVersions.Has "autoscaling/v2") }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
...
{{- end }}
الحلقات مع range
يُكرّر الإجراء range على القوائم والخرائط. إنه الآلية التي تقف وراء تصيير متغيرات البيئة وتوصيلات الأحجام والحاويات الأولية وأي حقل من نوع قائمة في Kubernetes manifests.
# templates/deployment.yaml — التكرار على قائمة وخريطة
# التكرار على قائمة متغيرات بيئة إضافية (كل عنصر خريطة بها name/value)
# values.yaml: extraEnv: [{name: "FEATURE_X", value: "on"}, {name: "REGION", value: "us-east-1"}]
env:
- name: PORT
value: {{ .Values.service.port | quote }}
{{- range .Values.extraEnv }}
- name: {{ .name | quote }}
value: {{ .value | quote }}
{{- end }}
# التكرار على خريطة — range يمنحك ($key, $val) أو $val فقط
# values.yaml: labels: {team: platform, env: prod}
{{- range $key, $val := .Values.extraLabels }}
{{ $key }}: {{ $val | quote }}
{{- end }}
# حلقة مع فهرس — مفيد حين يهم الترتيب (مثل init containers)
{{- range $i, $container := .Values.initContainers }}
- name: init-{{ $i }}
image: {{ $container.image | quote }}
command: {{ toYaml $container.command | nindent 6 }}
{{- end }}
يُكرّر إجراء range على قائمة في values.yaml ويُصيّر كتلة القالب مرة لكل عنصر، بانياً قائمة YAML النهائية.
تجميع كل شيء — قالب Deployment إنتاجي
القالب التالي تمثيلي لما تجده في chart ناضج وجاهز للإنتاج. يجمع جميع المفاهيم من هذا الدرس: مراجع القيم، وخطوط أنبوبية مع toYaml | nindent، وكتل ذات أعلام ميزات، وفحوصات القدرات، وحلقة range لمتغيرات البيئة.
تنقيح القوالب: استخدم helm template myapp ./mychart --values prod.yaml لتصيير القوالب محلياً دون لمس الكلاستر. أنبّب الناتج عبر | grep -A5 "kind: Deployment" للتركيز على مورد واحد. للفحص العميق، يضرب helm install myapp ./mychart --dry-run --debug API الكلاستر للتحقق لكن لا يُطبّق شيئاً — كما يطبع القيم المحسوبة للتحقق من صحة سلسلة التجاوز.
إتقان محرّك قوالب Helm — تدفق القيم، وخطوط أنبوبية الدوال، والشرطات الحاذفة للمسافات البيضاء، وكتل with وrange وif، والنقطة الجذر مقابل النطاقية — هو ما يُميّز chart يعمل في بيئة واحدة عن chart يُشغّل منصة متعددة المستأجرين ومتعددة البيئات بثقة. يمتدّ الدرس الخامس بهذا الموضوع نحو القوالب المُسمّاة والمساعدات لإزالة التكرار عبر الملفات.
نستخدم ملفات تعريف الارتباط لتشغيل هذا الموقع وتحليل الزيارات وعرض إعلانات مخصّصة. يمكنك قبول كل ملفات تعريف الارتباط أو رفض غير الأساسية منها.
سياسة الخصوصية