शेड्यूलिंग नियमों के कस्टम सेट के साथ एक अतिरिक्त क्यूब-शेड्यूलर बनाना

शेड्यूलिंग नियमों के कस्टम सेट के साथ एक अतिरिक्त क्यूब-शेड्यूलर बनाना

क्यूब-शेड्यूलर कुबेरनेट्स का एक अभिन्न अंग है, जो विशिष्ट नीतियों के अनुसार नोड्स में पॉड शेड्यूल करने के लिए जिम्मेदार है। अक्सर, कुबेरनेट्स क्लस्टर के संचालन के दौरान, हमें यह सोचने की ज़रूरत नहीं है कि पॉड्स को शेड्यूल करने के लिए कौन सी नीतियों का उपयोग किया जाता है, क्योंकि डिफ़ॉल्ट क्यूब-शेड्यूलर की नीतियों का सेट अधिकांश रोजमर्रा के कार्यों के लिए उपयुक्त है। हालाँकि, ऐसी परिस्थितियाँ होती हैं जब हमारे लिए पॉड्स के वितरण को ठीक करना महत्वपूर्ण होता है, और इस कार्य को पूरा करने के दो तरीके हैं:

  1. कस्टम नियम-सेट के साथ क्यूब-शेड्यूलर बनाएं
  2. अपना स्वयं का अनुसूचक लिखें और इसे एपीआई सर्वर अनुरोधों के साथ काम करना सिखाएं

इस लेख में, मैं हमारी एक परियोजना पर पॉड्स के असमान शेड्यूलिंग की समस्या को हल करने के पहले बिंदु के कार्यान्वयन का वर्णन करूंगा।

क्यूब-शेड्यूलर'ए के काम के बारे में संक्षिप्त परिचय

ध्यान देने योग्य तथ्य यह है कि क्यूब-शेड्यूलर सीधे पॉड को शेड्यूल करने के लिए ज़िम्मेदार नहीं है - यह केवल उस नोड को निर्धारित करने के लिए ज़िम्मेदार है जिस पर पॉड लगाया जाए। दूसरे शब्दों में, क्यूब-शेड्यूलर के कार्य का परिणाम उस नोड का नाम है जो शेड्यूलिंग अनुरोध के लिए एपीआई सर्वर पर लौटता है, और यहीं पर इसका काम समाप्त होता है।

सबसे पहले, क्यूब-शेड्यूलर उन नोड्स को सूचीबद्ध करता है जो एक पॉड को विधेय नीतियों के अनुसार निर्धारित किया जा सकता है। इसके अलावा, इस सूची के प्रत्येक नोड को प्राथमिकताओं की नीतियों के अनुसार निश्चित संख्या में अंक प्राप्त होते हैं। नतीजतन, उच्चतम स्कोर वाले नोड का चयन किया जाता है। यदि समान अधिकतम स्कोर वाले नोड हैं, तो एक यादृच्छिक चुना जाता है। विधेय (फ़िल्टरिंग) और प्राथमिकताओं (स्कोरिंग) नीतियों की एक सूची और विवरण में पाया जा सकता है प्रलेखन.

समस्या शरीर का विवरण

निक्सिस में बड़ी संख्या में अलग-अलग कुबेरनेट क्लस्टर बनाए रखने के बावजूद, हमें पहली बार शेड्यूलिंग पॉड की समस्या का सामना हाल ही में करना पड़ा, जब हमारी एक परियोजना के लिए बड़ी संख्या में आवधिक कार्यों (~ 100 क्रोनजॉब संस्थाओं) को चलाना आवश्यक हो गया। जितना संभव हो समस्या के विवरण को सरल बनाने के लिए, एक उदाहरण के रूप में, आइए एक माइक्रोसर्विस लें, जिसके भीतर सीपीयू पर कुछ लोड बनाते हुए, मिनट में एक बार क्रोन टास्क लॉन्च किया जाता है। क्रॉन टास्क के काम के लिए तीन बिल्कुल समान नोड्स (प्रत्येक पर 24 वीसीपीयू) आवंटित किए गए थे।

उसी समय, यह कहना असंभव है कि क्रोनजॉब कितने समय तक चलेगा, क्योंकि इनपुट डेटा की मात्रा लगातार बदल रही है। औसतन, सामान्य क्यूब-शेड्यूलर ऑपरेशन के दौरान, प्रत्येक नोड 3-4 जॉब इंस्टेंस चलाता है, जो प्रत्येक नोड के सीपीयू पर ~ 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) केवल कुछ प्राथमिकताओं के लिए बिंदुओं के सेट को दर्शाता है। उपरोक्त लॉग अंश में, आप देख सकते हैं कि लॉग में परिलक्षित सभी प्राथमिकताओं के लिए, नोड्स सामान्य और समस्या शेड्यूलिंग में समान अंक प्राप्त करते हैं, लेकिन समस्या शेड्यूलिंग के मामले में अंतिम परिणाम अलग होता है। इस प्रकार, हम यह निष्कर्ष निकाल सकते हैं कि कुछ प्राथमिकताओं के लिए स्कोरिंग "पर्दे के पीछे" होती है, और हमारे पास यह समझने का कोई तरीका नहीं है कि किस प्राथमिकता के लिए नोड को अंक नहीं मिले। हमने इस मुद्दे का विस्तार से वर्णन किया है मुद्दा गीथूब पर कुबेरनेट्स रिपॉजिटरी। लेखन के समय, डेवलपर्स से एक प्रतिक्रिया प्राप्त हुई थी कि कुबेरनेट्स v1.15,1.16 और 1.17 अपडेट में लॉगिंग समर्थन जोड़ा जाएगा।
  2. यह समझने का कोई आसान तरीका नहीं है कि क्यूब-शेड्यूलर वर्तमान में किन नीतियों के साथ काम कर रहा है। हां अंदर प्रलेखन यह सूची सूचीबद्ध है, लेकिन इसमें यह जानकारी नहीं है कि प्रत्येक प्राथमिकता नीतियों के लिए कौन से विशिष्ट भार निर्धारित किए गए हैं। आप डिफ़ॉल्ट क्यूब-शेड्यूलर में केवल वज़न देख सकते हैं या नीतियों को संपादित कर सकते हैं सूत्रों का कहना है.

यह ध्यान देने योग्य है कि एक बार जब हम यह ठीक करने में कामयाब रहे कि नोड को ImageLocalityPriority नीति के अनुसार अंक नहीं मिले, जो नोड को पुरस्कार देता है यदि उसके पास पहले से ही एप्लिकेशन को चलाने के लिए आवश्यक छवि है। अर्थात्, एप्लिकेशन के नए संस्करण को रोल आउट करने के समय, क्रॉन कार्य के पास दो नोड्स पर चलने का समय था, डॉकर रजिस्ट्री से एक नई छवि डाउनलोड करने के लिए, और इस प्रकार दो नोड्स को सापेक्ष उच्च अंतिम स्कोर प्राप्त हुआ। तीसरा वाला।

जैसा कि मैंने ऊपर लिखा है, लॉग में हमें ImageLocalityPriority नीति के मूल्यांकन के बारे में जानकारी नहीं दिखाई देती है, इसलिए, अपनी धारणा की जाँच करने के लिए, हमने तीसरे नोड के लिए एप्लिकेशन के नए संस्करण के साथ छवि को स्पूल किया, जिसके बाद नियोजन सही ढंग से काम किया। यह ImageLocalityPriority नीति के कारण था कि शेड्यूलिंग समस्या शायद ही कभी देखी गई थी, अधिक बार यह किसी और चीज़ से जुड़ी थी। इस तथ्य के कारण कि हम डिफ़ॉल्ट क्यूब-शेड्यूलर की प्राथमिकताओं की सूची में प्रत्येक नीति को पूरी तरह से डिबग नहीं कर सके, हमें पॉड शेड्यूलिंग नीतियों के लचीले प्रबंधन की आवश्यकता थी।

समस्या का निरूपण

हम चाहते थे कि समस्या का समाधान यथासंभव लक्षित हो, यानी कुबेरनेट्स की मुख्य संस्थाएँ (यहाँ हमारा मतलब डिफ़ॉल्ट क्यूब-शेड्यूलर से है) अपरिवर्तित रहना चाहिए। हम किसी समस्या को एक जगह सुलझाकर दूसरी जगह पैदा नहीं करना चाहते थे। इस प्रकार, हम लेख के परिचय में घोषित समस्या को हल करने के लिए दो विकल्पों पर आए - एक अतिरिक्त अनुसूचक बनाना या अपना खुद का लिखना। क्रोन कार्यों को शेड्यूल करने के लिए मुख्य आवश्यकता समान रूप से लोड को तीन नोड्स में वितरित करना है। यह आवश्यकता मौजूदा क्यूब-शेड्यूलर नीतियों द्वारा पूरी की जा सकती है, इसलिए हमारे कार्य के लिए अपना शेड्यूलर लिखने का कोई मतलब नहीं है।

एक अतिरिक्त क्यूब-शेड्यूलर बनाने और तैनात करने के निर्देश में वर्णित हैं प्रलेखन. हालाँकि, हमें ऐसा लगा कि क्यूब-शेड्यूलर जैसी महत्वपूर्ण सेवा के संचालन में दोष सहिष्णुता सुनिश्चित करने के लिए परिनियोजन इकाई पर्याप्त नहीं है, इसलिए हमने नए क्यूब-शेड्यूलर को एक स्टेटिक पॉड के रूप में तैनात करने का निर्णय लिया, जिसे क्यूबलेट सीधे मॉनिटर करेगा . इस प्रकार, हमारे पास नए क्यूब-शेड्यूलर के लिए निम्नलिखित आवश्यकताएं हैं:

  1. सेवा को सभी क्लस्टर मास्टर्स पर स्टेटिक पॉड के रूप में तैनात किया जाना चाहिए
  2. क्यूब-शेड्यूलर के साथ सक्रिय पॉड अनुपलब्ध होने पर फेलओवर प्रदान किया जाना चाहिए
  3. योजना बनाते समय मुख्य प्राथमिकता नोड पर उपलब्ध संसाधनों की मात्रा होनी चाहिए (LeastRequestedPriority)

कार्यान्वयन समाधान

यह तुरंत ध्यान दिया जाना चाहिए कि हम कुबेरनेट्स 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. पॉड और कंटेनर का नाम बदलकर क्यूब-शेड्यूलर-क्रॉन कर दिया गया है
  2. विकल्प के रूप में पोर्ट 10151 और 10159 का उपयोग करने के लिए निर्दिष्ट किया गया है hostNetwork: true और हम डिफ़ॉल्ट क्यूब-शेड्यूलर (10251 और 10259) के समान बंदरगाहों का उपयोग नहीं कर सकते
  3. --Config पैरामीटर का उपयोग करते हुए, कॉन्फ़िगरेशन फ़ाइल निर्दिष्ट करें जिसके साथ सेवा प्रारंभ होनी चाहिए
  4. होस्ट से कॉन्फ़िगरेशन फ़ाइल (शेड्यूलर-कस्टम.कॉन्फ़) और शेड्यूलिंग पॉलिसी फ़ाइल (शेड्यूलर-कस्टम-पॉलिसी-कॉन्फिग.जेसन) को माउंट करने के लिए कॉन्फ़िगर किया गया

यह मत भूलो कि हमारे क्यूब-शेड्यूलर को डिफ़ॉल्ट के समान अधिकारों की आवश्यकता होगी। इसकी क्लस्टर भूमिका संपादित करें:

kubectl edit clusterrole system:kube-scheduler

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

अब बात करते हैं कि कॉन्फ़िगरेशन फ़ाइल और शेड्यूलिंग नीति फ़ाइल में क्या शामिल होना चाहिए:

  • कॉन्फ़िगरेशन फ़ाइल (अनुसूचक-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. शेड्यूलरनाम को हमारी सेवा क्यूब-शेड्यूलर-क्रॉन के नाम पर सेट करें।
  2. पैरामीटर में lockObjectName हमें अपनी सेवा का नाम भी सेट करना होगा और यह सुनिश्चित करना होगा कि पैरामीटर leaderElect सही पर सेट करें (यदि आपके पास एक मास्टर नोड है, तो आप मान को गलत पर सेट कर सकते हैं)।
  3. पैरामीटर में शेड्यूलिंग नीतियों के विवरण के साथ फ़ाइल का पथ निर्दिष्ट करें algorithmSource.

यह दूसरे पैराग्राफ पर अधिक विस्तार से ध्यान देने योग्य है, जहां हम कुंजी के मापदंडों को संपादित करते हैं leaderElection. दोष सहिष्णुता के लिए, हमने सक्षम किया है (leaderElect) हमारे क्यूब-शेड्यूलर के पॉड्स के बीच उनके लिए एक समापन बिंदु का उपयोग करके एक नेता (मास्टर) चुनने की प्रक्रिया (resourceLock) नाम क्यूब-शेड्यूलर-क्रॉन (lockObjectName) क्यूब-सिस्टम नेमस्पेस में (lockObjectNamespace). कुबेरनेट कैसे मुख्य घटकों (क्यूब-शेड्यूलर सहित) की उच्च उपलब्धता सुनिश्चित करता है, इसमें पाया जा सकता है लेख.

  • निर्धारण नीति फ़ाइल (शेड्यूलर-कस्टम-नीति-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
}

तो क्यूब-शेड्यूलर पहले उन नोड्स को सूचीबद्ध करता है, जिन्हें एक पॉड को GeneralPredicates नीति के अनुसार निर्धारित किया जा सकता है (जिसमें PodFitsResources, PodFitsHostPorts, HostName, और MatchNodeSelector नीति सेट शामिल हैं)। और फिर प्राथमिकता सरणी में नीतियों के सेट के अनुसार प्रत्येक नोड का मूल्यांकन किया जाता है। अपने कार्य की शर्तों को पूरा करने के लिए, हमने माना कि नीतियों का ऐसा समूह सबसे अच्छा समाधान होगा। मैं आपको याद दिला दूं कि नीतियों का एक सेट उनके विस्तृत विवरण के साथ में उपलब्ध है प्रलेखन. अपने कार्य को पूरा करने के लिए, आप केवल उपयोग की जाने वाली नीतियों के सेट को बदल सकते हैं और उन्हें उचित भार प्रदान कर सकते हैं।

नया क्यूब-शेड्यूलर मैनिफ़ेस्ट जिसे हमने अध्याय की शुरुआत में बनाया था, उसे क्यूब-शेड्यूलर-कस्टम.यामल कहा जाएगा और तीन मास्टर नोड्स पर /etc/kubernetes/manifests में रखा जाएगा। यदि सब कुछ सही ढंग से किया जाता है, तो क्यूबलेट प्रत्येक नोड पर पॉड शुरू करेगा, और हमारे नए क्यूब-शेड्यूलर के लॉग में हम यह जानकारी देखेंगे कि हमारी नीति फ़ाइल सफलतापूर्वक लागू की गई थी:

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:{}]'

अब यह केवल हमारे CronJob के विनिर्देश में निर्दिष्ट करने के लिए बना हुआ है कि इसके पॉड्स को शेड्यूल करने के सभी अनुरोधों को हमारे नए क्यूब-शेड्यूलर द्वारा संसाधित किया जाना चाहिए:

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

निष्कर्ष

अंत में, हमें शेड्यूलिंग नीतियों के एक अनूठे सेट के साथ एक अतिरिक्त क्यूब-शेड्यूलर मिला, जिसकी निगरानी सीधे क्यूबलेट द्वारा की जाती है। इसके अलावा, यदि पुराने नेता किसी कारण से अनुपलब्ध हो जाते हैं, तो हम अपने क्यूब-शेड्यूलर के पॉड्स के बीच एक नए नेता के चुनाव की स्थापना करते हैं।

सामान्य एप्लिकेशन और सेवाएं डिफ़ॉल्ट क्यूब-शेड्यूलर के माध्यम से निर्धारित की जाती हैं, और सभी क्रॉन कार्यों को पूरी तरह से नए में स्थानांतरित कर दिया गया है। क्रॉन कार्यों द्वारा निर्मित लोड अब समान रूप से सभी नोड्स में वितरित किया जाता है। यह देखते हुए कि अधिकांश क्रॉन कार्यों को परियोजना के मुख्य अनुप्रयोगों के समान नोड्स पर निष्पादित किया जाता है, इससे संसाधनों की कमी के कारण पॉड्स के चलने का जोखिम काफी कम हो जाता है। अतिरिक्त क्यूब-शेड्यूलर की शुरुआत के बाद, क्रॉन जॉब्स के असमान शेड्यूलिंग के साथ कोई और समस्या नहीं थी।

हमारे ब्लॉग पर अन्य लेख भी पढ़ें:

स्रोत: www.habr.com

एक टिप्पणी जोड़ें