توقف عن خلط البيئات: لماذا يجب ألا تلمس بيئة التطوير والإنتاج بعضهما أبدًا

لديك ثلاثة مجلدات: dev وstaging وprod. كل منها يحتوي على ملفات التكوين وسجلات الحالة وتعريفات الموارد. عندما تحتاج إلى تحديث قاعدة جدار حماية، تفتح المجلدات الثلاثة وتجري نفس التغيير ثلاث مرات. في أحد الأيام، تنسى تحديث staging. بعد أسبوعين، يفشل نشر إلى staging لأن جدار الحماية يمنع اتصالًا يعمل في كل مكان آخر. لا أحد يلاحظ حتى يتم حظر الإصدار.

هذا الموقف شائع. تبدأ الفرق ببيئة واحدة، ثم تضيف أخرى، ثم أخرى. يبدو الفصل واضحًا لأن المجلدات لها أسماء مختلفة. لكن الفصل تجميلي فقط. المشكلة الحقيقية هي أن نفس الشخص، ونفس الأداة، ونفس نمط الوصول يمكنهم لمس كل بيئة دون أي حواجز حماية.

المشكلة الحقيقية في فصل البيئات

فصل البيئات لا يتعلق بأسماء المجلدات. يتعلق بضمان أن التغييرات في التطوير لا تؤثر أبدًا على الإنتاج عن طريق الخطأ، وأن الاختبار في staging يعكس ظروف الإنتاج الفعلية.

عندما تستخدم نفس ملف الحالة لجميع البيئات، فإنك تنشئ نقطة فشل واحدة. خطأ في التطوير يمكن أن يحذف موردًا في الإنتاج. خط أنابيب CI مهيأ بشكل خاطئ يمكن أن يطبق قيم staging على بنية الإنتاج التحتية. هذه ليست مخاطر نظرية. تحدث عندما تشارك الفرق ملفات الحالة، أو الخلفيات، أو بيانات اعتماد الوصول عبر البيئات.

الهدف هو جعل من المستحيل تعديل الإنتاج عن طريق الخطأ أثناء العمل على التطوير. هذا يتطلب أكثر من الانضباط. يتطلب فصلًا هيكليًا.

ثلاث طرق لفصل البيئات

1. مجلدات منفصلة

الرسم البياني التالي يوضح كل طريقة مع هيكلها وخصائصها الرئيسية:

flowchart TD subgraph Approach1["1. مجلدات منفصلة"] A1[كود + تكوين + حالة لكل بيئة] --> D1[dev] A1 --> S1[staging] A1 --> P1[prod] end subgraph Approach2["2. هيكل مشترك + ملفات تكوين"] A2[كود مشترك] --> C2[ملفات التكوين] C2 --> D2[dev] C2 --> S2[staging] C2 --> P2[prod] A2 -.->|نفس خلفية الحالة| D2 A2 -.->|نفس خلفية الحالة| S2 A2 -.->|نفس خلفية الحالة| P2 end subgraph Approach3["3. خلفيات حالة منفصلة"] A3[كود + تكوين مشترك] --> D3[dev] A3 --> S3[staging] A3 --> P3[prod] D3 --> B1[خلفية dev] S3 --> B2[خلفية staging] P3 --> B3[خلفية prod] end Approach1 -.->|تكرار عالي| L1[بسيط لكنه ينحرف] Approach2 -.->|عزل متوسط| L2[تكرار أقل، مخاطرة مشتركة] Approach3 -.->|عزل كامل| L3[الأفضل للتوسع والأمان]

هذه أبسط طريقة. تنشئ مجلدًا لكل بيئة: dev/ وstaging/ وprod/. يحتوي كل مجلد على ملفات التكوين الخاصة به وملف الحالة الخاص به. عندما تشغل أمرًا، تحدد أي مجلد ستستخدم.

هذا يعمل جيدًا للفرق الصغيرة ذات البيئات القليلة. يمكنك رؤية الاختلافات بين البيئات بمقارنة الملفات جنبًا إلى جنب. الهيكل سهل الفهم. يمكن لأعضاء الفريق الجدد العثور على ما يحتاجون إليه دون سؤال.

تظهر المشكلة عندما تشارك البيئات معظم تكوينها. قد يختلف التطوير و staging فقط في حجم الخادم واسم قاعدة البيانات. عندما تحتاج إلى تغيير إعداد أمان، يجب تحديث ثلاثة ملفات. نسيان واحد يخلق انحرافًا غير مرئي. بمرور الوقت، تتباعد البيئات حتى لا تعود staging تمثل الإنتاج.

2. هيكل مشترك مع ملفات تكوين منفصلة

بدلاً من تكرار التكوين بأكمله، تحتفظ بمجموعة واحدة من تعريفات الموارد وملفات منفصلة للقيم الخاصة بالبيئة. تحدد الملفات الرئيسية المنطق والهيكل. تحتوي ملفات التكوين على قيم مثل أسماء الخوادم وأحجام المثيلات وسلاسل الاتصال.

هذه الطريقة تقلل التكرار. تكتب تعريفات الموارد مرة واحدة. عندما تغير قاعدة جدار حماية، تغيرها في مكان واحد. تحتوي الملفات الخاصة بالبيئة فقط على القيم التي تختلف فعليًا.

المقايضة هي التعقيد. تحتاج إلى فهم كيفية دمج ملفات التكوين مع التعريفات الرئيسية. تحتاج إلى ضمان أن كل بيئة لديها ملف التكوين الصحيح. فقدان قيمة يمكن أن يتسبب في فشل النشر أو، الأسوأ، استخدام قيمة افتراضية خاطئة لتلك البيئة.

3. خلفيات حالة منفصلة

هذه هي الطريقة الأكثر نضجًا. تستخدم كل بيئة خلفية مختلفة لتخزين ملف الحالة الخاص بها. يسجل ملف الحالة كل مورد تم إنشاؤه وإدارته. عندما تكون الخلفيات منفصلة، لا يمكن لحالة التطوير أن تختلط بحالة الإنتاج عن طريق الخطأ.

إليك مثال ملموس لكيفية تكوين خلفيات حالة منفصلة في Terraform باستخدام S3:

# تكوين الخلفية لبيئة الإنتاج
terraform {
  backend "s3" {
    bucket = "my-company-tfstate"
    key    = "prod/terraform.tfstate"
    region = "us-east-1"
  }
}

بالنسبة لبيئة staging، ستستخدم نفس الحاوية ولكن بمفتاح مختلف:

terraform {
  backend "s3" {
    bucket = "my-company-tfstate"
    key    = "staging/terraform.tfstate"
    region = "us-east-1"
  }
}

وبالنسبة للتطوير:

terraform {
  backend "s3" {
    bucket = "my-company-tfstate"
    key    = "dev/terraform.tfstate"
    region = "us-east-1"
  }
}

يتم تخزين ملف الحالة لكل بيئة تحت بادئة منفصلة في نفس حاوية S3. يمكنك بعد ذلك فرض سياسات الوصول على مستوى الحاوية أو البادئة، مما يضمن أن المطورين يمكنهم فقط قراءة وكتابة بادئة dev/ بينما يكون الوصول إلى الإنتاج مقصورًا على خط أنابيب CI/CD الخاص بك.

يمكنك فرض سياسات الوصول على مستوى الخلفية. يمكن لأعضاء فريق التطوير الوصول فقط إلى خلفية التطوير. تحتفظ فرق العمليات أو SRE بالوصول إلى خلفية الإنتاج. لا يمكن للمطور الذي يشغل أمرًا من حاسوبه المحمول لمس موارد الإنتاج لأن بيانات اعتماده لا تملك حق الوصول إلى خلفية الإنتاج.

هذا الفصل بالغ الأهمية لأن ملفات الحالة تحتوي على معلومات حساسة. يسجل حالة الإنتاج عادةً عناوين IP للخوادم واتصالات قواعد البيانات وتكوينات الأمان. إذا تم تخزين حالتي الإنتاج والتطوير في نفس المكان، فإن تسربًا أو تغييرًا عرضيًا يؤثر على كلتا البيئتين. مع الخلفيات المنفصلة، يمكنك تطبيق سياسات أمان مختلفة على كل بيئة.

متى تستخدم كل طريقة

اختر المجلدات المنفصلة عندما يكون مشروعك صغيرًا، ولديك بيئات قليلة، وتختلف الموارد بشكل كبير بين البيئات. هذه نقطة بداية جيدة، لكن خطط للابتعاد عنها مع نمو الفريق.

اختر الهيكل المشترك مع ملفات تكوين منفصلة عندما يكون لبيئاتك نفس الهيكل ولكن بقيم مختلفة. هذا يعمل جيدًا للفرق التي قامت بتوحيد بنيتها التحتية وتحتاج فقط إلى تغيير معلمات مثل الحجم أو المنطقة أو التسمية.

اختر خلفيات الحالة المنفصلة عندما يكون فريقك كبيرًا، أو يجب حماية الإنتاج بشكل صارم، أو تحتاج إلى سجل تدقيق لكل تغيير. هذه هي الطريقة التي تتوسع مع تعقيد المؤسسة.

الجانب السياسي لفصل البيئات

الفصل التقني هو نصف الحل فقط. يمكن أن يكون لديك فصل مثالي للخلفيات، ولكن إذا كان كل عضو في الفريق لديه حق الوصول إلى خلفية الإنتاج من حاسوبه المحمول، فإن الفصل لا معنى له.

يتطلب فصل البيئات سياسة. من يمكنه قراءة حالة الإنتاج؟ من يمكنه تعديلها؟ من يمكنه الموافقة على التغييرات في البنية التحتية للإنتاج؟ يجب الإجابة على هذه الأسئلة وفرضها من خلال ضوابط الوصول، وليس من خلال الاتفاقات الشفهية.

تستخدم بعض الفرق خط أنابيب CI/CD منفصلًا لنشر الإنتاج. يعمل خط أنابيب الإنتاج فقط من فرع معين، ويتطلب موافقات، ويستخدم بيانات اعتماد غير متاحة للمطورين. هذا يضيف طبقة أخرى من الفصل تتجاوز الخلفية نفسها.

قائمة تحقق عملية

  • كل بيئة تستخدم خلفية حالة مختلفة
  • خلفية الإنتاج يمكن الوصول إليها فقط من خط أنابيب CI/CD، وليس من الأجهزة المحلية
  • خلفيات التطوير و staging متاحة للمطورين
  • ملفات الحالة مشفرة عند التخزين
  • الوصول إلى حالة الإنتاج يتطلب موافقة ويتم تسجيله
  • يتم التحقق من صحة قيم التكوين قبل وصولها إلى الإنتاج

الخلاصة الملموسة

فصل البيئات ليس مشكلة هيكل مجلدات. إنها مشكلة عزل الحالة. عندما تعامل كل بيئة كنظام منفصل تمامًا مع خلفية الحالة الخاصة به، وضوابط الوصول الخاصة به، وخط أنابيب النشر الخاص به، فإنك تزيل إمكانية التغييرات العرضية عبر البيئات. ابدأ بمجلدات منفصلة إذا كان يجب عليك، لكن انتقل إلى خلفيات منفصلة قبل أن ينمو فريقك إلى أكثر من خمسة أشخاص. تكلفة إصلاح انقطاع الإنتاج الناجم عن الحالة المشتركة دائمًا أعلى من تكلفة إعداد الفصل المناسب من البداية.