GitOps مع ArgoCD وFlux

تصميم مستودع GitOps

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

تصميم مستودع GitOps

القرار الأكثر أهمية الذي تتخذه عند اعتماد GitOps هو كيفية تنظيم مستوداتك. إذا أخطأت في ذلك، ستجد نفسك تصارع الأدوات كل يوم — انجراف بين البيئات، وترقيات غير مقصودة، وتسرب للأسرار بين حدود الفرق، وخطوط أنابيب CI تخشى الدمج. أما إذا أصبت، فلديك نظام تسليم يتوسع من فريق واحد ومجموعة واحدة إلى خمسين فريقاً ومئات المجموعات بأقل قدر من التعقيد.

يغطي هذا الدرس القرارات الهيكلية الثلاثة التي يجب على كل مؤسسة GitOps اتخاذها: مستودعات التطبيق مقابل مستودعات البنية التحتية، ومجلدات البيئة مقابل فروع البيئة، والمستودع الموحد مقابل المستودعات المتعددة. لكل قرار تكلفته الحقيقية، والإجابة الصحيحة تعتمد على هيكل فريقك ومتطلبات الامتثال لديك ومعدل التغيير المتوقع.

مستودعات التطبيق مقابل مستودعات البنية التحتية

الفصل الأساسي في GitOps هو بين المستودع الذي يحتوي على شفرة مصدر التطبيق والمستودع الذي يحتوي على ملفات الحالة المطلوبة للمجموعة. هذان اهتمامان مختلفان بمعدلات تغيير مختلفة وجماهير مختلفة وضوابط وصول مختلفة — إبقاؤهما منفصلين ليس مجرد اتفاقية، بل هو نظافة معمارية.

يحتوي مستودع التطبيق (يُسمى أحياناً "مستودع المصدر") على شفرة Go أو Python أو TypeScript أو Java، وDockerfile الخاصة به، وتعريف خط أنابيب CI. كل دمج إلى main يُطلق بناءً، ويشغّل الاختبارات، ويدفع صورة موسومة بـ SHA الخاص بـ Git، ثم — والأهم — يفتح طلب سحب ضد مستودع البنية التحتية لتحديث وسم الصورة. مستودع التطبيق لا ينشر أي شيء مباشرةً.

يحتوي مستودع البنية التحتية (مستودع الإعدادات أو مستودع GitOps) فقط على ملفات بيان Kubernetes وملفات قيم Helm أو تراكبات Kustomize. ليس فيه أي عناصر بناء أو منطق تطبيقي. مهمته الوحيدة هي أن يكون مصدر الحقيقة لما يجب تشغيله في كل مجموعة. يراقب ArgoCD أو Flux هذا المستودع ويتوافق مع المجموعة باستمرار.

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

يبدو تدفق CI الملموس الذي يربط هذين المستودعين على النحو التالي. يقوم سير عمل GitHub Actions أو GitLab CI في مستودع التطبيق بالبناء والدفع، ثم يستخدم PAT أو مفتاح نشر لفتح طلب سحب ضد مستودع البنية التحتية:

# .github/workflows/release.yml (يعيش في مستودع التطبيق) name: Build & Promote on: push: branches: [main] jobs: build-and-promote: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build & push image run: | IMAGE="ghcr.io/${{ github.repository }}:${{ github.sha }}" docker build -t "$IMAGE" . docker push "$IMAGE" - name: Bump image tag in infra repo env: GH_TOKEN: ${{ secrets.INFRA_REPO_PAT }} run: | gh repo clone org/infra /tmp/infra cd /tmp/infra yq e -i '.image.tag = "${{ github.sha }}"' \ apps/checkout/staging/values.yaml git config user.email "ci@org.internal" git config user.name "CI Bot" git checkout -b "promote/checkout-${{ github.sha }}" git add apps/checkout/staging/values.yaml git commit -m "chore: promote checkout to ${{ github.sha }}" gh pr create \ --title "Promote checkout to ${{ github.sha }}" \ --body "Auto-promotion from app CI" \ --base main \ --head "promote/checkout-${{ github.sha }}"

يراجع مهندس مناوب طلب السحب (أو يُدمج تلقائياً إذا كنت تثق باختبارات التكامل)، ويلتقط ArgoCD أو Flux التغيير المدموج في غضون ثوانٍ. نمط المستودعين هذا هو ما توثّقه Weaveworks وGoogle وLyft باعتباره البنية المعيارية لـ GitOps.

App repo to infra repo promotion flow App Repo source code Dockerfile · CI pipeline CI System build · test push image (SHA tag) push Infra Repo K8s manifests Helm values · Kustomize open PR GitOps Operator ArgoCD / Flux watches Cluster reconciled state applies
يبني نظام CI في مستودع التطبيق الصورة ويرقّيها إلى مستودع البنية التحتية؛ يتوافق مشغّل GitOps مع المجموعة باستمرار.

مجلدات البيئة مقابل فروع البيئة

بمجرد حصولك على مستودع بنية تحتية، تواجه قراراً ثانياً: كيف تمثل بيئات متعددة (dev، staging، production) داخله؟ مدرستا فكر موجودتان، وإحداهما ستسبب لك ألماً على نطاق واسع.

فروع البيئة — فرع Git مخصص لكل بيئة (env/dev، env/staging، env/prod) — تبدو بديهية لأن "الترقية تتم بالدمج". في الواقع، للفروع المخصصة للبيئة أوضاع فشل كارثية. تفشل الانتقاءات الدقيقة بصمت. تتراكم تعارضات الدمج بين فروع البيئة على مدى أسابيع. لا يمكنك بسهولة معرفة ما هو في staging ولكن ليس في prod دون مقارنة رؤوس الفروع عبر الشجرة بأكملها. الفروع المتباعدة طويلة الأمد هي بالضبط ما صُممت سير عمل Git الحديثة للقضاء عليه. لا تستخدم فروع البيئة.

مجلدات البيئة — فرع main واحد مع دلائل لكل بيئة — هي النهج الصحيح. كل تغيير هو طلب سحب عادي إلى main، والتاريخ خطي وقابل للقراءة، ومقارنة البيئات هي مقارنة نظام ملفات وليست مقارنة فروع Git. صُمم Kustomize خصيصاً لهذا النموذج؛ وصُممت ApplicationSets في ArgoCD وموارد Kustomization في Flux للإشارة إلى دلائل داخل فرع واحد.

تخطيط مستودع بنية تحتية جيد الهيكل:

infra/ ├── apps/ │ ├── checkout/ │ │ ├── base/ │ │ │ ├── deployment.yaml │ │ │ ├── service.yaml │ │ │ └── kustomization.yaml │ │ ├── dev/ │ │ │ ├── kustomization.yaml │ │ │ └── values.yaml │ │ ├── staging/ │ │ │ ├── kustomization.yaml │ │ │ └── values.yaml │ │ └── prod/ │ │ ├── kustomization.yaml │ │ └── values.yaml │ └── payment/ │ └── ... ├── clusters/ │ ├── dev-us-east-1/ │ │ └── apps.yaml │ ├── staging-eu-west-1/ │ │ └── apps.yaml │ └── prod-us-east-1/ │ └── apps.yaml └── platform/ ├── ingress-nginx/ ├── cert-manager/ └── monitoring/
انضباط الترقية بالمجلدات: عامل دلائل البيئة كوحدات نشر غير قابلة للتغيير. عندما يستقر staging لمدة 24 ساعة وتبدو المقاييس جيدة، ينسخ طلب سحب الترقية وسم الصورة الدقيق من staging/values.yaml إلى prod/values.yaml — ولا شيء آخر يتغير. هذا يجعل فرق الترقية سطراً واحداً والتراجع عنه عملية من سطر واحد — وكلاهما موثق في تاريخ Git للأبد.

المستودع الموحد مقابل المستودعات المتعددة

المحور الثالث هو ما إذا كانت جميع إعدادات بنية تحتية تطبيقاتك تعيش في مستودع واحد أو مقسمة لكل فريق أو لكل خدمة. هنا تهم طبولوجيا الفريق — قانون كونواي — أكثر من أي شيء آخر.

يعمل المستودع الموحد (جميع الخدمات في مستودع بنية تحتية واحد) بشكل ممتاز للمؤسسات التي تضم حتى ما بين عشرين وثلاثين فريقاً. يمنحك مكاناً واحداً لفرض السياسات، ويجعل تغييرات التبعية بين الخدمات ذرية، ويبسط إعداد مشغل GitOps. يشغّل Google وSpotify وShopify بنجاح مستودعات موحدة. التحدي التشغيلي هو التحكم في الوصول: يجب ألا تتمكن الفرق من تعديل دلائل بعضها البعض. حل ذلك عبر ملفات CODEOWNERS.

يوفر المستودعات المتعددة (مستودع بنية تحتية واحد لكل خدمة أو لكل فريق) حدود عزل صارمة وهو الاختيار الطبيعي عندما يتطلب الامتثال التنظيمي ذلك (عزل منطقة PCI DSS، وتجزئة بيانات HIPAA) أو عندما تكون الفرق في كيانات قانونية منفصلة. التكلفة هي تكاثر مشغّلات: كل كائن ArgoCD Application أو Flux GitRepository يتضاعف، والتغييرات بين الخدمات تحتاج إلى طلبات سحب منسقة في مستودعات متعددة.

مصيدة الإنتاج — الحادث الهجين: تبدأ كثير من المؤسسات بمستودع موحد وتفصل مستودعات تدريجياً مع نمو الفرق، لتنتهي بمزيج عشوائي من النمطين الموحد والمتعدد. هذا هو الأسوأ من كلا العالمين: يشير إعداد مشغّل GitOps إلى عشرات المستودعات المختلفة، وتناوب الأسرار يجب أن يحدث في ثلاثين مكاناً، وإدراج مهندس جديد يتطلب منح وصول إلى قائمة متنامية من المستودعات. قرر نموذجك مبكراً وطبّقه باتساق.

قاعدة عملية: ابدأ بمستودع موحد مقسم إلى دلائل فرعية teams/، مفروضة بـ CODEOWNERS. قم بنقل الفريق إلى مستودعه الخاص فقط عندما تكون هناك حدود امتثال أو تنظيمية موثقة تجعل ذلك إلزامياً. إليك نمط CODEOWNERS للتحكم في الوصول بالمستودع الموحد:

# جذر مستودع البنية التحتية: .github/CODEOWNERS # فريق المنصة يملك البنية التحتية على مستوى المجموعة /platform/ @org/platform-team # كل فريق تطبيق يملك دليله الخاص /apps/checkout/ @org/checkout-team /apps/payment/ @org/payment-team /apps/identity/ @org/identity-team # ملفات تمهيد المجموعة تحتاج موافقة المنصة /clusters/ @org/platform-team # أي شخص في المنصة يمكنه الموافقة على التغييرات الجذرية * @org/platform-team

مع حماية الفروع التي تتطلب مراجعة CODEOWNERS، لا يستطيع مطور في فريق payment بصورة عرضية أو متعمدة دفع تغيير يعدّل ملفات بيان خدمة checkout. هذا الملف الواحد يفرض العزل متعدد الفرق دون الحاجة إلى تقسيم المستودعات.

الجمع بين كل العناصر

تصميم مستودع GitOps المعياري للمؤسسات الهندسية المتنامية هو: فصل مستودعات التطبيق عن البنية التحتية، ومجلدات البيئة على فرع واحد، ومستودع موحد مع CODEOWNERS حتى تصل إلى سبب ملموس للتقسيم. يرقّي نظام CI في مستودع التطبيق بفتح طلبات سحب ضد مستودع البنية التحتية. يراقب مشغّل GitOps مسارات محددة داخل مستودع البنية التحتية لكل بيئة، ويطبق التغييرات تلقائياً عند الدمج.

الخلاصة الرئيسية: تصميم المستودع هو عقد اجتماعي بقدر ما هو عقد تقني. يحدد هيكل الدليل الذي تختاره من يمكنه تغيير ماذا، وكيف تُراجع الترقيات، وكم سرعة استعادتك من نشر سيئ. صمّمه للفريق الذي ستملكه بعد سنتين، لا للفريق الذي لديك اليوم.