حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes

ملحوظة. ترجمة.: هذه القصة التحذيرية لأوميو ، مجمع السفر الأوروبي ، يأخذ القراء من النظرية الأساسية إلى التعقيدات العملية الرائعة لتكوين Kubernetes. إن التعرف على مثل هذه الحالات لا يساعد فقط في توسيع آفاق المرء ، ولكن أيضًا في منع المشكلات غير التافهة.

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes

هل سبق لك أن واجهت حقيقة أن التطبيق "عالق" في مكانه ، وتوقف عن الاستجابة لطلبات الفحوصات الصحية ولم تستطع فهم سبب هذا السلوك؟ أحد التفسيرات المحتملة يتعلق بحد الحصة النسبية لموارد وحدة المعالجة المركزية. سيتم مناقشتها في هذه المقالة.

TL؛ DR:
نوصي بشدة بتعطيل حدود وحدة المعالجة المركزية في Kubernetes (أو تعطيل حصص CFS في Kubelet) في حالة استخدام إصدار من Linux kernel مع وجود خطأ في حصة CFS. في الصميم متاح جاد و معروف خلل يؤدي إلى الاختناق المفرط والتأخير
.

في أوميو تتم إدارة البنية التحتية بالكامل بواسطة Kubernetes. تعمل جميع أعباء العمل الخاصة بنا وعديمة الحالة حصريًا على Kubernetes (نستخدم Google Kubernetes Engine). في الأشهر الستة الماضية ، بدأنا في ملاحظة تباطؤ عشوائي. تجمد التطبيقات أو تتوقف عن الاستجابة للفحوصات الصحية ، أو تفقد الاتصال بالشبكة ، وما إلى ذلك. لقد حيرنا هذا السلوك لفترة طويلة ، وفي النهاية قررنا التعامل مع المشكلة بجدية.

ملخص المقال:

  • بضع كلمات عن الحاويات و Kubernetes ؛
  • كيف يتم تنفيذ طلبات وحدود وحدة المعالجة المركزية ؛
  • كيف يعمل حد وحدة المعالجة المركزية في بيئات متعددة النواة ؛
  • كيفية تتبع اختناق وحدة المعالجة المركزية ؛
  • حل المشكلات والتفاصيل.

بضع كلمات عن الحاويات و Kubernetes

Kubernetes هو في الأساس المعيار الحديث في عالم البنية التحتية. مهمتها الرئيسية هي تنظيم الحاويات.

حاويات

في الماضي ، كان علينا إنشاء أدوات مثل Java JARs / WARs أو Python Eggs أو الملفات التنفيذية للتشغيل على الخوادم. ومع ذلك ، لجعلها تعمل ، كان عليك القيام بعمل إضافي: تثبيت وقت التشغيل (Java / Python) ، ووضع الملفات الضرورية في الأماكن الصحيحة ، والتأكد من التوافق مع إصدار معين من نظام التشغيل ، وما إلى ذلك. بمعنى آخر ، كان عليك الانتباه عن كثب إلى إدارة التكوين (والتي غالبًا ما تسبب خلافًا بين المطورين ومسؤولي النظام).

لقد غيرت الحاويات كل شيء. الآن صورة الحاوية هي الأداة. يمكن تمثيله كنوع من الملفات القابلة للتنفيذ الموسعة التي لا تحتوي فقط على البرنامج ، ولكن أيضًا على بيئة وقت تشغيل كاملة (Java / Python / ...) ، بالإضافة إلى الملفات / الحزم الضرورية ، المثبتة مسبقًا وجاهزة للتشغيل. يمكن نشر الحاويات وتشغيلها على خوادم مختلفة دون أي خطوات إضافية.

بالإضافة إلى ذلك ، تعمل الحاويات في بيئة رمل خاصة بها. لديهم محول الشبكة الافتراضية الخاصة بهم ، ونظام الملفات الخاص بهم مع وصول محدود ، والتسلسل الهرمي للعمليات الخاصة بهم ، والقيود الخاصة بهم على وحدة المعالجة المركزية والذاكرة ، وما إلى ذلك ، يتم تنفيذ كل هذا بفضل نظام فرعي خاص من Linux kernel - مساحات الأسماء (مساحات الأسماء).

Kubernetes

كما ذكرنا سابقًا ، Kubernetes هو منظم حاويات. إنه يعمل على النحو التالي: تمنحه مجموعة من الأجهزة ، ثم تقول ، "مرحبًا Kubernetes ، قم بتشغيل عشر مثيلات من الحاوية الخاصة بي مع معالجين وذاكرة 2 جيجابايت لكل منهما ، واستمر في تشغيلهما!". سيهتم Kubernetes بالباقي. سيجد السعات المجانية ، وتشغيل الحاويات وإعادة تشغيلها إذا لزم الأمر ، وطرح تحديث عند تغيير الإصدارات ، وما إلى ذلك. في الأساس ، يسمح لك Kubernetes بالتخلص من الأجهزة وجعل جميع الأنظمة المتنوعة مناسبة لنشر التطبيقات وتشغيلها.

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes
Kubernetes من وجهة نظر شخص عادي بسيط

ما هي الطلبات والقيود في Kubernetes

حسنًا ، اكتشفنا الحاويات و Kubernetes. نعلم أيضًا أن العديد من الحاويات يمكن أن توجد على نفس الجهاز.

يمكنك رسم تشابه مع شقة مشتركة. تؤخذ غرفة واسعة (سيارات / مجمعات) وتأجيرها لعدة مستأجرين (حاويات). Kubernetes بمثابة سمسار عقارات. السؤال الذي يطرح نفسه ، كيف نمنع المستأجرين من النزاعات مع بعضهم البعض؟ ماذا لو قرر أحدهم ، على سبيل المثال ، أن يأخذ الحمام لمدة نصف يوم؟

هذا هو المكان الذي تلعب فيه الطلبات والقيود. وحدة المعالجة المركزية أطلب اللازمة لأغراض التخطيط فقط. هذا يشبه إلى حد ما "قائمة الرغبات" للحاوية ، ويستخدم لتحديد العقدة الأكثر ملاءمة. في نفس الوقت ، وحدة المعالجة المركزية قصر يمكن مقارنتها باتفاقية تأجير - بمجرد تحديد عقدة للحاوية ، هذا لن تكون قادرة تجاوز الحدود. وهنا تأتي المشكلة ...

كيف يتم تنفيذ الطلبات والحدود في Kubernetes

يستخدم Kubernetes آلية الاختناق (تخطي الساعة) المضمنة في النواة لتنفيذ حدود وحدة المعالجة المركزية. إذا تجاوز التطبيق الحد ، فسيتم تمكين الاختناق (أي يتلقى عددًا أقل من دورات وحدة المعالجة المركزية). يتم تنظيم طلبات الذاكرة وحدودها بشكل مختلف بحيث يسهل اكتشافها. للقيام بذلك ، يكفي التحقق من حالة إعادة التشغيل الأخيرة للجراب: هل هي "OOMKilled". إن اختناق وحدة المعالجة المركزية ليس بهذه السهولة ، حيث إن K8s توفر المقاييس فقط عن طريق الاستخدام ، وليس عن طريق مجموعات cgroups.

طلب وحدة المعالجة المركزية

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes
كيف يتم تنفيذ طلب وحدة المعالجة المركزية

من أجل البساطة ، دعنا نلقي نظرة على العملية باستخدام مثال جهاز مزود بوحدة معالجة مركزية رباعية النوى.

تستخدم K8s آلية cgroups لإدارة تخصيص الموارد (الذاكرة ووحدة المعالجة المركزية). يتوفر لها نموذج هرمي: يرث الطفل حدود المجموعة الرئيسية. يتم تخزين تفاصيل التوزيع في نظام الملفات الافتراضي (/sys/fs/cgroup). في حالة وجود معالج ، هذا /sys/fs/cgroup/cpu,cpuacct/*.

يستخدم K8s ملف cpu.share لتخصيص موارد المعالج. في حالتنا ، تتلقى مجموعة الجذر cgroup 4096 مشاركة من موارد وحدة المعالجة المركزية - 100٪ من طاقة المعالج المتاحة (نواة واحدة = 1 ؛ هذه قيمة ثابتة). توزع المجموعة الجذرية الموارد بشكل متناسب بناءً على مشاركات المتفرعة المحددة في cpu.share، وهؤلاء بدورهم يفعلون الشيء نفسه مع أحفادهم ، وهكذا. في مضيف Kubernetes النموذجي ، يكون لمجموعة الجذر ثلاثة أطفال: system.slice, user.slice и kubepods. يتم استخدام أول مجموعتين فرعيتين لتخصيص الموارد بين أحمال النظام الحرجة وبرامج المستخدم خارج K8s. آخر - kubepods - تم إنشاؤه بواسطة Kubernetes لتوزيع الموارد بين الكبسولات.

يوضح الرسم البياني أعلاه تلقي المجموعات الفرعية الأولى والثانية 1024 مشاركات ، بينما يتم تخصيص المجموعة الفرعية kuberpod 4096 تشارك. كيف يكون هذا ممكنا: بعد كل شيء ، مجموعة الجذر لديها حق الوصول فقط إلى 4096 ، ومجموع أسهم أحفادها يتجاوز هذا الرقم بشكل كبير (6144)؟ النقطة المهمة هي أن القيمة لها معنى منطقي ، لذلك يستخدمها برنامج جدولة Linux (CFS) لتخصيص موارد وحدة المعالجة المركزية بشكل متناسب. في حالتنا ، تتلقى أول مجموعتين 680 الأسهم الحقيقية (16,6٪ من 4096) ويحصل kubepod على الباقي 2736 تشارك. في حالة التعطل ، لن تستخدم أول مجموعتين الموارد المخصصة.

لحسن الحظ ، فإن المجدول لديه آلية لتجنب إهدار موارد وحدة المعالجة المركزية غير المستخدمة. ينقل السعة "الخاملة" إلى التجمع العالمي ، حيث يتم توزيعها على المجموعات التي تحتاج إلى طاقة إضافية للمعالج (يحدث النقل على دفعات لتجنب خسائر التقريب). نفس الطريقة تنطبق على جميع المتحدرين من الأحفاد.

تضمن هذه الآلية التوزيع العادل لقوة المعالج وتضمن عدم "سرقة" أي عملية للموارد من الآخرين.

حد وحدة المعالجة المركزية

على الرغم من أن تكوينات الحد والطلب في K8s تبدو متشابهة ، إلا أن تنفيذها يختلف اختلافًا جوهريًا: الأكثر تضليلًا والجزء الأقل توثيقًا.

دورات K8s آلية حصص CFS لفرض الحدود. الإعدادات الخاصة بهم محددة في الملفات cfs_period_us и cfs_quota_us في دليل cgroup (يوجد أيضًا ملف cpu.share).

على عكس cpu.share، تعتمد الحصة على فترة من الزمن، وليس على قوة المعالج المتاحة. cfs_period_us يحدد مدة الفترة (الحقبة) - دائمًا ما تكون 100000 مللي ثانية (100 مللي ثانية). هناك خيار في K8s لتغيير هذه القيمة ، ومع ذلك فهي متاحة فقط في ألفا في الوقت الحالي. يستخدم المجدول الحقبة لإعادة تشغيل الحصص المستخدمة. الملف الثاني cfs_quota_us، يحدد الوقت المتاح (الحصة) في كل حقبة. لاحظ أنه يتم تحديده أيضًا بالميكروثانية. يمكن أن تتجاوز الحصة طول حقبة ؛ بمعنى آخر ، قد يكون أكبر من 100 مللي ثانية.

لنلقِ نظرة على سيناريوهين على آلات ذات 16 نواة (النوع الأكثر شيوعًا من الآلات الموجودة لدينا في Omio):

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes
السيناريو 1: 2 خيوط و 200 مللي ثانية كحد أقصى. لا اختناق

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes
السيناريو 2: 10 سلاسل و 200 مللي ثانية كحد أقصى. يبدأ الخنق بعد 20 مللي ثانية ، ويستأنف الوصول إلى موارد وحدة المعالجة المركزية بعد 80 مللي ثانية أخرى

لنفترض أنك قمت بتعيين حد وحدة المعالجة المركزية على 2 حبات. سيترجم Kubernetes هذه القيمة إلى 200 مللي ثانية. هذا يعني أن الحاوية يمكنها استخدام 200 مللي ثانية كحد أقصى من وقت وحدة المعالجة المركزية دون اختناق.

وهنا تبدأ المتعة. كما ذكرنا أعلاه ، فإن الحصة المتاحة هي 200 ملي ثانية. إذا كان لديك عمل مواز عشرة الخيوط على آلة ذات 12 نواة (انظر الرسم التوضيحي للسيناريو 2) ، في حين أن جميع البودات الأخرى خاملة ، سيتم استنفاد الحصة في 20 مللي ثانية فقط (لأن 10 * 20 مللي ثانية = 200 مللي ثانية) ، وستعلق جميع سلاسل هذه الكبسولة » (خنق) لمدة 80 مللي ثانية. ومما زاد من تفاقم الوضع ما سبق ذكره علة المجدول، بسبب حدوث اختناق مفرط ولا تستطيع الحاوية حتى تحديد الحصة الحالية.

كيف يتم تقييم الاختناق في القرون؟

فقط قم بتسجيل الدخول إلى الكبسولة وافعل cat /sys/fs/cgroup/cpu/cpu.stat.

  • nr_periods هو العدد الإجمالي لفترات المجدول ؛
  • nr_throttled - عدد فترات الاختناق في التكوين nr_periods;
  • throttled_time هو الوقت التراكمي الخانق بالنانو ثانية.

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes

ما الذي يحدث بالفعل؟

نتيجة لذلك ، نحصل على اختناق عالي في جميع التطبيقات. في بعض الأحيان يكون في مرة ونصف أقوى مما كان متوقعا!

يؤدي هذا إلى العديد من الأخطاء - فشل عمليات التحقق من الجاهزية ، وتجميد الحاوية ، وانقطاع اتصال الشبكة ، وانتهاء المهلات داخل مكالمات الخدمة. في النهاية ، هذا يترجم إلى زيادة زمن الوصول وزيادة معدلات الخطأ.

القرار والعواقب

كل شيء بسيط هنا. تخلينا عن حدود وحدة المعالجة المركزية (CPU) وبدأنا في تحديث نواة نظام التشغيل في مجموعات إلى أحدث إصدار ، حيث تم إصلاح الخطأ. انخفض عدد الأخطاء (HTTP 5xx) في خدماتنا بشكل كبير على الفور:

أخطاء HTTP 5xx

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes
أخطاء HTTP 5xx لخدمة حرجة واحدة

وقت استجابة p95

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes
وقت استجابة طلبات الخدمة الحرجة ، 95 بالمائة

تكاليف التشغيل

حدود وحدة المعالجة المركزية والاختناق الشديد في Kubernetes
عدد ساعات المثيل التي تم إنفاقها

ما هي الفائدة؟

كما ورد في بداية المقال:

يمكنك رسم تشبيه مع شقة مشتركة ... يعمل Kubernetes كسمسار عقارات. ولكن كيف تحمي المستأجرين من النزاعات مع بعضهم البعض؟ ماذا لو قرر أحدهم ، على سبيل المثال ، أن يأخذ الحمام لمدة نصف يوم؟

ها هي الفائدة. يمكن أن تستهلك حاوية واحدة مهملة جميع موارد وحدة المعالجة المركزية المتاحة على الجهاز. إذا كان لديك مكدس تطبيقات ذكي (على سبيل المثال ، JVM ، Go ، Node VM تم تكوينه بشكل صحيح) ، فهذه ليست مشكلة: يمكنك العمل في مثل هذه الظروف لفترة طويلة. ولكن إذا تم تحسين التطبيقات بشكل سيئ أو لم يتم تحسينها على الإطلاق (FROM java:latest) ، يمكن أن يخرج الوضع عن السيطرة. في Omio ، لدينا ملفات Dockerfiles آلية مع الإعدادات الافتراضية المناسبة لمجموعة اللغات الأساسية ، لذلك لم تكن هذه المشكلة موجودة.

نوصي بمراقبة المقاييس استخدام (الاستخدام والتشبع والأخطاء) وتأخيرات واجهة برمجة التطبيقات ومعدلات الخطأ. تأكد من أن النتائج تطابق توقعاتك.

مراجع

هذا هو تاريخنا. ساعدت المواد التالية بشكل كبير في فهم ما يحدث:

تقارير خطأ Kubernetes:

هل واجهت مشاكل مماثلة في ممارستك أو لديك خبرة تتعلق بالاختناق في بيئات الإنتاج المعبأة في حاويات؟ شارك قصتك في التعليقات!

PS من المترجم

اقرأ أيضًا على مدونتنا:

المصدر: www.habr.com

إضافة تعليق