GitOps مع ArgoCD وFlux

ترقية البيئات

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

ترقية البيئات

ترقية البيئات هي عملية نقل منضبطة لأرتيفاكت تم التحقق منه — صورة حاوية عند digest محدد — من بيئة ذات ثقة منخفضة (dev) عبر بيئة staging وأخيراً إلى الإنتاج، مع commit في Git كسجل تدقيق غير قابل للتغيير في كل خطوة. في GitOps، الترقية ليست زراً في واجهة مستخدم أو علماً في سكريبت Shell. إنها تغيير متعمد للحالة المطلوبة المخزّنة في Git. هذا التمييز هو جوهر المسألة بأكملها.

نموذج الترقية المستخدم في شركات مثل Shopify وStripe وWeaveworks يعامل البيئات كمجلدات منفصلة (أو فروع) في مستودع الإعدادات، يُصالَح كل منها بشكل مستقل. لا تُرقّي "كوداً" أبداً — بل تُرقّي عنوان image أو digest محدد تم بناؤه وفحصه واختباره بالفعل من قِبل CI. السؤال الوحيد الذي يجب على Git الإجابة عليه هو: أي نسخة من هذا الأرتيفاكت مسموح لكل بيئة بتشغيلها؟

تشريح تدفق الترقية

مسار الترقية من ثلاث بيئات يبدو كالتالي من حيث Git:

  • dev: يتم تحديث عنوان الـ image تلقائياً من قِبل CI عند كل دمج إلى فرع main. يُصالح عميل GitOps خلال ثوانٍ. لا موافقة بشرية.
  • staging: يتم تحديث عنوان الـ image بواسطة سكريبت ترقية أو PR بشري. قد يتطلب أن تجتاز اختبارات smoke آلية أولاً. مُقيَّد بقاعدة حماية فرع أو فحص حالة مطلوب.
  • production: يتم تحديث عنوان الـ image فقط بعد موافقة بشرية على PR (أو موافقة آلية من محرك سياسات مثل OPA Gatekeeper). نوافذ تجميد التغييرات مُفعَّلة عبر قواعد حماية الفروع في مستودع الإعدادات.
GitOps environment promotion flow from dev to staging to production CI Pipeline build + scan image:sha-abc123 auto-commit Config Repository (gitops-config) env/dev image: sha-abc123 auto-updated PR + tests env/staging image: sha-abc123 human merge PR + review env/prod image: sha-abc123 approved merge dev-cluster Dev Cluster ArgoCD / Flux staging-cluster Staging Cluster ArgoCD / Flux prod-cluster Prod Cluster ArgoCD / Flux watches watches watches بوابات الترقية Dev: CI تُحدِّث الـ digest تلقائياً. لا بوابة بشرية. ArgoCD يُصالح خلال 60 ثانية. Staging: سكريبت الترقية يفتح PR. فحوصات الحالة المطلوبة: smoke tests، SAST، فحص الصورة. Prod: إنسان يوافق على PR. CODEOWNERS يفرض قاعدة شخصين. نوافذ التجميد مُفعَّلة بقواعد الفروع. كل بيئة تقرأ مساراً مختلفاً في مستودع الإعدادات نفسه — عزل تام، لا خطر لانجراف البيئات. image digest هو الأرتيفاكت غير القابل للتغيير. Git commit هو سجل الترقية غير القابل للتغيير.
تدفق الترقية في GitOps من البداية إلى النهاية: CI تبني صورة وتُدرج الـ digest في مجلد بيئة dev، وسلسلة PRs منضبطة ترقّيها إلى staging ثم الإنتاج. لكل بيئة عميل GitOps خاص بها يراقب مجلدها.

هيكل المستودع للـ GitOps متعدد البيئات

الهيكل القانوني الذي يتوسع مع المنظمات الكبيرة يستخدم مجلدات بيئة داخل مستودع إعدادات واحد (أو مستودعات منفصلة لكل بيئة لأقصى درجات العزل). إليك هيكلاً حقيقياً مبنياً على Kustomize:

# gitops-config/ apps/ api-service/ base/ deployment.yaml # image: ghcr.io/myorg/api:SHA (placeholder) service.yaml kustomization.yaml overlays/ dev/ kustomization.yaml # تحديد image tag، replicas=1 staging/ kustomization.yaml # تحديد image tag، replicas=2، حدود موارد production/ kustomization.yaml # تحديد image tag، replicas=6، HPA، PDB # overlays/dev/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../base images: - name: ghcr.io/myorg/api newTag: sha-abc1234 # <-- هذا السطر هو ما تُحدِّثه CI/سكريبتات الترقية patches: - patch: |- - op: replace path: /spec/replicas value: 1 target: kind: Deployment name: api-service
دائماً قيّد الإنتاج بـ image digest، وليس بعنوان قابل للتغيير. العناوين مثل v1.2.3 يمكن استبدالها بـ docker push. الـ digest مثل sha256:a3f7... غير قابل للتغيير تشفيرياً. استخدم kustomize edit set image مع الـ digest الكامل في سكريبت الترقية. ArgoCD Image Updater وFlux ImagePolicy يمكنهما أتمتة تثبيت الـ digest في dev وstaging مع إبقاء الإنتاج مثبتاً على digest موافق عليه بشرياً.

أتمتة ترقية Dev من CI

بعد نجاح بناء CI، تُحدِّث الـ pipeline طبقة dev تلقائياً. هذه هي البيئة الوحيدة التي تكتب فيها CI مباشرةً إلى مستودع الإعدادات. النمط يستخدم توكن بوت بصلاحيات كتابة محدودة على مستودع الإعدادات فقط:

# .github/workflows/ci.yml (مستودع التطبيق) name: Build and Promote to Dev on: push: branches: [main] jobs: build-and-promote: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build and push image id: build uses: docker/build-push-action@v5 with: push: true tags: ghcr.io/myorg/api-service:sha-${{ github.sha }} # digest متاح في steps.build.outputs.digest - name: Update dev overlay in config repo env: CONFIG_REPO_TOKEN: ${{ secrets.CONFIG_REPO_PAT }} IMAGE_DIGEST: ${{ steps.build.outputs.digest }} run: | git clone https://x-token:${CONFIG_REPO_TOKEN}@github.com/myorg/gitops-config.git cd gitops-config cd apps/api-service/overlays/dev kustomize edit set image \ ghcr.io/myorg/api-service@${IMAGE_DIGEST} git config user.email "ci-bot@myorg.com" git config user.name "CI Bot" git add kustomization.yaml git commit -m "chore(dev): promote api-service to ${IMAGE_DIGEST::19}" git push

الترقية إلى Staging: PR مدفوع بسكريبت

ترقية staging تُشغَّل عادةً يدوياً (مطور يشغّل سكريبتاً أو ينقر زراً في واجهة مستخدم بعد مراقبة dev) أو تلقائياً بعد فترة نقع محددة بالوقت في dev. يفتح السكريبت pull request؛ الدمج البشري مطلوب. فحوصات الحالة المطلوبة على الـ PR (اختبارات smoke، فحوصات أمان) تعمل كبوابة:

#!/usr/bin/env bash # scripts/promote.sh — يشغّله مطور: ./promote.sh staging sha-abc1234 set -euo pipefail ENV=$1 # staging | production DIGEST=$2 # sha256:... أو عنوان sha قصير REPO="myorg/gitops-config" BRANCH="promote/${ENV}-$(date +%Y%m%d-%H%M%S)" gh repo clone ${REPO} /tmp/promote-clone -- --depth 1 cd /tmp/promote-clone git checkout -b ${BRANCH} cd apps/api-service/overlays/${ENV} kustomize edit set image ghcr.io/myorg/api-service@${DIGEST} git add kustomization.yaml git commit -m "chore(${ENV}): promote api-service to ${DIGEST::19}" git push origin ${BRANCH} gh pr create \ --repo ${REPO} \ --title "Promote api-service to ${ENV}: ${DIGEST::19}" \ --body "Automated promotion PR. Merge after CI checks pass." \ --base main \ --head ${BRANCH}
Flux ImageUpdateAutomation مقابل السكريبتات اليدوية: يمتلك Flux CRD أصلياً اسمه ImageUpdateAutomation يمكنه مراقبة سجل الحاويات والـ commit بعناوين محدثة إلى Git تلقائياً، مع سياسات تتحكم في نطاقات semver المؤهلة. هذا ممتاز لـ dev وstaging. بالنسبة للإنتاج، عطّل الأتمتة واحتفظ ببوابة PR البشرية. ArgoCD يُفوِّض إلى أدوات خارجية مثل Renovate أو إضافة ArgoCD Image Updater لأتمتة مماثلة.

الترقية إلى الإنتاج: البوابة البشرية

ترقية الإنتاج تتبع نفس النمط كـ staging، لكن الـ PR يتطلب مراجعة بشرية صريحة. على نطاق big-tech يُفرض هذا هيكلياً وليس باتفاقية:

  • ملف CODEOWNERS: apps/api-service/overlays/production/ @myorg/oncall-approvers — GitHub/GitLab يطلب تلقائياً مراجعة هذا الفريق ويمنع الدمج حتى يوافق أحدهم.
  • قواعد حماية الفروع: تتطلب موافقتين، إلغاء المراجعات القديمة عند commits جديدة، تمرير جميع فحوصات الحالة (بما في ذلك فحص "تجميد التغيير" المخصص الذي يفشل خلال نوافذ التجميد المُعلنة).
  • محركات السياسات: سياسات OPA Conftest أو Kyverno تعمل في فحص CI على PR مستودع الإعدادات، للتحقق من أن الصورة اجتازت الفحص الأمني المطلوب، وأن الـ digest يطابق ما تمت ترقيته عبر staging، وأنه لم تُحذف حدود الموارد عن طريق الخطأ.
# .github/CODEOWNERS (في مستودع الإعدادات) # طبقات الإنتاج تتطلب موافقة صريحة من فريق oncall /apps/*/overlays/production/ @myorg/oncall-approvers /apps/*/overlays/staging/ @myorg/senior-engineers # إعدادات مستوى الكلاستر مخصصة لفريق المنصة فقط /clusters/ @myorg/platform-team

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

الترقيات تفشل بطرق يمكن التنبؤ بها. معرفة هذه الأنماط يتيح لك بناء حواجز قبل وصولها للإنتاج:

  • ترقية عنوان قابل للتغيير: CI تبني :latest، staging تجتاز، لكن بحلول وقت ترقية الإنتاج، يشير :latest إلى بناء مختلف. دائماً رقّ image digests بشكل sha256:...، ولا تُرقِّ عناوين قابلة للتغيير.
  • انجراف الإعدادات بين الطبقات: مطور يُعدِّل يدوياً طبقة staging لاختبار شيء، ينسى إزالته، وترقية staging-to-prod تحمل التغيير في صمت. استخدم kustomize build في CI لمقارنة الناتج المُعرض لـ staging مقابل prod قبل الدمج.
  • ظروف السباق في ترقيات الخدمات المتعددة: عندما تعتمد الخدمة A على API جديد للخدمة B، ترقية A قبل B تسبب أخطاء. استخدم sync waves في ArgoCD (annotation argocd.argoproj.io/sync-wave) أو dependsOn في Flux لتسلسل عمليات النشر.
  • نسيان تحديث الأسرار الخاصة بالبيئة: متغير بيئة جديد يُضاف في dev لكن الـ Secret أو ExternalSecret لا يُضاف إلى طبقة prod. التطبيق ينشر لكنه يتعطل. دائماً تحقق من صلاحية المانيفستات المُعرضة مقابل schema.
لا تسمح أبداً لـ CI bot بالكتابة مباشرةً إلى مسارات إعداد الإنتاج. يجب أن يمتلك البوت صلاحيات كتابة على طبقات dev فقط. مسارات staging والإنتاج يجب أن تتطلب PR من إنسان. هذا هو أهم ضبط للوصول في إعداد GitOps لديك. سر CI مخترق يمكنه الكتابة إلى إعداد الإنتاج هو سطح هجوم على سلسلة التوريد — يمكنه نشر كود تعسفي في كلاستر الإنتاج دون أن يراجعه أحد.

تتبع حالة الترقية

في نهاية الترقية، يجب أن تتمكن من الإجابة من Git وحده: أي image digest يعمل حالياً في كل بيئة؟ اتفاقية بسيطة هي VERSIONS.md أو versions.json منظم في جذر المستودع يتم تحديثه بواسطة سكريبت الترقية. الأفضل من ذلك، استعلم ArgoCD أو Flux مباشرةً:

# استعلام ArgoCD عن المراجعة المُزامَنة الحالية في كل بيئة argocd app get api-service-dev --output json | jq '.status.sync.revision' argocd app get api-service-staging --output json | jq '.status.sync.revision' argocd app get api-service-prod --output json | jq '.status.sync.revision' # مع Flux، تحقق من ImagePolicy لرؤية العنوان الذي تُثبّته كل بيئة kubectl get imagepolicy -n flux-system -o wide # أو فقط انظر إلى git log لكل مجلد overlay git log --oneline -- apps/api-service/overlays/production/kustomization.yaml # a3f91b2 chore(prod): promote api-service to sha256:a3f7... (2025-11-14) # 9e21c45 chore(prod): promote api-service to sha256:9e21... (2025-11-07)

ترقية البيئات المُنفَّذة بشكل صحيح هي الفرق بين عملية نشر يمكنك الوثوق بها في الساعة الثانية صباحاً وعملية تتهابها كل جمعة مساءً. انضباط "كل تغيير في كل بيئة هو Git commit مع سلسلة موافقة بشرية" هو ما يجعل GitOps أساس التسليم الآمن والقابل للتدقيق على نطاق واسع.