أفضل الممارسات لحاويات Kubernetes: الفحوصات الصحية

أفضل الممارسات لحاويات Kubernetes: الفحوصات الصحية

TL؛ DR

  • لتحقيق إمكانية ملاحظة عالية للحاويات والخدمات الصغيرة، لا تعد السجلات والمقاييس الأولية كافية.
  • من أجل التعافي بشكل أسرع وزيادة المرونة، يجب أن تطبق التطبيقات مبدأ قابلية المراقبة العالية (HOP).
  • على مستوى التطبيق، يتطلب NOP: التسجيل المناسب، والمراقبة الدقيقة، والتحقق من السلامة، وتتبع الأداء/الانتقال.
  • استخدم الشيكات كعنصر من عناصر NOR الاستعداد и مسبار الحياة كوبرنيتيس.

ما هو قالب التحقق من الصحة؟

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

مبدأ قابلية الملاحظة العالية (HOP)

مبدأ إمكانية الملاحظة العالية هو واحد من مبادئ تصميم التطبيقات المعبأة في حاويات. في بنية الخدمات الصغيرة، لا تهتم الخدمات بكيفية معالجة طلبها (وهذا صحيح)، ولكن ما يهم هو كيفية تلقي الاستجابات من الخدمات المتلقية. على سبيل المثال، لمصادقة مستخدم، ترسل إحدى الحاويات طلب HTTP إلى أخرى، وتتوقع استجابة بتنسيق معين - هذا كل شيء. يمكن لـ PythonJS أيضًا معالجة الطلب، ويمكن لـ Python Flask الاستجابة. الحاويات تشبه الصناديق السوداء بمحتوياتها المخفية لبعضها البعض. ومع ذلك، يتطلب مبدأ NOP من كل خدمة الكشف عن نقاط نهاية متعددة لواجهة برمجة التطبيقات (API) التي تشير إلى مدى صحتها، بالإضافة إلى حالة الاستعداد والتسامح مع الأخطاء. يطلب Kubernetes هذه المؤشرات من أجل التفكير في الخطوات التالية للتوجيه وموازنة التحميل.

يسجل التطبيق السحابي المصمم جيدًا أحداثه الرئيسية باستخدام تدفقات الإدخال/الإخراج القياسية STDERR وSTDOUT. بعد ذلك تأتي خدمة مساعدة، على سبيل المثال filebeat أو logstash أو Fluentd، لتوصيل السجلات إلى نظام مراقبة مركزي (على سبيل المثال Prometheus) ونظام جمع السجلات (مجموعة برامج ELK). يوضح الرسم البياني أدناه كيفية عمل التطبيق السحابي وفقًا لنمط اختبار الصحة ومبدأ إمكانية المراقبة العالية.

أفضل الممارسات لحاويات Kubernetes: الفحوصات الصحية

كيفية تطبيق نمط التحقق من الصحة في Kubernetes؟

خارج الصندوق، يقوم k8s بمراقبة حالة القرون باستخدام إحدى وحدات التحكم (نشر, مجموعات المقلدة, مجموعات الشيطان, الدولة الخ الخ). بعد اكتشاف سقوط الكبسولة لسبب ما، تحاول وحدة التحكم إعادة تشغيلها أو نقلها إلى عقدة أخرى. ومع ذلك، قد تشير الكبسولة إلى أنها قيد التشغيل، ولكنها في حد ذاتها لا تعمل. لنعطي مثالا: يستخدم تطبيقك Apache كخادم ويب، وقمت بتثبيت المكون على عدة وحدات من المجموعة. نظرًا لأنه تم تكوين المكتبة بشكل غير صحيح، فإن جميع طلبات التطبيق تستجيب بالرمز 500 (خطأ داخلي في الخادم). عند التحقق من التسليم، فإن التحقق من حالة البودات يعطي نتيجة ناجحة، لكن العملاء يفكرون بشكل مختلف. وسوف نصف هذا الوضع غير المرغوب فيه على النحو التالي:

أفضل الممارسات لحاويات Kubernetes: الفحوصات الصحية

في مثالنا، k8s يفعل ذلك فحص الوظائف. في هذا النوع من التحقق، يقوم kubelet بالتحقق بشكل مستمر من حالة العملية في الحاوية. وبمجرد أن يفهم أن العملية قد توقفت، فإنه سيعيد تشغيلها. إذا كان من الممكن حل الخطأ بمجرد إعادة تشغيل التطبيق، وكان البرنامج مصممًا لإيقاف التشغيل عند حدوث أي خطأ، فإن فحص صحة العملية هو كل ما تحتاجه لاتباع NOP ونمط اختبار الصحة. المؤسف الوحيد هو أنه لا يتم التخلص من جميع الأخطاء عن طريق إعادة التشغيل. في هذه الحالة، يقدم k8s طريقتين أعمق لتحديد مشاكل البود: مسبار الحياة и الاستعداد.

LivenessProbe

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

  • قم بإعداد طلب HTTP إلى الكبسولة. يجب أن تحتوي الاستجابة على رمز استجابة HTTP في النطاق من 200 إلى 399. وبالتالي، يشير الرمزان 5xx و4xx إلى أن الكبسولة تواجه مشكلات، على الرغم من أن العملية قيد التشغيل.
  • لاختبار البودات مع خدمات غير HTTP (على سبيل المثال، خادم بريد Postfix)، تحتاج إلى إنشاء اتصال TCP.
  • تنفيذ أمر تعسفي للجراب (داخليًا). يعتبر الفحص ناجحًا إذا كان رمز إكمال الأمر هو 0.

مثال على كيفية عمل هذا. يحتوي تعريف pod التالي على تطبيق NodeJS الذي يلقي خطأ 500 على طلبات HTTP، وللتأكد من إعادة تشغيل الحاوية عند تلقي مثل هذا الخطأ، نستخدم المعلمة LivenessProbe:

apiVersion: v1
kind: Pod
metadata:
 name: node500
spec:
 containers:
   - image: magalix/node500
     name: node500
     ports:
       - containerPort: 3000
         protocol: TCP
     livenessProbe:
       httpGet:
         path: /
         port: 3000
       initialDelaySeconds: 5

لا يختلف هذا عن أي تعريف pod آخر، لكننا نضيف كائنًا .spec.containers.livenessProbe. معامل httpGet يقبل المسار الذي يتم إرسال طلب HTTP GET إليه (في مثالنا هذا هو /ولكن في سيناريوهات القتال قد يكون هناك شيء من هذا القبيل /api/v1/status). يقبل LivenessProbe آخر معلمة initialDelaySeconds، والذي يأمر عملية التحقق بالانتظار لعدد محدد من الثواني. التأخير ضروري لأن الحاوية تحتاج إلى وقت للبدء، وعند إعادة تشغيلها ستكون غير متاحة لبعض الوقت.

لتطبيق هذا الإعداد على مجموعة، استخدم:

kubectl apply -f pod.yaml

بعد بضع ثوان، يمكنك التحقق من محتويات الكبسولة باستخدام الأمر التالي:

kubectl describe pods node500

في نهاية الإخراج، ابحث عن وهذا ما.

كما ترون، بدأ LivenessProbe طلب HTTP GET، وولدت الحاوية خطأ 500 (وهو ما تمت برمجته للقيام به)، وأعاد kubelet تشغيله.

إذا كنت تتساءل عن كيفية برمجة تطبيق NideJS، فإليك app.js وDockerfile اللذين تم استخدامهما:

app.js

var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(500, { "Content-type": "text/plain" });
    res.end("We have run into an errorn");
});

server.listen(3000, function() {
    console.log('Server is running at 3000')
})

Dockerfile

FROM node
COPY app.js /
EXPOSE 3000
ENTRYPOINT [ "node","/app.js" ]

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

الاستعداد

يعمل ReadyProbe بشكل مشابه لـ LivenessProbes (طلبات GET واتصالات TCP وتنفيذ الأوامر)، باستثناء إجراءات استكشاف الأخطاء وإصلاحها. لا تتم إعادة تشغيل الحاوية التي تم اكتشاف الفشل فيها، ولكنها معزولة عن حركة المرور الواردة. تخيل أن إحدى الحاويات تجري عددًا كبيرًا من العمليات الحسابية أو تتعرض لحمل ثقيل، مما يتسبب في زيادة أوقات الاستجابة. في حالة LivenessProbe، يتم تشغيل التحقق من توفر الاستجابة (عبر معلمة التحقق من timeoutSeconds)، وبعد ذلك يقوم kubelet بإعادة تشغيل الحاوية. عند البدء، تبدأ الحاوية في تنفيذ المهام كثيفة الاستخدام للموارد ويتم إعادة تشغيلها مرة أخرى. قد يكون هذا أمرًا بالغ الأهمية للتطبيقات التي تحتاج إلى سرعة الاستجابة. على سبيل المثال، تنتظر سيارة أثناء سيرها على الطريق ردًا من الخادم، وتتأخر الاستجابة - وتتعرض السيارة لحادث.

لنكتب تعريف redinessProbe الذي سيحدد وقت استجابة طلب GET بما لا يزيد عن ثانيتين، وسيستجيب التطبيق لطلب GET بعد 5 ثوانٍ. يجب أن يبدو ملف pod.yaml بالشكل التالي:

apiVersion: v1
kind: Pod
metadata:
 name: nodedelayed
spec:
 containers:
   - image: afakharany/node_delayed
     name: nodedelayed
     ports:
       - containerPort: 3000
         protocol: TCP
     readinessProbe:
       httpGet:
         path: /
         port: 3000
       timeoutSeconds: 2

دعونا ننشر جرابًا باستخدام kubectl:

kubectl apply -f pod.yaml

دعونا ننتظر بضع ثوانٍ ثم نرى كيف يعمل مسبار الاستعداد:

kubectl describe pods nodedelayed

في نهاية الإخراج يمكنك أن ترى أن بعض الأحداث متشابهة هذا.

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

لاحظ أنه بعد إلغاء تحميل الكبسولة، يقوم kubectl بتوجيه الطلبات إليها مرة أخرى: لم تعد الاستجابات لطلبات GET متأخرة.

للمقارنة، فيما يلي ملف app.js المعدل:

var http = require('http');

var server = http.createServer(function(req, res) {
   const sleep = (milliseconds) => {
       return new Promise(resolve => setTimeout(resolve, milliseconds))
   }
   sleep(5000).then(() => {
       res.writeHead(200, { "Content-type": "text/plain" });
       res.end("Hellon");
   })
});

server.listen(3000, function() {
   console.log('Server is running at 3000')
})

TL؛ DR
قبل ظهور التطبيقات السحابية، كانت السجلات هي الوسيلة الأساسية لمراقبة صحة التطبيق والتحقق منها. ومع ذلك، لم تكن هناك وسيلة لاتخاذ أي إجراء تصحيحي. لا تزال السجلات مفيدة حتى يومنا هذا، حيث يجب جمعها وإرسالها إلى نظام جمع السجلات لتحليل حالات الطوارئ واتخاذ القرارات. [كل هذا يمكن القيام به بدون التطبيقات السحابية باستخدام monit، على سبيل المثال، ولكن مع k8s أصبح الأمر أسهل بكثير :) - ملاحظة المحرر. ]

اليوم، يجب إجراء التصحيحات في الوقت الفعلي تقريبًا، لذلك لم تعد التطبيقات عبارة عن صناديق سوداء. لا، يجب أن تظهر نقاط النهاية التي تسمح لأنظمة المراقبة بالاستعلام وجمع بيانات قيمة حول حالة العمليات حتى تتمكن من الاستجابة على الفور إذا لزم الأمر. وهذا ما يسمى بنمط تصميم اختبار الأداء، والذي يتبع مبدأ قابلية الملاحظة العالية (HOP).

يقدم Kubernetes نوعين من فحوصات السلامة بشكل افتراضي: ReadyProbe وlivnessProbe. يستخدم كلاهما نفس أنواع الاختبارات (طلبات HTTP GET واتصالات TCP وتنفيذ الأوامر). إنهم يختلفون في القرارات التي يتخذونها استجابةً للمشاكل الموجودة في القرون. يعيد LivenessProbe تشغيل الحاوية على أمل عدم حدوث الخطأ مرة أخرى، ويقوم ReadyProbe بعزل الكبسولة عن حركة المرور الواردة حتى يتم حل سبب المشكلة.

يجب أن يتضمن التصميم المناسب للتطبيق كلا النوعين من الفحص والتأكد من جمعهما ما يكفي من البيانات، خاصة عند طرح استثناء. ويجب أن يُظهر أيضًا نقاط نهاية واجهة برمجة التطبيقات (API) الضرورية التي تزود نظام المراقبة (بروميثيوس) بمقاييس صحية مهمة.

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

إضافة تعليق