विफल रीपब्लिश कभी चालू बैकएंड को नहीं मिटाता
25 सितंबर को एक विफल रीपब्लिश ने एक ऐप का बैकएंड मिटा दिया, जो लगभग ढाई घंटे से लाइव और सही चल रहा था। विफल पब्लिश को पलटने वाला कोड उन सभी सर्वर ऐप्स को हटा देता था जिन्हें वह पब्लिश छू रहा था, जिनमें वे ऐप्स भी शामिल थे जो उससे पहले से चल रहे थे। अब केवल वे ऐप्स हटाए जाते हैं जो किसी पब्लिश ने बनाए थे; जो ऐप पहले से मौजूद था, उसे उसी वर्शन पर वापस लाया जाता है जिस पर वह पहले चल रहा था। उसी दिन दो और सुधार किए गए, ताकि होस्टिंग प्लेटफ़ॉर्म का अपना डिप्लॉय टूल विफल होने पर भी पलटना चले, और कोई स्वस्थ ऐप केवल इसलिए विफल न घोषित हो कि वह सो रहा था।
बैकएंड कैसे पब्लिश होता है
जब आपके Mythex ऐप में बैकएंड होता है, यानी API या सर्वर, न कि केवल स्टैटिक फ़ाइलें, तो पब्लिश उसे Dockerfile (एक नुस्खा जो ऐप को इमेज में पैक करता है) से बनाता है और उस इमेज को हमारे होस्टिंग प्लेटफ़ॉर्म की मशीनों पर रोल आउट करता है। फिर एक हेल्थ चेक इंतज़ार करता है कि नया वर्शन सच में ऊपर आए और चलता रहे, उसके बाद ही पब्लिश को लाइव मार्क किया जाता है।
अगर इस दौरान कुछ भी विफल होता है, तो उसे पलटने के लिए रोलबैक चलता है। रोलबैक को सही करना पब्लिशिंग की लगभग किसी भी दूसरी चीज़ से ज़्यादा मायने रखता है, क्योंकि यह ठीक तब चलता है जब कुछ पहले से गलत हो रहा होता है।
समस्या 1: रोलबैक ने वह मिटा दिया जिसे उसे वापस लाना था
रोलबैक एक सूची रखता था कि पब्लिश ने किन सर्वर ऐप्स पर डिप्लॉय किया था, और विफल होने पर उनमें से हर एक को नष्ट कर देता था। पहली बार के पब्लिश के लिए यह सही है: ऐप अभी-अभी बना था, उस पर कुछ निर्भर नहीं है, और उसे हटाने से सब कुछ पहले जैसा हो जाता है।
रीपब्लिश के लिए यह बिल्कुल गलत है। ऐप पहले से मौजूद था और असली विज़िटर्स को सेवा दे रहा था। 25 सितंबर को एक ऐप की API, जो लगभग ढाई घंटे से लाइव थी, एक विफल रीपब्लिश ने मिटा दी।
उसी कोड में एक और विफलता छिपी थी। जहाँ डिलीट नहीं हो पाया, वहाँ टूटी हुई नई इमेज मशीनों पर बनी रही, जबकि हम मालिक को बता रहे थे कि उसकी मौजूदा साइट अब भी लाइव है। जब तक हेल्थ चेक विफल हो सकता है, तब तक नई इमेज हर मशीन पर रोल आउट हो चुकी होती है। कुछ न करना और उसे पलटना एक बात नहीं है।
सुधार: केवल वही नष्ट करें जो आपने बनाया, बाकी को वापस लाएँ
अब हर पब्लिश, हर उस सर्वर ऐप के लिए जिसे वह छूता है, यह दर्ज करता है:
- क्या इस पब्लिश ने इसे बनाया है, और
- अगर नहीं, तो शुरू होने से ठीक पहले यह कौन सी इमेज चला रहा था।
विफल होने पर हर ऐप को तीन में से एक तरह से संभाला जाता है:
- इस पब्लिश ने बनाया: पहले की तरह नष्ट करें।
- पहले से मौजूद, पिछली इमेज ज्ञात: वही पिछली इमेज उसी कॉन्फ़िगरेशन के साथ फिर से डिप्लॉय करें। कोई बिल्ड नहीं, केवल इमेज वापस जाती है।
- पहले से मौजूद, पिछली इमेज अज्ञात: उसे छोड़ दें। मौजूदा ऐप को कभी भी नहीं मिटाया जाता, भले ही हम उसे वापस न ला सकें।
ये नियम अपने टेस्ट के साथ एक छोटा शुद्ध फ़ंक्शन हैं, ताकि फ़ैसला "सब कुछ नष्ट करो" वाली स्थिति में वापस न जाए, बिना किसी टेस्ट के फेल हुए।
समस्या 2: डिप्लॉय टूल तब विफल हो सकता था जब हमने उलटने का तरीका लिखा ही नहीं था
उस सुधार के कुछ ही बाद हमें उसमें एक कमी दिखी। होस्टिंग प्लेटफ़ॉर्म का डिप्लॉय टूल अपने स्मोक चेक चलाता है: अगर नई मशीनें क्रैश होती हैं, तो वह एरर के साथ बाहर निकलता है। लेकिन यह यह काम तब करता है जब नई इमेज मशीनों पर पहले ही आ चुकी होती है।
हमारा कोड किसी ऐप को रोलबैक सूची में तभी दर्ज करता था जब टूल सफलतापूर्वक लौटता था। जब टूल ने खुद डिप्लॉय विफल किया, तो ऐप अभी सूची में था ही नहीं, इसलिए कुछ वापस नहीं लाया गया। हमारे स्टेजिंग वातावरण में एक टूटे हुए रीपब्लिश ने टूटी हुई इमेज को सेवा देते रहने दिया।
सुधार: शुरू करने से पहले पलटना दर्ज करें
अब ऐप को रोलबैक के लिए तभी दर्ज कर दिया जाता है, जब वह तैयार हो जाता है और उस पर कुछ भी रोल आउट होने से पहले। बाद में जो भी विफल हो, रोलबैक जानता है कि क्या वापस रखना है, यानी ऐप बनाया गया था या नहीं और वह कौन सी इमेज चला रहा था। हमने इसे लोकल पर जाँचा: एक टूटा हुआ रीपब्लिश डिप्लॉय टूल के अपने स्मोक चेक में विफल हुआ, और पिछला वर्शन सेवा देता रहा।
समस्या 3: सोते हुए ऐप को "कभी शुरू नहीं हुआ" घोषित कर दिया गया
Mythex पर पब्लिश किए गए ऐप आपके क्रेडिट बचाने के लिए निष्क्रिय होने पर सो जाते हैं। रीपब्लिश एक सोई हुई मशीन को बंद छोड़ देता है, इसलिए हेल्थ चेक को उसे जगाना पड़ता है। वह प्लेटफ़ॉर्म से मशीन शुरू करने के लिए एक बार कहता था और जवाब पर ध्यान नहीं देता था।
25 सितंबर को वह एक शुरू करने का अनुरोध बेकार गया। एक स्वस्थ API पूरे पाँच मिनट के हेल्थ चेक के दौरान बंद पड़ी रही और "1 machine never started (last state: stopped)" के साथ विफल घोषित हुई।
प्लेटफ़ॉर्म कभी-कभी शुरू करने से मना भी कर देता है। इसे दोहराते समय उसने बिना हमारे उकसाए "lease currently held" कॉन्फ़्लिक्ट लौटाया, और जब मशीन अपडेट हो रही हो तो वह शुरू होने से मना करता है।
सुधार: पूछते रहें, और दरवाज़ा खटखटाएँ
हेल्थ चेक अब:
- इंतज़ार के दौरान हर 20 सेकंड में बंद मशीन को फिर से शुरू करने के लिए कहता है,
- जब प्लेटफ़ॉर्म मना करता है तो दर्ज करता है कि उसने क्या जवाब दिया, और
- ऐप को एक सामान्य अनुरोध भेजता है, ठीक वैसे जैसे कोई विज़िटर भेजता है। प्लेटफ़ॉर्म का प्रॉक्सी आने वाले अनुरोध पर सोई हुई मशीन को जगा देता है।
हमने असली प्लेटफ़ॉर्म पर एक अस्थायी ऐप के साथ इसे दोहराया जिसकी पहली शुरुआत मना कर दी गई थी। सुधार से पहले पब्लिश 91 सेकंड बाद विफल हुआ। सुधार के बाद वह 20 सेकंड में पब्लिश हो गया। जो ऐप सच में बूट पर क्रैश होता है, वह अब भी विफल होता है, जैसा होना चाहिए।
हमने इससे क्या सीखा
- रोलबैक को नए और मौजूदा में फर्क पता होना चाहिए। जो आपने बनाया है उसके लिए "पलटना" का मतलब डिलीट है। जो पहले से मौजूद था उसके लिए "पलटना" का मतलब वापस लाना है। दोनों को एक जैसा मानना ही वह तरीका है जिससे कोई सुरक्षा तंत्र चालू ऐप को मिटा देता है।
- कुछ करने से पहले लिखें कि उसे कैसे पलटना है। अगर पलटने का तरीका तभी दर्ज होता है जब कोई कदम सफल हो जाए, तो बीच में विफल होने वाला कदम पलटने के लिए कुछ नहीं छोड़ता।
- जिस अनुरोध पर आप निर्भर हैं, उसके जवाब को कभी अनदेखा न करें। एक अनदेखी "नहीं" ने एक स्वस्थ ऐप को विफल पब्लिश में बदल दिया।
उसी दिन का एक संबंधित सुधार: पब्लिश के तुरंत बाद क्रैश होने वाले ऐप्स को पकड़ना। जब आपकी ओर से पब्लिश विफल होता है तो क्या होता है, इसके लिए डॉक्स में पब्लिश समस्या-निवारण देखें।