
شبكة الخدمة Isstio
نحن في Namely نستخدم Istio لمدة عام الآن. ثم غادر للتو. كان لدينا انخفاض كبير في الأداء في مجموعة Kubernetes ، أردنا تتبع التوزيع وأخذنا Istio لتشغيل Jaeger واكتشافه. تتلاءم شبكة الخدمة جيدًا مع البنية التحتية الخاصة بنا والتي قررنا الاستثمار في هذه الأداة.
كان علي أن أعاني ، لكننا درسناه بعيدًا وواسعًا. هذا هو أول منشور في سلسلة حيث سأصف كيف يتكامل Istio مع Kubernetes وما تعلمناه عن عملها. في بعض الأحيان سوف نتجول في البرية التقنية ، ولكن ليس بعيدا جدا. كذلك سيكون هناك المزيد من الوظائف.
ما هو استيو؟
Istio هو أداة تكوين شبكة الخدمة. يقوم بقراءة حالة نظام Kubernetes والترقيات إلى الوكلاء L7 (HTTP و gRPC) ، والتي يتم تنفيذها على شكل جانبي في قرون Kubernetes. هذه الأزرار الجانبية عبارة عن حاويات Envoy التي تقرأ التكوين من Istio Pilot API (وخدمة gRPC) وتوجيه حركة المرور عبرها. مع وكيل L7 القوي تحت غطاء المحرك ، يمكننا استخدام المقاييس والتتبعات ومنطق إعادة المحاولة وقاطع الدائرة وموازنة التحميل ونشر الكناري.
لنبدأ من البداية: Kubernetes
في Kubernetes ، نقوم بإنشاء تحت استخدام نشر أو StatefulSet. أو يمكن أن يكون مجرد "الفانيليا" تحت بدون وحدة تحكم عالية المستوى. ثم Kubernetes يبذل قصارى جهده للحفاظ على الحالة المطلوبة - فإنه ينشئ القرون في الكتلة على العقدة ، ويتأكد من أنها تبدأ وإعادة تشغيل. عندما يتم إنشاء دالة under ، تمر Kubernetes خلال دورة حياة واجهة برمجة التطبيقات (API) ، وتتأكد من نجاح كل خطوة ، وعندئذٍ فقط تقوم بإنشاء علامة under على الكتلة.
مراحل دورة حياة واجهة برمجة التطبيقات:

بفضل Banzai Cloud للصورة الرائعة.
إحدى الخطوات هي تعديل webhooks القبول. هذا جزء منفصل من دورة الحياة في Kubernetes ، حيث يتم تخصيص الموارد قبل الالتزام بمستودع etcd ، مصدر الحقيقة لتكوين Kubernetes. وهنا Istio يفعل سحره.
تعديل القبول webhooks
عندما يتم إنشاء sub (عبر kubectl
أو Deployment
) ، فإنه يمر خلال دورة الحياة هذه ، ويغير الوصول إلى webhooks المعدلة قبل نقله إلى العالم الكبير.
أثناء تثبيت Istio ، تتم إضافة حاقن istio-sidecar كمورد تهيئة لتعديل خطافات الويب:
$ kubectl get mutatingwebhookconfiguration NAME AGE istio-sidecar-injector 87d
والتكوين:
apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration metadata: labels: app: istio-sidecar-injector chart: sidecarInjectorWebhook-1.0.4 heritage: Tiller name: istio-sidecar-injector webhooks: - clientConfig: caBundle: redacted service: name: istio-sidecar-injector namespace: istio-system path: /inject failurePolicy: Fail name: sidecar-injector.istio.io namespaceSelector: matchLabels: istio-injection: enabled rules: - apiGroups: - "" apiVersions: - v1 operations: - CREATE resources: - pods
تقول هنا أنه يجب على Kubernetes إرسال جميع أحداث إنشاء الموقد إلى istio-sidecar-injector
istio-system
مساحة الاسم istio-system
إذا كانت مساحة الاسم istio-injection=enabled
. يحتوي الحاقن على حاويتين أخريين في PodSpec: واحدة مؤقتة لإعداد قواعد الوكيل وواحدة للوكيل نفسه. حاقن istio-sidecar-injector
إدراج هذه الحاويات وفقا للقالب من خريطة تكوين istio-sidecar-injector
. وتسمى هذه العملية أيضا جانبا.
القرون Sidecar
Sidecar هي حيل الساحر لدينا Istio. يربط Istio كل شيء بذكاء بحيث يكون من الخارج مجرد سحر ، إذا كنت لا تعرف التفاصيل. ومعرفة هذه الأشياء مفيدة إذا كنت تحتاج فجأة إلى تصحيح طلبات الشبكة.
الحاويات الأولية والوكيل
تحتوي Kubernetes على حاويات أولية مؤقتة لمرة واحدة يمكن تشغيلها قبل العبوات الرئيسية. يقومون بتجميع الموارد أو ترحيل قواعد البيانات أو تكوين قواعد الشبكة ، كما هو الحال مع Istio.
يستخدم Istio برنامج Envoy للتوكيل على جميع طلبات التقديم على طول المسارات المطلوبة. للقيام بذلك ، تنشئ Istio قواعد iptables
، وترسل حركة المرور الواردة والصادرة مباشرة إلى Envoy ، وتقوم بتوصيل حركة المرور بدقة إلى وجهتها. تُحدث حركة المرور مسارًا صغيرًا ، لكنك وزّعت البحث عن المفقودين ومقاييس الاستعلام وإنفاذ السياسة. يوضح هذا الملف من مستودع Istio كيف ينشئ Istio قواعد iptables.
قام @ jimmysongio برسم مخطط اتصال ممتاز بين قواعد iptables ووكيل Envoy:

المبعوث - المبعوث المرور
يستقبل Envoy كل حركة المرور الواردة والصادرة ، وبالتالي تتحرك كل حركة المرور بشكل عام داخل Envoy ، كما في المخطط. وكيل Istio عبارة عن حاوية أخرى تضاف إلى جميع القرون التي يتم تعديلها بواسطة حاقن Istio الجانبي. في هذه الحاوية ، تبدأ عملية Envoy ، والتي تستقبل كل حركة المرور من الموقد (مع بعض الاستثناءات ، مثل حركة المرور من مجموعة Kubernetes الخاصة بك).
تكتشف عملية Envoy جميع المسارات من خلال واجهة برمجة تطبيقات Envoy v2 ، والتي تنفذ Istio.
المبعوث والطيار
المبعوث نفسه ليس لديه منطق للكشف عن القرون والخدمات في كتلة. إنها طائرة بيانات وتحتاج إلى طائرة تحكم لتوجيهها. تطلب معلمة تكوين Envoy من المضيف أو منفذ الخدمة استلام هذا التكوين من خلال واجهة برمجة تطبيقات gRPC. تستوفي Istio ، من خلال خدمتها التجريبية ، متطلبات واجهة برمجة تطبيقات gRPC. يتصل Envoy بواجهة برمجة التطبيقات هذه استنادًا إلى تكوين جانبي يتم تنفيذه من خلال تعديل webhook. تحتوي واجهة برمجة التطبيقات على جميع قواعد المرور التي يحتاج إليها المبعوث لاكتشاف نظام المجموعة وتوجيهه. هذه هي شبكة الخدمة.

تبادل البيانات "تحت <-> الطيار"
يتصل Pilot بمجموعة Kubernetes ، ويقرأ حالة الكتلة وينتظر التحديثات. يراقب الموقد والخدمات ونقاط النهاية في مجموعة Kubernetes ، ومن ثم إعطاء التكوين الصحيح لجميع جوانب السيارة Envoy المتصلة بالطيار. هذا هو الجسر بين Kubernetes و Envoy.

من الطيار إلى Kubernetes
عند إنشاء قرون أو خدمات أو نقاط نهاية في Kubernetes أو تحديثها ، يتعرف Pilot على ذلك ويرسل التكوين اللازم إلى جميع مثيلات Envoy المتصلة.
ما التكوين يتم إرسالها؟
ما التكوين الذي يحصل عليه المبعوث من Istio Pilot؟
بشكل افتراضي ، تعمل Kubernetes على حل مشكلات الشبكة لديك من خلال خدمة (خدمة) تدير endpoint
. يمكن فتح قائمة نقاط النهاية باستخدام الأمر:
kubectl get endpoints
هذه هي قائمة بجميع IP والمنافذ في الكتلة وعناوينها (وعادة ما تكون هذه القرون التي تم إنشاؤها من نشر). Istio من المهم أن تعرف من أجل تكوين وإرسال بيانات الطريق إلى Envoy.
الخدمات والمستمعين والطرق
عندما تقوم بإنشاء خدمة في مجموعة Kubernetes ، فإنك تقوم بتضمين اختصارات يتم من خلالها اختيار جميع البرامج المناسبة. عندما ترسل حركة مرور إلى عنوان IP للخدمة ، تختار Kubernetes حركة المرور لهذه الحركة. على سبيل المثال ، الأمر
curl my-service.default.svc.cluster.local:3000
أولاً ، سيعثر على IP الظاهري المعين لخدمة my-service
في مساحة الاسم default
، وسيعيد IP هذا توجيه حركة المرور إلى فرع فرعي يطابق تسمية الخدمة.
غيّر إستيو والمبعوث هذا المنطق بعض الشيء. يقوم Istio بتكوين Envoy استنادًا إلى الخدمات ونقاط النهاية في مجموعة Kubernetes ويستخدم ميزات التوجيه الذكية وموازنة التحميل من Envoy لتجاوز خدمة Kubernetes. بدلاً من بروكسي IP واحد في كل مرة ، يتصل Envoy مباشرة بموزع IP. للقيام بذلك ، يعين Istio تكوين Kubernetes إلى تكوين Envoy .
شروط Kubernetes و Istio و Envoy مختلفة قليلاً ، وليس من الواضح على الفور ما يأكلون.
الخدمات
تعيّن خدمة في Kubernetes كتلة في Envoy. تحتوي مجموعة Envoy على قائمة بنقاط النهاية ، أي IP (أو أسماء المضيف) لمثيلات معالجة الطلبات. للاطلاع على قائمة الكتل التي تم تكوينها في Istio sidecar-pod ، قم بتشغيل istioctl proxy-config cluster < >
. يوضح هذا الأمر الوضع الحالي من حيث الموقد. فيما يلي مثال من إحدى بيئاتنا:
$ istioctl proxy-config cluster taxparams-6777cf899c-wwhr7 -n applications SERVICE FQDN PORT SUBSET DIRECTION TYPE BlackHoleCluster - - - STATIC accounts-grpc-gw.applications.svc.cluster.local 80 - outbound EDS accounts-grpc-public.applications.svc.cluster.local 50051 - outbound EDS addressvalidator.applications.svc.cluster.local 50051 - outbound EDS
جميع الخدمات نفسها موجودة في مساحة الاسم هذه:
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) accounts-grpc-gw ClusterIP 10.3.0.91 <none> 80/TCP accounts-grpc-public ClusterIP 10.3.0.202 <none> 50051/TCP addressvalidator ClusterIP 10.3.0.56 <none> 50051/TCP
كيف يعرف Istio البروتوكول الذي يستخدم الخدمة؟ يقوم بتشكيل بروتوكولات الخدمة التي تظهر بواسطة حقل name
في إدخال المنفذ.
$ kubectl get service accounts-grpc-public -o yaml apiVersion: v1 kind: Service metadata: name: accounts-grpc-public spec: ports: - name: grpc port: 50051 protocol: TCP targetPort: 50051
إذا كان هناك grpc
أو بادئة grpc-
، فسيقوم Istio بتكوين بروتوكول HTTP2 للخدمة. لقد تعلمنا من خلال التجربة المريرة كيف يستخدم Istio اسم المنفذ عندما تكون تهيئة الخادم الوكيل تالفة لأنها لم تحدد بادئات http أو grpc ...
إذا كنت تستخدم kubectl وصفحة توجيه منفذ المسؤول في Envoy ، فيمكنك أن ترى أن نقاط النهاية الخاصة بالحساب - grpc - العام يتم تنفيذها بواسطة Pilot ككتلة في Envoy مع بروتوكول HTTP2. هذا يؤكد افتراضاتنا:
$ kubectl -n applications port-forward otherpod-dc56885ff-dqc6t 15000:15000 & $ curl http://localhost:15000/config_dump | yq r - ... - cluster: circuit_breakers: thresholds: - {} connect_timeout: 1s eds_cluster_config: eds_config: ads: {} service_name: outbound|50051||accounts-grpc-public.applications.svc.cluster.local http2_protocol_options: max_concurrent_streams: 1073741824 name: outbound|50051||accounts-grpc-public.applications.svc.cluster.local type: EDS ...
المنفذ 15000 هو صفحة المسؤول Envoy ، وهي متوفرة في كل جانب جانبي.
المستمعين
يتعرف المستمعون على نقاط النهاية في Kubernetes لتمرير حركة المرور إلى الموقد. تحتوي خدمة التحقق من العنوان على نقطة نهاية واحدة هنا:
$ kubectl get ep addressvalidator -o yaml apiVersion: v1 kind: Endpoints metadata: name: addressvalidator subsets: - addresses: - ip: 10.2.26.243 nodeName: ip-10-205-35-230.ec2.internal targetRef: kind: Pod name: addressvalidator-64885ccb76-87l4d namespace: applications ports: - name: grpc port: 50051 protocol: TCP
لذلك ، يحتوي موقد التحقق من العنوان على مستمع واحد على المنفذ 50051:
$ kubectl -n applications port-forward addressvalidator-64885ccb76-87l4d 15000:15000 & $ curl http://localhost:15000/config_dump | yq r - ... dynamic_active_listeners: - version_info: 2019-01-13T18:39:43Z/651 listener: name: 10.2.26.243_50051 address: socket_address: address: 10.2.26.243 port_value: 50051 filter_chains: - filter_chain_match: transport_protocol: raw_buffer ...
طرق
في Istio ، بدلاً من كائن Kubernetes Ingress القياسي ، يتم VirtualService
مورد مخصص أكثر تجريدًا وفعالية - VirtualService
. تقوم خدمة VirtualService بتخطيط الطرق إلى الكتل الأولية عن طريق ربطها بالبوابة. هذه هي كيفية استخدام Kubernetes Ingress مع وحدة تحكم Ingress.
في Namely ، نستخدم Istio Ingress-Gateway لجميع زيارات GRPC الداخلية:
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: grpc-gateway spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: http2 number: 80 protocol: HTTP2 --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: grpc-gateway spec: gateways: - grpc-gateway hosts: - '*' http: - match: - uri: prefix: /namely.address_validator.AddressValidator retries: attempts: 3 perTryTimeout: 2s route: - destination: host: addressvalidator port: number: 50051
للوهلة الأولى ، لن تفهم أي شيء في المثال. هذا غير مرئي هنا ، لكن سجلات نشر Istio-IngressGateway هي نقاط النهاية المطلوبة بناءً على istio: ingressgateway
. في هذا المثال ، يقوم IngressGateway بتوجيه حركة المرور لجميع المجالات عبر المنفذ 80 عبر HTTP2. تقوم VirtualService بتنفيذ التوجيهات الخاصة بهذه البوابة ، /namely.address_validator.AddressValidator
البادئة /namely.address_validator.AddressValidator
وتمرير addressvalidator
عبر المنفذ 50051 إلى الخدمة الأولية addressvalidator
قاعدة إعادة المحاولة في ثانيتين.
إذا قمنا بإعادة توجيه منفذ جراب Istio-IngressGateway وشاهدنا تكوين Envoy ، فسنرى ما تقوم به VirtualService:
$ kubectl -n istio-system port-forward istio-ingressgateway-7477597868-rldb5 15000 ... - match: prefix: /namely.address_validator.AddressValidator route: cluster: outbound|50051||addressvalidator.applications.svc.cluster.local timeout: 0s retry_policy: retry_on: 5xx,connect-failure,refused-stream num_retries: 3 per_try_timeout: 2s max_grpc_timeout: 0s decorator: operation: addressvalidator.applications.svc.cluster.local:50051/namely.address_validator.AddressValidator* ...
ما نحن googled أثناء الحفر في Istio
خطأ 503 أو 404 يحدث
الأسباب مختلفة ، ولكن عادة ما تكون هذه:
- يتعذر على تطبيقات Sidecar الاتصال بـ Pilot (تحقق من تشغيل Pilot).
- يحتوي بيان خدمة Kubernetes على بروتوكول غير صالح.
- تكوين VirtualService / Envoy يكتب المسار إلى كتلة upstream خاطئ. ابدأ بخدمة الحافة ، حيث تتوقع حركة المرور الواردة ، وفحص سجلات Envoy. أو استخدم شيئًا مثل جايجر للعثور على الأخطاء.
ماذا يعني NR / UH / UF في سجلات الوكيل Istio؟
- NR - لا يوجد طريق
- UH - المنبع غير صحية (المنبع غير صالحة للعمل).
- UF - فشل المنبع (فشل المنبع).
اقرأ المزيد على موقع المبعوث .
بشأن توافر عالية مع Istio
- أضف NodeAffinity إلى مكونات Istio لتوزيع الموقد بالتساوي عبر مناطق توفر مختلفة وزيادة الحد الأدنى لعدد النسخ المتماثلة.
- قم بتشغيل الإصدار الجديد من Kubernetes باستخدام ميزة Horizontal Pod Autoscaling. وأهم الموقد سوف مقياس على أساس الحمل.
لماذا لا ينتهي cronjob؟
عند اكتمال عبء العمل الرئيسي ، تستمر الحاوية الجانبية في العمل. لإيجاد حل بديل للمشكلة ، قم بتعطيل التطبيق الجانبي في cronjobs عن طريق إضافة تعليق توضيحي sidecar.istio.io/inject: “false”
إلى PodSpec.
كيفية تثبيت Istio؟
نحن نستخدم Spinnaker للنشر ، لكننا نأخذ عادةً أحدث مخططات Helm ، helm template -f values.yml
، helm template -f values.yml
ونلزم الملفات على Github لرؤية التغييرات قبل تطبيقها عبر kubectl apply -f -
. هذا من أجل عدم تغيير CRD أو API بطريق الخطأ في إصدارات مختلفة.
بفضل Bobby Tables ومايكل Hamrah للمساعدة في كتابة هذا المقال.