بازگشت به میکروسرویس ها با ایستیو. قسمت 2

بازگشت به میکروسرویس ها با ایستیو. قسمت 2

توجه داشته باشید. ترجمه: بخش اول این مجموعه به معرفی قابلیت های ایستیو و نمایش آن ها در عمل اختصاص داشت. اکنون در مورد جنبه‌های پیچیده‌تر پیکربندی و استفاده از این سرویس مش، و به‌ویژه، در مورد مسیریابی دقیق و مدیریت ترافیک شبکه صحبت خواهیم کرد.

همچنین به شما یادآوری می کنیم که این مقاله از تنظیمات (مانیفست های Kubernetes و Istio) از مخزن استفاده می کند. تسلط istio.

مدیریت ترافیک

با Istio، قابلیت‌های جدیدی در خوشه ظاهر می‌شوند تا موارد زیر را ارائه دهند:

  • مسیریابی درخواست پویا: نصب قناری، تست A/B.
  • تعادل بار: ساده و سازگار، بر اساس هش.
  • بهبودی پس از سقوط: وقفه، تلاش مجدد، قطع کننده مدار.
  • درج عیوب: تأخیرها، درخواست های حذف شده و غیره

همانطور که مقاله ادامه دارد، این قابلیت ها با استفاده از اپلیکیشن انتخاب شده به عنوان مثال نشان داده شده و مفاهیم جدیدی در این مسیر معرفی خواهند شد. اولین چنین مفهومی خواهد بود DestinationRules (یعنی قوانین مربوط به گیرنده ترافیک/درخواست - تقریباً ترجمه)، که به کمک آن تست A/B را فعال می کنیم.

تست A/B: قوانین مقصد در عمل

تست A/B در مواردی استفاده می‌شود که دو نسخه از یک برنامه وجود دارد (معمولاً از نظر بصری متفاوت هستند) و ما 100٪ مطمئن نیستیم که کدام یک تجربه کاربر را بهبود می‌بخشد. بنابراین، ما هر دو نسخه را به طور همزمان اجرا می کنیم و معیارها را جمع آوری می کنیم.

برای استقرار نسخه دوم frontend که برای نمایش تست A/B لازم است، دستور زیر را اجرا کنید:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created

مانیفست استقرار برای نسخه سبز در دو مکان متفاوت است:

  1. تصویر بر اساس یک برچسب متفاوت است - istio-green,
  2. غلاف ها دارای برچسب هستند version: green.

از آنجایی که هر دو استقرار دارای یک برچسب هستند app: sa-frontend، درخواست هایی که توسط سرویس مجازی مسیریابی می شوند sa-external-services برای خدمات sa-frontend، به تمام نمونه های آن هدایت می شود و بار از طریق آن توزیع می شود الگوریتم دورگرد، که منجر به وضعیت زیر می شود:

بازگشت به میکروسرویس ها با ایستیو. قسمت 2
فایل های درخواستی یافت نشد

این فایل‌ها یافت نشدند زیرا در نسخه‌های مختلف برنامه نام‌های متفاوتی دارند. بیایید از این مطمئن شویم:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js

این بدان معناست که index.htmlبا درخواست یک نسخه از فایل های استاتیک، می توان توسط load balancer به پادهایی که نسخه متفاوتی دارند ارسال کرد، جایی که به دلایل واضح، چنین فایل هایی وجود ندارند. بنابراین، برای اینکه برنامه کار کند، باید یک محدودیت ایجاد کنیم:همان نسخه برنامه ای که index.html را ارائه می کند باید درخواست های بعدی را ارائه دهد'.

ما با تعادل بار مبتنی بر هش سازگار به آنجا خواهیم رسید (تعادل بار هش مداوم)... در این مورد درخواست‌های یک مشتری به همان نمونه پشتیبان ارسال می‌شوند، که برای آن از یک ویژگی از پیش تعریف شده استفاده می شود - به عنوان مثال، یک هدر HTTP. با استفاده از DestinationRules پیاده سازی شده است.

قوانین مقصد

پس از سرویس مجازی درخواستی را به سرویس مورد نظر ارسال کرد، با استفاده از DestinationRules می‌توانیم خط‌مشی‌هایی را تعریف کنیم که برای ترافیک مقصد برای نمونه‌هایی از این سرویس اعمال می‌شوند:

بازگشت به میکروسرویس ها با ایستیو. قسمت 2
مدیریت ترافیک با منابع ایستیو

یادداشت: تاثیر منابع Istio بر ترافیک شبکه در اینجا به گونه ای ارائه شده است که به راحتی قابل درک است. به طور دقیق، تصمیم گیری در مورد اینکه به کدام نمونه درخواست ارسال شود، توسط فرستاده در دروازه ورودی پیکربندی شده در CRD گرفته می شود.

با قوانین مقصد، می‌توانیم توازن بار را برای استفاده از هش‌های ثابت پیکربندی کنیم و اطمینان حاصل کنیم که همان نمونه سرویس به همان کاربر پاسخ می‌دهد. پیکربندی زیر به شما امکان می دهد به این هدف برسید (destinationrule-sa-frontend.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1

1 - هش بر اساس محتویات هدر HTTP ایجاد می شود version.

تنظیمات را با دستور زیر اعمال کنید:

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created

حالا دستور زیر را اجرا کنید و مطمئن شوید که فایل های مناسب را هنگام تعیین هدر دریافت کرده اید version:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' 'n' | grep main

یادداشت: برای افزودن مقادیر مختلف در هدر و تست نتایج به طور مستقیم در مرورگر، می توانید استفاده کنید این پسوند به کروم (یا با این برای فایرفاکس - تقریبا ترجمه.).

به طور کلی، DestinationRules دارای قابلیت های بیشتری در زمینه تعادل بار است - برای جزئیات در اسناد رسمی.

قبل از مطالعه بیشتر VirtualService، اجازه دهید "نسخه سبز" برنامه و قانون جهت ترافیک مربوطه را با اجرای دستورات زیر حذف کنیم:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions “sa-frontend-green” deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io “sa-frontend” deleted

Mirroring: خدمات مجازی در عمل

سایه ("سپر") یا Mirroring ("آینه کاری") در مواردی استفاده می‌شود که می‌خواهیم تغییری در تولید را بدون تأثیرگذاری بر کاربران نهایی آزمایش کنیم: برای انجام این کار، درخواست‌های («آینه‌ای») را به نمونه دومی که تغییرات مورد نظر ایجاد شده است، کپی می‌کنیم و به عواقب آن نگاه می‌کنیم. به زبان ساده، این زمانی است که همکار شما بحرانی‌ترین موضوع را انتخاب می‌کند و به شکل توده‌ای عظیم از خاک درخواست می‌کند که هیچ‌کس واقعاً نمی‌تواند آن را بررسی کند.

برای آزمایش این سناریو در عمل، اجازه دهید نمونه دوم SA-Logic را با اشکالات ایجاد کنیم (buggy) با اجرای دستور زیر:

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created

و حالا بیایید دستور را اجرا کنیم تا مطمئن شویم که همه نمونه ها با app=sa-logic آنها همچنین دارای برچسب هایی با نسخه های مربوطه هستند:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2

سرویس sa-logic غلاف ها را با یک برچسب هدف قرار می دهد app=sa-logic، بنابراین همه درخواست ها بین همه موارد توزیع می شود:

بازگشت به میکروسرویس ها با ایستیو. قسمت 2

... اما ما می خواهیم درخواست ها به نمونه های v1 ارسال شوند و به نمونه های v2 منعکس شوند:

بازگشت به میکروسرویس ها با ایستیو. قسمت 2

ما از طریق VirtualService در ترکیب با DestinationRule به این امر دست خواهیم یافت، جایی که قوانین زیرمجموعه‌ها و مسیرهای VirtualService را به یک زیر مجموعه خاص تعیین می‌کنند.

تعریف زیر مجموعه ها در قوانین مقصد

زیر مجموعه ها (زیر مجموعه ها) با پیکربندی زیر تعیین می شوند (sa-logic-subsets-destinationrule.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2

  1. میزبان (host) تعریف می کند که این قانون فقط برای مواردی اعمال می شود که مسیر به سمت سرویس می رود sa-logic;
  2. عناوین (name) هنگام مسیریابی به نمونه های زیر مجموعه از زیر مجموعه ها استفاده می شود.
  3. برچسب (label) جفت‌های کلید-مقدار را تعریف می‌کند که نمونه‌ها باید مطابقت داشته باشند تا بخشی از زیر مجموعه شوند.

تنظیمات را با دستور زیر اعمال کنید:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
destinationrule.networking.istio.io/sa-logic created

اکنون که زیر مجموعه‌ها تعریف شده‌اند، می‌توانیم ادامه دهیم و VirtualService را پیکربندی کنیم تا قوانینی را برای درخواست‌ها به sa-logic اعمال کند تا آنها:

  1. به یک زیر مجموعه هدایت شده است v1,
  2. به یک زیر مجموعه منعکس شده است v2.

مانیفست زیر به شما امکان می دهد به برنامه های خود برسید (sa-logic-subsets-shadowing-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2

اینجا نیازی به توضیح نیست، پس بیایید آن را در عمل ببینیم:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created

بیایید با فراخوانی دستور زیر بار را اضافه کنیم:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment 
    -H "Content-type: application/json" 
    -d '{"sentence": "I love yogobella"}'; 
    sleep .8; done

بیایید به نتایج در Grafana نگاه کنیم، جایی که می توانید ببینید که نسخه با باگ (buggy) منجر به شکست برای 60٪ درخواست ها می شود، اما هیچ یک از این خرابی ها بر کاربران نهایی تأثیر نمی گذارد زیرا یک سرویس در حال اجرا به آنها پاسخ می دهد.

بازگشت به میکروسرویس ها با ایستیو. قسمت 2
پاسخ های موفق نسخه های مختلف سرویس sa-logic

در اینجا ما برای اولین بار دیدیم که چگونه VirtualService برای فرستادگان خدمات ما اعمال می شود: وقتی sa-web-app درخواست می کند به sa-logic، از طریق sidecar Envoy می رود، که - از طریق VirtualService - پیکربندی شده است تا درخواست را به زیر مجموعه v1 هدایت کند و درخواست را به زیر مجموعه v2 سرویس منعکس کند. sa-logic.

می دانم، ممکن است فکر کنید که خدمات مجازی ساده است. در بخش بعدی، آن را با گفتن اینکه آنها واقعاً عالی هستند نیز توضیح خواهیم داد.

عرضه قناری

Canary Deployment فرآیند ارائه نسخه جدید یک برنامه کاربردی برای تعداد کمی از کاربران است. برای اطمینان از اینکه هیچ مشکلی در انتشار وجود ندارد استفاده می شود و تنها پس از آن، با اطمینان از کیفیت (نسخه) آن، آن را بین کاربران دیگر توزیع می کند.оمخاطب بزرگتر

برای نشان دادن عرضه قناری، ما به کار با زیر مجموعه ادامه خواهیم داد buggy у sa-logic.

بیایید وقت خود را با چیزهای بی اهمیت تلف نکنیم و فوراً 20٪ از کاربران را به نسخه دارای اشکالات بفرستیم (این نشان دهنده عرضه قناری ما است) و 80٪ باقی مانده را به سرویس عادی ارسال کنیم. برای این کار از VirtualService زیر استفاده کنید (sa-logic-subsets-canary-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20 # 1

1 وزن است (weight) که درصد درخواست هایی را که به یک گیرنده یا زیرمجموعه ای از گیرنده ارسال می شود را مشخص می کند.

بیایید پیکربندی VirtualService قبلی را به روز کنیم sa-logic با دستور زیر:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

... و بلافاصله خواهیم دید که برخی از درخواست ها منجر به شکست می شوند:

$ while true; do 
   curl -i http://$EXTERNAL_IP/sentiment 
   -H "Content-type: application/json" 
   -d '{"sentence": "I love yogobella"}' 
   --silent -w "Time: %{time_total}s t Status: %{http_code}n" 
   -o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500

VirtualServices عرضه قناری را فعال می کند: در این مورد، ما تأثیر بالقوه مشکلات را به 20٪ از پایگاه کاربر کاهش داده ایم. فوق العاده! حال در هر موردی که از کد خود مطمئن نیستیم (به عبارت دیگر - همیشه...) می توانیم از Mirroring و Canary rollout استفاده کنیم.

مهلت زمانی و تلاش مجدد

اما باگ‌ها همیشه به کد ختم نمی‌شوند. در لیست از "8 تصور غلط در مورد محاسبات توزیع شده"در وهله اول این باور اشتباه است که "شبکه قابل اعتماد است." در واقع شبکه هیچ قابل اعتماد، و به همین دلیل ما نیاز به تایم اوت داریم (تایم اوت) و دوباره تلاش می کند (تلاش مجدد).

برای نمایش به استفاده از همان نسخه مشکل ادامه خواهیم داد sa-logic (buggy) و ما غیرقابل اعتماد بودن شبکه را با خرابی های تصادفی شبیه سازی می کنیم.

اجازه دهید سرویس ما با اشکالات 1/3 شانس طولانی برای پاسخ دادن، 1/3 احتمال پایان یافتن با خطای سرور داخلی، و 1/3 شانس برای بازگشت موفقیت آمیز صفحه داشته باشد.

برای کاهش تأثیر چنین مشکلاتی و بهبود زندگی برای کاربران، می‌توانیم:

  1. اگر سرویس بیش از 8 ثانیه طول بکشد تا پاسخ دهد، مهلت زمانی اضافه کنید،
  2. اگر درخواست شکست خورد، دوباره امتحان کنید.

برای پیاده سازی، از تعریف منبع زیر استفاده خواهیم کرد (sa-logic-retries-timeouts-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s # 3

  1. مدت زمان درخواست 8 ثانیه تنظیم شده است.
  2. درخواست ها 3 بار تکرار می شوند.
  3. و اگر زمان پاسخگویی بیش از 3 ثانیه باشد، هر تلاش ناموفق تلقی می شود.

این یک بهینه سازی است زیرا کاربر مجبور نخواهد بود بیش از 8 ثانیه منتظر بماند و در صورت شکست سه بار تلاش جدید برای دریافت پاسخ انجام خواهیم داد و شانس پاسخ موفقیت آمیز را افزایش خواهیم داد.

تنظیمات به روز شده را با دستور زیر اعمال کنید:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

و در نمودارهای Grafana بررسی کنید که تعداد پاسخ های موفق در بالا افزایش یافته است:

بازگشت به میکروسرویس ها با ایستیو. قسمت 2
بهبود در آمار پاسخ‌های موفقیت‌آمیز پس از افزودن وقفه‌ها و تلاش‌های مجدد

قبل از اینکه به بخش بعدی بروید (یا بهتر است به قسمت بعدی مقاله بروید، زیرا در این مورد آزمایش عملی دیگری وجود نخواهد داشت - تقریباً ترجمه.)، حذف sa-logic-buggy و VirtualService با اجرای دستورات زیر:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions “sa-logic-buggy” deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io “sa-logic” deleted

مدار شکن و الگوهای باک

ما در مورد دو الگوی مهم در معماری میکروسرویس صحبت می کنیم که به شما امکان می دهد به بازیابی خود برسید (خود درمانی) خدمات.

مدار شکن ("شکن مدار") برای خاتمه دادن به درخواست‌هایی که به نمونه‌ای از سرویسی که ناسالم تلقی می‌شود و بازیابی آن استفاده می‌شود در حالی که درخواست‌های مشتری به نمونه‌های سالم آن سرویس هدایت می‌شوند (که درصد پاسخ‌های موفق را افزایش می‌دهد). (توجه: توضیحات دقیق تری از الگو را می توان یافت، به عنوان مثال، اینجا.)

فلوچارت ("تقسیم بندی") خرابی های سرویس را از تأثیر بر کل سیستم جدا می کند. به عنوان مثال، سرویس B خراب است و سرویس دیگری (سرویس B's client) درخواستی را به سرویس B ارائه می دهد و باعث می شود تا thread pool خود را تمام کند و نتواند به سایر درخواست ها سرویس دهد (حتی اگر از سرویس B نباشند). (توجه: توضیحات دقیق تری از الگو را می توان یافت، به عنوان مثال، اینجا.)

من جزئیات پیاده سازی این الگوها را حذف می کنم زیرا یافتن آنها آسان است اسناد رسمی، و همچنین من واقعاً می خواهم تأیید اعتبار و مجوز را نشان دهم که در قسمت بعدی مقاله مورد بحث قرار خواهد گرفت.

PS از مترجم

در وبلاگ ما نیز بخوانید:

منبع: www.habr.com

اضافه کردن نظر