إصدار Canary السلس باستخدام APISIX Ingress Controller مع Flagger
Hengliang Tan
January 19, 2023
المؤلف: هينغليانغ تان، مدير هندسة في XPENG
في عملية تطوير المشاريع، غالبًا ما تكون تحديثات الخدمة تحديًا. لتوفير أفضل تجربة مستخدم، نحتاج إلى تجنب خطر عدم توفر الخدمة قدر الإمكان. ومن هنا ولد التسليم المستمر، الذي تم قبوله كممارسة برمجية للمؤسسات، وهو تطور طبيعي لمبادئ التكامل المستمر الراسخة. ومع ذلك، لا يزال النشر المستمر نادرًا جدًا بسبب تعقيد الإدارة والخوف من أن تؤثر إخفاقات النشر على توفر النظام. يعتبر الإصدار الكناري ربما السيناريو الأكثر كلاسيكية في نظام التسليم المستمر. بناءً على ذلك، يمكننا اكتشاف الخدمات غير الصحية والمشكلة بسرعة والتراجع إلى الإصدار السابق بسهولة.
الإصدار الكناري
يُعرف الإصدار الكناري أيضًا باسم الإصدار الرمادي. بشكل عام، يتم إصدار ونشر الإصدار الجديد من التطبيق كـ "كناري" لاختبار الأداء. يبقى الإصدار القديم للعمليات العادية في نفس المرحلة. أثناء الترقية، سيتم توجيه بعض المستخدمين لاستخدام الإصدار الجديد، بينما سيستمر المستخدمون الآخرون في استخدام الإصدار القديم. على أساس ضمان استقرار النظام العام، يمكن اكتشاف الأخطاء مبكرًا وإجراء التعديلات في الوقت المناسب.
لا يقوم الإصدار الكناري بإصدار التحديث مباشرة. بل يقوم بتوجيه نسبة معينة من الحركة إلى عدد صغير من المستخدمين. إذا لم يتم اكتشاف أي أخطاء، سيتم ترقيته لجميع المستخدمين، وسيتم التخلص من الإصدار القديم. هذه الطريقة تقلل من خطر إدخال وظائف جديدة في بيئة الإنتاج.
ستقدم هذه المقالة كيفية تحقيق إصدار كناري سلس من خلال Apache APISIX Ingress وFlagger، وتحسين كفاءة الإصدار، وتقليل مخاطر الإصدار.
حول Apache APISIX Ingress
يتم تحقيق Apache APISIX Ingress بواسطة Kubernetes Ingress Controller الذي يستخدم Apache APISIX كبروكسي مستوى البيانات. يوفر مئات الوظائف، مثل موازنة الحمل، المنبع الديناميكي، الإصدار الكناري، التوجيه الدقيق، الحد من المعدل، تخفيض الخدمة، كسر دائرة الخدمة، المصادقة، والمراقبة. تم اعتماده من قبل شركات ومنظمات محلية ودولية، بما في ذلك Zoom، Tencent Cloud، Jiakaobaodian، Horizon Robotics، European Copernicus Reference System، وغيرها.
حول Flagger
Flagger هو مشروع CNCF (Cloud Native Computing Foundation) وجزء من عائلة أدوات GitOps الخاصة بـ Flux. مؤخرًا، أعلنت CNCF أيضًا عن التخرج الرسمي لـ Flux، وهو مؤشر جيد على نجاح واعد لتقنية الحوسبة السحابية. كأداة تسليم تدريجي، يقوم Flagger بأتمتة عملية الإصدار للتطبيقات التي تعمل على Kubernetes. يقلل من خطر إدخال إصدار برمجي جديد في الإنتاج عن طريق تحويل الحركة تدريجيًا إلى الإصدار الجديد مع قياس مقاييس التحليلات وإجراء اختبارات التوافق.
بعد الجهود المستمرة لمجتمعات Apache APISIX وFlux، أطلق Flagger مؤخرًا الإصدار v1.27.0، الذي يدعم الإصدار الكناري التلقائي باستخدام Apache APISIX Ingress وFlagger.
لنختبر معًا عملية الإصدار الكناري السلسة هذه.
البيئة
يتطلب مجموعة Kubernetes من الإصدار v1.19 أو أحدث، والتي يمكنك تثبيتها عبر kind.
تثبيت المكونات
استخدم Helm V3 لتثبيت Apache APISIX وApache APISIX Ingress Controller
helm repo add apisix https://charts.apiseven.com
kubectl create ns apisix
helm upgrade -i apisix apisix/apisix --version=0.11.3 \
--namespace apisix \
--set apisix.podAnnotations."prometheus\.io/scrape"=true \
--set apisix.podAnnotations."prometheus\.io/port"=9091 \
--set apisix.podAnnotations."prometheus\.io/path"=/apisix/prometheus/metrics \
--set pluginAttrs.prometheus.export_addr.ip=0.0.0.0 \
--set pluginAttrs.prometheus.export_addr.port=9091 \
--set pluginAttrs.prometheus.export_uri=/apisix/prometheus/metrics \
--set pluginAttrs.prometheus.metric_prefix=apisix_ \
--set ingress-controller.enabled=true \
--set ingress-controller.config.apisix.serviceNamespace=apisix
قم بتثبيت مكونات Flagger وPrometheus في مساحة الاسم apisix.
helm repo add flagger https://flagger.app
helm upgrade -i flagger flagger/flagger \
--namespace apisix \
--set prometheus.install=true \
--set meshProvider=apisix
ملاحظة: إذا كنت بحاجة إلى تخصيص Prometheus أو Prometheus Operator، يمكنك البحث عن مقالات ذات صلة للتعديل.
تهيئة التطبيق
يمكن تطبيق Flagger على نشر Kubernetes وأحمال عمل أخرى، ويمكن أيضًا دمجه مع HPA. سيتم إنشاء سلسلة من الكائنات: نشرات Kubernetes، خدمات ClusterIP، وApisixRoute. يمكن لهذه الكائنات تعريض التطبيقات خارج المجموعات لتوفير الخدمات وتستخدم لتحليل عملية الإصدار الكناري.
قم بإنشاء مساحة اسم اختبار جديدة:
kubectl create ns test
قم بإنشاء نشر جديد وHPA. هنا نستخرج نموذج الكود الرسمي من Flagger.
kubectl apply -k https://github.com/fluxcd/flagger//kustomize/podinfo?ref=main
قم بنشر خدمة اختبار الحمل الخاصة بـ Flagger لتوليد حركة أثناء الإصدار الكناري للتحليل.
helm upgrade -i flagger-loadtester flagger/loadtester \ --namespace=test
قم بإنشاء ApisixRoute
الخاص بـ Apache APISIX، ثم سيقوم Flagger بالإشارة إلى المورد الذي تم إنشاؤه وإنشاء ApisixRoute
الخاص بـ Apache APISIX Ingress في الإصدار الكناري. (استبدل app.example.com
في المثال أدناه باسم النطاق الفعلي الخاص بك)
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: podinfo
namespace: test
spec:
http:
- backends:
- serviceName: podinfo
servicePort: 80
match:
hosts:
- app.example.com
methods:
- GET
paths:
- /*
name: method
plugins:
- name: prometheus
enable: true
config:
disable: false
prefer_name: true
احفظه كـ podinfo-apisixroute.yaml
وقم بتقديمه إلى المجموعة:
kubectl apply -f ./podinfo-apisixroute.yaml
قم بإنشاء مورد مخصص Flagger Canary. (استبدل app.example.com
في المثال باسم النطاق الفعلي الخاص بك)
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: podinfo
namespace: test
spec:
provider: apisix
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
# Refer apisix route
routeRef:
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
name: podinfo
progressDeadlineSeconds: 60
service:
port: 80
targetPort: 9898
analysis:
interval: 10s
# maximum number of failures for roll back
threshold: 10
# maximum percentage of traffic to the canary version
# (0-100)
maxWeight: 50
# the step size of the canary analysis
# (0-100)
stepWeight: 10
# use Prometheus to check the traffic information of APISIX
metrics:
- name: request-success-rate
# the minimum success rate (none 5xx responses)
# (0-100)
thresholdRange:
min: 99
interval: 1m
- name: request-duration
# P99 is the largest request delay(ms)
thresholdRange:
max: 500
interval: 30s
webhooks:
# automated traffic for canary analysis, modified based on the actual scenario
- name: load-test
url: http://flagger-loadtester.test/
timeout: 5s
type: rollout
metadata:
cmd: |-
hey -z 1m -q 10 -c 2 -h2 -host app.example.com http://apisix-gateway.apisix/api/info
احفظه كـ podinfo-canary.yaml
وقم بتقديمه إلى المجموعة:
kubectl apply -f ./podinfo-canary.yaml
سيقوم Flagger تلقائيًا بإنشاء الموارد ذات الصلة:
# تم تقديمه deployment.apps/podinfo horizontalpodautoscaler.autoscaling/podinfo apisixroute/podinfo canary.flagger.app/podinfo
# تم إنشاؤه تلقائيًا deployment.apps/podinfo-primary horizontalpodautoscaler.autoscaling/podinfo-primary service/podinfo service/podinfo-canary service/podinfo-primary apisixroute/podinfo-podinfo-canary
في هذه المرحلة، يمكنك الوصول إلى التطبيق عبر النطاق app.example.com (استبدل app.example.com
في المثال باسم النطاق الفعلي الخاص بك)، وسترى الإصدار الحالي من التطبيق.
أتمتة الإصدار الكناري
يقوم Flagger بتنفيذ حلقة تحكم تقوم بتحويل الحركة تدريجيًا إلى العقد الكناري مع قياس مقاييس الأداء الرئيسية مثل معدل نجاح طلبات HTTP، متوسط مدة الطلب، وصحة الـ pod. وفقًا لتحليل المؤشرات ذات الصلة، يتم إصدار أو إيقاف النشر الكناري ونشر نتائج التحليل إلى منصات ذات صلة مثل Slack، MS Teams أو Prometheus Alert Manager، إلخ.
قم بتشغيل إصدار كناري عن طريق تحديث إصدار صورة الحاوية
kubectl -n test set image deployment/podinfo \ podinfod=stefanprodan/podinfo:6.0.1
سيقوم Flagger بالكشف عن وجود إصدار جديد من النشر وسيبدأ تشغيل تجريبي لتحليل الإصدار الكناري.
kubectl -n test describe canary/podinfo
Status:
Canary Weight: 0
Conditions:
Message: Canary analysis completed successfully, promotion finished.
Reason: Succeeded
Status: True
Type: Promoted
Failed Checks: 1
Iterations: 0
Phase: Succeeded
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Synced 2m59s flagger podinfo-primary.test not ready: waiting for rollout to finish: observed deployment generation less than desired generation
Warning Synced 2m50s flagger podinfo-primary.test not ready: waiting for rollout to finish: 0 of 1 (readyThreshold 100%) updated replicas are available
Normal Synced 2m40s (x3 over 2m59s) flagger all the metrics providers are available!
Normal Synced 2m39s flagger Initialization done! podinfo.test
Normal Synced 2m20s flagger New revision detected! Scaling up podinfo.test
Warning Synced 2m (x2 over 2m10s) flagger canary deployment podinfo.test not ready: waiting for rollout to finish: 0 of 1 (readyThreshold 100%) updated replicas are available
Normal Synced 110s flagger Starting canary analysis for podinfo.test
Normal Synced 109s flagger Advance podinfo.test canary weight 10
Warning Synced 100s flagger Halt advancement no values found for apisix metric request-success-rate probably podinfo.test is not receiving traffic: running query failed: no values found
Normal Synced 90s flagger Advance podinfo.test canary weight 20
Normal Synced 80s flagger Advance podinfo.test canary weight 30
Normal Synced 69s flagger Advance podinfo.test canary weight 40
Normal Synced 59s flagger Advance podinfo.test canary weight 50
Warning Synced 30s (x2 over 40s) flagger podinfo-primary.test not ready: waiting for rollout to finish: 1 old replicas are pending termination
Normal Synced 9s (x3 over 50s) flagger (combined from similar events): Promotion completed! Scaling down podinfo.test
خلال عملية الإصدار الكناري، ستتلقى ردودًا مختلفة عند الوصول إلى التطبيق عبر النطاق app.example.com (استبدل app.example.com
باسم النطاق الفعلي الخاص بك).
عند عرض مورد ApisixRoute
podinfo-podinfo-canary
الخاص بـ Apache APISIX الذي تم إنشاؤه تلقائيًا بواسطة Flagger، ستجد أن أوزان الخدمة podinfo-primary
والخدمة podinfo-canary
تتغير مع عملية النشر.
spec:
http:
- backends:
- serviceName: podinfo-primary
servicePort: 80
# تم تعديله تلقائيًا بواسطة Flagger
weight: 80
- serviceName: podinfo-canary
servicePort: 80
# تم تعديله تلقائيًا بواسطة Flagger
weight: 20
سترى الإصدار المستقر الأخير عند اكتمال النشر النهائي.
ملاحظة: سيقوم Flagger بإعادة تشغيل تحليل الكناري إذا قمت بتغيير النشر مرة أخرى أثناء الإصدار الكناري.
يمكنك مراقبة جميع الإصدارات الكنارية باستخدام هذا الأمر:
watch kubectl get canaries --all-namespaces
NAMESPACE NAME STATUS WEIGHT LASTTRANSITIONTIME
test podinfo-2 Progressing 10 2022-11-23T05:00:54Z
test podinfo Succeeded 0 2022-11-23T06:00:54Z
التراجع
خلال تحليل الإصدار الكناري، يمكنك اختبار Flagger لإيقاف الإصدار الكناري والتراجع إلى الإصدار القديم عن طريق توليد طلب HTTP 500 Bad Request.
قم بتشغيل إصدار كناري آخر:
kubectl -n test set image deployment/podinfo \ podinfod=stefanprodan/podinfo:6.0.2
ادخل إلى حاوية اختبار الحمل
kubectl -n test exec -it deploy/flagger-loadtester bash
قم بتوليد خطأ HTTP 500:
hey -z 1m -c 5 -q 5 -host app.example.com http://apisix-gateway.apisix/status/500
قم بمحاكاة تأخير الخادم:
watch -n 1 curl -H \"host: app.example.com\" http://apisix-gateway.apisix/delay/1
عندما يصل عدد الإخفاقات المكتشفة إلى عتبة تحليل الكناري، يتم توجيه الحركة تلقائيًا إلى العقدة الرئيسية، يتم تقليص العقدة الكنارية إلى الصفر، ويتم تمييز عملية الإصدار الكناري بالفشل.
kubectl -n apisix logs deploy/flagger -f | jq .msg
"New revision detected! Scaling up podinfo.test"
"canary deployment podinfo.test not ready: waiting for rollout to finish: 0 of 1 (readyThreshold 100%) updated replicas are available"
"Starting canary analysis for podinfo.test"
"Advance podinfo.test canary weight 10"
"Halt podinfo.test advancement success rate 0.00% < 99%"
"Halt podinfo.test advancement success rate 26.76% < 99%"
"Halt podinfo.test advancement success rate 34.19% < 99%"
"Halt podinfo.test advancement success rate 37.32% < 99%"
"Halt podinfo.test advancement success rate 39.04% < 99%"
"Halt podinfo.test advancement success rate 40.13% < 99%"
"Halt podinfo.test advancement success rate 48.28% < 99%"
"Halt podinfo.test advancement success rate 50.35% < 99%"
"Halt podinfo.test advancement success rate 56.92% < 99%"
"Halt podinfo.test advancement success rate 67.70% < 99%"
"Rolling back podinfo.test failed checks threshold reached 10"
"Canary failed! Scaling down podinfo.test"
تخصيص المقاييس لتحليل الكناري
يمكن توسيع تحليل الكناري عن طريق استعلام مقاييس Prometheus. نقوم بالتخصيص بناءً على سيناريوهات العمل الفعلية. قم بإنشاء قالب مقياس وقم بتقديمه إلى المجموعة.
apiVersion: flagger.app/v1beta1
kind: MetricTemplate
metadata:
name: not-found-percentage
namespace: test
spec:
provider:
type: prometheus
address: http://flagger-prometheus.apisix:9090
query: |
sum(
rate(
apisix_http_status{
route=~"{{ namespace }}_{{ route }}-{{ target }}-canary_.+",
code!~"4.."
}[{{ interval }}]
)
)
/
sum(
rate(
apisix_http_status{
route=~"{{ namespace }}_{{ route }}-{{ target }}-canary_.+"
}[{{ interval }}]
)
) * 100
# قم بتعديل التحليل في الإصدار الكناري وإضافة قالب المؤشر الذي تم إنشاؤه أعلاه.
analysis:
metrics:
- name: "404s percentage"
templateRef:
name: not-found-percentage
thresholdRange:
max: 5
interval: 1m
يقوم التكوين أعلاه بالتحقق من الكناري عن طريق التحقق مما إذا كان معدل QPS (الاستعلامات في الثانية) لطلبات HTTP 404 أعلى من 5% من إجمالي الحركة. يفشل النشر الكناري إذا تجاوزت طلبات HTTP 404 عتبة 5%.
الخلاصة
يمكن توسيع العملية أعلاه مع المزيد من فحوصات المقاييس المخصصة، Webhook، الموافقات اليدوية وإشعارات Slack أو MS Teams.
تم تحقيق إصدار كناري سلس للغاية من خلال تكامل Apache APISIX وFlagger، مما يحسن كفاءة الإصدار ويقلل من مخاطر الإصدار. في المستقبل، ستعمل المجتمعات بشكل أوثق لتحقيق المزيد من قدرات النشر مثل Blue/Green Mirroring وA/B Testing.