أكثر وعود GitOps التي يُقلَّل من شأنها ليست النشر السريع — بل القدرة على الإجابة عن سؤالين يُرعبان مهندسي الاستجابة للحوادث: "كيف وصل الكلاستر إلى هذه الحالة؟" و"كيف نعيده إلى حالة معروفة جيداً بسرعة؟" هذا الدرس يمثّل جوهر GitOps التشغيلي: اكتشاف الانجراف، والتراجع عبر Git revert، وإعادة بناء كلاستر بأكمله من Git بعد فشل كارثي.
ما هو الانجراف في الإعدادات؟
الانجراف (Drift) هو أي تباين بين الحالة المطلوبة المُعلنة في Git والحالة الفعلية الحية للكلاستر. يحدث الانجراف باستمرار في المنظمات الحقيقية، وأسبابه تقع ضمن مجموعة متوقعة:
تعديلات kubectl اليدوية: مهندس يصحّح Deployment مباشرةً خلال حادثة. سريع في اللحظة، غير مرئي في Git.
طفرات Admission Controller: Mutating Admission Webhook يحقن حاويات جانبية أو حدود موارد أو labels عند القبول. الكلاستر يحمل أكثر مما أُعلن في Git.
محاكيات التوسع التلقائي: HPA أو KEDA يغيّران عدد النسخ. هذا انجراف مقصود ويجب استثناؤه صراحةً من المصالحة.
آثار جانبية لـ Helm hooks: Jobs وConfigMaps التي أنشأتها Helm hooks قد تستمر أطول من عمرها المقصود وتتباين عن الـ chart.
تفاوت إصدارات CRD: ترقية Kubernetes جديدة ترفع إصدار CRD، تاركةً الموارد الموجودة في مجموعة API مهجورة.
Secrets منتهية الصلاحية أو متجددة: نظام خارجي يدفع بيانات اعتماد متجددة مباشرةً إلى Kubernetes Secret دون تحديث مستودع GitOps.
الانجراف ليس دائماً عرضياً. الطفرات الحية المقصودة — مثل النسخ التي تديرها HPA أو معاملات kernel على مستوى العقدة التي تضبطها DaemonSet — يجب استثناؤها صراحةً من المصالحة باستخدام قواعد ignoreDifferences في ArgoCD أو تصحيحات spec.ignore في Flux. الإخفاق في ذلك يسبب ضجيج "OutOfSync" دائم يُخفي الانجراف الحقيقي.
اكتشاف الانجراف: ArgoCD
يحسب ArgoCD الانجراف بمقارنة مانيفستات موارد Kubernetes الحية (المسحوبة من خادم API) مع المانيفستات المُصيَّرة من Git (بعد templating عبر Helm أو Kustomize). النتيجة هي حالة مزامنة للتطبيق إما Synced أو OutOfSync.
تحقق من الانجراف عبر واجهة الأوامر:
# عرض كل التطبيقات وحالة مزامنتها
argocd app list
# فحص الفرق لتطبيق محدد (ما في Git مقابل ما في الكلاستر)
argocd app diff my-api --local
# الحصول على الفرق الكامل بما في ذلك الحقول التي أضافها الكلاستر
argocd app diff my-api --hard-refresh
# مثال على المخرجات:
# ===== apps/Deployment my-api/api-service ======
# 104c104
# < replicas: 3
# ---
# > replicas: 7
لإخفاء الانجراف المقصود (النسخ التي تديرها HPA) حتى لا تلوّث حالة المزامنة، أضف كتلة ignoreDifferences إلى مانيفست التطبيق:
يُظهر Flux الانجراف من خلال كائنات Kustomization وHelmRelease. شرط Ready بسبب ReconciliationFailed أو DriftDetected يشير إلى أن الكلاستر انحرف عن Git.
# التحقق من حالة kustomization في Flux
flux get kustomizations --all-namespaces
# حالة مفصّلة تشمل آخر رسالة انجراف
flux get kustomization my-api -n flux-system -o yaml | grep -A10 conditions
# إجبار دورة مصالحة فورية
flux reconcile kustomization my-api --with-source
# تعليق المصالحة لإجراء عمليات طوارئ يدوية بأمان
flux suspend kustomization my-api
# استئناف المصالحة بعد حل الطوارئ
flux resume kustomization my-api
دورة حياة اكتشاف الانجراف والمصالحة: يقارن العميل باستمرار حالة Git مع الحالة الحية ويُصلح ذاتياً أي تباين غير مستثنى.
التراجع عبر Git Revert: الطريقة الصحيحة
في GitOps، التراجع ليس أمر argocd app rollback (وإن كان موجوداً). التراجع القانوني هو Git revert — لأن أي تغيير دائم على الكلاستر يجب أن يوجد كـ commit في Git. التراجع الذي يتجاوز Git هو مجرد انجراف إضافي.
سير عمل التراجع القياسي:
# 1. تحديد الـ commit السيء (الذي أدخل التغيير المعطوب)
git log --oneline --graph origin/main
# مثال على المخرجات:
# * f3a9c21 (HEAD, origin/main) chore: bump api-service to v2.3.1
# * 8d4b10e feat: increase replicas to 5 in production overlay
# * c1e77f3 fix: update HPA maxReplicas to 20
# * a9f2b8c feat: bump api-service to v2.3.0
# 2. التراجع عن الـ commit السيء — ينشئ commit جديداً، يحفظ التاريخ
git revert f3a9c21 --no-edit
git push origin main
# 3. إجبار مزامنة فورية (بدلاً من انتظار فترة الاستطلاع)
# ArgoCD:
argocd app sync my-api
# Flux:
flux reconcile kustomization my-api --with-source
# 4. مراقبة عملية الإطلاق
kubectl rollout status deployment/api-service -n production
kubectl rollout history deployment/api-service -n production
لا تستخدم git reset --hard مع force push للتراجع على main أبداً. Force push يُعيد كتابة التاريخ، مما يكسر جميع PRs الجارية، ويُربك مؤشر commit لعميل GitOps، ويدمر سجل التدقيق. استخدم دائماً git revert. الـ commit الإضافي للتراجع هو سجل التدقيق — يُظهر بالضبط متى حدث التراجع ومن أطلقه. في Google وStripe، الـ force pushes على فروع إعدادات الإنتاج محظورة على مستوى المستودع.
للتراجع عن خدمات متعددة حيث إصدار واحد يمس عدة مستودعات، استخدم ArgoCD ApplicationSet أو تثبيت إصدار chart في Flux HelmRelease للتراجع في commit واحد منسّق:
# تراجع متنسّق لخدمات متعددة عبر إعادة patch لعناوين الصور في Kustomize
# في kustomization.yaml الخاص بالبيئة، أعد عناوين الصور للخدمات المتأثرة:
# git diff HEAD~1 apps/overlays/production/kustomization.yaml
# - - name: ghcr.io/myorg/api-service
# - newTag: v2.3.1
# + - name: ghcr.io/myorg/api-service
# + newTag: v2.3.0
# - - name: ghcr.io/myorg/worker-service
# - newTag: v1.9.0
# + - name: ghcr.io/myorg/worker-service
# + newTag: v1.8.5
# commit واحد لـ git revert يتراجع عن كلتا الخدمتين في آنٍ واحد
git revert HEAD --no-edit
git push origin main
# مراقبة ArgoCD وهو يتلقى التغيير ويزامن كلا التطبيقين في وقت واحد
argocd app list --output wide
التراجع عبر ArgoCD Application (الحالة الطارئة)
يحتفظ ArgoCD بذاكرة تخزين مؤقت محلية للمانيفستات المُنشرة مسبقاً (حتى spec.revisionHistoryLimit إدخالاً، الافتراضي 10). في حالة طوارئ حقيقية حيث Git غير متاح أو تحتاج للتراجع أسرع من الوقت اللازم لدورة Git، يمكنك التراجع إلى إدخال تاريخ مخزّن:
# عرض تاريخ الإصدارات لتطبيق
argocd app history my-api
# ID DATE REVISION
# 0 2025-11-01 03:12:11 +0000 UTC a9f2b8c
# 1 2025-11-02 11:44:05 +0000 UTC 8d4b10e
# 2 2025-11-03 14:22:33 +0000 UTC f3a9c21 <-- معطوب
# التراجع إلى الإصدار 1 (يتجاوز Git للسرعة — للحالات الطارئة فقط)
argocd app rollback my-api 1
# حرج: أتبع ذلك فوراً بـ git revert حتى يتطابق Git مع الكلاستر مجدداً
# وإلا سيُعيد ArgoCD تطبيق الـ commit المعطوب في الدورة التالية
أمر app rollback في ArgoCD يُنشئ انجرافاً مقصوداً. الكلاستر يشغّل الآن حالة الإصدار 1، لكن Git لا يزال يحمل الـ commit المعطوب على HEAD. إذا كانت المزامنة التلقائية مفعّلة، سيُعيد ArgoCD تطبيق الحالة المعطوبة خلال دقائق. بعد استخدام app rollback كإجراء طارئ، يجب فوراً تعطيل المزامنة التلقائية (argocd app set my-api --sync-policy none) ثم دفع git revert لمحاذاة المستودع. هذه العملية ذات الخطوتين هي بروتوكول الطوارئ الآمن الوحيد.
التعافي من الكوارث: إعادة بناء كلاستر من Git
الوعد الأسمى لـ GitOps: كلاستر يتدمر (منطقة سحابية سيئة، ترقية كارثية، برمجيات فدية). لديك Git وكلاستر جديد. وقت التعافي يتحدد بمدى جودة تصميم مستودع GitOps، لا بمن يتذكر أوامر kubectl التي شغّلها قبل ستة أشهر.
إجراء DR على مستوى الإنتاج باستخدام ArgoCD:
# --- الخطوة 1: تهيئة ArgoCD على الكلاستر الجديد ---
# تثبيت ArgoCD على الكلاستر الجديد
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# انتظار جاهزية ArgoCD
kubectl wait --for=condition=available deployment/argocd-server -n argocd --timeout=300s
# --- الخطوة 2: استعادة secrets لـ ArgoCD (بيانات اعتماد المستودع والكلاستر)
# مخزّنة خارج Git (مثلاً Vault أو AWS Secrets Manager أو sealed-secrets backup)
# مثال: استعادة من Vault عبر External Secrets Operator
kubectl apply -f bootstrap/argocd-repo-secret.yaml # مُنشأ مسبقاً من Vault
# --- الخطوة 3: تطبيق مانيفست App-of-Apps الجذري
# هذا المانيفست الواحد يخبر ArgoCD بجميع التطبيقات الأخرى
kubectl apply -f clusters/production/argocd-apps.yaml -n argocd
# --- الخطوة 4: مراقبة ArgoCD وهو يصالح الكلاستر بأكمله من Git
argocd app wait --all --health --timeout 600
# ArgoCD سيقوم الآن بـ:
# 1. قراءة كل Application مُعلن في argocd-apps.yaml
# 2. تصيير مانيفستات Helm/Kustomize لكل تطبيق من Git
# 3. تطبيقها على الكلاستر بترتيب التبعيات
# 4. الإبلاغ عن الصحة لكل تطبيق
# --- الخطوة 5: التحقق من مطابقة حالة الكلاستر لـ Git
argocd app list
# NAME CLUSTER NAMESPACE SYNC-STATUS HEALTH-STATUS
# my-api in-cluster production Synced Healthy
# payment-service in-cluster production Synced Healthy
# ...
المكافئ للكلاسترات التي تديرها Flux:
# --- Flux DR: التهيئة على كلاستر جديد ---
# الخطوة 1: تثبيت Flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash
# الخطوة 2: تهيئة Flux — توجيهه إلى نفس مستودع GitOps
# Flux يثبّت نفسه وينشئ كائنات GitRepository + Kustomization خاصة به
flux bootstrap github \
--owner=myorg \
--repository=gitops-config \
--branch=main \
--path=clusters/production \
--personal=false \
--token-auth
# Flux سيثبّت نفسه ذاتياً، ثم يسحب مسار cluster/production من Git،
# والذي بدوره يشير إلى جميع Kustomizations و HelmReleases للتطبيقات.
# يُعاد بناء الكلاستر بأكمله تلقائياً من حالة Git.
# الخطوة 3: مراقبة التقدم
flux get all --all-namespaces
# الخطوة 4: استعادة secrets من Vault / AWS SM / SOPS backup (انظر الدرس 8)
# إذا استخدمت SOPS: مفتاح age أو AWS KMS يمنح Flux الوصول تلقائياً
# إذا استخدمت ESO: يُشغَّل عبر HelmRelease الخاص به في Git
RTO (وقت التعافي المستهدف) في GitOps DR يعتمد على ثلاثة عوامل:
وقت تهيئة Secrets: إذا تطلّبت Secrets تدخلاً يدوياً للاستعادة، فإن RTO يصبح ساعات. أتمتها بنمط Vault+ESO أو SOPS مع مفتاح KMS.
وقت سحب الصور: سحب مئات صور الحاويات على مجموعة عقد جديدة يستغرق وقتاً. مرآة ECR/GCR إقليمية في منطقة DR تقلّص ذلك بشكل كبير.
ترتيب التبعيات: إذا لم تُطبَّق CRDs قبل الموارد التي تستخدمها، سيفشل ArgoCD/Flux في حلقات المصالحة. استخدم Sync Waves (ArgoCD) أو تبعيات Kustomization (Flux) لفرض الترتيب في Git.
مراقبة الانجراف باستمرار في الإنتاج
على نطاق كبير، لا تنتظر أن يلاحظ مهندس شارة "OutOfSync" في واجهة ArgoCD. تُصدّر مقاييس الانجراف وتنبّه عليها:
عتبات التنبيه في الإنتاج: نبّه على OutOfSync بعد 5 دقائق (وليس فوراً — الانجراف العابر البسيط خلال التحديثات المتدرجة طبيعي). نبّه على صحة Degraded بعد 3 دقائق. استدعِ المهندس المناوب إذا كان التطبيق OutOfSync لأكثر من 15 دقيقة — هذا يعني في الغالب مزامنة معطوبة تفشل في إصلاحها التلقائي، ويحتاج الأمر نظرة بشرية على الفرق.
اكتشاف الانجراف، والتراجع النظيف عبر Git revert، وكتاب تشغيل DR مُختبَر يُعيد البناء من Git — هذه الركائز التشغيلية الثلاث هي ما يميّز منصة GitOps ناضجة عن تجربة تجريبية. الدرس التالي يختتم البرنامج التعليمي بمشروع شامل: تصميم وتنفيذ pipeline تسليم GitOps متكاملة من البداية إلى النهاية.
نستخدم ملفات تعريف الارتباط لتشغيل هذا الموقع وتحليل الزيارات وعرض إعلانات مخصّصة. يمكنك قبول كل ملفات تعريف الارتباط أو رفض غير الأساسية منها.
سياسة الخصوصية