GitOps مع ArgoCD وFlux

معمارية Flux

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

معمارية Flux

Flux هو محرك GitOps الثاني الرئيسي لـ Kubernetes، أنشأته Weaveworks (الذين ابتكروا أيضاً مصطلح "GitOps") وهو الآن مشروع CNCF متخرّج. حيث يقدم ArgoCD مستوى تحكم متكاملاً مع واجهة مستخدم غنية، يتبع Flux فلسفة مختلفة جذرياً: مجموعة أدوات قابلة للتركيب من متحكمات صغيرة ومُركّزة، كل منها مسؤولة عن مخاوف واحدة، تتواصل جميعها عبر تعريفات الموارد المخصصة لـ Kubernetes (CRDs). يُعدّ فهم معمارية Flux ضرورياً لأنها تُشكّل أساس بناء خطوط GitOps واسعة النطاق في شركات مثل Weaveworks وGrafana Labs وخدمة GitOps الخاصة بـ Microsoft Azure.

يغطي هذا الدرس عائلات المتحكمات الثلاث التي تُشكّل حلقة تحكم Flux — source وkustomize وhelm — والـ CRDs الذي ستكتبهما يومياً: GitRepository وKustomization.

فلسفة مجموعة الأدوات

Flux ليس ملفاً ثنائياً واحداً. إنه مجموعة من متحكمات Kubernetes — تُسمى GitOps Toolkit — مُثبَّتة كـ Deployments في namespace flux-system. المتحكمات الرئيسية هي:

  • source-controller — يراقب المصادر الخارجية (مستودعات Git وسجلات OCI ومستودعات Helm وحاويات S3) ويجلب محتواها. يُعرض هذا المحتوى كخادم HTTP للقطع الأثرية داخل المجموعة لتستهلكه المتحكمات الأخرى.
  • kustomize-controller — يقرأ CRD باسم Kustomization، يسحب قطعة أثرية من source-controller، يُشغّل kustomize build، ويُطبّق النتيجة على المجموعة. على الرغم من الاسم، يمكنه تطبيق YAML عادي أيضاً — Kustomize اختياري.
  • helm-controller — يقرأ CRD باسم HelmRelease، يسحب قطعة أثرية HelmChart من source-controller، وينفّذ عمليات تثبيت/ترقية/استرجاع Helm. يحل محل الحاجة لتشغيل helm بشكل أمري في خطوط CI.
  • notification-controller — يُوجّه الأحداث من كل المتحكمات الأخرى إلى الأنظمة الخارجية (Slack وTeams وPagerDuty وحالات commit على GitHub والـ webhooks). يُتيح هذا مراقبة غنية دون تلويث متحكمات التوفيق بمنطق الإشعارات.
  • image-reflector-controller + image-automation-controller — يفحصان سجلات الصور بحثاً عن وسوم جديدة ويكتبان تلقائياً مراجع الصور المُحدَّثة إلى مستودع Git. هذا يُغلق الحلقة لخطوط التسليم المؤتمتة بالكامل.
الفهم المعماري الأساسي: كل متحكم في Flux يتحدث عبر CRDs وأحداث Kubernetes. لا يحتفظ أي متحكم بحالة مشتركة خارج etcd. هذا يعني أن كل متحكم يمكن ترقيته أو إعادة تشغيله أو حتى إزالته مؤقتاً دون إفساد الآخرين — خاصية موثوقية جوهرية لا تستطيع المعماريات المتكاملة تقديمها.

تثبيت Flux: أمر Bootstrap

يُحضَّر Flux باستخدام أداة سطر أوامر flux، التي تُنشئ namespace flux-system وتُثبّت كل Deployments للمتحكمات وتُودع المانيفستات الناتجة في مستودع Git — فيُدير Flux نفسه فوراً عبر GitOps.

# تثبيت Flux CLI (macOS / Linux) curl -s https://fluxcd.io/install.sh | sudo bash # التحقق من المتطلبات المسبقة — يفحص إصدار Kubernetes والوصول لخادم API flux check --pre # تمهيد Flux لمستودع GitHub (ينشئ مجلد flux-system/ في المستودع) # Flux ينشئ Deploy Key على المستودع ويخزنه كـ Kubernetes Secret flux bootstrap github \ --owner=my-org \ --repository=gitops-fleet \ --branch=main \ --path=clusters/production \ --personal=false \ --token-auth=false # بعد التمهيد، تحقق من تشغيل كل المتحكمات kubectl -n flux-system get pods # افحص حالة Flux عبر كل CRDs flux get all

CRD GitRepository: source-controller بعمق

يُخبر كائن GitRepository الـ source-controller من أين يجلب المحتوى وكم مرة يفحص التغييرات. هو نقطة الدخول لأي خط GitOps مدعوم بـ Git. عندما ينجح source-controller في جلب مراجعة وأرشفتها، يُحدّث حقل .status.artifact للكائن بعنوان URL يشير إلى ملف tar على خادم HTTP المدمج — تُرجع إليه المتحكمات الأخرى لتنزيل المانيفستات دون الحاجة لبيانات اعتماد Git بأنفسها.

# gitrepository.yaml — مثال إنتاجي مع شروح apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: gitops-fleet namespace: flux-system spec: interval: 1m # استطلع الخادم البعيد كل 60 ثانية url: https://github.com/my-org/gitops-fleet ref: branch: main # تابع فرعاً # tag: v1.2.3 # أو اثبّت على وسم محدد # semver: ">=1.0.0" # أو نطاق SemVer عبر الوسوم secretRef: name: gitops-fleet-auth # مفتاح SSH أو رمز مخزن في Secret timeout: 60s ignore: | # تجاهل الملفات التي تتغير كثيراً لكن لا تؤثر على حالة المجموعة # يستخدم صياغة .gitignore /docs/ /tests/ **/*.md --- # الـ Secret المقابل (نهج مفتاح SSH) apiVersion: v1 kind: Secret metadata: name: gitops-fleet-auth namespace: flux-system type: Opaque data: identity: <base64-encoded-ssh-private-key> identity.pub: <base64-encoded-ssh-public-key> known_hosts: <base64-encoded-known-hosts>

بعد التطبيق، يمكنك فحص حالة القطعة الأثرية بـ flux get source git gitops-fleet. المخرج الصحي يُظهر عنوان URL غير فارغ في عمود ARTIFACT REVISION. إن كان العمود فارغاً أو يُظهر failed، تحقق من kubectl -n flux-system describe gitrepository gitops-fleet — يشرح قسم Conditions بالضبط ما الذي فشل (خطأ مصادقة، تعارض مفتاح SSH، انتهاء مهلة الشبكة، إلخ).

CRD Kustomization: kustomize-controller بعمق

يُوجّه CRD Kustomization (لا يُخلط مع ملف kustomization.yaml الخاص بـ Kustomize) الـ kustomize-controller لأخذ قطعة أثرية من مصدر، تمريرها اختيارياً عبر Kustomize، وتطبيق النتيجة على المجموعة. هو كائن التوفيق الأساسي الذي ستُنشئه لكل حمل عمل.

# kustomization.yaml — مثال إنتاجي مع شروح apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: apps-production namespace: flux-system spec: interval: 5m # أعد التوفيق كل 5 دقائق (تصحيح الانجراف) retryInterval: 30s # فترة التراجع عند الفشل timeout: 3m # أخفق بسرعة إن استغرق التطبيق أكثر من 3 دقائق sourceRef: kind: GitRepository name: gitops-fleet # مرجع إلى GitRepository المعرّف أعلاه path: ./environments/production # المسار الفرعي في المستودع للمعالجة prune: true # احذف موارد المجموعة المُزالة من Git (حرج) wait: true # افحص صحة كل الموارد المُطبَّقة قبل وضع علامة Ready force: false # لا تُطبّق بالقوة (سيحذف+يُعيد إنشاء الحقول غير القابلة للتغيير) healthChecks: - apiVersion: apps/v1 kind: Deployment name: api-gateway namespace: production postBuild: substitute: ENVIRONMENT: production REPLICA_COUNT: "3" substituteFrom: - kind: ConfigMap name: cluster-vars # أدخل متغيرات خاصة بالمجموعة دون تكرار YAMLs decryption: provider: sops # فكّ تشفير الأسرار المشفرة بـ SOPS أثناء التطبيق secretRef: name: sops-age-key
مصيدة إنتاجية — prune: true: بدون prune: true، ستبقى الموارد المحذوفة من Git في المجموعة إلى أجل غير مسمى. هذا هو المصدر الأكثر شيوعاً لموارد "الأشباح" في المجموعات التي يُديرها Flux — Deployments وServices وCronJobs القديمة التي لا أحد يتذكرها لكنها لا تزال تستهلك موارد وتُعطّل الأمور أحياناً. اضبط دائماً prune: true في الإنتاج. مخاطر الحذف العرضي تُخفَّف بحقيقة أن الحذف نفسه هو git commit يمكن عكسه.
Flux Control Loop: Source, Kustomize, and Helm Controllers Git Remote GitHub / GitLab source-controller GitRepository CRD Artifact HTTP Server kustomize-controller Kustomization CRD kustomize build + kubectl apply helm-controller HelmRelease CRD helm install / upgrade K8s API Server Deployments Services ConfigMaps... poll / clone artifact URL artifact URL apply apply notification-controller Slack / PD / Webhook events
حلقة تحكم Flux: يجلب source-controller محتوى Git ويُعرض القطع الأثرية؛ يستهلك kustomize-controller وhelm-controller تلك القطع الأثرية ويُطبّقان المانيفستات على Kubernetes API Server؛ يُوجّه notification-controller الأحداث للأنظمة الخارجية.

متحكم Helm وCRD HelmRelease

يُلغي helm-controller الحاجة لتشغيل helm upgrade --install في خطوط CI، الذي يكون عديم الحالة وصعب المراقبة. بدلاً من ذلك، تُعلن حالة إصدار Helm المطلوبة في CRD HelmRelease والمتحكم يمتلك دورة حياة الإصدار الكاملة — التثبيت والترقية والاختبار والاسترجاع وإلغاء التثبيت — مُسجّلاً التاريخ في أسرار إصدار Helm تماماً كما تفعل أداة helm اليدوية.

# HelmRepository CRD: أخبر source-controller بمكان فهرس Helm chart apiVersion: source.toolkit.fluxcd.io/v1 kind: HelmRepository metadata: name: ingress-nginx namespace: flux-system spec: interval: 10m url: https://kubernetes.github.io/ingress-nginx --- # HelmRelease CRD: أعلن حالة الإصدار المطلوبة apiVersion: helm.toolkit.fluxcd.io/v2 kind: HelmRelease metadata: name: ingress-nginx namespace: infrastructure spec: interval: 10m chart: spec: chart: ingress-nginx version: "4.x" # قيد SemVer — يترقّى تلقائياً ضمن النطاق sourceRef: kind: HelmRepository name: ingress-nginx namespace: flux-system values: controller: replicaCount: 3 resources: requests: cpu: 100m memory: 90Mi limits: cpu: 500m memory: 256Mi metrics: enabled: true serviceMonitor: enabled: true install: remediation: retries: 3 # أعد محاولة التثبيت الفاشل حتى 3 مرات upgrade: remediation: retries: 3 remediateLastFailure: true # استرجع إن فشل الترقية cleanupOnFail: true rollback: timeout: 5m cleanupOnFail: true
ممارسة احترافية — نمط تجاوز القيم: في المؤسسات الكبيرة، تقع قيم Helm الأساسية في مانيفست HelmRelease مشترك بينما تأتي التجاوزات الخاصة بالبيئة من ConfigMap يُشار إليه بـ valuesFrom. هذا يتجنب تكرار كتل values بأكملها عبر كائنات HelmRelease للتجهيز والإنتاج — سبب شائع لانجراف الإعدادات عندما تنسخ الفرق المانيفستات. استخدم spec.valuesFrom مرجعاً إلى ConfigMap أو Secret لأي قيم تختلف بين البيئات.

مراقبة توفيق Flux في الوقت الفعلي

فهم حالة التوفيق أمر حرج لتشخيص عمليات النشر. يوفر Flux مراقبة من الدرجة الأولى عبر CLI وأحداث Kubernetes.

# أظهر حالة توفيق كل كائنات Flux flux get all -A # راقب توفيق Kustomization محدد في الوقت الفعلي flux reconcile kustomization apps-production --with-source --watch # أجبر توفيقاً فورياً (تجاوز مؤقت الفترة الزمنية) flux reconcile source git gitops-fleet flux reconcile kustomization apps-production # افحص كائناً فاشلاً — الشروط تحكي القصة الكاملة kubectl -n flux-system describe kustomization apps-production # تابع سجلات المتحكم (أضف --since=5m لتقليل الضوضاء) kubectl -n flux-system logs deploy/kustomize-controller --since=5m | tail -50 kubectl -n flux-system logs deploy/source-controller --since=5m | tail -50 # تحقق من الأحداث في namespace flux-system للنشاط الأخير kubectl -n flux-system get events --sort-by='.lastTimestamp' | tail -20

أنماط فشل الإنتاج وكيفية تشخيصها

أكثر أنماط فشل Flux شيوعاً في الإنتاج، وكيفية حل كل منها:

  • GitRepository عالق على "GitOperationFailed": تقريباً دائماً بسبب تدوير مفتاح SSH أو انتهاء صلاحية رمز GitHub. تحقق من Secret المُشار إليه بـ secretRef، أعد إنشاءه ببيانات الاعتماد الجديدة، ثم flux reconcile source git <name>.
  • Kustomization "health check timeout": مورد طُبّق بواسطة Flux فشل في فحص جاهزيته الخاص (مثلاً، Deployment لا يصل لعدد نسخه المطلوب). الـ Kustomization نفسه سليم — الحمل الأساسي ليس كذلك. شخّص الحمل مباشرة: kubectl describe pod وkubectl logs.
  • HelmRelease عالق في "upgrade retries exhausted": قيم الـ chart غير صالحة أو الـ chart به خلل. سيكون Flux قد استرجع تلقائياً إن كان remediateLastFailure: true. افحص تاريخ Helm: helm history ingress-nginx -n infrastructure لترى أي مراجعة فشلت وما الخطأ الذي أعاده Helm.
  • لا يُصحَّح الانجراف: تحقق من انقضاء interval وأن .status.lastAppliedRevision للـ Kustomization يتطابق مع HEAD في Git. عدم التطابق يعني أن source-controller يملك محتوى جديداً لم يستهلكه kustomize-controller بعد — تحقق من سجلات source-controller.
المقايضة المعمارية بين Flux وArgoCD: Flux أخف تشغيلياً (لا خادم UI، لا Redis، لا قاعدة بيانات للتطبيق) ويتكامل بشكل أكثر طبيعية مع سير عمل CLI/IaC أولاً. يوفر ArgoCD RBAC أغنى متعدد المستأجرين وواجهة مستخدم مرئية تجدها فرق العمليات لا غنى عنها. على نطاق واسع، تُشغّل كثير من المؤسسات كليهما: Flux للبنية التحتية الآلية وموارد مستوى المجموعة (CRDs والمشغّلات وcert-manager وPrometheus)، وArgoCD لسير عمل فرق التطبيقات حيث تهم واجهة المستخدم وتفويض RBAC. اختر بناءً على نموذج تشغيل فريقك، لا على تفضيل العلامة التجارية.

الخلاصة

تُفصل معمارية مجموعة أدوات Flux الجلب (source-controller) من العرض (kustomize-controller) ومن الإصدار (helm-controller) في مكونات مستقلة وقابلة للاستبدال. CRD GitRepository هو نقطة دخولك لأي مصدر مدعوم بـ Git، وCRD Kustomization هو كائن التوفيق الذي يُترجم محتوى Git إلى حالة مجموعة حية. إتقان هاذين الـ CRDs — وفهم كيف يُفصل نموذج القطع الأثرية لـ source-controller معالجة بيانات الاعتماد عن التوفيق — هو الأساس لبناء خطوط Flux الإنتاجية المُغطّاة في الدروس التالية.