لماذا لا يشبه التراجع عن البنية التحتية التراجع عن التطبيق
تقوم بدفع تحديث تطبيق معيب. يبدأ المستخدمون في رؤية أخطاء. يقوم فريقك بتبديل موازن التحميل (load balancer) مرة أخرى إلى الإصدار السابق، أو يعيد خط الأنابيب (pipeline) نشر الأرتيفكت (artifact) القديم. في غضون دقائق، يعمل التطبيق بالكود القديم. البيانات سليمة. قاعدة البيانات لم تتغير. الخوادم هي نفس الأجهزة التي كانت عليها من قبل. المشكلة اختفت.
هذا هو التراجع عن التطبيق (application rollback). يعمل هذا لأن التطبيقات في الغالب عديمة الحالة (stateless). تقوم بتبديل الكود، ويعود السلوك القديم. لا توجد آثار جانبية دائمة.
الآن تخيل أنك غيرت قاعدة جدار حماية (firewall rule)، أو غيرت حجم قرص قاعدة بيانات (database disk)، أو حدثت تكوين شبكة فرعية (subnet configuration). شيء ما ينكسر. تريد العودة. هل يمكنك فقط إعادة تطبيق التكوين القديم وتتوقع أن يعمل كل شيء؟
على الأرجح لا.
التراجع عن البنية التحتية (infrastructure rollback) هو فئة مختلفة من المشاكل. الموارد المعنية تحتوي على بيانات، وتدير مسارات الشبكة، وتوفر خدمات أساسية تعتمد عليها أنظمة أخرى. عندما تغير البنية التحتية، فأنت لا تقوم فقط بتبديل الكود. أنت تغير حالة شيء قد يحتوي على سنوات من البيانات، أو اتصالات بعشرات الخدمات، أو دور كأساس لكل ما هو فوقه.
الحالة هي المشكلة الأولى
التطبيقات مصممة لتكون قابلة للاستبدال (disposable). يمكنك قتل حاوية (container)، وتشغيل واحدة جديدة بكود قديم، ويبدأ التطبيق من جديد. لا ذاكرة للإصدار السابق. لا بيانات متبقية من النشر الفاشل.
البنية التحتية هي العكس. قاعدة البيانات تحتفظ ببياناتها حتى لو غيرت تكوينها. قرص التخزين يحتفظ بملفاته حتى لو غيرت حجمه. هذه الموارد ذات حالة (stateful). تحتفظ بحالة تستمر بعد دورة حياة أي تغيير في التكوين.
عندما تتراجع عن تطبيق، فإنك تستعيد الكود فقط. عندما تتراجع عن بنية تحتية، يجب عليك استعادة التكوين دون تدمير البيانات التي تراكمت داخل المورد. هذا ليس ممكنًا دائمًا.
هذا مثال ملموس. تقوم بترقية نوع مثيل قاعدة بيانات (database instance type) من صغير إلى كبير لأن حركة المرور زادت. النوع الجديد من المثيل به مشكلة. تريد العودة إلى المثيل الصغير. ولكن خلال الوقت الذي كان فيه المثيل الكبير قيد التشغيل، تمت كتابة المزيد من البيانات إلى قاعدة البيانات. المثيل الصغير القديم لم يعد يتسع لتلك البيانات. التراجع ليس آمنًا. لا يمكنك تقليص المثيل دون فقدان البيانات، ولا يمكنك الاحتفاظ بالبيانات إذا عدت.
يصبح الفرق واضحًا عندما تقارن المسارين جنبًا إلى جنب.
هذه ليست مشكلة أداة. هذا قيد أساسي للموارد ذات الحالة. إن تشغيل التكوين الجديد يغير المورد بطرق لا يمكن للتكوين القديم استيعابها.
التبعيات تضاعف المخاطر
نادرًا ما توجد موارد البنية التحتية بمفردها. يمكن لتغيير واحد أن يلمس عشرة موارد مترابطة: VPC، شبكة فرعية (subnet)، مجموعة أمان (security group)، موازن تحميل (load balancer)، عدة مثيلات (instances)، وقاعدة بيانات. كل مورد يعتمد على الآخرين بطرق محددة.
عندما تتراجع عن مورد واحد، تتأثر الموارد التي تعتمد عليه. استعادة مجموعة أمان قديمة يمكن أن تقطع الاتصال بين موازن التحميل والمثيلات. استعادة شبكة فرعية يمكن أن تقطع اتصال قاعدة البيانات. التراجع ليس عملية واحدة. إنه تسلسل يجب ترتيبه بعناية، ويعتمد الترتيب على كيفية إنشاء الموارد في الأصل وكيف تغيرت منذ ذلك الحين.
من الناحية العملية، هذا يعني أنه لا يمكنك فقط تشغيل terraform apply على ملف الحالة القديم (state file) والمغادرة. قد تتعارض الحالة القديمة مع الحالة الحالية للموارد الأخرى التي لم يتم التراجع عنها. غالبًا ما تكون النتيجة استردادًا جزئيًا يترك البنية التحتية في حالة معطلة.
التطبيق المتكرر (Idempotent Apply) لا يعني تراجعًا آمنًا
خطوط أنابيب البنية التحتية مصممة لتكون متكررة (idempotent). يمكنك تشغيل نفس التكوين عدة مرات والحصول على نفس النتيجة. هذا يعمل بشكل جيد لتطبيق التغييرات. لكن التطبيق المتكرر لا يعني تراجعًا آمنًا.
ضع في اعتبارك حجم القرص. تعلن عن قرص بسعة 100 جيجابايت، وتطبقه، ويتم إنشاء القرص. تقوم بتشغيل نفس التكوين مرة أخرى، ولا شيء يتغير. هذا هو التكرار. الآن تقوم بتغيير التكوين إلى 200 جيجابايت وتطبقه. ينمو القرص. ثم تقوم بتغيير التكوين مرة أخرى إلى 100 جيجابايت وتطبقه مرة أخرى. ماذا يحدث؟
معظم أدوات البنية التحتية إما سترفض العملية أو تدمر القرص وتنشئ قرصًا جديدًا. لا يمكنها تقليص قرص دون المخاطرة بفقدان البيانات. التكوين متكرر من الناحية النظرية، لكن المورد الفعلي قد تغير بطريقة لا يمكن عكسها.
يسمى هذا انحراف الحالة (state drift). التكوين في الكود الخاص بك يقول شيئًا، لكن المورد الفعلي في السحابة أو على الخادم مختلف. عندما تحاول التراجع، فأنت لا تقوم فقط بعكس الكود. أنت تحاول التوفيق بين تكوين لم يعد يطابق الواقع. والواقع غالبًا ما ينتصر.
ماذا يعني هذا لفريقك
يتطلب التراجع عن البنية التحتية نوعًا مختلفًا من التحضير عن التراجع عن التطبيق. لا يمكنك الاعتماد على نفس خط الأنابيب أو نفس النموذج الذهني. تحتاج إلى معرفة أي الموارد آمنة للتراجع عنها، وأيها ليست كذلك، وأي ترتيب يجب اتباعه.
بعض التغييرات قابلة للعكس. تغيير تكوين فحص الصحة (health check) لموازن التحميل عادة ما يكون آمنًا للتراجع عنه. تغيير مجموعة معلمات قاعدة بيانات (database parameter group) قد يكون آمنًا إذا لم تغير المعلمات الجديدة البيانات المخزنة. لكن تغيير حجم المثيل، أو حجم القرص، أو طوبولوجيا الشبكة، أو محرك التخزين غالبًا ما يكون غير قابل للعكس دون فقدان البيانات أو توقف الخدمة.
النهج الأكثر أمانًا هو التخطيط للاسترداد (recovery)، وليس فقط التراجع. الاسترداد يعني قبول أن التكوين القديم قد لا يكون صالحًا بعد الآن وبناء مسار للأمام بدلاً من الخلف. قد يتضمن ذلك إنشاء مورد جديد بالتكوين القديم وترحيل البيانات، أو قبول حالة متدهورة أثناء تطوير إصلاح.
قائمة تحقق عملية لتغييرات البنية التحتية
قبل تطبيق أي تغيير في البنية التحتية، اطرح هذه الأسئلة:
- هل هذا المورد يحتفظ بحالة (state)؟ إذا كانت الإجابة بنعم، هل يمكن الحفاظ على الحالة إذا أعدنا التكوين؟
- ما هي الموارد الأخرى التي تعتمد على هذا المورد؟ هل سيؤدي التراجع إلى قطع اتصالها؟
- هل التغيير قابل للعكس؟ هل يمكن للأداة تقليص قرص، أو خفض مستوى مثيل، أو استعادة مسار شبكة دون تدمير البيانات؟
- ما هي خطة الاسترداد الفعلية إذا فشل التغيير؟ هل هي تراجع، أم ترحيل، أم إعادة بناء؟
- هل اختبرنا مسار الاسترداد في بيئة غير إنتاجية؟
الخلاصة
التراجع عن التطبيق هو تبديل كود. التراجع عن البنية التحتية هو مشكلة التوفيق بين الحالة (state reconciliation). معاملتهم بنفس الطريقة يؤدي إلى أنظمة معطلة، وبيانات مفقودة، وأوقات استرداد طويلة. خطط للاسترداد، وليس فقط للتراجع. اعرف أي التغييرات قابلة للعكس، واختبر مسار الاسترداد الخاص بك قبل أن تحتاج إليه.