شیڈولنگ کے قواعد کے حسب ضرورت سیٹ کے ساتھ ایک اضافی کیوب-شیڈیولر بنانا

شیڈولنگ کے قواعد کے حسب ضرورت سیٹ کے ساتھ ایک اضافی کیوب-شیڈیولر بنانا

Kube-scheduler Kubernetes کا ایک لازمی جزو ہے، جو مخصوص پالیسیوں کے مطابق نوڈس میں پوڈس کو شیڈول کرنے کا ذمہ دار ہے۔ اکثر، کبرنیٹس کلسٹر کے آپریشن کے دوران، ہمیں یہ سوچنے کی ضرورت نہیں ہے کہ پوڈز کو شیڈول کرنے کے لیے بالکل کون سی پالیسیاں استعمال کی جاتی ہیں، کیونکہ کیوب-شیڈیولر کی پالیسیوں کا ڈیفالٹ سیٹ زیادہ تر روزمرہ کے کاموں کے لیے موزوں ہوتا ہے۔ تاہم، ایسے حالات ہیں جہاں ہمارے لیے پھلیوں کی تقسیم کو ٹھیک کرنا ضروری ہے، اور اس کام کو پورا کرنے کے دو طریقے ہیں:

  1. اپنی مرضی کے مطابق قواعد کے ساتھ کیوب شیڈیولر بنائیں
  2. اپنا شیڈولر لکھیں اور اسے API سرور کی درخواستوں کے ساتھ کام کرنا سکھائیں۔

اس آرٹیکل میں، میں اپنے ایک پروجیکٹ پر پوڈز کے غیر مساوی نظام الاوقات کے مسئلے کو حل کرنے کے لیے بالکل پہلے نقطہ کے نفاذ کی وضاحت کروں گا۔

kube-scheduler'a کے کام کے بارے میں مختصر تعارف

قابل غور حقیقت یہ ہے کہ kube-scheduler براہ راست پوڈ کو شیڈول کرنے کا ذمہ دار نہیں ہے - یہ صرف اس نوڈ کے تعین کے لیے ذمہ دار ہے جس پر پوڈ رکھنا ہے۔ دوسرے لفظوں میں، کیوب-شیڈیولر کے کام کا نتیجہ نوڈ کا نام ہے، جسے وہ شیڈولنگ کی درخواست کے لیے API سرور کو واپس کرتا ہے، اور اس سے اس کا کام ختم ہو جاتا ہے۔

سب سے پہلے، کیوب-شیڈیولر ان نوڈس کی فہرست بناتا ہے جن کے لیے ایک پوڈ پیشین گوئی کی پالیسیوں کے مطابق شیڈول کیا جا سکتا ہے۔ مزید، اس فہرست سے ہر نوڈ کو ترجیحات کی پالیسیوں کے مطابق پوائنٹس کی ایک خاص تعداد ملتی ہے۔ نتیجے کے طور پر، سب سے زیادہ سکور کے ساتھ نوڈ منتخب کیا جاتا ہے. اگر ایک ہی زیادہ سے زیادہ سکور کے ساتھ نوڈس ہیں، تو ایک بے ترتیب کو منتخب کیا جاتا ہے۔ پیشین گوئی (فلٹرنگ) اور ترجیحات (اسکورنگ) کی پالیسیوں کی فہرست اور تفصیل اس میں مل سکتی ہے۔ دستاویزات.

مسئلہ کے جسم کی تفصیل

Nixys میں مختلف کبرنیٹس کلسٹرز کی بڑی تعداد برقرار رکھنے کے باوجود، ہمیں پہلی بار پوڈز کو شیڈول کرنے کے مسئلے کا سامنا حال ہی میں ہوا، جب ہمارے ایک پروجیکٹ کے لیے متواتر کاموں کی ایک بڑی تعداد (~ 100 CronJob اداروں) کو چلانا ضروری ہو گیا۔ مسئلے کی تفصیل کو زیادہ سے زیادہ آسان بنانے کے لیے، مثال کے طور پر، آئیے ایک مائیکرو سروس لیتے ہیں، جس کے اندر ایک منٹ میں ایک بار کرون ٹاسک شروع کیا جاتا ہے، جس سے CPU پر کچھ بوجھ پڑتا ہے۔ کرون ٹاسک کے کام کے لیے، تین بالکل ایک جیسے نوڈس (ہر ایک پر 24 vCPUs) مختص کیے گئے تھے۔

ایک ہی وقت میں، یہ کہنا ناممکن ہے کہ کرون جاب کتنی دیر تک چلے گا، کیونکہ ان پٹ ڈیٹا کی مقدار مسلسل بدل رہی ہے۔ اوسطا، عام کیوب-شیڈیولر آپریشن کے دوران، ہر نوڈ 3-4 جاب انسٹینس چلاتا ہے، جو ہر نوڈ کے CPU پر ~ 20-30% بوجھ پیدا کرتا ہے:

شیڈولنگ کے قواعد کے حسب ضرورت سیٹ کے ساتھ ایک اضافی کیوب-شیڈیولر بنانا

خود مسئلہ یہ ہے کہ بعض اوقات کرون ٹاسک پوڈز تین نوڈس میں سے کسی ایک کے لیے شیڈول ہونا بند کر دیتے ہیں۔ یعنی، کسی وقت، نوڈس میں سے کسی ایک کے لیے ایک پوڈ کا منصوبہ نہیں بنایا گیا تھا، جب کہ دیگر دو نوڈس پر 6-8 ٹاسک انسٹینسز چل رہے تھے، جس سے CPU پر ~ 40-60% بوجھ پیدا ہو رہا تھا:

شیڈولنگ کے قواعد کے حسب ضرورت سیٹ کے ساتھ ایک اضافی کیوب-شیڈیولر بنانا

مسئلہ بالکل بے ترتیب تعدد کے ساتھ دہرایا گیا تھا اور کبھی کبھار کوڈ کے نئے ورژن کو رول آؤٹ کرنے کے لمحے سے منسلک کیا گیا تھا۔

کیوب-شیڈیولر کی لاگنگ لیول کو 10 (-v=10) تک بڑھا کر، ہم نے یہ ریکارڈ کرنا شروع کیا کہ تشخیص کے عمل میں ہر نوڈ کتنے پوائنٹس اسکور کرتا ہے۔ عام شیڈولنگ کے دوران، درج ذیل معلومات لاگز میں دیکھی جا سکتی ہیں:

resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node03: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1387 millicores 4161694720 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node02: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1347 millicores 4444810240 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node03: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1387 millicores 4161694720 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node01: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1687 millicores 4790840320 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node02: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1347 millicores 4444810240 memory bytes, score 9
resource_allocation.go:78] cronjob-1574828880-mn7m4 -> Node01: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1687 millicores 4790840320 memory bytes, score 9
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: NodeAffinityPriority, Score: (0)                                                                                       
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node01: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: TaintTolerationPriority, Score: (10)                                                                                   
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node02: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node01: SelectorSpreadPriority, Score: (10)                                                                                                        
interpod_affinity.go:237] cronjob-1574828880-mn7m4 -> Node03: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node02: SelectorSpreadPriority, Score: (10)                                                                                                        
selector_spreading.go:146] cronjob-1574828880-mn7m4 -> Node03: SelectorSpreadPriority, Score: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node01: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node02: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574828880-mn7m4_project-stage -> Node03: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:781] Host Node01 => Score 100043                                                                                                                                                                        
generic_scheduler.go:781] Host Node02 => Score 100043                                                                                                                                                                        
generic_scheduler.go:781] Host Node03 => Score 100043

وہ. نوشتہ جات سے حاصل کردہ معلومات کو دیکھتے ہوئے، ہر نوڈس نے مساوی تعداد میں فائنل پوائنٹس حاصل کیے اور منصوبہ بندی کے لیے بے ترتیب ایک کا انتخاب کیا گیا۔ مسئلہ کی منصوبہ بندی کے وقت، نوشتہ جات اس طرح نظر آتے تھے:

resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1587 millicores 4581125120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1087 millicores 3532549120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node02: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1587 millicores 4581125120 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: BalancedResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 987 millicores 3322833920 memory bytes, score 9
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node01: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 987 millicores 3322833920 memory bytes, score 9 
resource_allocation.go:78] cronjob-1574211360-bzfkr -> Node03: LeastResourceAllocation, capacity 23900 millicores 67167186944 memory bytes, total request 1087 millicores 3532549120 memory bytes, score 9
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node03: InterPodAffinityPriority, Score: (0)                                                                                                        
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node02: InterPodAffinityPriority, Score: (0)                                                                                                        
interpod_affinity.go:237] cronjob-1574211360-bzfkr -> Node01: InterPodAffinityPriority, Score: (0)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node03: SelectorSpreadPriority, Score: (10)                                                                                                        
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node02: SelectorSpreadPriority, Score: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: TaintTolerationPriority, Score: (10)                                                                                   
selector_spreading.go:146] cronjob-1574211360-bzfkr -> Node01: SelectorSpreadPriority, Score: (10)                                                                                                        
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node03: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: TaintTolerationPriority, Score: (10)                                                                                   
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node02: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: NodeAffinityPriority, Score: (0)                                                                                       
generic_scheduler.go:726] cronjob-1574211360-bzfkr_project-stage -> Node01: SelectorSpreadPriority, Score: (10)                                                                                    
generic_scheduler.go:781] Host Node03 => Score 100041                                                                                                                                                                        
generic_scheduler.go:781] Host Node02 => Score 100041                                                                                                                                                                        
generic_scheduler.go:781] Host Node01 => Score 100038

جس سے یہ دیکھا جا سکتا ہے کہ ایک نوڈس نے دوسروں کے مقابلے میں کم کل پوائنٹس حاصل کیے، اور اس لیے منصوبہ بندی صرف دو نوڈس کے لیے کی گئی جنہوں نے زیادہ سے زیادہ سکور کیا۔ اس طرح، ہمیں یقین تھا کہ مسئلہ پھلیوں کی منصوبہ بندی میں بالکل مضمر ہے۔

مسئلے کو حل کرنے کے لیے مزید الگورتھم ہمارے لیے واضح تھا - لاگز کا تجزیہ کرنا، یہ سمجھنا کہ نوڈ کو کس ترجیح سے پوائنٹس نہیں ملے اور، اگر ضروری ہو تو، ڈیفالٹ کیوب-شیڈیولر کی پالیسیوں کو ایڈجسٹ کریں۔ تاہم، یہاں ہمیں دو اہم مشکلات کا سامنا ہے:

  1. لاگنگ کی زیادہ سے زیادہ سطح (10) صرف کچھ ترجیحات کے لیے پوائنٹس کے سیٹ کی عکاسی کرتی ہے۔ مندرجہ بالا لاگ کے اقتباس میں، آپ دیکھ سکتے ہیں کہ نوشتہ جات میں جھلکنے والی تمام ترجیحات کے لیے، نوڈس نارمل اور پرابلم شیڈولنگ میں پوائنٹس کی ایک ہی تعداد اسکور کرتے ہیں، لیکن مسئلہ شیڈولنگ کے معاملے میں حتمی نتیجہ مختلف ہوتا ہے۔ اس طرح، ہم یہ نتیجہ اخذ کر سکتے ہیں کہ کچھ ترجیحات کے لیے اسکورنگ "پردے کے پیچھے" ہوتی ہے، اور ہمارے پاس یہ سمجھنے کا کوئی طریقہ نہیں ہے کہ نوڈ کو کس ترجیح کے لیے پوائنٹس نہیں ملے۔ اس مسئلے کو ہم نے تفصیل سے بیان کیا ہے۔ مسئلہ Github پر Kubernetes ذخیرہ۔ لکھنے کے وقت، ڈویلپرز کی طرف سے جواب موصول ہوا کہ لاگنگ سپورٹ Kubernetes v1.15,1.16 اور 1.17 اپ ڈیٹس میں شامل کی جائے گی۔
  2. یہ سمجھنے کا کوئی آسان طریقہ نہیں ہے کہ کیوب-شیڈیولر فی الحال پالیسیوں کے کس مخصوص سیٹ کے ساتھ کام کر رہا ہے۔ ہاں، میں دستاویزات یہ فہرست درج ہے، لیکن اس میں یہ معلومات شامل نہیں ہے کہ ترجیحات میں سے ہر ایک پالیسی کے لیے کون سے مخصوص وزن مقرر کیے گئے ہیں۔ آپ صرف وزن دیکھ سکتے ہیں یا پہلے سے طے شدہ کیوب-شیڈیولر کی پالیسیوں میں ترمیم کر سکتے ہیں۔ ذرائع.

یہ بات قابل غور ہے کہ ایک بار جب ہم یہ ٹھیک کرنے میں کامیاب ہو گئے کہ نوڈ نے ImageLocalityPriority پالیسی کے مطابق پوائنٹس حاصل نہیں کیے، جو نوڈ کو پوائنٹس دیتا ہے اگر اس کے پاس ایپلی کیشن کو چلانے کے لیے ضروری امیج موجود ہو۔ یعنی، ایپلی کیشن کے نئے ورژن کو رول آؤٹ کرنے کے وقت، کرون ٹاسک کے پاس دو نوڈس پر چلنے کا وقت تھا، ڈوکر رجسٹری سے ان پر ایک نئی امیج ڈاؤن لوڈ کرنا، اور اس طرح دو نوڈس نے اس کے مقابلے میں زیادہ فائنل اسکور حاصل کیا۔ تیسرا

جیسا کہ میں نے اوپر لکھا ہے، لاگز میں ہمیں ImageLocalityPriority پالیسی کی تشخیص کے بارے میں معلومات نظر نہیں آتی ہیں، اس لیے، اپنے مفروضے کو جانچنے کے لیے، ہم نے ایپلیکیشن کے نئے ورژن کے ساتھ تصویر کو تیسرے نوڈ پر ڈال دیا، جس کے بعد منصوبہ بندی صحیح طریقے سے کام کیا. یہ خاص طور پر ImageLocalityPriority پالیسی کی وجہ سے تھا کہ شیڈولنگ کا مسئلہ شاذ و نادر ہی دیکھا گیا، زیادہ تر اس کا تعلق کسی اور چیز سے تھا۔ اس حقیقت کی وجہ سے کہ ہم ڈیفالٹ کیوب-شیڈیولر کی ترجیحات کی فہرست میں ہر ایک پالیسی کو مکمل طور پر ڈیبگ نہیں کر سکے، ہمیں پوڈ شیڈولنگ پالیسیوں کے لچکدار انتظام کی ضرورت تھی۔

مسئلہ کی تشکیل

ہم چاہتے تھے کہ مسئلے کے حل کو زیادہ سے زیادہ ہدف بنایا جائے، یعنی Kubernetes کے اہم اداروں (یہاں ہمارا مطلب ڈیفالٹ کیوب-شیڈیولر ہے) کو کوئی تبدیلی نہیں ہونی چاہیے۔ ہم کسی مسئلے کو ایک جگہ حل کرکے دوسری جگہ بنانا نہیں چاہتے تھے۔ اس طرح، ہمارے پاس اس مسئلے کو حل کرنے کے لیے دو آپشنز آئے جن کا اعلان مضمون کے تعارف میں کیا گیا تھا - ایک اضافی شیڈولر بنانا یا اپنا لکھنا۔ کرون کاموں کو شیڈول کرنے کے لیے بنیادی ضرورت یہ ہے کہ تینوں نوڈس میں بوجھ کو یکساں طور پر تقسیم کیا جائے۔ اس ضرورت کو موجودہ کیوب-شیڈیولر پالیسیوں سے پورا کیا جا سکتا ہے، اس لیے ہمارے کام کے لیے اپنا شیڈولر لکھنا کوئی معنی نہیں رکھتا۔

ایک اضافی کیوب-شیڈیولر بنانے اور تعینات کرنے کی ہدایات میں بیان کی گئی ہیں۔ دستاویزات. تاہم، ہمیں ایسا لگتا تھا کہ تعیناتی ادارہ کیوب-شیڈیولر جیسی اہم سروس کے آپریشن میں غلطی کو برداشت کرنے کے لیے کافی نہیں تھا، اس لیے ہم نے نئے کیوب-شیڈیولر کو اسٹیٹک پوڈ کے طور پر تعینات کرنے کا فیصلہ کیا، جس کی براہ راست نگرانی کبلیٹ کرے گی۔ . اس طرح، ہمارے پاس نئے کیوب-شیڈیولر کے لیے درج ذیل تقاضے ہیں:

  1. سروس کو تمام کلسٹر ماسٹرز پر سٹیٹک پوڈ کے طور پر تعینات کیا جانا چاہیے۔
  2. کیوب شیڈیولر کے ساتھ فعال پوڈ دستیاب نہ ہونے کی صورت میں فیل اوور فراہم کیا جانا چاہیے۔
  3. منصوبہ بندی کرتے وقت بنیادی ترجیح نوڈ پر دستیاب وسائل کی مقدار ہونی چاہیے (LeastRequestedPriority)

حل پر عمل درآمد

یہ فوری طور پر نوٹ کرنا چاہئے کہ ہم Kubernetes v1.14.7 میں تمام کام انجام دیں گے، کیونکہ یہ ورژن اس منصوبے میں استعمال کیا گیا تھا. آئیے اپنے نئے کیوب شیڈیولر کے لیے مینی فیسٹ لکھ کر شروع کریں۔ آئیے ڈیفالٹ مینی فیسٹ (/etc/kubernetes/manifests/kube-scheduler.yaml) کو ایک بنیاد کے طور پر لیتے ہیں اور اسے درج ذیل شکل میں لائیں:

kind: Pod
metadata:
  labels:
    component: scheduler
    tier: control-plane
  name: kube-scheduler-cron
  namespace: kube-system
spec:
      containers:
      - command:
        - /usr/local/bin/kube-scheduler
        - --address=0.0.0.0
        - --port=10151
        - --secure-port=10159
        - --config=/etc/kubernetes/scheduler-custom.conf
        - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
        - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
        - --v=2
        image: gcr.io/google-containers/kube-scheduler:v1.14.7
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 8
          httpGet:
            host: 127.0.0.1
            path: /healthz
            port: 10151
            scheme: HTTP
          initialDelaySeconds: 15
          timeoutSeconds: 15
        name: kube-scheduler-cron-container
        resources:
          requests:
            cpu: '0.1'
        volumeMounts:
        - mountPath: /etc/kubernetes/scheduler.conf
          name: kube-config
          readOnly: true
        - mountPath: /etc/localtime
          name: localtime
          readOnly: true
        - mountPath: /etc/kubernetes/scheduler-custom.conf
          name: scheduler-config
          readOnly: true
        - mountPath: /etc/kubernetes/scheduler-custom-policy-config.json
          name: policy-config
          readOnly: true
      hostNetwork: true
      priorityClassName: system-cluster-critical
      volumes:
      - hostPath:
          path: /etc/kubernetes/scheduler.conf
          type: FileOrCreate
        name: kube-config
      - hostPath:
          path: /etc/localtime
        name: localtime
      - hostPath:
          path: /etc/kubernetes/scheduler-custom.conf
          type: FileOrCreate
        name: scheduler-config
      - hostPath:
          path: /etc/kubernetes/scheduler-custom-policy-config.json
          type: FileOrCreate
        name: policy-config

اہم تبدیلیوں پر مختصراً:

  1. پوڈ اور کنٹینر کا نام kube-scheduler-cron میں تبدیل کر دیا گیا۔
  2. پورٹ 10151 اور 10159 کو استعمال کرنے کے لیے مخصوص کیا گیا ہے جیسا کہ آپشن کی وضاحت کی گئی ہے hostNetwork: true اور ہم ڈیفالٹ کیوب شیڈیولر (10251 اور 10259) جیسی بندرگاہوں کو استعمال نہیں کرسکتے ہیں۔
  3. --config پیرامیٹر کا استعمال کرتے ہوئے، کنفیگریشن فائل کی وضاحت کریں جس کے ساتھ سروس شروع ہونی چاہیے۔
  4. میزبان سے کنفیگریشن فائل (scheduler-custom.conf) اور شیڈولنگ پالیسی فائل (scheduler-custom-policy-config.json) کو ماؤنٹ کرنے کے لیے ترتیب دیا گیا

یہ نہ بھولیں کہ ہمارے کیوب-شیڈیولر کو پہلے سے طے شدہ حقوق کی طرح کی ضرورت ہوگی۔ اس کے کلسٹر رول میں ترمیم کریں:

kubectl edit clusterrole system:kube-scheduler

...
   resourceNames:
    - kube-scheduler
    - kube-scheduler-cron
...

اب آئیے اس بارے میں بات کرتے ہیں کہ کنفیگریشن فائل اور شیڈولنگ پالیسی فائل میں کیا ہونا چاہیے:

  • ترتیب دینے کی فائل (scheduler-custom.conf)
    ڈیفالٹ کیوب-شیڈیولر کی ترتیب حاصل کرنے کے لیے، آپ کو پیرامیٹر استعمال کرنے کی ضرورت ہے۔ --write-config-to کی دستاویزات. ہم نتیجے کی ترتیب کو /etc/kubernetes/scheduler-custom.conf فائل میں رکھیں گے اور اسے درج ذیل شکل میں لائیں گے۔

apiVersion: kubescheduler.config.k8s.io/v1alpha1
kind: KubeSchedulerConfiguration
schedulerName: kube-scheduler-cron
bindTimeoutSeconds: 600
clientConnection:
  acceptContentTypes: ""
  burst: 100
  contentType: application/vnd.kubernetes.protobuf
  kubeconfig: /etc/kubernetes/scheduler.conf
  qps: 50
disablePreemption: false
enableContentionProfiling: false
enableProfiling: false
failureDomains: kubernetes.io/hostname,failure-domain.beta.kubernetes.io/zone,failure-domain.beta.kubernetes.io/region
hardPodAffinitySymmetricWeight: 1
healthzBindAddress: 0.0.0.0:10151
leaderElection:
  leaderElect: true
  leaseDuration: 15s
  lockObjectName: kube-scheduler-cron
  lockObjectNamespace: kube-system
  renewDeadline: 10s
  resourceLock: endpoints
  retryPeriod: 2s
metricsBindAddress: 0.0.0.0:10151
percentageOfNodesToScore: 0
algorithmSource:
   policy:
     file:
       path: "/etc/kubernetes/scheduler-custom-policy-config.json"

اہم تبدیلیوں پر مختصراً:

  1. شیڈولر نام کو ہماری سروس kube-scheduler-cron کے نام پر سیٹ کریں۔
  2. پیرامیٹر میں lockObjectName ہمیں اپنی سروس کا نام بھی سیٹ کرنا ہوگا اور اس بات کو یقینی بنانا ہوگا کہ پیرامیٹر leaderElect سچ پر سیٹ کریں (اگر آپ کے پاس ایک ماسٹر نوڈ ہے، تو آپ ویلیو کو غلط پر سیٹ کر سکتے ہیں)۔
  3. پیرامیٹر میں شیڈولنگ پالیسیوں کی تفصیل کے ساتھ فائل کا راستہ بتا دیا۔ algorithmSource.

یہ دوسرے پیراگراف پر مزید تفصیل سے رہنے کے قابل ہے، جہاں ہم کلید کے پیرامیٹرز میں ترمیم کرتے ہیں۔ leaderElection. غلطی کو برداشت کرنے کے لیے، ہم نے فعال کیا ہے (leaderElect) ہمارے کیوب-شیڈیولر کے پوڈز کے درمیان لیڈر (ماسٹر) کو منتخب کرنے کا عمل ان کے لیے ایک ہی اختتامی نقطہ کا استعمال کرتے ہوئے (resourceLock) کا نام kube-scheduler-cron (lockObjectName) کیوب سسٹم نام کی جگہ میں (lockObjectNamespace)۔ کس طرح Kubernetes اہم اجزاء (بشمول کیوب-شیڈیولر) کی اعلی دستیابی کو یقینی بناتا ہے اس میں پایا جا سکتا ہے آرٹیکل.

  • شیڈولنگ پالیسی فائل (scheduler-custom-policy-config.json)
    جیسا کہ میں نے پہلے لکھا تھا، ہم صرف اپنے کوڈ کا تجزیہ کرکے یہ جان سکتے ہیں کہ ڈیفالٹ کیوب-شیڈیولر کن مخصوص پالیسیوں کے ساتھ کام کرتا ہے۔ یعنی، ہم فائل کو ڈیفالٹ کیوب-شیڈیولر کی شیڈولنگ پالیسیوں کے ساتھ، کنفیگریشن فائل کے ساتھ مشابہت سے حاصل نہیں کر سکتے۔ آئیے ذیل میں /etc/kubernetes/scheduler-custom-policy-config.json فائل میں ہماری دلچسپی کی شیڈولنگ پالیسیوں کی وضاحت کرتے ہیں:

{
  "kind": "Policy",
  "apiVersion": "v1",
  "predicates": [
    {
      "name": "GeneralPredicates"
    }
  ],
  "priorities": [
    {
      "name": "ServiceSpreadingPriority",
      "weight": 1
    },
    {
      "name": "EqualPriority",
      "weight": 1
    },
    {
      "name": "LeastRequestedPriority",
      "weight": 1
    },
    {
      "name": "NodePreferAvoidPodsPriority",
      "weight": 10000
    },
    {
      "name": "NodeAffinityPriority",
      "weight": 1
    }
  ],
  "hardPodAffinitySymmetricWeight" : 10,
  "alwaysCheckAllPredicates" : false
}

لہذا kube-scheduler سب سے پہلے ان نوڈس کی فہرست بناتا ہے جن کے لیے Pod کو GeneralPredicates پالیسی (جس میں PodFitsResources، PodFitsHostPorts، HostName، اور MatchNodeSelector پالیسی سیٹ شامل ہے) کے مطابق شیڈول کیا جا سکتا ہے۔ اور پھر ہر نوڈ کی ترجیحات کی صف میں پالیسیوں کے سیٹ کے مطابق جانچ کی جاتی ہے۔ اپنے کام کی شرائط کو پورا کرنے کے لیے، ہم نے سوچا کہ اس طرح کی پالیسیاں بہترین حل ہوں گی۔ میں آپ کو یاد دلاتا ہوں کہ ان کی تفصیلی وضاحت کے ساتھ پالیسیوں کا ایک سیٹ میں دستیاب ہے۔ دستاویزات. اپنے کام کو پورا کرنے کے لیے، آپ استعمال شدہ پالیسیوں کے سیٹ کو آسانی سے تبدیل کر سکتے ہیں اور انہیں مناسب وزن تفویض کر سکتے ہیں۔

نیا کیوب-شیڈیولر مینی فیسٹ جو ہم نے باب کے شروع میں بنایا ہے اسے kube-scheduler-custom.yaml کہا جائے گا اور اسے تین ماسٹر نوڈس پر /etc/kubernetes/manifests میں رکھا جائے گا۔ اگر سب کچھ صحیح طریقے سے کیا جاتا ہے تو، Kubelet ہر نوڈ پر پوڈ شروع کرے گا، اور ہمارے نئے kube-scheduler کے لاگ میں ہم یہ معلومات دیکھیں گے کہ ہماری پالیسی فائل کو کامیابی کے ساتھ لاگو کیا گیا تھا:

Creating scheduler from configuration: {{ } [{GeneralPredicates <nil>}] [{ServiceSpreadingPriority 1 <nil>} {EqualPriority 1 <nil>} {LeastRequestedPriority 1 <nil>} {NodePreferAvoidPodsPriority 10000 <nil>} {NodeAffinityPriority 1 <nil>}] [] 10 false}
Registering predicate: GeneralPredicates
Predicate type GeneralPredicates already registered, reusing.
Registering priority: ServiceSpreadingPriority
Priority type ServiceSpreadingPriority already registered, reusing.
Registering priority: EqualPriority
Priority type EqualPriority already registered, reusing.
Registering priority: LeastRequestedPriority
Priority type LeastRequestedPriority already registered, reusing.
Registering priority: NodePreferAvoidPodsPriority
Priority type NodePreferAvoidPodsPriority already registered, reusing.
Registering priority: NodeAffinityPriority
Priority type NodeAffinityPriority already registered, reusing.
Creating scheduler with fit predicates 'map[GeneralPredicates:{}]' and priority functions 'map[EqualPriority:{} LeastRequestedPriority:{} NodeAffinityPriority:{} NodePreferAvoidPodsPriority:{} ServiceSpreadingPriority:{}]'

اب یہ صرف ہمارے کرون جاب کی قیاس آرائی میں بتانا باقی ہے کہ اس کے پوڈ کو شیڈول کرنے کی تمام درخواستوں پر ہمارے نئے کیوب-شیڈیولر کے ذریعہ کارروائی کی جانی چاہئے:

...
 jobTemplate:
    spec:
      template:
        spec:
          schedulerName: kube-scheduler-cron
...

حاصل يہ ہوا

آخر میں، ہمیں شیڈولنگ پالیسیوں کے ایک منفرد سیٹ کے ساتھ ایک اضافی کیوب-شیڈیولر ملا، جس کی نگرانی براہ راست کیوبلیٹ کرتی ہے۔ اس کے علاوہ، اگر پرانا لیڈر کسی وجہ سے دستیاب نہ ہو جائے تو ہم اپنے کیوب-شیڈیولر کے پوڈز کے درمیان ایک نئے لیڈر کا انتخاب ترتیب دیتے ہیں۔

عام ایپلیکیشنز اور خدمات ڈیفالٹ کیوب شیڈیولر کے ذریعے شیڈول کی جاتی ہیں، اور تمام کرون ٹاسک مکمل طور پر نئے میں منتقل کر دیے گئے ہیں۔ کرون ٹاسک کے ذریعہ تیار کردہ بوجھ اب تمام نوڈس میں یکساں طور پر تقسیم کیا گیا ہے۔ اس بات پر غور کرتے ہوئے کہ زیادہ تر کرون کام اسی نوڈس پر انجام پاتے ہیں جیسے پروجیکٹ کے اہم ایپلی کیشنز، اس نے وسائل کی کمی کی وجہ سے پوڈز کے حرکت پذیر ہونے کے خطرے کو نمایاں طور پر کم کردیا۔ اضافی کیوب-شیڈیولر کے متعارف ہونے کے بعد، کرون جابز کے غیر مساوی شیڈولنگ کے ساتھ مزید مسائل نہیں تھے۔

ہمارے بلاگ پر دیگر مضامین بھی پڑھیں:

ماخذ: www.habr.com

نیا تبصرہ شامل کریں