لماذا إعادة البناء للإنتاج أكثر خطورة مما تبدو عليه
لديك بناء ناجح في بيئة الاختبار. اجتازت الاختبارات. الفريق مستعد للنشر. يقول أحدهم: "لنقم فقط بسحب نفس العلامة، وإعادة البناء، والنشر للإنتاج. لسنا بحاجة للاحتفاظ بالقطع الأثرية القديمة."
يبدو الأمر فعالاً. لا حاجة لإدارة تخزين القطع الأثرية. لا حاجة للبحث في البنيات القديمة. فقط أعد تشغيل البناء وانشر. لكن هذا الاختصار الذي يبدو عملياً يقدم مشكلتين تقوضان بهدوء كل ما تحاول تحقيقه من خلال خط أنابيب التسليم: تفقد إمكانية التتبع، وتفقد قابلية إعادة الإنتاج.
مشكلة إمكانية التتبع
عندما تعيد البناء للإنتاج، فإن القطعة الأثرية التي تعمل في الإنتاج ليست نفس القطعة الأثرية التي اجتازت الاختبارات في بيئة الاختبار. لقد بنيتها من نفس الكود المصدري، لكن عملية البناء أنشأت قطعة أثرية جديدة بهوية جديدة. لها مجموع اختباري مختلف، وطابع زمني مختلف للبناء، وبيانات وصفية مضمنة مختلفة.
إذا حدث خطأ ما في الإنتاج، لا يمكنك الإشارة إلى نتائج الاختبار والقول "هذه القطعة الأثرية بالضبط تم اختبارها." عليك أن تثق في أن البناء الثاني أنتج نتيجة متطابقة. بدون تحقق، هذه الثقة عمياء.
يُظهر مخطط التدفق التالي الفرق بين المسارين:
إمكانية التتبع ليست مسألة أوراق. إنها تتعلق بالقدرة على الإجابة على سؤال بسيط: "ما الذي يعمل بالضبط في الإنتاج الآن، وكيف أعرف أنه يطابق ما اختبرناه؟" عندما تعيد البناء، يصبح هذا السؤال أصعب في الإجابة بثقة.
مشكلة قابلية إعادة الإنتاج
حتى لو قمت بسحب نفس الالتزام بالضبط، فإن عملية البناء لا تنتج دائمًا نفس المخرجات. يمكن للعديد من العوامل تغيير النتيجة بين بنائين:
انحراف التبعيات. بناؤك الأول يوم الاثنين سحب الإصدار 1.2.3 من مكتبة مفتوحة المصدر. بحلول الأربعاء، أصدر المشرف الإصدار 1.2.4. بناؤك الثاني يسحب الإصدار الجديد تلقائيًا. لم يتغير أي كود مصدري، لكن سلوك التطبيق ربما تغير. قد يؤدي تصحيح بسيط إلى إصلاح خطأ كنت تعتمد عليه، أو إدخال تراجع. قد يسحب أيضًا ثغرة أمنية بصمت.
تحديثات الصورة الأساسية. إذا كان بناؤك يستخدم صورة Docker أساسية موسومة بـ latest أو حتى إصدار ثانوي محدد يتم تصحيحه، فقد يستخدم البناء الثاني طبقة نظام تشغيل أساسية مختلفة. كود التطبيق هو نفسه، لكن بيئة التشغيل تحولت تحته.
اختلافات بيئة البناء. ربما كان لدى عداء CI الذي بنى بيئة الاختبار إصدار JDK مختلف قليلاً، أو Node.js، أو مكتبة نظام. ربما انتهت صلاحية ذاكرة التخزين المؤقت للبناء بين عمليات التشغيل، مما تسبب في إعادة ترجمة كاملة تنتج bytecode مختلف. نادرًا ما تظهر هذه الاختلافات أثناء التطوير، لكنها يمكن أن تسبب أعطالاً دقيقة في الإنتاج.
الطوابع الزمنية والبيانات الوصفية. تقوم العديد من أدوات البناء بتضمين الطوابع الزمنية أو أرقام البناء أو تجزئات الالتزام في القطعة الأثرية. حتى لو كان الكود الوظيفي متطابقًا، تختلف البيانات الوصفية للقطعة الأثرية. هذا يجعل التصحيح أصعب عندما تحتاج إلى ربط سلوك الإنتاج ببناء معين.
التأثير في العالم الحقيقي
هذه المشكلات ليست نظرية. قامت فرق بشحن إعادة بناء إلى الإنتاج فقط لتكتشف أن تبعية تم تحديثها تلقائيًا أدخلت ثغرة أمنية. رأى آخرون تغير سلوك التطبيق لأن تحديثًا على مستوى التصحيح في مكتبة غيّر كيفية عمل دالة. في بعض الحالات، أنتجت إعادة البناء قطعة أثرية عملت بشكل جيد في التطوير لكنها فشلت في الإنتاج لأن بيئة البناء كان بها إصدار مترجم مختلف.
الجزء الأسوأ هو أن هذه المشكلات يصعب اكتشافها. يظهر خط الأنابيب باللون الأخضر. تتطابق تجزئة الالتزام. كل شيء يبدو على ما يرام حتى يلاحظ شخص ما أن شيئًا ما غير صحيح في الإنتاج، وعندها يصبح تتبع السبب الجذري تحقيقًا جنائيًا.
المبدأ: ابنِ مرة، روج عدة مرات
لهذا السبب يوجد مبدأ "ابنِ مرة، روج عدة مرات". تقوم ببناء القطعة الأثرية مرة واحدة، والتحقق منها، ثم ترقية نفس القطعة الأثرية بالضبط عبر كل بيئة: التطوير، الاختبار، الإنتاج. لا إعادة بناء. لا فرص ثانية.
مع هذا النهج، القطعة الأثرية في الإنتاج متطابقة فعليًا مع القطعة الأثرية التي اجتازت جميع الاختبارات. يتطابق المجموع الاختباري. تتطابق البيانات الوصفية المضمنة. أنت تعرف بالضبط ما تم اختباره وما تم شحنه. إمكانية التتبع مدمجة لأن كل قطعة أثرية لها معرف فريد مرتبط بالتزامها، وتكوين البناء، والطابع الزمني. قابلية إعادة الإنتاج ليست مصدر قلق لأنك لا تعيد إنتاج أي شيء - أنت تستخدم نفس الملف الثنائي.
عندما تكون إعادة البناء حتمية
هناك حالات مشروعة تكون فيها إعادة البناء ضرورية. قد تكون قطعة أثرية قديمة غير متوافقة مع ترقية البنية التحتية للإنتاج. قد يجبر تصحيح أمني حاسم في صورة أساسية على إعادة البناء. قد يتطلب متطلب امتثال أن يتم بناء القطع الأثرية للإنتاج من بيئة مقواة محددة.
هذه المواقف موجودة، لكن يجب أن تكون استثناءات، وليس القاعدة. في كل مرة يقرر فيها فريقك إعادة البناء للإنتاج، يجب أن تعترف صراحة بالمخاطر: أنت تكسر إمكانية التتبع، وتراهن على أن البناء قابل لإعادة الإنتاج. وثق القرار، وتحقق من المخرجات مقابل البناء الأصلي، وعامله كفرصة لمراجعة الحادث لمنع عمليات إعادة البناء المستقبلية.
قائمة تحقق عملية قبل إعادة البناء للإنتاج
- هل يمكنك التحقق من أن القطعة الأثرية المعاد بناؤها متطابقة وظيفيًا مع القطعة الأثرية المختبرة؟
- هل قمت بتثبيت جميع إصدارات التبعيات، بما في ذلك التبعيات غير المباشرة؟
- هل بيئة البناء (المترجم، وقت التشغيل، مكتبات النظام) متطابقة مع البناء الأصلي؟
- هل الصور الأساسية مثبتة على ملخصات محددة، وليس علامات؟
- هل لديك سبب موثق لعدم إمكانية ترقية القطعة الأثرية الأصلية؟
- هل وافق الفريق على معاملة هذا كاستثناء، وليس ممارسة قياسية؟
الخلاصة
كل إعادة بناء للإنتاج تدخل عدم يقين في خط أنابيب التسليم الخاص بك. تفقد القدرة على القول بثقة أن القطعة الأثرية التي تعمل في الإنتاج هي نفسها التي اجتازت الاختبار. التوفير في تخزين القطع الأثرية أو الراحة نادرًا ما يستحق تكلفة التصحيح عندما يحدث خطأ ما. ابنِ مرة. روج نفس القطعة الأثرية في كل مكان. اجعل إعادة البناء هي الاستثناء الذي يتطلب تبريرًا صريحًا، وليس المسار الافتراضي للإنتاج.