رسومات Helm: إدارة حزم Kubernetes

نشرات Kubernetes باستخدام إدارة الحزم Helm

أعاد Helm تجربة نشر تطبيقات Kubernetes من خلال تقديم مفاهيم إدارة الحزم المألوفة من أنظمة التشغيل التقليدية.

مع نمو اعتماد Kubernetes، تصبح إدارة التطبيقات المعقدة التي تحتوي على مئات الملفات YAML تحديًا. تحل Charts الخاصة بـ Helm هذه المشكلة من خلال تجميع جميع الموارد في حزم قابلة للتخصيص ومُنسقة.

مطور برمجيات في الطبيعة هذا الصورة الرائعة تُولَّد بواسطة نموذج الذكاء الاصطناعي Flux 1 dev.

فهم Helm: مدير الحزم في Kubernetes

Helm هو ما يشبه apt بالنسبة لـ Debian، أو yum بالنسبة لـ RedHat، أو Homebrew بالنسبة لـ macOS. يقوم بحزم تطبيقات Kubernetes إلى Charts – مجموعات من الملفات التي تصف الموارد المرتبطة بـ Kubernetes. يمكن أن يقوم Chart واحد بنشر تطبيق كامل: خوادم ويب، قواعد بيانات، طبقات التخزين المؤقت، قواعد الدخول، ومكونات المراقبة. بالنسبة للأشخاص الجدد على Kubernetes، يوفر قائمة الأوامر الأساسية لـ Kubernetes الأوامر وال念 الأساسية للبدء.

لماذا يهم Helm في DevOps الحديث

تقليل التعقيد: بدلًا من إدارة 20+ ملف YAML، تُدار Chart واحدة مع قيم قابلة للتخصيص.

القابلية للتكرار: يمكن نشر التكوينات نفسها عبر البيئات المختلفة (التطوير، التصحيح، الإنتاج) مع تجاوزات القيم المخصصة لكل بيئة. هذا يصبح مفيدًا بشكل خاص عند نشر معمارية ميكرو خدمات معقدة حيث تهم القابلية للتكرار.

التحكم في الإصدار: يتم ترقيم Charts، مما يسمح بسهولة التراجع والتعقب عند التحديث.

البيئة المجتمعية: تتوفر آلاف Charts الجاهزة عبر Artifact Hub (سابقًا Helm Hub) لتطبيقات شائعة مثل PostgreSQL، Redis، NGINX، Prometheus، وغيرها.

قوة النمذجة: تسمح نماذج Go بإنشاء موارد ديناميكية بناءً على القيم المدخلة، مما يقلل من التكرار.

بنية Helm وفكرة أساسية

بنية Helm 3

تبسيطت بنية Helm 3 من خلال إزالة Tiller، المكون الخادم الذي كان م有问题 في Helm 2:

  • Helm Client: أداة CLI تتفاعل مباشرة مع واجهة برمجة التطبيقات لـ Kubernetes
  • Chart: تنسيق الحزمة يحتوي على النماذج والمعلومات
  • Release: نسخة من Chart تعمل داخل كластر Kubernetes
  • Repository: موقع تخزين Charts (خادم HTTP أو سجل OCI)

المكونات الأساسية لـ Helm Chart

my-app-chart/
├── Chart.yaml          # معلومات Chart ورقم الإصدار
├── values.yaml         # القيم الافتراضية للتكوين
├── charts/             # Charts التابعة
├── templates/          # نماذج الموارد لـ Kubernetes
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── _helpers.tpl    # مساعدي النماذج
│   └── NOTES.txt       # ملاحظات بعد التثبيت
├── .helmignore         # الملفات التي يجب تجاهلها عند التعبئة
├── README.md
└── LICENSE

إنشاء Chart Helm الخاص بك

تهيئة Chart جديد

helm create my-application
cd my-application

هذا يولد Chart نموذجيًا مع نماذج مثالية لـ deployment، service، و ingress.

Chart.yaml: تعريف البيانات

apiVersion: v2
name: my-application
description: Chart تطبيق جاهز للإنتاج
type: application
version: 1.0.0        # إصدار Chart
appVersion: "2.4.1"   # إصدار التطبيق

maintainers:
  - name: فريقك
    email: team@company.com

dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

values.yaml: إدارة التكوين

يحدد ملف values.yaml القيم الافتراضية التي يمكن للمستخدمين تجاوزها. هذا النهج يفصل التكوين عن النماذج، مما يجعل إدارة البيئات المختلفة (التطوير، التصحيح، الإنتاج) وتعديل النشر بدون تعديل ملفات النماذج سهلًا.

replicaCount: 3

image:
  repository: myapp/backend
  tag: "1.0.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: "nginx"
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: myapp.example.com
      paths:
        - path: /
          pathType: Prefix

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 250m
    memory: 256Mi

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

النماذج: مانيفستات Kubernetes الديناميكية

تستخدم النماذج لغة النمذجة Go لإنشاء موارد Kubernetes ديناميكياً. يمكن لهذه النماذج إنشاء أي نوع من موارد Kubernetes، من Deployments البسيطة إلى StatefulSets المعقدة لتطبيقات تتطلب تخزينًا مستقرًا. للتطبيقات التي تحتاج إلى هويات مستقرة وتخزين مستقر، ستحتاج إلى استخدام StatefulSets بدلًا من Deployments، كما تتم تفاصيل ذلك في دليلنا حول StatefulSets وتخزين البيانات المستقرة في Kubernetes.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-application.fullname" . }}
  labels:
    {{- include "my-application.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "my-application.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-application.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: 8080
          protocol: TCP
        resources:
          {{- toYaml .Values.resources | nindent 10 }}

مساعدي النماذج (_helpers.tpl)

أنشئ وظائف قابلة لإعادة الاستخدام لتجنب التكرار:

{{/*
توسيع اسم Chart.
*/}}
{{- define "my-application.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
إنشاء اسم تطبيق كامل بشكل افتراضي.
*/}}
{{- define "my-application.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}

{{/*
العلامات الشائعة
*/}}
{{- define "my-application.labels" -}}
helm.sh/chart: {{ include "my-application.chart" . }}
{{ include "my-application.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

إدارة Charts Helm: التثبيت والتشغيل

تثبيت Chart

# تثبيت من مستودع
helm install my-release bitnami/postgresql

# تثبيت من دليل محلي
helm install my-app ./my-application

# تثبيت مع قيم مخصصة
helm install my-app ./my-application -f values-production.yaml

# تثبيت مع تجاوزات قيم مدمجة
helm install my-app ./my-application \
  --set replicaCount=5 \
  --set image.tag=2.0.0

تحديث الإصدارات

# تحديث مع قيم جديدة
helm upgrade my-app ./my-application -f values-production.yaml

# تحديث مع تراجع تلقائي في حالة الفشل
helm upgrade my-app ./my-application --atomic --timeout 5m

# إجبار تحديث الموارد
helm upgrade my-app ./my-application --force

التراجع والسجل

# عرض سجل الإصدار
helm history my-app

# التراجع إلى الإصدار السابق
helm rollback my-app

# التراجع إلى إصدار محدد
helm rollback my-app 3

الاختبار والتصحيح

# تشغيل جاف لرؤية المانيفستات المُولَّدة
helm install my-app ./my-application --dry-run --debug

# عرض النماذج دون تثبيت
helm template my-app ./my-application

# فحص Chart للحصول على مشاكل
helm lint ./my-application

# اختبار الإصدار مع م-hooks
helm test my-app

ميزات Helm المتقدمة

اعتمادات Chart

يمكن لـ Charts Helm أن تعتمد على Charts أخرى، مما يسمح لك بتركيب تطبيقات معقدة من مكونات قابلة لإعادة الاستخدام. هذا مفيد بشكل خاص عند نشر ميكرو خدمات تحتاج إلى قواعد بيانات، أو طوابير الرسائل، أو خدمات داعمة أخرى. اعرِض الاعتماديات في Chart.yaml:

dependencies:
  - name: redis
    version: "17.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

تحديث الاعتماديات:

helm dependency update ./my-application

م-hooks Helm لإدارة دورة الحياة

تُنفَّذ م-hooks في نقاط محددة من دورة حياة الإصدار:

apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "my-application.fullname" . }}-db-migration
  annotations:
    "helm.sh/hook": pre-upgrade,pre-install
    "helm.sh/hook-weight": "5"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      containers:
      - name: db-migrate
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        command: ["python", "manage.py", "migrate"]
      restartPolicy: Never

أنواع م-hooks تشمل:

  • pre-install: قبل تثبيت الموارد
  • post-install: بعد تثبيت جميع الموارد
  • pre-upgrade: قبل التحديث
  • post-upgrade: بعد التحديث
  • pre-delete: قبل الحذف
  • post-delete: بعد الحذف
  • pre-rollback: قبل التراجع
  • post-rollback: بعد التراجع

المنطق الشرطي والتحكم في التدفق

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "my-application.fullname" . }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  {{- if .Values.ingress.className }}
  ingressClassName: {{ .Values.ingress.className }}
  {{- end }}
  rules:
  {{- range .Values.ingress.hosts }}
  - host: {{ .host | quote }}
    http:
      paths:
      {{- range .paths }}
      - path: {{ .path }}
        pathType: {{ .pathType }}
        backend:
          service:
            name: {{ include "my-application.fullname" $ }}
            port:
              number: {{ $.Values.service.port }}
      {{- end }}
  {{- end }}
{{- end }}

دعم مستودع OCI: توزيع Chart الحديث

منذ Helm 3.8، أصبح دعم مستودع OCI (Open Container Initiative) مستقرًا، مما يسمح بتخزين Charts بجانب صور الحاويات.

نشر إلى مستودع OCI

# تسجيل الدخول إلى المستودع
helm registry login registry.example.com

# تعبئة Chart
helm package ./my-application

# دفع إلى مستودع OCI
helm push my-application-1.0.0.tgz oci://registry.example.com/charts

# تثبيت من مستودع OCI
helm install my-app oci://registry.example.com/charts/my-application --version 1.0.0

فوائد مستودعات OCI

  • تخزين موحد: Charts والصور في مكان واحد
  • أدوات معيارية: استخدام البنية التحتية الموجودة للمستودع
  • الأمان الأفضل: الاستفادة من مصادقة المستودع والفحص
  • إدارة أبسط: لا حاجة لخادم مستودع Chart منفصل

أفضل الممارسات لـ Charts Helm في الإنتاج

1. بنية القيم والتوثيق

وثّق جميع القيم مع التعليقات:

# -- عدد النسخ الاحتياطية للتطبيق
replicaCount: 3

# -- تكوين الصورة
image:
  # -- مستودع الصورة
  repository: myapp/backend
  # -- سياسة سحب الصورة
  pullPolicy: IfNotPresent
  # -- إصدار الصورة (يُحدد افتراضيًا إلى إصدار Chart appVersion)
  tag: ""

2. إدارة الموارد

حدد دائمًا طلبات وحدود الموارد:

resources:
  limits:
    cpu: 1000m
    memory: 1Gi
  requests:
    cpu: 500m
    memory: 512Mi

3. سياقات الأمان

حدد سياقات الأمان للحاويات:

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 1000
  capabilities:
    drop:
    - ALL
  readOnlyRootFilesystem: true

4. فحوصات الصحة

أضف فحوصات التفاعل والجاهزية:

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

5. إدارة ConfigMap وSecrets

إدارة Secrets بشكل صحيح ضرورية للنشر في الإنتاج. استخدم أدوات إدارة Secrets الخارجية (مثل Sealed Secrets، External Secrets Operator، أو Vault) بدلًا من تخزين Secrets في ملفات القيم. هذا يضمن معالجة البيانات الحساسة مثل كلمات مرور قواعد البيانات، مفاتيح API، والشهادات بشكل آمن:

envFrom:
- secretRef:
    name: {{ include "my-application.fullname" . }}-secrets
- configMapRef:
    name: {{ include "my-application.fullname" . }}-config

6. التحقق من صحة المخطط

أنشئ ملف values.schema.json لفحص إدخالات المستخدم:

{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1
    },
    "image": {
      "type": "object",
      "properties": {
        "repository": {
          "type": "string"
        },
        "tag": {
          "type": "string"
        }
      },
      "required": ["repository"]
    }
  },
  "required": ["image"]
}

7. ملف NOTES.txt لتقديم الإرشادات للمستخدم

قدم تعليمات ما بعد التثبيت:

1. احصل على عنوان URL للتطبيق عن طريق تشغيل:
{{- if .Values.ingress.enabled }}
  https://{{ (index .Values.ingress.hosts 0).host }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "my-application.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- end }}

2. مراقبة النشر:
  kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/name={{ include "my-application.name" . }}"

اختبار Charts Helm والتكامل مع CI/CD

اختبار Charts مع chart-testing (ct)

# تثبيت chart-testing
brew install chart-testing

# فحص Charts
ct lint --config ct.yaml

# تثبيت واختبار Charts
ct install --config ct.yaml

مثال GitHub Actions

name: Helm Chart CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lint-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: إعداد Helm
        uses: azure/setup-helm@v3
        with:
          version: 3.12.0

      - name: إعداد chart-testing
        uses: helm/chart-testing-action@v2

      - name: فحص Charts
        run: ct lint --config ct.yaml

      - name: إنشاء كластر kind
        uses: helm/kind-action@v1

      - name: تثبيت Charts
        run: ct install --config ct.yaml

GitOps مع Helm: ArgoCD و Flux

أدوات GitOps مثل ArgoCD و Flux تتكامل بسلاسة مع Charts Helm، مما يسمح بتشغيل نشرات تلقائية ومعلنة. تراقب هذه الأدوات مستودع Git الخاص بك للحصول على التغييرات وتنسق تلقائيًا إصدارات Helm، مما يجعل النشر المستمر سهلًا. للعمليات المعقدة في معمارية ميكرو خدمات، فكّر في كيفية استخدام أنماط المعاملات الموزعة مثل أنماط Saga لضمان التوافق عبر الخدمات المُنشرة عبر Helm.

تطبيق ArgoCD

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-application
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/my-app-chart
    targetRevision: main
    path: charts/my-application
    helm:
      valueFiles:
        - values-production.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

HelmRelease من Flux

apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: my-application
  namespace: flux-system
spec:
  interval: 5m
  chart:
    spec:
      chart: my-application
      version: '1.x.x'
      sourceRef:
        kind: HelmRepository
        name: my-charts
  values:
    replicaCount: 5
    image:
      tag: "2.0.0"

حل مشاكل Helm الشائعة

المشكلة: تحديث فشل وتوقف في الانتظار

# تحقق من حالة الإصدار
helm list --all-namespaces

# الحصول على تفاصيل الإصدار
helm status my-app -n namespace

# حذف إجباري إذا لزم الأمر (استخدم بحذر)
kubectl delete secret -n namespace -l owner=helm,name=my-app

المشكلة: أخطاء في توليد النماذج

# تصحيح توليد النماذج
helm template my-app ./my-application --debug

# التحقق من Kubernetes
helm template my-app ./my-application | kubectl apply --dry-run=client -f -

المشكلة: القيم لم تُطبَّق

# تحقق من القيم المدمجة
helm get values my-app

# عرض جميع القيم المحسوبة
helm get values my-app --all

البيئة Helm والأدوات

تشمل بيئة Helm أدوات عديدة تمتد من قدراتها وتتكامل مع تقنيات Kubernetes الأخرى. عند نشر تطبيقات تتطلب ميزات شبكة متقدمة مثل الاتصال بين الخوادم، إدارة المرور، والسياسات الأمنية، فكّر في دمجها مع شبكة خدمة مع Istio و Linkerd، والتي يمكن نشرها وإدارتها عبر Charts Helm.

أدوات أساسية

  • Helmfile: مواصفة إعلانية لنشر Charts Helm
  • Helm Diff: معاينة التغييرات قبل التحديث
  • Helm Secrets: إدارة السرّيات مع SOPS
  • Nova: العثور على Charts Helm القديمة
  • Pluto: اكتشاف APIs Kubernetes القديمة

مثال Helmfile

repositories:
  - name: bitnami
    url: https://charts.bitnami.com/bitnami

releases:
  - name: postgresql
    namespace: database
    chart: bitnami/postgresql
    version: 12.x.x
    values:
      - postgresql:
          auth:
            database: myapp
            username: appuser

  - name: my-app
    namespace: production
    chart: ./charts/my-application
    values:
      - values-production.yaml
    needs:
      - database/postgresql

مستقبل Helm

تستمر بيئة Helm في التطور:

  • OCI-Native: الانتقال الكامل إلى مستودعات OCI كالمعيار
  • الأمان المحسّن: إدارة السرّيات ووظائف التوقيع بشكل أفضل
  • الأداء: تحسين سرعة توليد ونشر Charts الكبيرة
  • دعم WASM: WebAssembly لـ Chart Plugins والتوسعات
  • التحقق من الصحة المحسّن: تحقق محسن من المخططات وفرض السياسات

الخاتمة

أصبح Helm المعيار المقبول لإدارة الحزم في Kubernetes، ومعرفته ضرورية لممارسات DevOps الحديثة. من خلال فهم بنية Chart، النمذجة، إدارة القيم، والممارسات الجيدة، يمكنك إنشاء نشرات Kubernetes قابلة للصيانة، آمنة، وقابلة للتوسع.

ابدأ بـ Charts بسيطة، وقم تدريجيًا بدمج ميزات متقدمة مثل Hooks والاعتماديات، ودمجها مع أدوات GitOps للبنية التحتية من الدرجة الأولى. توفر مجتمع Helm آلاف Charts الجاهزة، ولكن القوة الحقيقية تأتي من إنشاء Charts مخصصة تتناسب مع احتياجات منظمةك. سواء كنت تنشر تطبيقات لا تُحتاج إلى تخزين مستقر أو تحميلات تتطلب تخزينًا مستقرًا، فإن Helm تبسيط تعقيد إدارة موارد Kubernetes. للفرق التي تنشئ كластرات Kubernetes جديدة، فكّر في تثبيت Kubernetes مع Kubespray أو استكشاف توزيعات Kubernetes مثل k3s أو MicroK8s لبيئات التطوير. إذا كنت تقيّم أي توزيع يناسب احتياجاتك في مختبر منزلي أو كластر صغير، راجع مراجعتنا الشاملة لـ مقارنة توزيعات Kubernetes للتحليل التفصيلي.

روابط مفيدة