إصدار 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: