إصدار Canary السلس باستخدام APISIX Ingress Controller مع Flagger

Hengliang Tan

January 19, 2023

Ecosystem

المؤلف: هينغليانغ تان، مدير هندسة في 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.

featured-<Flagger and Apache APISIX Ingress>.jpg

لنختبر معًا عملية الإصدار الكناري السلسة هذه.

البيئة

يتطلب مجموعة 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

featured-<version 1>.jpg

في هذه المرحلة، يمكنك الوصول إلى التطبيق عبر النطاق app.example.com (استبدل app.example.com في المثال باسم النطاق الفعلي الخاص بك)، وسترى الإصدار الحالي من التطبيق.

أتمتة الإصدار الكناري

يقوم Flagger بتنفيذ حلقة تحكم تقوم بتحويل الحركة تدريجيًا إلى العقد الكناري مع قياس مقاييس الأداء الرئيسية مثل معدل نجاح طلبات HTTP، متوسط مدة الطلب، وصحة الـ pod. وفقًا لتحليل المؤشرات ذات الصلة، يتم إصدار أو إيقاف النشر الكناري ونشر نتائج التحليل إلى منصات ذات صلة مثل Slack، MS Teams أو Prometheus Alert Manager، إلخ.

Flagger Control Loop

قم بتشغيل إصدار كناري عن طريق تحديث إصدار صورة الحاوية

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 باسم النطاق الفعلي الخاص بك).

featured-<version 2>.jpg

عند عرض مورد 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

سترى الإصدار المستقر الأخير عند اكتمال النشر النهائي.

featured-<version 3>.jpg

ملاحظة: سيقوم 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.

Tags: