جراحة حالة Terraform
جراحة حالة Terraform
تُعدّ حالة Terraform المصدرَ الوحيد للحقيقة الذي يربط إعدادات HCL بالبنية التحتية الفعلية في السحابة. في عالم مثالي لن تضطر إلى لمسها مباشرةً أبدًا — فكل مورد يُولَد عبر terraform apply ويُزال عبر terraform destroy. لكن الإنتاج ليس مثاليًا؛ تواجه الفرق موارد قديمة أُنشئت قبل وجود Terraform، وعمليات إعادة هيكلة تُغيّر أسماء الموارد، وتلفًا محتملًا في ملف الحالة، والحاجة إلى تقسيم ملفات الحالة الضخمة. إتقان جراحة الحالة — أي التعامل مع الحالة بأمان دون تدمير البنية التحتية الفعلية — مهارة لا غنى عنها في أي مؤسسة تُشغّل Terraform على نطاق واسع.
terraform destroy يطال موردًا واحدًا. أما عملية جراحة حالة خاطئة فقد تُفقد المزامنة بين عشرات الموارد دفعةً واحدة، فيحاول Terraform إعادة إنشاء كل شيء في التطبيق التالي. احرص دائمًا على نسخ احتياطي من الحالة قبل أي عملية جراحية، ثم نفّذ terraform plan بعدها للتحقق من أن نية Terraform تطابق ما تقصده.
نسخ الحالة احتياطيًا قبل الجراحة
سواء كانت الواجهة الخلفية S3 أو GCS أو Terraform Cloud، التقط نسخة محلية قبل أن تبدأ:
في واجهات S3 مع تفعيل الإصدار، تُحفظ نسخة الحالة السابقة تلقائيًا — لكن السحب الصريح يمنحك نسخة محلية يمكنك فحصها والاستعادة منها دون الحاجة إلى الوصول السحابي.
أمر terraform import
استخدم import حين يكون مورد موجودًا في السحابة فعليًا لكن لا يوجد له سجل مقابل في حالة Terraform. أبرز السيناريوهات: مدير قاعدة بيانات أنشأ نسخة RDS يدويًا لأسباب طارئة، أو مهندس أضاف قاعدة في مجموعة أمان عبر وحدة التحكم، أو تبنّيت حسابًا AWS قديمًا لم يُدار بـ IaC قط.
المسار الصحيح هو: اكتب إعداد HCL أولًا، ثم استورد المورد الفعلي إلى الحالة. لا يولّد Terraform الكود نيابةً عنك عبر terraform import بمفرده — وإن كانت ميزة terraform plan -generate-config-out المُضافة في Terraform 1.5 تستطيع توليد هيكل أولي للإعداد كنقطة انطلاق.
في Terraform 1.5 وما بعده، يمكنك أيضًا الإعلان عن عمليات الاستيراد داخل HCL عبر كتلة import، وهي مثالية وآمنة للتنفيذ في خطوط الأنابيب:
terraform import من سطر الأوامر عملية آنية لا تترك أثرًا في Git. أما كتل import فهي تصريحية، تُراجَع في طلبات السحب، ويمكن تطبيقها عبر خط أنابيب CI/CD الاعتيادي. بعد تطبيق الاستيراد، احذف الكتلة من الكود (المورد بات تحت إدارة Terraform والكتلة لن تحدث شيئًا لو بقيت، لكنها تُشوّش القراءة).
كتلة moved — إعادة التسمية بلا تدمير
حين تُعيد هيكلة HCL — إعادة تسمية مورد، نقله إلى وحدة، أو تغيير مفتاح for_each — يرى Terraform أن العنوان القديم اختفى والجديد ظهر. في غياب توجيه صريح، سيُخطط لحذف المورد القديم وإنشاء مورد جديد، مما يعني انقطاعًا في الإنتاج. كتلة moved (مُقدَّمة في Terraform 1.1) تُخبر Terraform أن العنوانين القديم والجديد يشيران إلى الكائن الفعلي ذاته، فلا تحدث دورة حذف/إنشاء.
كتل moved هي سجلات تاريخية دائمة — احتفظ بها في الكود حتى يُطبّقها جميع المهندسون وخطوط الأنابيب، ثم احذفها بعد فترة استقرار (عادةً سبرينت واحد). إن حذفتها مبكرًا، سيرى المهندس الذي لم يُطبّق بعدُ دورة حذف/إنشاء في تطبيقه التالي.
تُعالج الكتلة أيضًا إعادة تسمية مفاتيح for_each، وهي من أكثر نقاط الألم في عمليات إعادة الهيكلة:
أوامر CLI للحالة: mv وrm وlist
أوامر terraform state الفرعية هي أدوات جراحية للحالات التي لا تكفي فيها كتل HCL — كالنقل عبر مساحات العمل أو الواجهات الخلفية المختلفة.
terraform state list — يسرد جميع عناوين الموارد المُتتبَّعة حاليًا في الحالة. أساسي قبل أي عملية جراحية لفهم ما بين يديك:
terraform state mv — ينقل موردًا من عنوان إلى آخر داخل ملف الحالة ذاته، أو بين ملفي حالة مختلفين. استخدمه حين لا تصلح كتل moved (كالنقل عبر مساحات العمل):
terraform state rm — يحذف موردًا من الحالة دون تدمير البنية التحتية الفعلية. استخدمه حين تريد إيقاف إدارة Terraform لمورد ما (تسليمه لإدارة يدوية أو ترحيله لأداة أخرى) مع إبقاء المورد السحابي سليمًا:
state rm، سيُظهر terraform plan التالي المورد كـ "سيُنشأ" — لأن Terraform لم يعد يعلم بوجود المورد الفعلي. أضف إما lifecycle { ignore_changes = all }، أو احذف المورد من HCL كليًا، أو أعد استيراده. تأكد دائمًا من وجود نية واضحة قبل الحذف من الحالة.
إعادة الهيكلة بلا تدمير: النمط الآمن
أفضل طريقة لإعادة هيكلة كود Terraform الكبير تتبع هذا التسلسل:
- نسخ احتياطي للحالة —
terraform state pull > backup.tfstate - كتابة HCL الجديد — إعادة تسمية الموارد، استخراج الوحدات، إعادة الهيكلة
- إضافة كتل
moved— واحدة لكل عنوان أُعيدت تسميته أو نُقل - تشغيل
terraform plan— يجب أن يُظهر صفر إضافات وصفر حذوفات؛ فقط ملاحظات النقل تظهر - التطبيق على بيئة غير إنتاجية أولًا — للتحقق من نظافة عملية إعادة الهيكلة
- التطبيق على الإنتاج — مع مراجعة مهندس آخر لناتج plan قبل التأكيد
- حذف كتل
moved— بعد تطبيق جميع البيئات بنجاح
أنماط الفشل في الإنتاج
أخطر أخطاء جراحة الحالة على نطاق واسع:
- التطبيق بلا plan بعد الاستيراد — إذا لم يتطابق إعداد المورد المستورَد مع الواقع، سيُعدّل Terraform خصائصه أو يحذفها. نفّذ plan فورًا بعد كل استيراد وحلّ جميع الفوارق قبل المتابعة.
- حذف كتل moved مبكرًا — المهندسون الذين لم يُطبّقوا بعد سيواجهون دورات حذف/إنشاء في تطبيقهم التالي. احتفظ بكتل moved طوال دورة إصدار كاملة على الأقل.
- دفع الحالة بلا قفل — دفع ملف حالة معدَّل يدويًا عبر
terraform state pushيتجاوز القفل الموزّع. إن كان خط أنابيب يُطبّق في الوقت ذاته، سيُتلف الدفع الحالة. استخدم-lock=falseكملاذ أخير حصرًا حين تتيقن من عدم وجود تطبيق نشط. - الجمع بين
state mvوكتل moved للمورد ذاته — تطبيق كتلة moved بعد تشغيلstate mvعلى المورد نفسه سيُسبّب خطأ في Terraform. اختر مسارًا واحدًا والتزم به.
terraform state push مباشرةً يستلزم موافقة مهندس ثانٍ، وتذكرة حادثة مرتبطة، ويُطلق تنبيهًا تلقائيًا لفريق المنصة. حتى في المؤسسات الأصغر، تعامل مع أي تعديل يدوي للحالة باعتباره حدثًا بمستوى حادثة: وثّق ما فعلته، ولماذا، وماذا أظهر plan بعدها.