AWS Certified CloudOps Engineer - Associate
CloudFormation StackSets
نشر قالب واحد على حسابات ومناطق كثيرة من عملية واحدة: stack set وstack instance والحزمة، ونموذجا الصلاحيات، وأهداف النشر ومرشّحات الحسابات، والتزامن وحدّ تحمّل الفشل، والانحراف، والفشل الذي يختبئ خلف حالة SUCCEEDED.
- ميّز بين stack set وstack instance والحزمة، واشرح لماذا قد توجد stack instance بلا حزمة
- اختر بين الصلاحيات الذاتية والصلاحيات المُدارة بالخدمة، وسمِّ الأدوار التي يطلبها كل نموذج
- استهدف منظمة كاملة أو OUs بعينها أو حسابات مُرشَّحة، وتوقّع أي الحسابات ستستقبل حزمة
- اضبط حدّ تحمّل الفشل وأقصى عدد حسابات متزامنة وتزامن المناطق بما يناسب خطورة النشر
- فسّر حالات stack set وstack instance، ومنها OUTDATED وINOPERABLE
- اشرح كيف يختلف اكتشاف الانحراف على مستوى stack set عنه على مستوى الحزمة الواحدة
- شخّص أعطال StackSets الشائعة، ومنها عملية تبلّغ SUCCEEDED بينما فشلت حزم
يحتاج فريق أمان إلى دور IAM للقراءة فقط، وConfig recorder، وقاعدة تشحن السجلات، في 40 حساباً عبر 4 مناطق. هذه 160 حزمة. والنسخة المكتوبة بسكربت حلقة تتقمّص دوراً في كل حساب وتستدعي create-stack، وتعمل حتى يصطدم الحساب رقم 23 بحصّة خدمة، فتواصل الحلقة طريقها، ولا ينتبه أحد ثلاثة أسابيع إلى أن أربعة حسابات بلا Config recorder.
المشكلة ليست في الحلقة، بل في أنها بلا ذاكرة. لا شيء يسجّل أن هذه الحزم الـ160 يُفترض أن تكون الشيء نفسه، فلا شيء يستطيع أن يخبرك أيّها محدَّث، وأيّها فشل، وأيّها عدّله أحدهم بيده.
وStackSets هي تلك الذاكرة. تعرّف القالب مرة واحدة، وتسمّي الحسابات والمناطق، ويتتبّع CloudFormation كل حزمة ناتجة بوصفها جزءاً من مجموعة واحدة مُدارة.
stack set وstack instance وحزمة
ثلاثة مصطلحات تبدو مترادفة وليست كذلك.
stack set هو الحاوية: قالب واحد، ومجموعة parameters واحدة، وتهيئة النشر. يعيش في الحساب الإداري (administrator account)، وهو مورد إقليمي. أنشئ stack set في eu-west-1 ولن تراه حين يتحوّل الـ Console إلى us-east-1، وهذا يفاجئ من يفترض أن ميزة متعدّدة المناطق لا بدّ أن تكون عالمية بنفسها.
stack instance إشارة إلى حزمة داخل حساب هدف (target account) واحد ضمن منطقة واحدة. ثلاثة حسابات عبر منطقتين تعطيك 6 stack instances، وكل واحدة تحمل حالتها الخاصة.
والحزمة هي حزمة CloudFormation العادية التي تحمل الموارد فعلاً، وتقع داخل الحساب الهدف.
الفصل بين النسخة والحزمة يبدو تدقيقاً محاسبياً حتى يقع أول فشل. تستطيع stack instance أن توجد بلا حزمة: إن فشل الإنشاء فلا حزمة، لكن النسخة تبقى وتحمل السبب. وهذا ما يجعل عملية نشر فاشلة قابلة للتشخيص بدل أن تكون غير مرئية.
aws cloudformation list-stack-instances --stack-set-name org-baseline \
--filters Name=DETAILED_STATUS,Values=FAILED
نموذجا الصلاحيات، وخيار واحد حقيقي
النشر داخل حساب آخر يعني تقمّص دور هناك. ويعطيك StackSets طريقتين لترتيب ذلك، والاختبار يسأل أي منهما يفرضه السيناريو.
الصلاحيات الذاتية (self-managed) تعني أنك تبني سلسلة الثقة بنفسك، بدورين أسماؤهما مهمّة:
AWSCloudFormationStackSetAdministrationRoleفي الحساب الإداري. سياسة الثقة فيه تسمح لـcloudformation.amazonaws.comبتقمّصه، وسياسة الصلاحيات تسمح بـsts:AssumeRoleعلى دور التنفيذ في الأهداف.AWSCloudFormationStackSetExecutionRoleفي كل حساب هدف، ويثق بالحساب الإداري. يحتاج هذا الدور صلاحيات CloudFormation كاملة، وصلاحيات كل ما ينشئه القالب.
استخدم هذين الاسمين بالضبط فيلتقطهما StackSets تلقائياً. واستخدم أسماء مخصّصة فتضطرّ كل عملية إلى تسميتهما صراحةً. والقوالب التي تنشرها AWS لهذين الدورين تمنح "Action": "*" على دور التنفيذ، وهذا مقبول لتجربة أولى وخاطئ لأي شيء دائم. ضيّق دور التنفيذ على أنواع الموارد التي ينشئها قالبك فعلاً، لأن ذلك الدور هو السقف الأعلى لما تستطيع أي عملية stack set فعله في ذلك الحساب.
والصلاحيات المُدارة بالخدمة (service-managed) تسلّم مشكلة الأدوار إلى CloudFormation. تفعّل الوصول الموثوق بين CloudFormation وAWS Organizations، ومن تلك اللحظة ينشئ CloudFormation الأدوار في حسابات الأعضاء ويصونها نيابةً عنك. وتستهدف OUs بدل سرد معرّفات الحسابات، وتحصل على النشر التلقائي.
| الصلاحيات الذاتية | المُدارة بالخدمة | |
|---|---|---|
| الحسابات الهدف | أي حساب تستطيع إنشاء دور فيه | حسابات منظمتك وحدها |
| إعداد الأدوار | تنشئ الدورين بنفسك | ينشئهما CloudFormation |
| صيغة تحديد الأهداف | معرّفات الحسابات | جذر المنظمة أو معرّفات OU |
| انضمام حساب جديد إلى الـ OU | لا يحدث شيء | النشر التلقائي يضيف حزمة |
| يُشغَّل من | أي حساب | الحساب الإداري للمنظمة أو مدير مفوَّض |
| الحزم المتداخلة وmacros وtransforms | مدعومة | غير مدعومة |
وقيدان على النموذج المُدار بالخدمة يستحقّان الحفظ لأنهما يناقضان ما يفترضه الناس.
الحساب الإداري للمنظمة لا يستقبل حزمة أبداً. استهدف المنظمة كلها وسيتخطّاه CloudFormation. وإن احتاج ذلك الحساب الأساس نفسه فهو يأخذ حزمته الخاصة أو stack set ذاتياً خاصاً به.
المديرون المفوَّضون لا يمكن تقييد نطاقهم. يستطيع الحساب الإداري تسجيل ما يصل إلى 5 حسابات أعضاء مديرين مفوَّضين، فيشغّل فريق منصّة مركزي stack sets على مستوى المنظمة دون أن يملك بيانات اعتماد الحساب الإداري. لكن المدير المفوَّض يملك وصولاً كاملاً إلى كل حساب في المنظمة. لا يوجد إعداد يقول «هذا الفريق ينشر إلى Sandbox OU وحده».
aws organizations register-delegated-administrator \
--service-principal member.org.stacksets.cloudformation.amazonaws.com \
--account-id 444455556666
ومن حساب المدير المفوَّض يحمل كل أمر --call-as DELEGATED_ADMIN. أسقطه وسيبحث الـ CLI عن stack sets ذاتية داخل حساب العضو نفسه، فلا يجد شيئاً، ويُرجع قائمة فارغة تبدو كمشكلة صلاحيات.
من يحصل على حزمة
مع الصلاحيات المُدارة بالخدمة، أهداف النشر هي جذر المنظمة أو قائمة معرّفات OU. واستهداف OU أب يشمل أبناءه تلقائياً، وهذا هو السلوك الذي تريده لأساس أمني، وهو نفسه السلوك الذي يفاجئك حين يلتقط sandbox OU متداخل سياسة إنتاج.
وافتراضياً يستقبل كل حساب في OU مستهدف حزمة. ومرشّحات الحسابات تضيّق ذلك:
| نوع المرشّح | المعنى |
|---|---|
NONE (الافتراضي) | كل حساب في الـ OUs المذكورة |
INTERSECTION | الحسابات المذكورة وحدها، وفقط إن كانت داخل الـ OUs المذكورة |
DIFFERENCE | كل حساب في الـ OUs المذكورة عدا الحسابات المذكورة |
UNION | كل حساب في الـ OUs المذكورة، مضافاً إليه الحسابات المذكورة |
aws cloudformation create-stack-instances --stack-set-name org-baseline \
--deployment-targets OrganizationalUnitIds=ou-rcuk-1x5j1lwo,Accounts=111122223333,AccountFilterType=DIFFERENCE \
--regions eu-west-1 us-east-1
وDIFFERENCE هو المرشّح الذي يثبت جدواه عملياً. أساس ينطبق على Workloads OU كله عدا حساب قديم واحد سينكسر معه، فتعبّر عن ذلك الاستثناء داخل النشر بدل أن تسحب الحساب من الـ OU الخاص به.
التزامن وحدّ تحمّل الفشل
دفع قالب إلى 160 موضعاً دفعةً واحدة طريقة ممتازة لكسر 160 موضعاً دفعةً واحدة. وأربعة إعدادات تتحكّم في نطاق الضرر، وهي متشابكة.
أقصى عدد حسابات متزامنة يحدّ كم حساباً هدفاً تلمسه العملية في الوقت نفسه، عدداً أو نسبة مئوية. والنسب تُقرَّب نزولاً: 25 بالمئة من 10 حسابات تساوي 2 لا 3.
حدّ تحمّل الفشل هو عدد أو نسبة حالات الفشل المسموح بها لكل منطقة قبل أن يتوقّف CloudFormation. ويُقرَّب نزولاً أيضاً.
تزامن المناطق إما SEQUENTIAL (الافتراضي، منطقة واحدة في كل مرة بترتيب النشر الذي حدّدته) أو PARALLEL (كل المناطق معاً).
وضع التزامن (concurrency mode) يقرّر ما يحدث للتزامن حين يبدأ الفشل. STRICT_FAILURE_TOLERANCE يبقي أقصى عدد حسابات متزامنة عند حدّ تحمّل الفشل زائد واحد على الأكثر، فيتباطأ كلّما تراكم الفشل. وSOFT_FAILURE_TOLERANCE يحافظ على مستوى التزامن الذي اخترته مهما حدث.
لنمشِ مع عملية واحدة. تنشر إلى 10 حسابات في eu-west-1 ثم us-east-1 ثم ap-southeast-2 بهذا الترتيب، وحدّ تحمّل الفشل 20 بالمئة، وأقصى عدد حسابات متزامنة 50 بالمئة، والمناطق متتابعة.
- 20 بالمئة من 10 تُقرَّب نزولاً إلى فشلين مسموحين لكل منطقة. و50 بالمئة من 10 تعني 5 حسابات في المرة الواحدة.
- تعمل
eu-west-1على 5 حسابات ثم الخمسة الباقية. يفشل حسابان. هذا هو الحدّ بالضبط، فتُنهي المنطقة عملها وتنتقل العملية. - تعمل
us-east-1ويفشل فيها حساب ثالث. تجاوز الحدّ هناك يجعل حالة العمليةFAILED، وتُلغىap-southeast-2كلياً.
حدّ تحمّل الفشل يُصفَّر مع كل منطقة. وهذا ما يجعل النشر المتتابع آلية أمان مفيدة: القالب المعطوب في كل مكان يفشل في المنطقة الأولى ولا يصل إلى البقية.
والقيم الافتراضية متحفّظة عن قصد، MaxConcurrentCount=1 وFailureToleranceCount=0 في أمثلة الـ CLI، أي حساب واحد في المرة وتوقّف عند أول فشل. وهذا الخيار الصحيح لأول نشر لقالب جديد. ارفعه بعد أن يثبت القالب نفسه.
الحالات، والحالة التي تكذب
تبلّغ عمليات stack set إحدى الحالات RUNNING أو SUCCEEDED أو FAILED أو QUEUED أو STOPPING أو STOPPED. وتظهر QUEUED مع النشر التلقائي: انقل حساباً بين OUs فيشغّل StackSets حذفاً لحزمة الـ OU القديم ويضع إنشاءً في الطابور للجديد.
وتحمل stack instances حالاتها الخاصة، واثنتان منها تعنيان أن عملاً ينتظرك:
OUTDATEDتعني أن الحزمة ليست محدَّثة مع الـ stack set، وغالباً لأن إنشاءً أو تحديثاً فشل هناك، أو لأن العملية توقّفت قبل أن تصل إليها.INOPERABLEتعني أن عملية حذف نسخ فشلت وتركت الحزمة في حالة غير مستقرّة. والنسخ في هذه الحالة مستبعَدة من تحديثات الـ stack set اللاحقة، فتتوقّف بصمت عن استقبال تغييراتك. والتعافي يعني حذف النسخة معRetainStacksمضبوطة على true، ثم تنظيف الحزمة يدوياً.
والآن الالتباس الذي يكلّف الناس تغطية حقيقية. العملية بحالة SUCCEEDED لا تعني أن كل حزمة نجحت. تعني أن حدّ تحمّل الفشل لم يُتجاوز. اضبط حدّ تحمّل الفشل على 10 عبر 10 حسابات، وعملية تفشل فيها كل حزمة على الإطلاق ستُرجع SUCCEEDED، لأنك أخبرت CloudFormation أن هذا القدر من الفشل مقبول.
والرقم الذي تريده فعلاً موجود في تفاصيل الحالة:
aws cloudformation describe-stack-set-operation \
--stack-set-name org-baseline --operation-id 5550e62f-c822-4331-88fa-21c1d7bafc60
{
"StackSetOperation": {
"Status": "SUCCEEDED",
"StatusDetails": { "FailedStackInstancesCount": 3 }
}
}
SUCCEEDED مع FailedStackInstancesCount غير صفري هي بصمة أساس نُشر جزئياً. عامل ذلك الحقل، لا حالة العملية، تعريفاً لاكتمال العمل.
الانحراف عبر stack set
اكتشاف الانحراف على مستوى الـ stack set يشغّل اكتشافاً على مستوى الحزمة لكل stack instance ويجمّع الأجوبة صعوداً. مورد منحرف واحد يجعل حزمته منحرفة، وحزمة منحرفة واحدة تجعل نسختها منحرفة، ونسخة منحرفة واحدة تجعل الـ stack set كله DRIFTED.
aws cloudformation detect-stack-set-drift --stack-set-name org-baseline
تُرجع العملية معرّفاً لأنها طويلة التشغيل، ويبلّغ describe-stack-set-operation بالعدّادات أثناء تقدّمها: DriftedStackInstancesCount وInSyncStackInstancesCount وInProgressStackInstancesCount وFailedStackInstancesCount من أصل TotalStackInstancesCount. ولا تعمل إلا عملية اكتشاف انحراف واحدة على stack set معيّن في وقت واحد، وتستطيع إيقافها بـ stop-stack-set-operation.
وحدّان يقرّران كم تساوي النتيجة النظيفة:
- التغييرات التي تمرّ عبر CloudFormation ليست انحرافاً أبداً. حدّث حزمة حساب هدف واحد مباشرةً إلى قالب مختلف وسيبلّغ الاكتشاف
IN_SYNC، لأن الحزمة تطابق تهيئتها المتوقّعة هي. وتلك الحزمة صارت الآن غير متّسقة مع أخواتها، وهذه مشكلة حقيقية، واكتشاف الانحراف ليس الأداة التي تجدها. - الاكتشاف على مستوى الحزمة لا يصعد. شغّل الاكتشاف على حزمة مفردة داخل حساب هدف ولن تظهر تلك النتائج في صفحة StackSets. ابدأ الاكتشاف على مستوى الـ stack set أو ستبقى حالة انحرافه قديمة.
وتجاوز قيم الـ parameters يُعالَج بشكل صحيح: لأن الاكتشاف يجري لكل حزمة، تُقارَن النسخة ذات القيم المتجاوَزة بتوقّعاتها هي لا بقيم الـ stack set الافتراضية.
حين تفشل العمليات
تتجمّع حالات الفشل في قائمة قصيرة، وسبب الحالة يسمّي المشكلة مباشرةً في الغالب.
| العَرَض | السبب |
|---|---|
should have 'AWSCloudFormationStackSetExecutionRole' role with trust relationship... | سلسلة الثقة الذاتية مفقودة أو أسماؤها خاطئة في الهدف |
| فشل في حساب واحد والقالب سليم في غيره | صلاحيات ناقصة في دور التنفيذ لنوع مورد في ذلك الحساب |
| فشل عبر حسابات كثيرة على اسم عالمي | القالب ينشئ مورداً فريداً عالمياً، مثل دلو S3 باسم ثابت |
| خطأ حصّة في بعض الحسابات دون غيرها | الحساب الهدف بلغ الحدّ الأقصى لمورد ينشئه القالب، مثل أدوار IAM |
| فشل الحذف على حزمة واحدة | حماية الإنهاء مفعّلة على تلك الحزمة |
نسخة عالقة على INOPERABLE بعد استيراد | فشل الاستيراد؛ احذف النسخة مع RetainStacks ثم أصلح وأعد المحاولة |
وإعادة المحاولة ليست API خاصة. تصلح السبب الجذري، ثم تشغّل تحديثاً على الـ stack set بالقالب نفسه أو بقالب مصحَّح، فتلحق نسخ OUTDATED بالركب.
والحصص التي تهمّ عند الحجم الكبير: 1,000 stack set لكل حساب إداري، و100,000 stack instance لكل stack set، و10,000 عملية stack instance متزامنة لكل منطقة لكل حساب إداري عبر كل الـ stack sets. وبلوغ الأخيرة هو ما يجعل عملية نشر كبيرة بطيئة بشكل غامض بدل أن تفشل.
نصائح للاختبار
- «انشر القالب نفسه على حسابات ومناطق كثيرة من مكان واحد» هي StackSets. والإجابة التي تصف سكربتاً يدور على الحسابات خاطئة ولو كانت ستعمل.
- «حسابات تديرها AWS Organizations» مع «الحسابات الجديدة يجب أن تحصل عليه تلقائياً» تعني صلاحيات مُدارة بالخدمة مع نشر تلقائي. و«حسابات خارج المنظمة» أو «لا توجد منظمة» تفرض الصلاحيات الذاتية.
AWSCloudFormationStackSetAdministrationRoleيعيش في الحساب الإداري، وAWSCloudFormationStackSetExecutionRoleفي كل هدف. وسبب حالة يسمّي دور التنفيذ هو مشكلة ثقة في النموذج الذاتي، لا مشكلة وصول موثوق أبداً.- الحساب الإداري للمنظمة لا يحصل على stack instance مُدارة بالخدمة. انتبه للسيناريوهات التي يكون فيها الحساب الغائب هو الحساب الإداري.
- حدّ تحمّل الفشل لكل منطقة ويُقرَّب نزولاً. وتجاوزه في منطقة واحدة يلغي المناطق الباقية.
- عملية بحالة
SUCCEEDEDمع موارد غائبة تعني أن حدّ تحمّل الفشل امتصّ حالات الفشل. انظر إلىFailedStackInstancesCount. - الإبقاء على الحزم يحفظ الموارد ويسقط الارتباط بالـ stack set. وهو لا يحذف شيئاً.
OUTDATEDتعني عملية فشلت أو تُخطّيت. وINOPERABLEتعني أن النسخة مستبعَدة من التحديثات اللاحقة حتى تحذفها.- stack sets المُدارة بالخدمة لا تدعم الحزم المتداخلة ولا macros ولا transforms، ومنها
AWS::Serverless. - اكتشاف الانحراف على stack set لا يعامل تغييراً تمّ عبر CloudFormation انحرافاً أبداً.
القاعدة التي تخرج بها من هذا الدرس: مع StackSets، «تم النشر» حقيقة على مستوى النسخة لا على مستوى العملية. قبل أن تعلن اكتمال عملية نشر، انظر إلى حالات النسخ وإلى عدّاد النسخ الفاشلة، لأن حالة العملية مصمّمة لتخبرك بشيء أضيق ممّا تريد معرفته.
StackSets يدفع موارد متطابقة إلى الحسابات. والدرس التالي يغطّي الحركة المعاكسة: أن تبقي مورداً واحداً في حساب واحد وتدع الحسابات الأخرى تستخدمه، عبر AWS RAM.
