58 CloudWatch अलार्म और आठ मेट्रिक फ़िल्टर को एक अलग CloudFormation स्टैक में ले जाने से हमारे ऐप की रिलीज़ रुक गईं। सोर्स स्टैक UPDATE_ROLLBACK_FAILED पर पहुँच गया; खाली डेस्टिनेशन स्टैक ROLLBACK_FAILED पर। रोलबैक के पाँच अनुरोध स्वीकार हुए, लेकिन स्टैक फिर भी ठीक नहीं हुए। आखिरकार AWS की आंतरिक टीम ने उन्हें ठीक किया। फिर एक साथ कई संसाधन ले जाने का हमारा अगला प्रयास एक अलग त्रुटि के साथ विफल हो गया।
हम अपने ओपन-सोर्स फ़्लैशकार्ड ऐप की मॉनिटरिंग को अलग कर रहे थे। यह वही प्रोजेक्ट है जिसके एजेंट API के बारे में मैंने यहाँ लिखा था। सोर्स में 497 भौतिक संसाधन थे। हम मॉनिटरिंग के 66 संसाधन दूसरे स्टैक में ले जाना चाहते थे और डेटाबेस को वहीं रखना चाहते थे। जिस असर की हमने पुष्टि की, वह रिलीज़ का रुकना था; ऐप बंद होने या डेटा खोने की पुष्टि नहीं हुई थी।
आखिर में हमने सभी 66 संसाधन स्थानांतरित किए, माइग्रेशन के दौरान उनकी मूल पहचान बरकरार रखी और उसके बाद सामान्य रिलीज़ भी पूरी कीं। इस घटना का उपयोगी हिस्सा यह है कि भ्रामक स्टेटस फ़ील्ड और स्वामित्व टैग के बावजूद हमने इनमें से हर परिणाम की पुष्टि कैसे की।
आपकी रिफैक्टरिंग अटकी है, तो यहाँ से शुरू करें
| क्या दिख रहा है | अगला कदम |
|---|---|
| रिफैक्टरिंग का प्रीव्यू पूरा हो गया है | Status के साथ ExecutionStatus और उसका कारण भी पढ़ें। ऑपरेशन चलाने से पहले हर प्रस्तावित संसाधन मैपिंग की तुलना अपनी शुरुआती स्थिति के रिकॉर्ड से करें। |
UPDATE_ROLLBACK_FAILED या रिफैक्टरिंग का विफल रोलबैक | ऑपरेशन, दोनों स्टैक और समय सहित त्रुटियों का रिकॉर्ड रखें। दोबारा कोशिश तभी करें जब पता हो कि कौन-सी आवश्यक शर्त बदल चुकी है। |
AlarmName के null होने या असमर्थित टैग स्कीमा की त्रुटि | सटीक संदेश को उसके ऑपरेशन से जोड़कर रखें। हमारी घटना में ये अलग-अलग चरणों में आए थे। |
| इन्वेंटरी और सिस्टम टैग मेल नहीं खाते | भौतिक ID और प्रोवाइडर की सेटिंग्स की तुलना दोनों स्टैक की इन्वेंटरी से करें। स्वामित्व स्पष्ट होने तक निर्भर डिप्लॉयमेंट रोकें। |
| AWS का कहना है कि रिकवरी पूरी हो गई | स्टैक का काम करना, संसाधनों का सुरक्षित रहना, ऐप की स्थिति और सामान्य डिप्लॉयमेंट, इन सबकी अलग-अलग जाँच करें। |
AWS ने मूल स्टैक ठीक कर दिए थे। उसके बाद हमने सीमित दायरे में प्रयोग किए और उनके नतीजों से प्रोडक्शन के बैचों का आकार तय किया। ये नतीजे आगे जाँच करने के आधार हैं, रिकवरी का कोई सार्वभौमिक तरीका नहीं।

दोबारा कोशिश करने से पहले मौजूदा स्थिति दर्ज करें
ये कमांड AWS की स्थिति केवल पढ़ती हैं। कोटेशन में दिए हर प्लेसहोल्डर की जगह अपना मान रखें, JSON को निजी तौर पर सुरक्षित रखें और शामिल हर स्टैक के लिए स्टैक वाली कमांड दोहराएँ। टेम्पलेट और आउटपुट में संवेदनशील जानकारी हो सकती है।
शुरुआत कॉलर, स्टैक की स्थिति और रिफैक्टरिंग के सटीक ऑपरेशन से करें:
aws --profile '<profile>' --region '<region>' sts get-caller-identity \
--output json --no-cli-pager
aws --profile '<profile>' --region '<region>' cloudformation describe-stacks \
--stack-name '<stack-id>' --output json --no-cli-pager
aws --profile '<profile>' --region '<region>' cloudformation describe-stack-refactor \
--stack-refactor-id '<refactor-id>' --output json --no-cli-pager
get-caller-identity आपके जाँच वाले सेशन की पहचान बताता है। यह उन सभी रोल की पहचान नहीं बताता जिन्हें CloudFormation ने विफलता के दौरान इस्तेमाल किया था। स्टैक में RoleARN मौजूद हो तो उसे रिकॉर्ड में रखें और ऑपरेशन चलाने वाली पहचान की अलग से जाँच करें।
फिर इवेंट, इन्वेंटरी, टेम्पलेट और प्रस्तावित कार्रवाइयाँ इकट्ठा करें:
aws --profile '<profile>' --region '<region>' cloudformation describe-stack-events \
--stack-name '<stack-id>' --output json --no-cli-pager
aws --profile '<profile>' --region '<region>' cloudformation list-stack-resources \
--stack-name '<stack-id>' --output json --no-cli-pager
aws --profile '<profile>' --region '<region>' cloudformation get-template \
--stack-name '<stack-id>' --output json --no-cli-pager
aws --profile '<profile>' --region '<region>' cloudformation list-stack-refactor-actions \
--stack-refactor-id '<refactor-id>' --output json --no-cli-pager
aws --profile '<profile>' --region '<region>' cloudformation list-stack-refactors \
--output json --no-cli-pager
पेजिनेशन चालू रहता है। --no-cli-pager टर्मिनल का व्यूअर बंद करता है, पेजिनेशन नहीं। पूरे प्रमाण इकट्ठा करते समय --no-paginate न जोड़ें और --max-items की सीमा लगाने पर बाकी नतीजे लेना न भूलें। CLI के नतीजे जानबूझकर सीमित रखे हों, तो लौटाए गए टोकन को --starting-token में देकर आगे बढ़ें; सीधे API कॉल करने वालों को हर NextToken का इस्तेमाल करके बाकी नतीजे लेने होंगे। CLI के पेजिनेशन विकल्प और ListStackRefactors API देखें।
हर प्रभावित अलार्म के लिए प्रोवाइडर की स्थिति और टैग की तुलना स्टैक की इन्वेंटरी से करें:
aws --profile '<profile>' --region '<region>' cloudwatch describe-alarms \
--alarm-names '<alarm-name>' --output json --no-cli-pager
aws --profile '<profile>' --region '<region>' cloudwatch list-tags-for-resource \
--resource-arn '<alarm-arn>' --output json --no-cli-pager
स्थानांतरण से पहले और बाद की लॉजिकल से भौतिक ID की मैपिंग, संसाधनों के प्रकार और सेटिंग्स सुरक्षित रखें। फ़िल्टर शामिल हों तो मेट्रिक फ़िल्टर की सेटिंग्स भी रखें। नया स्नैपशॉट बताता है कि अभी क्या मौजूद है; क्या-क्या सुरक्षित रहा, यह साबित करने के लिए स्थानांतरण से पहले का रिकॉर्ड फिर भी चाहिए।
स्वामित्व अस्पष्ट हो, कोई ऑपरेशन टाइम आउट हो जाए, या कोई आवश्यक शर्त बदले बिना वही प्रयास फिर विफल हो, तो उस पर निर्भर डिप्लॉयमेंट रोक दें। टाइम आउट होना इस बात का प्रमाण नहीं है कि ऑपरेशन रुक गया। संसाधन हटाने, रोल बदलने, स्थानांतरण उलटने या retain/import अपनाने, इन सबके लिए अलग रिकवरी प्लान चाहिए जिसकी समीक्षा हो चुकी हो।
AWS Support के लिए ये विवरण निजी तौर पर इकट्ठा करें: अकाउंट और रीजन, स्टैक और ऑपरेशन ID, UTC टाइमलाइन, सटीक त्रुटियाँ और अनुरोध ID, कमिट और CI रन, रोल/पॉलिसी के प्रमाण, टेम्पलेट की तुलनाएँ, स्किप किए गए ID, रिकवरी के प्रयास और ऐप पर असर। अगर Support घटना की स्थिति जस की तस रखने को कहे, तो यह रोक हटने तक केवल स्थिति पढ़ते रहें।
सफल प्रीव्यू का मतलब सफल स्थानांतरण नहीं था
AWS की अंतर्निहित CloudFormation स्टैक रिफैक्टरिंग मौजूदा संसाधनों के गुण और डेटा सुरक्षित रखते हुए उन्हें नए सिरे से व्यवस्थित करती है। स्थानांतरण की कोशिश से पहले संसाधनों की पात्रता, स्टैक पॉलिसी, निर्भरताओं और स्टैक पर निर्भर स्यूडो-पैरामीटर से जुड़ी पाबंदियाँ जाँचें। कॉन्फ़िगरेशन में बदलाव अलग अपडेट में करें।
API रिफैक्टर ऑपरेशन बनाने और उसे चलाने में फ़र्क करता है। बाद में हुए हमारे एक विफल प्रयोग में ये दोनों फ़ील्ड मिले:
{
"Status": "CREATE_COMPLETE",
"ExecutionStatus": "ROLLBACK_COMPLETE"
}
प्रीव्यू पूरा हो चुका था; स्थानांतरण रोलबैक हो गया था। कारण बताने वाले दोनों फ़ील्ड भी पढ़ें: StatusReason और ExecutionStatusReason। DescribeStackRefactor API का रेफ़रेंस इन्हें अलग-अलग परिभाषित करता है।
हमारी शुरुआती रोलबैक समस्या का लक्षण अलग था। अलार्म संसाधनों के पुराने रिकॉर्ड में प्रोवाइडर का यह संदेश था, जिसमें से अनुरोध टोकन हटा दिया गया है:
Resource handler returned message: "Cannot invoke "String.equals(Object)" because the return value of "software.amazon.cloudwatch.alarm.ResourceModel.getAlarmName()" is null" (HandlerErrorCode: InternalFailure)
AlarmName का null होना समस्या को आगे जाँच के लिए भेजने में उपयोगी प्रमाण था। इससे ऐसा कोई उपाय पता नहीं चला जिसे हम खुद लागू करके समस्या ठीक कर सकते।
रोलबैक के पाँच स्वीकृत अनुरोधों के बाद भी हम अटके रहे
हमारे पाँच प्रयासों में 22 अलार्म स्किप करने का एक पुष्ट अनुरोध और 27 सितंबर को 08:39 UTC पर AWS इंजीनियर के कहने पर किया गया एक और प्रयास शामिल था। सर्विस ने अनुरोध स्वीकार किए, लेकिन उनके ऑपरेशन विफल रहे। कॉल दोहराने से प्रगति साबित नहीं हुई।
AWS continue-update-rollback और ResourcesToSkip के इस्तेमाल को एक खास रिकवरी प्रक्रिया तक सीमित रखता है: रोलबैक के दौरान विफल हुए पात्र संसाधन ही स्किप करें, उनकी संख्या जितनी ज़रूरी हो उतनी ही रखें और अगले अपडेट से पहले स्किप किए गए संसाधनों को टेम्पलेट के अनुरूप लाएँ। स्किप होने से यह साबित नहीं होता कि लाइव संसाधन टेम्पलेट से मेल खाता है। यह निर्णय लेने के लिए AWS की रोलबैक प्रक्रिया का पालन करें।
1 अक्टूबर को लगभग 22:00 UTC पर दोनों स्टैक के स्टेटस बदले। अगली सुबह AWS Support ने पुष्टि की कि उसकी आंतरिक टीम ने दोनों स्टैक ठीक कर दिए हैं और डिप्लॉयमेंट फिर शुरू हो सकते हैं। हमें उस अटकी हुई स्थिति से निकालने के लिए उस टीम का धन्यवाद। AWS ने आंतरिक मरम्मत की कोई कमांड नहीं दी और न ही यह पुष्टि की कि उसने सर्विस के लिए कोई सामान्य पैच जारी किया है। संवेदनशील विवरण हटाकर तैयार किया गया घटनाक्रम हमारी निश्चित कमिट से जुड़ी घटना-प्रक्रिया में है।
RDS वाली व्याख्या इस पर निर्भर थी कि रीड किस पहचान से हुई
AWS ने शुरुआती विफलता की वजह एक्ज़िक्यूशन रोल में rds:DescribeDBInstances अनुमति की कमी बताई। उसका कहना था कि स्टैक के आउटपुट में RDS एंडपॉइंट पता करने के लिए यह रीड ज़रूरी थी, भले ही डेटाबेस ऐप के स्टैक में ही रहने वाला था।
यह AWS का आकलन था। हमारी स्वतंत्र जाँच से पूरी मूल वजह साबित नहीं हुई। हमने बताए गए रोल पर AdministratorAccess देखा था और IAM सिमुलेशन में भी अनुमति मिली थी। लेकिन इन दोनों से यह पता नहीं चला कि विफलता के समय कौन-सी पॉलिसी लागू थी या सर्विस का वास्तविक सेशन क्या था।
कई पहचानों का हिसाब रखना पड़ता है: CI कॉलर, डिप्लॉयमेंट या लुकअप के लिए assume किए गए रोल, अंतर्निहित रिफैक्टर API का कॉलर और CloudFormation का एक्ज़िक्यूशन रोल। आपके शेल से डेटाबेस रीड सफल होने पर केवल उस पहचान की जाँच होती है जिसे वह शेल इस्तेमाल करता है। सर्विस रोल के दस्तावेज़ बताते हैं कि CloudFormation कब कॉन्फ़िगर किए गए रोल के क्रेडेंशियल इस्तेमाल करता है; IAM सिमुलेटर के दस्तावेज़ बताते हैं कि सिमुलेशन लाइव अनुरोध से अलग क्यों हो सकता है।
व्यावहारिक जाँच यही है कि पहचान की इस पूरी शृंखला और प्रोवाइडर की ज़रूरी रीड को ट्रेस करें, जिनमें आउटपुट में संदर्भित संसाधनों की रीड भी शामिल हैं। हमारे प्रमाण इस दावे का समर्थन नहीं करते कि RDS की एक अतिरिक्त अनुमति देना अलार्म रिफैक्टरिंग की विफलता का इलाज है।
कई अलार्म एक साथ ले जाने पर आई अगली त्रुटि RDS के बिना भी दोहराई गई
AWS की आंतरिक रिकवरी के बाद प्रोडक्शन में कई संसाधन एक साथ ले जाने का एक और प्रयास रोलबैक हो गया। एक अलग प्रयोग में 58 अलार्म और अंतर्निहित रिफैक्टरिंग से बने डेस्टिनेशन के साथ वही त्रुटि दोहराई गई। उस प्रयोग में RDS की कोई निर्भरता नहीं थी। स्टैक ARN का प्रीफ़िक्स हटाने के बाद कारण यह था:
Stack Refactor does not support AWS::CloudWatch::Alarm because the resource type defines an unsupported tag schema.
केवल RDS रीड इस बाद वाले नतीजे की व्याख्या नहीं कर सकती थी। संदेश का दावा भी हमारे प्रयोगों से साबित हुई बात से व्यापक लगता था: अंतर्निहित रिफैक्टरिंग से अलार्म स्थानांतरित करने के कई प्रयास सफल रहे थे।
| प्रयोग | देखा गया नतीजा |
|---|---|
| अपने-आप बने या स्पष्ट रूप से दिए नाम वाले एक-एक अलार्म, जिनमें टैग अनुपस्थित, खाली या मौजूद थे | अंतर्निहित रिफैक्टरिंग से स्थानांतरण सफल; भौतिक पहचान, डेस्टिनेशन टैग और सफ़ाई की पुष्टि हुई। |
| अंतर्निहित रिफैक्टरिंग से बने डेस्टिनेशन, जिनमें 2, 10 और 25 अलार्म थे | सफल; ID, कॉन्फ़िगरेशन, डेस्टिनेशन के सिस्टम टैग और सफ़ाई की पुष्टि हुई। |
| अंतर्निहित रिफैक्टरिंग से बना डेस्टिनेशन, 58 अलार्म और कोई RDS नहीं | असमर्थित टैग स्कीमा की त्रुटि के साथ रोलबैक हुआ। |
| 58 अलार्म का अलग मामला, जिसमें डेस्टिनेशन पहले से बनाया गया था | InternalFailure लौटा, जो अलग त्रुटि थी। |
| दो प्रभावित अलार्म स्थानांतरित किए, फिर उसी डेस्टिनेशन में दो और | दोनों स्थानांतरण सफल; सभी 58 मूल पहचान और कॉन्फ़िगरेशन सुरक्षित रहे। |
सार्वजनिक रिकॉर्ड में 2/10/25 वाला रन, 58 अलार्म वाला रन और डेस्टिनेशन दोबारा इस्तेमाल करने वाला रन शामिल हैं। लॉग की उपलब्धता की अवधि खत्म हो सकती है या उन्हें देखने के लिए साइन इन करना पड़ सकता है; निश्चित कमिट वाले घटना दस्तावेज़ में निष्कर्ष सुरक्षित हैं।
अंतर्निहित रिफैक्टरिंग से बने डेस्टिनेशन वाला एक मामला डेस्टिनेशन के RoleARN के बिना भी सफल रहा, इसलिए केवल उस फ़ील्ड की अनुपस्थिति से विफलता दोहराई नहीं गई। इम्पोर्ट से तैयार किया गया एक अस्थायी परीक्षण भी सफल रहा, लेकिन हमने प्रोडक्शन की रिकवरी के लिए इम्पोर्ट इस्तेमाल नहीं किया। स्पष्ट नाम वाला इम्पोर्ट प्रयोग शुरू ही नहीं हुआ, इसलिए उससे कोई नतीजा नहीं मिलता।
25 अलार्म का बैच हमारे परीक्षण में सफल रहा था; इससे AWS की कोई सीमा साबित नहीं हुई। संसाधनों की संख्या, डेस्टिनेशन कैसे बना और रोलबैक के बाद क्या बचा रहा, ये जाँच के उपयोगी पहलू थे। ये नतीजे न तो सर्विस के भीतर की मूल वजह बताते हैं, न इस बात की गारंटी देते हैं कि छोटे बैच किसी दूसरे स्टैक को ठीक कर देंगे।
रोलबैक के बाद स्टैक की इन्वेंटरी और टैग मेल नहीं खा रहे थे
अलग वातावरण में किए गए 58 अलार्म वाले प्रयोग की विफलता के बाद CloudFormation की इन्वेंटरी में अलार्म वापस सोर्स में थे। फिर भी 49 अलार्म पर सिस्टम टैग उस डेस्टिनेशन का नाम बता रहे थे जिसे बाद में हटा दिया गया था; केवल नौ पर सोर्स का नाम था। सफ़ाई के दौरान GetTemplate में InternalFailure भी आया।
इसलिए केवल aws:cloudformation:stack-id पर आधारित स्वामित्व की जाँच गलत तस्वीर देती। हमने स्टैक की इन्वेंटरी, भौतिक ID, लाइव कॉन्फ़िगरेशन और टैग की अलग-अलग तुलना की। निर्भर रिलीज़ शुरू करने से पहले इस असंगति को सुलझाना ज़रूरी था।
रिकवरी के प्रयोग में हमने उसी डेस्टिनेशन में पहले दो अलार्म और फिर दो और अलार्म भेजे। दोनों स्थानांतरणों के बाद सभी 58 पहचान और कॉन्फ़िगरेशन सुरक्षित रहे। स्थानांतरित किए गए चारों अलार्म के सिस्टम टैग सही थे। हमने संरक्षित aws: टैग खुद नहीं लिखे। बाद में सफ़ाई की पुष्टि भी हुई और परीक्षण के लिए बनाए गए कोई स्टैक या अलार्म बाकी नहीं रहे।
दो पुराने विवरण नई जाँच को भी भटका सकते थे। स्टैक ठीक होने के बाद भी अलार्म की 22 UPDATE_FAILED पंक्तियाँ बची हुई थीं; केवल उन पंक्तियों से यह साबित नहीं होता था कि अभी कोई भौतिक अलार्म विफल है। एक अप्रचलित प्रीव्यू ListStackRefactors से गायब हो गया था, लेकिन उसकी सटीक ID से उसे अब भी पढ़ा जा सकता था। टाइमस्टैम्प की तुलना प्रोवाइडर की लाइव स्थिति से करें और ज्ञात ऑपरेशन का विवरण सीधे उसकी ID से पढ़ें, भले ही वह सूची में न आए। हमारी निश्चित कमिट वाली स्वामित्व गाइड में दोनों अवलोकन दर्ज हैं।
रिकवरी एक सामान्य रिलीज़ के साथ पूरी हुई
प्रोडक्शन का स्थानांतरण अंतर्निहित रिफैक्टरिंग के चार बैचों में पूरा हुआ: आठ मेट्रिक फ़िल्टर, फिर 25 अलार्म, 25 अलार्म और आठ अलार्म। माइग्रेशन के दौरान सभी 497 मूल भौतिक संसाधनों की पहचान और प्रकार सुरक्षित रहे। मॉनिटरिंग के सभी 66 संसाधन मॉनिटरिंग स्टैक में पहुँच गए।
हमने रिकवरी से जुड़े चार सवाल अलग रखे:
| रिकवरी का परिणाम | कौन-से प्रमाण इकट्ठा करें |
|---|---|
| स्टैक का काम करना | दोनों स्टैक के नए स्टेटस और हर ज्ञात रिफैक्टर ऑपरेशन की स्पष्ट स्थिति। |
| संसाधन, कॉन्फ़िगरेशन और डेटा का सुरक्षित रहना | पहले और बाद की पहचान व सेटिंग्स की तुलना, साथ में संबंधित सर्विस के डेटा की जाँच। केवल भौतिक ID का न बदलना डेटा की अखंडता साबित नहीं कर सकता। |
| ऐप का ठीक काम करना | मौजूदा हेल्थ चेक और संबंधित वेब, Agent API तथा MCP स्मोक फ़्लो। |
| सामान्य डिप्लॉयमेंट कर पाने की क्षमता | सामान्य रिलीज़ प्रक्रिया से सफलतापूर्वक डिप्लॉय किया गया कोई ज्ञात कमिट। |
अलग स्टैक बनने के बाद पहली सामान्य रिलीज़, कमिट ad297a8 पर, सफल रही। उसके बाद की सामान्य रिलीज़, कमिट 0a530c7 पर, सभी नौ जॉब और तीनों स्मोक फ़्लो में सफल रही। प्लेटफ़ॉर्म, वेब और एडमिन ने अपेक्षित कमिट के डिप्लॉय होने की सूचना दी।
उस बाद वाली रिलीज़ ने जानबूझकर एक अपरिवर्तनीय AWS::Lambda::Version को बदला। बाकी 496 मूल पहचान, जिनमें मॉनिटरिंग के सभी 66 संसाधन शामिल थे, नहीं बदलीं। यह तुलना माइग्रेशन के दौरान सभी 497 पहचान सुरक्षित रहने वाली तुलना से अलग है: सामान्य रिलीज़ में नया Lambda वर्ज़न बनना पहले के माइग्रेशन के नतीजे को गलत नहीं ठहराता। निश्चित कमिट पर सुरक्षित समापन के प्रमाण में दोनों दर्ज हैं।
पुष्टि करने के बाद हमने रिफैक्टरिंग के लिए दी गई अस्थायी पहुँच और जाँच की व्यवस्था हटा दी। रिकवरी पूरी होने पर रिलीज़ हेल्पर का काम स्वामित्व जाँचना था; माइग्रेशन दोबारा चलाना नहीं। हमारे लिए काम तब पूरा हुआ जब किसी ज्ञात कमिट की सामान्य रिलीज़ सफल रही और उसके साथ संसाधनों की तुलना तथा ऐप के काम करने की जाँच भी उपलब्ध थी। यही प्रमाण था कि हम फिर से रिलीज़ कर सकते हैं।



