Kubernetes में सीपीयू सीमा और आक्रामक थ्रॉटलिंग

ध्यान दें perev। : यूरोपीय यात्रा एग्रीगेटर, ओमियो की यह सावधानीपूर्ण कहानी, बुनियादी सिद्धांत से पाठकों को कुबेरनेट विन्यास की मनोरम व्यावहारिक पेचीदगियों के लिए निर्देशित करती है। ऐसे मामलों से परिचित न केवल किसी के क्षितिज को व्यापक बनाने में मदद करता है, बल्कि गैर-तुच्छ समस्याओं को भी रोकता है।



क्या आपने कभी इस तथ्य का सामना किया है कि आवेदन "अटक गया", स्वास्थ्य जांच के अनुरोधों का जवाब देना बंद कर दिया, और आप इस व्यवहार के कारण को समझ नहीं पाए? एक संभावित स्पष्टीकरण सीपीयू संसाधनों के लिए कोटा सीमा है। इस लेख में उनकी चर्चा की जाएगी।

TL; DR:
हम दृढ़ता से अनुशंसा करते हैं कि आप Kubernetes में CPU सीमा को मना कर दें (या Kubelet में CFS कोटा अक्षम करें) यदि आप किसी CFS कोटा त्रुटि के साथ लिनक्स कर्नेल संस्करण का उपयोग कर रहे हैं। वहां के मूल मेंएक गंभीर और प्रसिद्ध बग जो अत्यधिक थ्रॉटलिंग और देरी की ओर जाता है


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

लेख का सारांश:

  • कंटेनर और कुबेरनेट के बारे में कुछ शब्द;
  • सीपीयू अनुरोध और सीमाएं कैसे लागू की जाती हैं;
  • मल्टी-कोर वातावरण में सीपीयू सीमा कैसे काम करती है;
  • थ्रॉटलिंग सीपीयू को कैसे ट्रैक करें;
  • समस्या और बारीकियों को हल करना।

कंटेनर और कुबेरनेट के बारे में कुछ शब्द


कुबेरनेट्स, वास्तव में, बुनियादी ढांचे की दुनिया में आधुनिक मानक है। इसका मुख्य कार्य कंटेनरों का ऑर्केस्ट्रेशन है।

कंटेनर


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

कंटेनरों ने सब कुछ बदल दिया है।अब कंटेनर की छवि एक विरूपण साक्ष्य के रूप में कार्य करती है। यह एक प्रकार की विस्तारित निष्पादन योग्य फ़ाइल के रूप में प्रस्तुत किया जा सकता है, जिसमें न केवल एक कार्यक्रम है, बल्कि एक पूर्ण रनटाइम (जावा / पायथन / ...), साथ ही आवश्यक फाइलें / पैकेज हैं जो पहले से स्थापित हैं और चलाने के लिए तैयार हैं। कंटेनरों को तैनात किया जा सकता है और बिना किसी अतिरिक्त कदम के विभिन्न सर्वरों पर चलाया जा सकता है।

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

Kubernetes


जैसा कि पहले कहा गया है, कुबेरनेट्स एक कंटेनर ऑर्केस्ट्रा है। यह निम्नानुसार काम करता है: आप इसे मशीनों के एक पूल के साथ प्रदान करते हैं, और फिर कहते हैं: "हे कुबेरनेट्स, मेरे कंटेनर के 2 इंस्टेंस 2 प्रोसेसर और 3 जीबी मेमोरी प्रत्येक के साथ लॉन्च करें, और उन्हें चालू रखें!" कुबेरनेट्स बाकी की देखभाल करते हैं। वह मुफ्त क्षमताओं को ढूंढेगा, कंटेनरों को लॉन्च करेगा और यदि आवश्यक हो तो उन्हें फिर से शुरू कर सकता है, संस्करणों को बदलते समय अपडेट अपडेट कर सकता है, आदि। वास्तव में, कुबेरनेट्स आपको हार्डवेयर घटक से अमूर्त करने की अनुमति देता है और पूरी तरह से सिस्टम की तैनाती और अनुप्रयोगों के संचालन के लिए उपयुक्त बनाता है।


एक साधारण आम आदमी के दृष्टिकोण से कुबेरनेट्स

कुबेरनेट्स में अनुरोध और सीमा क्या है


ठीक है, हमने कंटेनरों और कुबेरनेट्स का पता लगाया। हम यह भी जानते हैं कि कई कंटेनर एक ही मशीन पर हो सकते हैं।

आप एक सांप्रदायिक अपार्टमेंट के साथ एक सादृश्य आकर्षित कर सकते हैं। एक विशाल कमरा (कार / नोड्स) लिया गया है और कई किरायेदारों (कंटेनरों) को पट्टे पर दिया गया है। Kubernetes एक रियाल्टार के रूप में कार्य करता है। सवाल उठता है कि किरायेदारों को एक-दूसरे के साथ संघर्ष से कैसे रखा जाए? क्या होगा यदि उनमें से एक, कहे, तो आधे दिन के लिए बाथरूम पर कब्जा करने का फैसला करता है?

यह वह जगह है जहाँ अनुरोध और सीमा खेल में आती है। सीपीयू अनुरोध केवल नियोजन उद्देश्यों के लिए है। यह कंटेनर की "इच्छा सूची" की तरह है, और इसका उपयोग सबसे उपयुक्त नोड को चुनने के लिए किया जाता है। इसी समय, सीपीयू सीमा की तुलना एक पट्टे के साथ की जा सकती है - जैसे ही हम कंटेनर के लिए एक नोड उठाते हैं, वहस्थापित सीमाओं से परे जाने में सक्षम नहीं होगाऔर यहाँ एक समस्या उत्पन्न होती है ...

कुबेरनेट्स में अनुरोध और सीमाएं कैसे लागू की जाती हैं


CPU सीमाओं को लागू करने के लिए Kubernetes कर्नेल थ्रॉटलिंग (स्किपिंग क्लॉक) तंत्र का उपयोग करता है। यदि एप्लिकेशन सीमा से अधिक है, थ्रॉटलिंग सक्षम है (अर्थात यह कम सीपीयू चक्र प्राप्त करता है)। मेमोरी के लिए अनुरोध और सीमाएं अलग-अलग आयोजित की जाती हैं, इसलिए उन्हें पता लगाना आसान होता है। ऐसा करने के लिए, यह अंतिम पॉड रिस्टार्ट स्थिति की जांच करने के लिए पर्याप्त है: चाहे वह "OOMKilled" हो। CPU के थ्रॉटलिंग के साथ, सब कुछ इतना सरल नहीं है, क्योंकि K8s केवल उपयोग के लिए मैट्रिक्स उपलब्ध कराता है, cgroups नहीं।

सीपीयू अनुरोध



सीपीयू अनुरोध कैसे कार्यान्वित किया जाता है

सादगी के लिए, आइए 4-कोर सीपीयू के साथ मशीन के उदाहरण का उपयोग करके एक प्रक्रिया देखें।

K8s संसाधनों (मेमोरी और प्रोसेसर) के आवंटन को नियंत्रित करने के लिए cgroups तंत्र का उपयोग करता है। एक पदानुक्रमित मॉडल उसके लिए उपलब्ध है: एक वंशज मूल समूह की सीमाओं को प्राप्त करता है। वितरण विवरण वर्चुअल फ़ाइल सिस्टम ( /sys/fs/cgroup) में संग्रहीत हैं । प्रोसेसर के मामले में, यह /sys/fs/cgroup/cpu,cpuacct/*

K8s cpu.shareप्रोसेसर संसाधनों को आवंटित करने के लिए फ़ाइल का उपयोग करता है । हमारे मामले में, रूट कंट्रोल समूह को सीपीयू संसाधनों के 4096 शेयर मिलते हैं - उपलब्ध प्रोसेसर शक्ति का 100% (1 कोर = 1024; यह एक निश्चित मूल्य है)। रूट समूह निर्धारित वंशजों के शेयरों के आधार पर आनुपातिक रूप से संसाधनों का वितरण करता हैcpu.share, और वे, बदले में, उनके वंशजों के लिए भी यही करते हैं। आमतौर पर Kubernetes रूट नोड नियंत्रण समूह तीन बच्चे हैं: system.slice, user.sliceऔर kubepods। पहले दो उपसमूहों का उपयोग K8s के बाहर महत्वपूर्ण सिस्टम लोड और उपयोगकर्ता कार्यक्रमों के बीच संसाधनों को वितरित करने के लिए किया जाता है। अंतिम - - kubepodsकुबेरनेट्स द्वारा फली के बीच संसाधनों को वितरित करने के लिए बनाया गया है।

ऊपर दिए गए आरेख से पता चलता है कि कुबेरपॉड उपसमूह को आवंटित 4096 शेयरों के साथ पहले और दूसरे उपसमूह को 1024 शेयर मिले । यह कैसे संभव है: आखिरकार, रूट समूह के पास केवल 4096 शेयर उपलब्ध हैं, और इसके वंशजों के शेयरों का योग इस संख्या से अधिक है ( 6144))? तथ्य यह है कि मूल्य तार्किक अर्थ बनाता है, इसलिए लिनक्स शेड्यूलर (सीएफएस) इसका उपयोग आनुपातिक रूप से सीपीयू संसाधनों को आवंटित करने के लिए करता है। हमारे मामले में, पहले दो समूहों को 680 वास्तविक शेयर (4096 का 16.6%) प्राप्त होता है, और कुबेपोड को शेष 2736 शेयर प्राप्त होते हैं । डाउनटाइम के मामले में, पहले दो समूह आवंटित संसाधनों का उपयोग नहीं करेंगे।

सौभाग्य से, अनुसूचक के पास अप्रयुक्त सीपीयू संसाधनों के नुकसान से बचने के लिए एक तंत्र है। यह "निष्क्रिय" क्षमताओं को वैश्विक पूल में स्थानांतरित करता है, जहां से उन्हें उन समूहों में वितरित किया जाता है जिन्हें अतिरिक्त प्रोसेसर क्षमता की आवश्यकता होती है (गोलाई में नुकसान से बचने के लिए बैचों में स्थानांतरण होता है)। इसी तरह की विधि वंशजों के सभी वंशों पर लागू होती है।

यह तंत्र प्रोसेसर शक्ति का उचित वितरण सुनिश्चित करता है और यह सुनिश्चित करता है कि कोई भी प्रक्रिया दूसरों से "चोरी" न करे।

सीपीयू सीमा


इस तथ्य के बावजूद कि K8 में सीमाओं और अनुरोधों के कॉन्फ़िगरेशन समान दिखते हैं, उनका कार्यान्वयन मौलिक रूप से अलग है: यह सबसे भ्रामक और कम से कम दस्तावेज वाला हिस्सा है।

K8s सीएफएस कोटा तंत्र का उपयोग सीमाओं को लागू करने के लिए करता है। उनकी सेटिंग फ़ाइलों में निर्दिष्ट कर रहे हैं cfs_period_usऔर cfs_quota_us(फ़ाइल भी वहाँ स्थित है cgroup निर्देशिका में cpu.share)।

इसके विपरीत cpu.share, कोटा समय की अवधि पर आधारित है , और उपलब्ध प्रोसेसर शक्ति पर नहीं। cfs_period_usअवधि (युग) की अवधि निर्धारित करता है - यह हमेशा 100,000 μs (100 एमएस) है। K8s में इस मान को बदलने की क्षमता है, लेकिन यह वर्तमान में केवल अल्फा संस्करण में उपलब्ध है। शेड्यूलर उपयोग किए गए कोटा को पुनः आरंभ करने के लिए युग का उपयोग करता है। दूसरी फाइलcfs_quota_us, प्रत्येक युग में उपलब्ध समय (कोटा) निर्धारित करता है। कृपया ध्यान दें कि यह माइक्रोसेकंड में भी इंगित किया गया है। कोटा युग की अवधि से अधिक हो सकता है; दूसरे शब्दों में, यह 100 एमएस से अधिक हो सकता है।

आइए 16-कोर मशीनों (ओमियो में सबसे सामान्य प्रकार के कंप्यूटर) पर दो परिदृश्य देखें:


परिदृश्य 1: 2 थ्रेड्स और 200 एमएस की सीमा। थ्रॉटलिंग के बिना


परिदृश्य 2: 10 प्रवाह और 200 एमएस की सीमा। थ्रॉटलिंग 20 एमएस के बाद शुरू होता है, प्रोसेसर संसाधनों तक पहुंच एक और 80 एमएस के बाद शुरू होती है

मान लीजिए कि आपने सीपीयू की सीमा 2 कोर पर सेट की है ; कुबेरनेट्स इस मान का 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 - नैनोस्कॉन्ड्स में संचयी थ्रोट समय।



वास्तव में क्या हो रहा है?


नतीजतन, हम सभी अनुप्रयोगों में उच्च थ्रॉटलिंग प्राप्त करते हैं। कभी-कभी यह गणना की तुलना में डेढ़ गुना अधिक मजबूत होता है!

यह विभिन्न त्रुटियों की ओर जाता है - तत्परता की जांच विफलताओं, कंटेनर हैंग, नेटवर्क कनेक्शन टूट जाता है, सर्विस कॉल के अंदर टाइमआउट। अंततः, यह बढ़ी हुई विलंबता और बढ़ी हुई त्रुटियों में बदल जाता है।

निर्णय और परिणाम


यहां सब कुछ सरल है। हमने सीपीयू सीमा को छोड़ दिया और क्लस्टर में ओएस कर्नेल को नवीनतम संस्करण में अपडेट करना शुरू कर दिया, जिसमें बग को ठीक किया गया था। हमारी सेवाओं में त्रुटियों की संख्या (HTTP 5xx) तुरंत काफी गिर गई:

HTTP त्रुटियां 5xx



HTTP 5xx एक महत्वपूर्ण सेवा की त्रुटियाँ

P95 प्रतिक्रिया समय



गंभीर सेवा अनुरोध विलंब, 95 प्रतिशत

परिचालन लागत



कई घंटे बिताए

क्या चालबाजी है?


जैसा कि लेख की शुरुआत में कहा गया है:

आप एक सांप्रदायिक अपार्टमेंट के साथ एक सादृश्य आकर्षित कर सकते हैं ... कुबेरनेट्स एक रियाल्टार के रूप में कार्य करता है। लेकिन किरायेदारों को एक-दूसरे के साथ संघर्ष से कैसे रखा जाए? क्या होगा यदि उनमें से एक, कहे, तो आधे दिन के लिए बाथरूम पर कब्जा करने का फैसला करता है?

यह पकड़ है। एक लापरवाह कंटेनर मशीन पर सभी उपलब्ध प्रोसेसर संसाधनों को अवशोषित कर सकता है। यदि आपके पास एक बुद्धिमान एप्लिकेशन स्टैक है (उदाहरण के लिए, जेवीएम, गो, नोड वीएम ठीक से कॉन्फ़िगर किया गया है), तो यह कोई समस्या नहीं है: आप लंबे समय तक ऐसी स्थितियों में काम कर सकते हैं। लेकिन यदि एप्लिकेशन खराब रूप से अनुकूलित हैं या बिल्कुल भी अनुकूलित नहीं हैं ( FROM java:latest), स्थिति हाथ से निकल सकती है। ओमियो में हमारे पास मुख्य भाषाओं के ढेर के लिए पर्याप्त डिफ़ॉल्ट सेटिंग्स के साथ बुनियादी डॉकफाइल्स स्वचालित हैं, इसलिए ऐसी कोई समस्या नहीं थी।

हम अनुशंसा करते हैं कि आप USE मेट्रिक्स (उपयोग, संतृप्ति और त्रुटियां), API देरी और त्रुटि दर की निगरानी करेंसुनिश्चित करें कि परिणाम उम्मीद के मुताबिक हैं।

संदर्भ


वह हमारी कहानी है। निम्नलिखित सामग्रियों ने यह समझने में बहुत मदद की है कि क्या हो रहा है:


कुबेरनेट्स त्रुटि रिपोर्टिंग:


क्या आपको अपने अभ्यास में समान समस्याओं का सामना करना पड़ा है या आपको कंटेनरीकृत उत्पादन वातावरण में थ्रॉटलिंग के साथ अनुभव है? अपनी कहानी टिप्पणियों में साझा करें!

अनुवादक से पी.एस.


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


All Articles