GitOps والتسليم المستمر
التسليم التدريجي
3 دقيقة للقراءة
التسليم التدريجي يوسع التسليم المستمر مع استراتيجيات نشر متحكم بها. باستخدام Argo Rollouts، يمكن لفرق المنصة توفير أنماط نشر أكثر أمانًا تكتشف وتتراجع تلقائيًا عن الإصدارات المشكلة.
لماذا التسليم التدريجي؟
النشر التقليدي هو كل شيء أو لا شيء:
النشر التقليدي:
┌─────────────────────────────────────────────────────────┐
│ │
│ v1 (100%) ───────────────────► v2 (100%) │
│ │
│ المشكلة: إذا كان v2 به مشاكل، 100% من المستخدمين متأثرون │
│ │
└─────────────────────────────────────────────────────────┘
التسليم التدريجي:
┌─────────────────────────────────────────────────────────┐
│ │
│ v1 (100%) → v1 (90%) → v1 (50%) → v1 (0%) │
│ → v2 (10%) → v2 (50%) → v2 (100%) │
│ │ │
│ فحص المقاييس، التراجع التلقائي إذا لزم │
│ │
└─────────────────────────────────────────────────────────┘
تثبيت Argo Rollouts
# تثبيت وحدة تحكم Argo Rollouts
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
# تثبيت إضافة kubectl
brew install argoproj/tap/kubectl-argo-rollouts
# أو: curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
# التحقق من التثبيت
kubectl argo rollouts version
# فتح لوحة التحكم
kubectl argo rollouts dashboard
# زيارة http://localhost:3100
نشر Canary
تحويل حركة المرور تدريجيًا للإصدار الجديد:
# rollout-canary.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: user-service
namespace: production
spec:
replicas: 10
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:v2.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
strategy:
canary:
# توجيه حركة المرور عبر service mesh أو ingress
canaryService: user-service-canary
stableService: user-service-stable
# تقسيم حركة المرور (يتطلب إدارة حركة المرور)
trafficRouting:
nginx:
stableIngress: user-service-ingress
steps:
# الخطوة 1: 10% حركة مرور لـ canary
- setWeight: 10
- pause: { duration: 5m }
# الخطوة 2: تشغيل التحليل
- analysis:
templates:
- templateName: success-rate
args:
- name: service-name
value: user-service-canary
# الخطوة 3: 30% حركة مرور
- setWeight: 30
- pause: { duration: 5m }
# الخطوة 4: 50% حركة مرور
- setWeight: 50
- pause: { duration: 10m }
# الخطوة 5: نشر كامل
- setWeight: 100
نشر Blue-Green
تبديل كل حركة المرور دفعة واحدة بعد التحقق:
# rollout-bluegreen.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: order-service
namespace: production
spec:
replicas: 5
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: order-service:v3.0.0
ports:
- containerPort: 8080
strategy:
blueGreen:
# الخدمة تشير للإنتاج الحالي
activeService: order-service-active
# الخدمة تشير للإصدار الجديد (للاختبار)
previewService: order-service-preview
# الترقية التلقائية بعد التحليل الناجح
autoPromotionEnabled: true
# انتظار التحليل قبل الترقية
prePromotionAnalysis:
templates:
- templateName: smoke-tests
args:
- name: service-url
value: http://order-service-preview.production.svc
# تقليص الإصدار القديم بعد الترقية
scaleDownDelaySeconds: 300
قوالب التحليل
تحديد المقاييس لقرارات النشر التلقائية:
# analysis-template-success-rate.yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
namespace: production
spec:
args:
- name: service-name
metrics:
- name: success-rate
# استعلام Prometheus لمعدل النجاح
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{
service="{{args.service-name}}",
status=~"2.."
}[5m])) /
sum(rate(http_requests_total{
service="{{args.service-name}}"
}[5m])) * 100
# معايير النجاح
successCondition: result[0] >= 99
failureLimit: 3
interval: 60s
count: 5
- name: error-rate
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{
service="{{args.service-name}}",
status=~"5.."
}[5m])) /
sum(rate(http_requests_total{
service="{{args.service-name}}"
}[5m])) * 100
successCondition: result[0] <= 1
failureLimit: 3
interval: 60s
count: 5
- name: latency-p99
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket{
service="{{args.service-name}}"
}[5m])) by (le)
)
successCondition: result[0] <= 0.5
failureLimit: 3
interval: 60s
count: 5
إدارة النشر
# مراقبة حالة النشر
kubectl argo rollouts get rollout user-service -w
# ترقية canary للخطوة التالية
kubectl argo rollouts promote user-service
# تخطي التحليل الحالي
kubectl argo rollouts promote user-service --skip-current-step
# إلغاء النشر (التراجع)
kubectl argo rollouts abort user-service
# إعادة محاولة النشر الفاشل
kubectl argo rollouts retry rollout user-service
# عرض تاريخ النشر
kubectl argo rollouts history user-service
# التراجع للمراجعة السابقة
kubectl argo rollouts undo user-service
التكامل مع ArgoCD
Argo Rollouts يعمل بسلاسة مع ArgoCD:
# application-with-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: user-service
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/acme/gitops-repo.git
path: apps/user-service
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
# ArgoCD يكتشف موارد Rollout ويعرض
# حالة التسليم التدريجي في الواجهة
مقارنة استراتيجيات النشر
# دليل اختيار الاستراتيجية
strategies:
canary:
when_to_use:
- "تحويل حركة المرور التدريجي مطلوب"
- "تريد الاختبار مع مجموعة فرعية من المستخدمين"
- "متطلبات تحليل معقدة"
traffic_pattern: "تدريجي (10% → 30% → 50% → 100%)"
rollback_speed: "فوري (تحويل حركة المرور مرة أخرى)"
bluegreen:
when_to_use:
- "تحتاج اختبار البيئة الكاملة قبل التبديل"
- "تغييرات مخطط قاعدة البيانات"
- "إدارة حركة مرور أبسط"
traffic_pattern: "تبديل كل شيء أو لا شيء"
rollback_speed: "فوري (التبديل إلى blue)"
recreate:
when_to_use:
- "بيئات التطوير"
- "أحمال العمل غير الحرجة"
- "تغييرات جذرية لا يمكن تشغيلها جنبًا إلى جنب"
traffic_pattern: "إيقاف، ثم تشغيل"
rollback_speed: "إعادة نشر كاملة"
في الدرس التالي، سندمج GitOps مع Crossplane وBackstage لسير عمل IDP كامل. :::