كيفية الوصول إلى موارد Kubernetes Pod

The Reward by Tohad



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



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



قام فريق Kubernetes aaS من Mail.ru بترجمة مقالة حول موارد الحاوية (CPU و MEM) والطلبات وحدود الموارد. سوف تتعلم فوائد هذه الإعدادات وماذا يحدث إذا لم تقم بتثبيتها.



موارد الحوسبة



لدينا نوعان من الموارد بالوحدات التالية:



  • وحدة المعالجة المركزية (CPU) - النوى ؛
  • ذاكرة (MEM) - بايت.


يتم تحديد الموارد لكل حاوية. في ملف YAML pod التالي ، سترى قسم موارد يحتوي على الموارد المطلوبة والمحدودة:



  • موارد القرنة المطلوبة = مجموع الموارد المطلوبة لجميع القرون ؛
  • حدود موارد Pod = مجموع الموارد الهامشية لجميع الحاويات.


apiVersion: v1
kind: Pod
metadata:
  name: backend-pod-name
  labels:
    application: backend
spec:
  containers:
    — name: main-container
      image: my-backend
      tag: v1
      ports:
      — containerPort: 8080
      resources:
        requests:
          cpu: 0.2 # REQUESTED CPU: 200m cores
          memory: "1Gi" # REQUESTED MEM: 1Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi
    — name: other-container
      image: other-app
      tag: v1
      ports:
      — containerPort: 8000
      resources:
        requests:
          cpu: "200m" # REQUESTED CPU: 200m cores
          memory: "0.5Gi" # REQUESTED MEM: 0.5Gi
        limits:
          cpu: 1 # MAX CPU USAGE: 1 core
          memory: "1Gi" # MAX MEM USAGE:  1Gi
مثال على الموارد المطلوبة والمحدودة يعد



الحقل resources.requestedمن مواصفات Pod أحد العناصر المستخدمة للعثور على العقدة المطلوبة. بالفعل عليه ، يمكنك جدولة نشر Pod. كيف تجد عقدة مناسبة؟



يتكون Kubernetes من عدة مكونات ، بما في ذلك العقدة الرئيسية أو العقدة الرئيسية (Kubernetes Control Plane). توجد عدة عمليات في العقدة الرئيسية: kube-apiserver و kube-controller-manager و kube-Scheduler.



عملية kube-Scheduler هي المسؤولة عن النظر في الوحدات النمطية التي تم إنشاؤها حديثًا والبحث عن عقد عاملة محتملة تتطابق مع جميع طلبات الوحدة ، بما في ذلك عدد الموارد المطلوبة. يتم ترتيب قائمة العقد التي تم العثور عليها بواسطة kube-Scheduler. تم التخطيط للحجرة للموقع الذي يحقق أعلى الدرجات.



أين سيتم وضع القرنة الأرجواني؟



تظهر الصورة أن kube-Scheduler يجب أن يقوم بجدولة قرنة أرجوانية جديدة. تحتوي مجموعة Kubernetes على عقدتين: A و B. كما ترى ، لا يمكن لـ kube-Scheduler جدولة Pod إلى العقدة A - الموارد المتاحة (غير المرغوب فيها) لا تتطابق مع طلبات Pod الأرجواني. على سبيل المثال ، الذاكرة التي تبلغ 1 جيجا بايت المطلوبة بواسطة Pod الأرجواني لن تناسب العقدة A ، حيث أن الذاكرة المتوفرة هي 0.5 جيجا بايت لكن العقدة ب لديها موارد كافية. نتيجة لذلك ، قرر kube-Scheduler أن وجهة Pod الأرجواني هي Node B.



الآن نحن نعرف كيف تؤثر الموارد المطلوبة على اختيار العقدة لبدء Pod. لكن كيف تؤثر الموارد الهامشية؟



حدود الموارد هي حدود لا يمكن لوحدة CPU / MEM عبورها. ومع ذلك ، فإن وحدة المعالجة المركزية مرنة ، لذا لن تتسبب الحاويات التي تصل إلى حد وحدة المعالجة المركزية في إيقاف تشغيل Pod. بدلاً من ذلك ، سيبدأ التحكم في وحدة المعالجة المركزية. إذا تم الوصول إلى حد استخدام MEM ، فسيتم إيقاف الحاوية بسبب OOM-Killer وإعادة تشغيلها ، إذا سمح بذلك إعداد RestartPolicy.



طلبت وحد من الموارد بالتفصيل



علاقة الموارد بين Docker و Kubernetes



أفضل طريقة لشرح كيفية عمل الموارد المطلوبة والمحدودة هي تمثيل العلاقة بين Kubernetes و Docker. في الصورة أعلاه ، يمكنك أن ترى كيف ترتبط حقول Kubernetes وعلامات تشغيل Docker.



الذاكرة: الطلب والحد



containers:
...
 resources:
   requests:
     memory: "0.5Gi"
   limits:
     memory: "1Gi"


كما ذكر أعلاه ، يتم قياس الذاكرة بالبايت. استنادًا إلى وثائق Kubernetes ، يمكننا تحديد الذاكرة كرقم. عادةً ما يكون عددًا صحيحًا ، على سبيل المثال 2678 - أي 2678 بايت. يمكنك أيضا استخدام اللواحق Gو Giالأهم من ذلك، تذكر أنها ليست ما يعادلها. الأول عشري والثاني ثنائي. على سبيل المثال ، ورد ذكره في الوثائق K8S: 128974848، 129e6، 129M، 123Mi- إنها متكافئة تقريبًا.



تطابق معلمة Kubernetes limits.memoryالعلامة --memoryمن Docker. في حالةrequest.memoryلا يوجد سهم لـ Docker لأن Docker لا يستخدم هذا الحقل. قد تسأل إذا كان هذا ضروريًا على الإطلاق؟ نعم تحتاج. كما قلت من قبل ، فإن المجال مهم بالنسبة لـ Kubernetes. بناءً على المعلومات الواردة منه ، يقرر kube-Scheduler العقدة التي يجب جدولة Pod إليها.



ماذا يحدث إذا لم تكن هناك ذاكرة مثبتة كافية للاستعلام؟



إذا وصلت الحاوية إلى حدود الذاكرة المطلوبة ، فسيتم وضع Pod في مجموعة Pod ، والتي تتوقف عند عدم وجود ذاكرة في العقدة.



ماذا يحدث إذا قمت بتعيين حد الذاكرة منخفضًا جدًا؟



إذا تجاوزت الحاوية حد الذاكرة ، فسيتم إنهاؤها بسبب OOM-Killed. وستتم إعادة تشغيله إن أمكن بناءً على RestartPolicy ، حيث يكون الإعداد الافتراضي Always.



ماذا يحدث إذا لم تحدد الذاكرة المطلوبة؟



سوف يأخذ Kubernetes الحد ويضعه كإعداد افتراضي.



ماذا يمكن أن يحدث إذا لم تحدد حد الذاكرة؟



الحاوية ليس لها حدود ، يمكنها استخدام أكبر قدر من الذاكرة كما تريد. إذا بدأ في استخدام كل الذاكرة المتاحة للعقدة ، فسوف يقتله OOM. سيتم بعد ذلك إعادة تشغيل الحاوية إذا أمكن بناءً على RestartPolicy.



ماذا يحدث إذا لم تحدد حدود الذاكرة؟



هذا هو السيناريو الأسوأ: لا يعرف المجدول مقدار الموارد التي تحتاجها الحاوية ، وهذا يمكن أن يسبب مشاكل خطيرة في العقدة. في هذه الحالة ، سيكون من الجيد وجود قيود افتراضية لمساحة الاسم (يتم تعيينها بواسطة LimitRange). لا توجد حدود افتراضيًا - لا توجد حدود للبود ، يمكنه استخدام أكبر قدر من الذاكرة كما يريد.



إذا كانت الذاكرة المطلوبة أكبر مما يمكن أن تقدمه العقدة ، فلن تتم جدولة Pod. من المهم أن تتذكر أن هذه Requests.memoryليست قيمة دنيا. هذا وصف لمقدار الذاكرة الكافي لتشغيل الحاوية بشكل مستمر.



يوصى عادةً بتعيين نفس القيمة لـ request.memoryوlimit.memory... هذا يمنع Kubernetes من جدولة Pod على عقدة بها ذاكرة كافية لتشغيل Pod ولكنها ليست كافية للتشغيل. ضع في اعتبارك: عند جدولة Pod ، فإن Kubernetes مهم فقط requests.memory، limits.memoryوليس مهمًا .



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



containers:
...
 resources:
   requests:
     cpu: 1
   limits:
     cpu: "1200m"


باستخدام وحدة المعالجة المركزية ، يصبح كل شيء أكثر تعقيدًا. بالعودة إلى صورة العلاقة بين Kubernetes و Docker ، يمكنك أن ترى أنها request.cpuتتطابق --cpu-shares، بينما limit.cpuتتطابق مع العلم cpusفي Docker.



يتم ضرب وحدة المعالجة المركزية التي يطلبها Kubernetes في 1024 ، وهي نسبة دورات وحدة المعالجة المركزية. إذا كنت ترغب في طلب نواة كاملة واحدة ، فيجب عليك إضافتها cpu: 1كما هو موضح أعلاه.



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





طلب وحدة المعالجة المركزية - نظام أحادي النواة



لنفترض أن لديك نظام مضيف أساسي واحد يقوم بتشغيل الحاويات. قامت أمي (Kubernetes) بخبز كعكة (CPU) وتريد مشاركتها بين الأطفال (حاويات). ثلاثة أطفال يريدون كعكة كاملة (النسبة = 1024) ، طفل آخر يريد نصف الكعكة (512). تريد أمي أن تكون عادلة وتقوم بعملية حسابية بسيطة.



#    ?
# 3           
cakesNumberKidsWant = (3 * 1) + (1 * 0.5) = 3.5
#   :
3 (/) * 1 ( / ) + 1 (/) * 0.5 ( / )
#   ?
availableCakesNumber = 1
#   ()    ?
newMaxRequest = 1 / 3.5 =~ 28%


بناءً على الحساب ، سيحصل ثلاثة أطفال على 28٪ من النواة ، وليس النواة بأكملها. الطفل الرابع سيحصل على 14٪ من النواة الكاملة وليس النصف. لكن الأمور ستكون مختلفة إذا كان لديك نظام متعدد النواة.





طلب وحدة المعالجة المركزية - نظام متعدد النواة (4)



في الصورة أعلاه ، يمكنك أن ترى أن ثلاثة أطفال يريدون فطيرة كاملة والآخر يريد نصفًا. منذ أن قامت أمي بخبز أربع كعكات ، سيحصل كل طفل من أطفالها على أكبر قدر ممكن. في نظام متعدد النواة ، تنتشر موارد المعالجات عبر جميع نوى المعالجات المتاحة. إذا كانت الحاوية محدودة بأقل من نواة كاملة لوحدة المعالجة المركزية ، فلا يزال بإمكانها استخدامها بنسبة 100٪.



تم تبسيط الحسابات المذكورة أعلاه لفهم كيفية تخصيص وحدة المعالجة المركزية بين الحاويات. بالطبع ، بالإضافة إلى الحاويات نفسها ، هناك عمليات أخرى تستخدم أيضًا موارد وحدة المعالجة المركزية. عندما تكون العمليات في حاوية واحدة خاملة ، يمكن للآخرين استخدام مواردها. CPU: "200m"يتوافق CPU: 0,2، أي حوالي 20٪ من نواة واحدة.



الآن دعنا نتحدث عنlimit.cpu... يتم ضرب وحدة المعالجة المركزية التي تحد Kubernetes في 100. والنتيجة هي مقدار الوقت الذي يمكن للحاوية استخدام كل 100 ميكرو ثانية ( cpu-period).



limit.cpuيطابق علم Docker --cpus. هذا هو مزيج جديد من القديم --cpu-periodو --cpu-quota. من خلال تعيينه ، نحدد عدد موارد وحدة المعالجة المركزية المتاحة التي يمكن للحاوية استخدامها إلى الحد الأقصى حتى تبدأ في التحكم:





ماذا يحدث إذا كانت وحدة المعالجة المركزية المطلوبة غير كافية؟



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



ماذا يحدث إذا قمت بتعيين حد غير كافٍ لوحدة المعالجة المركزية؟



نظرًا لأن مورد وحدة المعالجة المركزية قابل للتعديل ، فسيتم تشغيل الاختناق.



ماذا يحدث إذا لم تحدد طلب وحدة المعالجة المركزية؟



كما هو الحال مع الذاكرة ، فإن قيمة الطلب تساوي الحد.



ماذا يحدث إذا لم تحدد حد وحدة المعالجة المركزية؟



ستستخدم الحاوية قدر ما تحتاجه من وحدة المعالجة المركزية. إذا تم تحديد سياسة وحدة المعالجة المركزية الافتراضية (LimitRange) في مساحة الاسم ، فسيتم استخدام هذا الحد للحاوية أيضًا.



ماذا يحدث إذا لم تحدد الطلب أو حد وحدة المعالجة المركزية؟



كما هو الحال مع الذاكرة ، هذا هو السيناريو الأسوأ. لا يعرف المجدول مقدار الموارد التي تحتاجها الحاوية ، وقد يتسبب ذلك في مشاكل خطيرة في العقدة. لتجنب ذلك ، تحتاج إلى تعيين الحدود الافتراضية لمساحات الأسماء (LimitRange).



تذكر ، إذا طلبت وحدة معالجة مركزية أكثر مما يمكن أن توفره العقد ، فلن تتم جدولة Pod. Requests.cpu- ليست قيمة دنيا ، ولكنها قيمة كافية لبدء Pod والعمل دون إخفاقات. إذا لم يقم التطبيق الخاص بك بإجراء عمليات حسابية معقدة ، فإن أفضل خيار هو تثبيت request.cpu <= 1وتشغيل العديد من النسخ المتماثلة حسب الحاجة.



الكمية المثالية من الموارد المطلوبة أو حد الموارد



لقد تعلمنا عن محدودية موارد الحوسبة. حان الوقت الآن للإجابة على السؤال ، "كم عدد الموارد التي يحتاجها Pod لتشغيل التطبيق دون مشاكل؟ ما هو المبلغ المثالي؟



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



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



انظر إلى لوحة معلومات Grafana هذه كمثال .... يعرض الفرق بين الموارد المطلوبة أو حد الموارد واستخدام الموارد الحالي.



خاتمة



يساعد الاستعلام عن الموارد وتحديدها في الحفاظ على صحة مجموعة Kubernetes. يؤدي تكوين الحدود بشكل صحيح إلى تقليل التكاليف والحفاظ على تشغيل التطبيقات في جميع الأوقات.



باختصار ، هناك بعض الأشياء التي يجب وضعها في الاعتبار:



  1. الموارد المطلوبة هي التكوين الذي يؤخذ في الاعتبار أثناء بدء التشغيل (عندما يخطط Kubernetes لاستضافة التطبيق). في المقابل ، يعد تحديد الموارد أمرًا مهمًا في وقت التشغيل - عندما يكون التطبيق قيد التشغيل بالفعل على العقدة.
  2. بالمقارنة مع الذاكرة ، فإن وحدة المعالجة المركزية هي مورد منظم. في حالة عدم كفاية وحدة المعالجة المركزية ، لن يتم إغلاق Pod الخاص بك ، وسيبدأ في الاختناق.
  3. الموارد المطلوبة وحدود الموارد ليست قيم دنيا وقيم قصوى! من خلال تحديد الموارد المطلوبة ، فإنك تضمن تشغيل التطبيق الخاص بك بسلاسة.
  4. يعد تعيين طلب الذاكرة مساويًا لحد الذاكرة من الممارسات الجيدة.
  5. من الجيد التثبيت كما هو مطلوب CPU <=1إذا لم يقم التطبيق بإجراء حسابات معقدة.
  6. إذا طلبت موارد أكثر مما تمتلكه العقدة ، فلن تتم جدولة Pod لهذه العقدة مطلقًا.
  7. استخدم اختبار الحمل والمراقبة لتحديد المقدار الصحيح من الموارد المطلوبة / حدود الموارد.


آمل أن تساعدك هذه المقالة في فهم المفهوم الأساسي للحد من الموارد. وستكون قادرًا على تطبيق هذه المعرفة في عملك.



حظا سعيدا!



ماذا تقرأ:



  1. إمكانية ملاحظة SRE: مساحات الأسماء والهيكل المتري .
  2. 90+ Kubernetes: , , , .
  3. Kubernetes .



All Articles