· 3 دقائق قراءة
الانتقال إلى Kubernetes بقلبة واحدة
كيف انتقل ClickFortify من خادم افتراضي واحد إلى Kubernetes عبر تشغيل المنظومة الجديدة خلف أسماء نطاقات تجريبية، والتحقق منها هناك، ثم توجيه الإنتاج إليها بتغيير واحد في DNS.
ترجمة آلية. اقرأ النسخة الأصلية
بدأ ClickFortify حياته على خادم افتراضي (VM) واحد يشغّل docker-compose. وهو يعمل الآن على Kubernetes في GCP ويُنشر عبر ArgoCD. تتناول هذه التدوينة الانتقال بين الاثنين، ولماذا انتهى بي الأمر إلى تنفيذه بقلبة واحدة بدلاً من ترحيل تدريجي.
المنتج لا يحتمل التوقف
يجمع ClickFortify النقرات الإعلانية من حركة المرور الحية، ويقيّمها، ويكتب الاستبعادات في Google Ads وMeta. تصل النقرات على مدار الساعة. وأي خطة ترحيل تتطلب نافذة صيانة، أو تترك المتتبّع نصفه على منظومة ونصفه على أخرى، تكلّف معلنين حقيقيين ميزانية حقيقية.
لذلك لم يكن السؤال "كيف ننقل كل شيء؟" بل كان "كيف نجعل التحويل خطوة واحدة صغيرة وقابلة للعكس؟"
اضبط مسار النشر أولاً
قبل نقل أي حركة مرور، احتاج العنقود إلى مسار نشر أثق به. يستخدم إعداد GitOps ثلاثة مستودعات: التطبيق، وملفات manifests التي ينشرها ArgoCD، والبنية التحتية للمنصة. كانت الخطة الأصلية تُبقي ملفات manifests داخل المستودع الأحادي (monorepo) للتطبيق. فصلتها لأن ArgoCD يعيد استنساخ المستودع عند كل تحديث والمستودع الأحادي ضخم، ولأن للمنصة دورة حياة ومراجعين خاصين بها، ولأن CI الخاص بالتطبيق لا يملك حينها أي وصول إلى مستودع المنصة.
هذا مهم عند التحويل. إذا نُشر الجانب الجديد بالطريقة نفسها التي سيُنشر بها دائماً بعد ذلك، فإن التحقق منه في اليوم الأول يتحقق أيضاً من عملية الإصدار.
مجموعة موازية من أسماء النطاقات التجريبية
تألفت الخطة التي استقررت عليها من ثلاث خطوات:
- نشر المنظومة الجديدة كاملة على العنقود خلف مجموعة موازية من أسماء النطاقات التجريبية، مثل
stage.example.com. - التحقق منها هناك.
- توجيه أسماء نطاقات الإنتاج إلى العنقود بقلبة واحدة.
لم يتغير شيء في الإنتاج أثناء اختبار الجانب الجديد. ظل الخادم الافتراضي القديم يخدم كل طلب حقيقي، ومنحتني أسماء النطاقات التجريبية مكاناً لاختبار المنظومة الجديدة من طرف إلى طرف.
لا ترحيل للبيانات، والمحاذير التي تصاحب ذلك
استخدم الجانبان قواعد البيانات نفسها. وهذا ما جعل القلبة الواحدة ممكنة: لم تكن هناك نسخة يجب تشغيلها، ولا مزامنة يجب الحفاظ على اتساقها، ولا لحظة تختلف فيها المنظومتان بشأن البيانات. وعندما انتقل DNS، كانت المنظومة الجديدة تقرأ وتكتب بالفعل الصفوف نفسها التي كانت القديمة تتعامل معها.
المحذور هو أن الجانب التجريبي لم يكن قط بيئة معزولة (sandbox) حقاً. فكل ما كتبه وصل إلى بيانات الإنتاج. استُخدمت في الاختبار مساحة مخصصة جرى تخصيصها لهذا الغرض، ولم يُوجَّه أبداً أي سكربت لعميل حقيقي إلى المتتبّع التجريبي.
لماذا بقي العامل عند الصفر
العامل (worker) هو الخدمة التي تشغّل المهام المجدولة. على قاعدة بيانات مشتركة، وجود عاملين يعني أن كل مهمة مجدولة تُنفَّذ مرتين: تُرسل الرسائل الإلكترونية مرتين، وتحذف عمليات التنظيف مرتين. لذلك بقي العامل في الجانب الجديد عند صفر نسخ متماثلة طوال فترة الاختبار التجريبي.
# Illustrative: keep the new side's worker off until the flip
kubectl scale deployment worker --replicas=0القلبة، والتحقق من صمودها
كانت القلبة نفسها تغييراً في DNS: وُجِّهت أسماء نطاقات الإنتاج إلى العنقود. وقبل ذلك، تحققت من أن بصمات الصور (image digests) العاملة على العنقود تطابق ما كنت أتوقع شحنه.
بعد ذلك، كان أهم فحص على المتتبّع. فهو يقع خلف CDN وخادم وكيل عكسي (reverse proxy)، ومعرفة عنوان IP الحقيقي للزائر خلفهما هو بالضبط نوع الأمور التي تتعطل عندما تتغير البنية. أظهرت حركة المرور الحية على المتتبّع بعد القلبة عناوين IP حقيقية للزوار ولم تُظهر أي عناوين لحواف CDN. وبعد أن ثبت ذلك، أُزيلت أسماء النطاقات التجريبية.
مباشرة بعد القلبة، كان التراجع هو الخطوة نفسها بالعكس: إعادة توجيه أسماء النطاقات إلى الخادم الافتراضي القديم، الذي أوقفته بدلاً من حذفه.
ما سأقوله لمن يجري الانتقال نفسه
- إذا كان بإمكان الجانبين مشاركة قواعد البيانات، فافعل ذلك. فهذا يُلغي ترحيل البيانات ويجعل التحويل تغييراً واحداً في DNS.
- أعدّ قائمة بكل مهمة مجدولة وتأكد من أنها تعمل في مكان واحد فقط خلال الاختبار التجريبي، حتى لو عنى ذلك أن خدمة ما لا يمكن التمرّن عليها.
- أفرغ المهام المنتظرة في الطوابير والمؤجلة أو صدّرها قبل القلبة. فهي تعيش خارج قاعدة البيانات.
- حدّد فحص التحقق قبل القلبة، واجعله قائماً على حركة مرور حقيقية، لا على نقاط فحص السلامة (health endpoints).