प्रतिनिधि इंटरव्यू विषय

सिस्टम डिज़ाइन इंटरव्यू: सर्वर-साइड शार्ड किए गए List और Watch के साथ Kubernetes कंट्रोलर्स को स्केल करें

सिस्टम डिज़ाइनकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक कंट्रोलर फ्लीट लाखों Pods को वॉच करता है। वर्तमान में प्रत्येक रेप्लिका पूरी List और Watch स्ट्रीम प्राप्त करती है, स्थानीय रूप से फ़िल्टर करती है, और API सर्वर व नेटवर्क को ओवरलोड करती है। Kubernetes v1.36 सर्वर-साइड शार्ड किए गए List और Watch में माइग्रेशन डिज़ाइन करें: आप रेंज कैसे असाइन करते हैं, कवरेज कैसे साबित करते हैं, असमर्थित सर्वरों व रीशार्डिंग को कैसे संभालते हैं, और यह कैसे सत्यापित करते हैं कि कोई भी ऑब्जेक्ट छूटे नहीं या दो बार प्रोसेस न हो?

समस्या और दायरा

यह प्लेटफ़ॉर्म और Kubernetes इंजीनियरों के लिए कंट्रोल-प्लेन सिस्टम-डिज़ाइन से जुड़ा प्रश्न है। Kubernetes v1.36 ने ShardedListAndWatch गेट के पीछे एक अल्फा सुविधा के रूप में सर्वर-साइड शार्ड किए गए List और Watch को पेश किया है। इस सुविधा को वैकल्पिक मानें और एक ऐसा कंट्रोलर डिज़ाइन करें जो गेट अक्षम होने पर भी सही ढंग से कार्य करे।

इंटरव्यूअर क्या मूल्यांकन करता है

  • एक शार्ड ओनरशिप मॉडल जो की-स्पेस को ठीक एक बार (exactly once) कवर करता है।
  • सही प्रारंभिक List, resource-version हैंडलिंग, और Watch पुनः कनेक्ट व्यवहार।
  • ऐसे API सर्वर की पहचान जिसने चयनकर्ता (selector) को अनदेखा कर दिया।
  • रीशार्डिंग, रेप्लिका चर्न, और ओवरलैप व गैप के बीच ट्रेड-ऑफ।
  • API सर्वर CPU, नेटवर्क, इन्फॉर्मर मेमोरी, और रिकवरी स्टॉर्म के लिए क्षमता का तर्क।

ओनरशिप की (key) क्या है?

अल्फा कार्यान्वयन object.metadata.uid और object.metadata.namespace का समर्थन करता है। UID हैशिंग स्थिर वितरण प्रदान करती है; नेमस्पेस हैशिंग टेनेंट लोकैलिटी को बनाए रख सकती है लेकिन विषम (skewed) हो सकती है। यह चयन बैलेंसिंग, सुरक्षा सीमाओं और माइग्रेशन लागत को बदल देता है।

शुद्धता का लक्ष्य क्या है?

पूछें कि क्या कम से कम एक बार (at-least-once) समाधान (reconciliation) स्वीकार्य है और क्या डुप्लिकेट प्रोसेसिंग आइडम्पोटेंट है। यदि कोई व्यावसायिक साइड इफेक्ट डुप्लिकेट को सहन नहीं कर सकता है, तो केवल इवेंट स्ट्रीम पर निर्भर रहने के बजाय एक टिकाऊ वर्क की (work key) और फेंसिंग जोड़ें।

क्या प्रत्येक API सर्वर और क्लाइंट एक साथ अपग्रेड हो सकते हैं?

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

30-सेकंड उत्तर रूपरेखा

“मैं एक डिटरमिनिस्टिक 64-बिट हैश स्पेस को गैर-अतिव्यापी (non-overlapping) श्रेणियों में विभाजित करूँगा और प्रत्येक श्रेणी को एक कंट्रोलर रेप्लिका को सौंपूँगा। प्रत्येक इन्फॉर्मर List और Watch दोनों पर एक शार्ड चयनकर्ता भेजता है, फिर सत्यापित करता है कि प्रतिक्रिया में मेल खाने वाला शार्ड मेटाडेटा है। एक अनुपस्थित पावती (acknowledgment) एक सुरक्षित पूर्ण-स्ट्रीम फ़ॉलबैक को ट्रिगर करती है या अनुकूलन को अक्षम करती है। रीशार्डिंग में ओवरलैप, आइडम्पोटेंट समाधान और कवरेज, डुप्लिकेट, लैग और फ़ॉलबैक ट्रैफ़िक के लिए मेट्रिक्स के साथ एक जेनरेशन और हैंडऑफ़ प्रोटोकॉल का उपयोग किया जाता है।”

चरण-दर-चरण डिज़ाइन

विभाजन और असाइनमेंट

64-बिट रिंग पर ओनरशिप को आधे-खुले (half-open) रेंज [start, end) के रूप में दर्शाएं। प्रत्येक रेंज के लिए एक जेनरेशन, ओनर और लीज (lease) स्टोर करें। दो-रेप्लिका परिनियोजन रिंग को दो हिस्सों में विभाजित कर सकता है; अधिक रेप्लिकाएँ एक कंट्रोलर-प्रबंधित रेंज टेबल का उपयोग करती हैं। केवल रेप्लिका ऑर्डिनल से ओनरशिप प्राप्त न करें क्योंकि पुनरारंभ (restart) से अन्यथा गैप बन सकते हैं।

text
Replica A: [0000..., 8000...)
Replica B: [8000..., 1000...)

List और Watch को एक प्रोटोकॉल बनाएं

प्रारंभिक List और प्रत्येक Watch पुनः कनेक्ट में समान चयनकर्ता और एक resource version होना चाहिए। इन्फॉर्मर प्रारंभिक सूची पूर्ण होने के बाद ही अपने स्थानीय स्टोर को बदलता है, फिर लौटाए गए resource version से वॉच शुरू करता है। एक 410 Gone या समाप्त (expired) संस्करण उस शार्ड के लिए एक नई सूची का कारण बनता है, न कि किसी अन्य रेंज का अंधाधुंध रीप्ले।

सर्वर समर्थन सत्यापित करें

v1.36 ब्लॉग एक shardInfo प्रतिक्रिया फ़ील्ड का वर्णन करता है जो लागू चयनकर्ता को दोहराता है। यदि यह अनुपस्थित है, तो मान लें कि सर्वर ने संपूर्ण संग्रह वापस कर दिया है। क्लाइंट शुद्धता के लिए स्थानीय रूप से फ़िल्टर कर सकता है, लेकिन उसे एक फ़ॉलबैक मीट्रिक उत्सर्जित करना चाहिए और बैकप्रेशर लागू करना चाहिए ताकि एक असमर्थित सर्वर सभी रेप्लिकाओं में मेमोरी के उपयोग को कई गुना न बढ़ाए।

बिना किसी गैप के रीशार्डिंग

रेंज की एक नई जेनरेशन बनाएं। हैंडऑफ़ के दौरान, पुराना ओनर समाधान करना जारी रखता है जबकि नया ओनर एक सूची को वार्म करता है और एक ज्ञात resource version पर वॉच की प्रतीक्षा करता है। दोनों पक्षों द्वारा तैयारी की रिपोर्ट करने के बाद ही ओनरशिप परिवर्तन कमिट करें; जब समाधान आइडम्पोटेंट हो तो डुप्लिकेट इवेंट स्वीकार्य हैं। यदि तत्परता विफल हो जाती है, तो लीज समाप्त कर दें और पुराने ओनर को बनाए रखें।

क्षमता और विफलता पथ

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

उच्च गुणवत्ता वाला नमूना उत्तर

“मैं UID के डिटरमिनिस्टिक हैश पर जेनरेशन-स्टैम्प्ड रेंज टेबल का उपयोग करूँगा। इन्फॉर्मर्स List और Watch पर उस चयनकर्ता को शामिल करते हैं और अनुकूलन को सक्रिय मानने से पहले shardInfo की आवश्यकता होती है। एक अनुपस्थित फ़ील्ड ग्लोबल समवर्ती बजट के साथ स्थानीय फ़िल्टरिंग पर वापस आ जाता है। रीशार्डिंग एक नई जेनरेशन बनाती है, resource version से आने वाले ओनर को वार्म करती है, और तैयारी के बाद ही लीज स्विच करती है; समाधान आइडम्पोटेंट है इसलिए ओवरलैप सुरक्षित है। मैं फ़ीचर गेट को कैनरी करूँगा और API CPU, बाइट्स, लिस्ट लेटेंसी, वॉच पुनः कनेक्ट, शार्ड कवरेज, डुप्लिकेट और फ़ॉलबैक दर की तुलना करूँगा।”

सामान्य गलतियाँ

  • रेप्लिका इंडेक्स द्वारा शार्ड्स असाइन करना → पुनरारंभ ओनरशिप को बदलते हैं और गैप बनाते हैं → एक जेनरेशन-स्टैम्प्ड रेंज टेबल बनाए रखें।
  • केवल Watch पर चयनकर्ता लागू करना → प्रारंभिक List अभी भी सर्वर को ओवरलोड करती है और स्ट्रीम से असहमत हो सकती है → दोनों के लिए समान चयनकर्ता और resource-version नियमों का उपयोग करें।
  • असमर्थित सर्वर पर भरोसा करना → प्रत्येक रेप्लिका को पूर्ण स्ट्रीम प्राप्त होती है → shardInfo की आवश्यकता रखें और फ़ॉलबैक ट्रैफ़िक को उजागर करें।
  • एक रेंज को तुरंत स्थानांतरित करना → हैंडऑफ़ के दौरान इवेंट्स छूट सकते हैं → ओनर्स को ओवरलैप करें, जेनरेशन के साथ फेंस करें, और समाधान को आइडम्पोटेंट बनाएं।
  • केवल कंट्रोलर CPU मापना → API-सर्वर हैशिंग या रीकनेक्ट स्टॉर्म अदृश्य रहते हैं → कंट्रोल-प्लेन और क्लाइंट मेट्रिक्स की एक साथ निगरानी करें।

स्कोरिंग रूब्रिक और सेल्फ़-चेक

विभाजन शुद्धता, list-watch सेमेंटिक्स, फ़ॉलबैक, रीशार्डिंग, क्षमता और अवलोकनीयता का स्कोर करें। एक मजबूत उत्तर इनवेरिएंट बताता है: प्रत्येक ऑब्जेक्ट एक सक्रिय रेंज जेनरेशन से संबंधित है, और प्रत्येक हैंडऑफ़ में एक resource-version सीमा होती है। यह यह भी बताता है कि समाधान आइडम्पोटेंट होने पर गैप की तुलना में डुप्लिकेट अधिक सुरक्षित क्यों हैं।

फॉलो-अप और विस्तार

क्या होगा यदि एक नेमस्पेस दूसरों की तुलना में बहुत बड़ा है?

संतुलन के लिए UID हैशिंग को प्राथमिकता दें, या हॉट नेमस्पेस को कई UID श्रेणियों में विभाजित करें। समान ऑब्जेक्ट काउंट मानने के बजाय रेंज लोड को मापें।

आप एक साइलेंट गैप का पता कैसे लगाते हैं?

नमूनाकृत ग्लोबल ऑब्जेक्ट काउंट्स की तुलना शार्ड काउंट्स के यूनियन से करें, चयनकर्ता जेनरेशन रिकॉर्ड करें, और प्रत्येक रेंज के माध्यम से आवधिक सिंथेटिक ऑब्जेक्ट चलाएं। लैग या कवरेज ड्रिफ्ट पर अलर्ट सेट करें।

API-सर्वर अपग्रेड के दौरान क्या होता है?

फ़ीचर गेट को तब तक अक्षम रखें जब तक कि कैनरी प्रत्येक सेवारत एंडपॉइंट से shardInfo का अवलोकन न कर लें। मिश्रित प्रतिक्रियाएं फ़ॉलबैक और एक सीमित पुनः कनेक्ट दर को ट्रिगर करती हैं।

क्या कोई कंट्रोलर एक ही ऑब्जेक्ट को दो बार प्रोसेस कर सकता है?

हाँ, ओवरलैप या पुनः कनेक्ट के दौरान। साइड इफेक्ट्स को आइडम्पोटेंट बनाने के लिए ऑब्जेक्ट संस्करण और एक टिकाऊ वर्क की का उपयोग करें; मिस्ड स्टेट के असीमित जोखिम के लिए कभी भी डुप्लिकेट समाधान का समझौता न करें।

सार्वजनिक स्रोत

संबंधित प्रश्न

संबंधित इंटरव्यू टूल

सिस्टम डिज़ाइन उत्तर के लिए हल करें का उपयोग करें

पहले आवश्यकताओं को स्पष्ट करें, फिर स्केल, आर्किटेक्चर, कंपोनेंट चयन और ट्रेड-ऑफ की ओर बढ़ें।

टूल देखें