مقال مرتبط · هذا الدليل جزء من سلسلة Kubernetes منزلي على Proxmox VE. الدليل السابق: Rook-Ceph storage. الدليل التالي: kube-prometheus-stack الرصد.
النشر اليدوي بـ kubectl apply يعمل لاثنين أو ثلاثة أحمال. ما فوق ذلك، حالة العنقود تنحرف خفية عمّا نظنّ أنّنا أعلنّاه، الرجوع للخلف يصير محفوفًا بالمخاطر، ونفقد تاريخ التغييرات. نمط GitOps يحلّ هذه المشاكل الثلاث بوضع مستودع Git مصدرًا وحيدًا للحقيقة: العنقود لا يفعل سوى مزامنة ما هو مُلتزَم. Argo CD هو التطبيق المرجعي لهذا النمط. النسخة 3.4، المُسَلَّمة في مايو 2026، تُضيف Application Controller متعدّد المسارات أسرع وإدارة محسَّنة لـ ApplicationSet. يُثَبِّت هذا الدليل Argo CD 3.4، يُهَيكِل مستودع Git، يُنشئ أوّل Application تنشر حِملًا من Git، ثم يُهَيِّئ ApplicationSet يُكرِّر نفس الحمل على عدّة namespaces.
الخطوة 1 — تحضير مستودع Git مصدر الحقيقة
مستودع Git هو القطعة المركزية. يمكن استضافته على GitHub أو GitLab أو Gitea أو Forgejo أو أيّ خادم SSH.
mkdir homelab-gitops && cd homelab-gitops
git init
mkdir -p apps clusters/homelab/bootstrap clusters/homelab/infra clusters/homelab/apps
echo "# Homelab GitOps" > README.md
git add . && git commit -m "Initial structure"
git remote add origin git@github.com:moncompte/homelab-gitops.git
git branch -M main
git push -u origin main
البنية تُنشئ ثلاثة مستويات: apps/ للمنفستات القابلة للاستعمال، clusters/homelab/ للإعداد الخاصّ بالعنقود، وثلاثة مجلّدات فرعية bootstrap/، infra/، apps/. هذه التنظيمة تصمد للتوسيع، لأنّها تُتيح إضافة عنقود آخر دون إعادة هيكلة المستودع.
الخطوة 2 — تثبيت Argo CD 3.4 عبر Helm
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
kubectl create namespace argocd
helm install argocd argo/argo-cd \
--version 9.5.12 \
--namespace argocd \
--set server.service.type=ClusterIP \
--set server.extraArgs[0]=--insecure \
--set configs.params.server.insecure=true \
--set redis-ha.enabled=false \
--set controller.replicas=1 \
--set server.replicas=2 \
--set repoServer.replicas=2 \
--set applicationSet.enabled=true \
--set notifications.enabled=true
الـ chart 9.5.12 يُسَلِّم Argo CD 3.4.x. الخيار --insecure يتفادى ازدواج TLS حين نكشفه خلف Ingress. احسب 3 دقائق قبل أن تكون الـ pods في Running.
الخطوة 3 — استرداد كلمة سرّ admin والوصول للواجهة
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d ; echo
kubectl -n argocd port-forward svc/argocd-server 8080:80 &
# افتح http://localhost:8080، login admin، كلمة السرّ أعلاه
الواجهة تعرض شاشة « No Applications ». غيِّر كلمة سرّ admin عبر User Info ← Update Password، أو الأفضل، عطِّل التوثيق الداخلي واستعمل SSO (Keycloak أو Authentik).
الخطوة 4 — ربط Argo CD بمستودع Git
apiVersion: v1
kind: Secret
metadata:
name: homelab-gitops-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: git@github.com:moncompte/homelab-gitops.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
[محتوى المفتاح الخاصّ المنشور بقراءة فقط على GitHub]
-----END OPENSSH PRIVATE KEY-----
kubectl apply -f homelab-gitops-repo.yaml
# Settings ← Repositories: يجب أن يظهر CONNECTION SUCCESSFUL
الخطوة 5 — إنشاء أوّل Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: podinfo-demo
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:moncompte/homelab-gitops.git
targetRevision: main
path: apps/podinfo-demo
destination:
server: https://kubernetes.default.svc
namespace: demo
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
kubectl apply -f podinfo-app.yaml
kubectl get pods -n demo
pod podinfo الذي يظهر في namespace demo أُنشئ دون kubectl apply يدوي: Argo CD زامنه من Git. إن التزمنا تغييرًا على فرع main، Argo CD يكتشف الانحراف في أقلّ من 3 دقائق ويُطبّق التغيير. الرجوع بـ git revert يُزامَن عكسيًّا.
الخطوة 6 — وضع app-of-apps
نمط app-of-apps يقوم بإنشاء Application جذرية تنشر بنفسها كلّ Applications الأخرى. تكراري ومكتفٍ ذاتيًّا: kubectl apply أوّلي واحد يكفي، ثم كلّ شيء يعيش في Git.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: bootstrap-homelab
namespace: argocd
spec:
project: default
source:
repoURL: git@github.com:moncompte/homelab-gitops.git
targetRevision: main
path: clusters/homelab/bootstrap
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
المجلّد clusters/homelab/bootstrap/ يحوي بعدها منفستات Application تُشير إلى infra/ وapps/. هذه البنية تُتيح إعادة بناء عنقود كامل في أمرين: helm install argocd ثم kubectl apply -f bootstrap-homelab.yaml.
الخطوة 7 — التكرار على عدّة بيئات بـ ApplicationSet
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: monitoring-everywhere
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: homelab
url: https://kubernetes.default.svc
- cluster: labo
url: https://10.0.1.10:6443
template:
metadata:
name: '{{cluster}}-kube-prometheus-stack'
spec:
project: default
source:
repoURL: git@github.com:moncompte/homelab-gitops.git
targetRevision: main
path: clusters/{{cluster}}/infra/kube-prometheus-stack
destination:
server: '{{url}}'
namespace: monitoring
syncPolicy:
automated:
prune: true
بـ ApplicationSet واحد، يُنشَأ تطبيقان: homelab-kube-prometheus-stack وlabo-kube-prometheus-stack. إضافة عنقود ثالث تأخذ ثلاثة أسطر بدل نسخ ثلاثين سطرًا YAML.
الخطوة 8 — التحقّق من السلسلة الكاملة بعد commit
cd homelab-gitops
yq -i '.spec.replicas = 3' apps/podinfo-demo/deployment.yaml
git add apps/podinfo-demo/deployment.yaml
git commit -m "Scale podinfo to 3 replicas"
git push origin main
kubectl get pods -n demo -l app=podinfo -w
# يجب الانتقال من 1 pod Running إلى 3 pods Running
رؤية الـ 3 pods تظهر دون تشغيل أمر kubectl scale يُؤكِّد أنّ حلقة GitOps كاملة: Git ← Argo CD ← العنقود. من الآن، كلّ تعديل يمرّ عبر commit، لا عبر أمر مباشر.
أخطاء شائعة وحلولها
| العَرَض | السبب | الحلّ |
|---|---|---|
| Application تبقى OutOfSync | انحراف، sync تلقائي مُعَطَّل | انقر Sync أو فعِّل syncPolicy.automated |
| Connection Failed على المستودع | مفتاح SSH خاطئ | أعِد توليد المفتاح وأضفه في Deploy keys |
| sync يفشل بـ « namespace not found » | CreateNamespace=true غير مُفَعَّل | أضف syncOptions: [CreateNamespace=true] |
| Argo CD ينقل الموارد لكن لا يحذفها | prune: false افتراضيًّا |
فعِّل prune: true |
| واجهة بطيئة على عنقود كبير | Application Controller مُشبَع | زد controller.replicas وفعِّل sharding |
لاستكمال المسار
النشر مُقاد بـ Git. الطبقة المفقودة هي المراقبة. دليل مراقبة Kubernetes مع kube-prometheus-stack يُفَصِّل تثبيت chart 84.5.0. للنظرة العامّة، عُد إلى الدليل الرئيسي.
مصادر وتوثيق رسمي
- توثيق Argo CD:
argo-cd.readthedocs.io - ملاحظات إصدار Argo CD 3.4:
github.com/argoproj/argo-cd/releases - نمط app-of-apps:
argo-cd.readthedocs.io/cluster-bootstrapping - مواصفات ApplicationSet:
argo-cd.readthedocs.io/applicationset - Charts Helm Argo:
artifacthub.io/argo-cd
الخطوة 9 — تأمين الأسرار في Git بـ Sealed Secrets
نمط GitOps له عيب واضح: لا يمكن التزام Secrets Kubernetes في الواضح. sealed-secrets من Bitnami حلّ بسيط: متحكّم في العنقود يملك مفتاحًا خاصًّا يفكّ تشفير SealedSecret مُلتَزَم في Git.
# تثبيت sealed-secrets
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets \
--namespace kube-system
# تثبيت kubeseal CLI على المحطّة
KUBESEAL_VERSION=0.36.6
curl -OL https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz
tar xfz kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz
sudo install kubeseal /usr/local/bin/
# شَفِّر secret قائمًا
kubectl create secret generic db-password \
--from-literal=password=monsecret \
--dry-run=client -o yaml | \
kubeseal --format yaml > apps/myapp/db-password.sealed.yaml
الملفّ sealed يمكن التزامه في الواضح في Git، غير قابل للاستعمال خارج العنقود. حين يُزامن Argo CD، يُنشئ SealedSecret، يُحوِّله المتحكّم إلى Secret Kubernetes. مفتاح المتحكّم الخاصّ يجب حفظه احتياطيًّا خارج العنقود.
الخطوة 10 — تفعيل تنبيهات المزامنة
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.webhook.discord: |
url: https://discord.com/api/webhooks/...
headers:
- name: Content-Type
value: application/json
template.app-sync-failed: |
webhook:
discord:
method: POST
body: |
{"content": "🔴 {{.app.metadata.name}} sync failed: {{.app.status.operationState.message}}"}
trigger.on-sync-failed: |
- description: Application sync failed
send: [app-sync-failed]
when: app.status.operationState.phase in ['Error', 'Failed']
كلّ إخفاق مزامنة يُشغّل رسالة Discord. للمستخدمين بلا Discord، webhook يعمل مع أيّ خدمة (Mattermost، Matrix، Pushover).
الخطوة 11 — فهم فخاخ selfHeal
selfHeal: true قوي لكن له أثر جانبي: إن طبّق مُشَغِّل patch طارئ يدويًّا (مثلًا kubectl scale)، Argo CD سيُلغيه عند المزامنة التالية لأنّه لا يطابق Git. التفافان: وَسم المورد بـ argocd.argoproj.io/sync-options: IgnoreExtraneous=true أو التزام patch في Git. عمليًّا، نتعلّم ألّا نستعمل kubectl apply أبدًا على موارد مُدارة بـ Argo CD. هذا الانضباط يُحوِّل تشغيل العنقود: تاريخ كلّ تغيير، إعادة تشغيل تكوين قبل 3 أشهر، نشر تصحيح على 10 عناقيد عبر ApplicationSet واحد.
الخطوة 12 — التحقّق من إدارة Argo CD لنفسه
الخطوة النهائية لـ GitOps جعل Argo CD يُدير نفسه. chart Helm يُضاف للمستودع، Application تُشير إليه، وكلّ تحديث لـ Argo CD يمرّ عبر commit. بمجرّد مزامنة هذه Application، تحديث Argo CD يصير تعديل targetRevision: 9.5.12 إلى 8.5.0 والتزام. المتحكّم يُرَقِّي بنفسه نشره معاملاتيًّا. هذا إكمال سلسلة GitOps: كلّ العنقود، حتى الأداة التي تُزامنه، يعيش في Git.