بقلم Kristijan Sekereš
إيقاف Azure Cloud Services (Extended Support) في 31 مارس 2027: نقل أدوار الويب والعامل

أعلنت Microsoft إهمال Azure Cloud Services (extended support) في 31 مارس 2025، وستوقفها نهائياً في 31 مارس 2027. فإن كان أحد تطبيقات أعمالك يعمل في صورة أدوار ويب (web roles) وأدوار عامل (worker roles)، فيجب أن يعمل في مكان آخر على Azure قبل ذلك التاريخ. والأسئلة الشائعة حول الإيقاف صريحة في السؤالين اللذين يطرحهما الجميع أولاً: Microsoft "لا تستطيع منح طلبات التمديد"، و"لا تتوفر أدوات ترحيل بنقرة واحدة".
من اليوم، 3 أكتوبر 2026، يبقى ستة أشهر.
لمن هذا المقال
الحالة النموذجية: تطبيق ASP.NET على .NET Framework، بدور ويب في الواجهة ودور عامل أو اثنين خلفه يعالجان الطوابير، بنته وكالة قبل ثماني أو عشر سنوات. وكثيراً ما تكون الوكالة قد انتقلت إلى غيره، بينما لا يزال التطبيق يشغّل معالجة الطلبات أو بوابة العملاء، ولم يفتح أحد ملف .csdef منذ آخر ترحيل.
لمعرفة ما إذا كنت متأثراً، افتح بوابة Azure واسرد الموارد من نوع "Cloud services (extended support)". فإشعار الإيقاف من Microsoft يحيل مباشرة إلى ذلك العرض. وإن كان فارغاً، فقد انتهيت.
هذا المقال لا يتناول Cloud Services (classic)، التي أُوقفت في 2024. وإن كان مورّد يستضيف المنتج لك، فالترحيل مسؤوليته: اطلب منه موعده كتابةً. كل ما يلي للفرق التي تملك الشيفرة، أو تملكها على الورق وعليها أن تجد من يفهمها.
لماذا هذا أصعب من انتقال 2024
انتقلت شركات كثيرة إلى extended support في 2024، حين أُوقفت classic. وكان ذلك الانتقال رخيصاً عن قصد. فـ نظرة Microsoft العامة على extended support تقول إن ملفات .csdef و.cscfg و.cspkg "تُنقل كما هي ولا يوجد تغيير في الصيغ"، وإنه "لا يلزم أي تغيير في شيفرة وقت التشغيل". بل كان هناك ترحيل في المكان نفسه. واقترحت الصفحة نفسها extended support للتطبيقات التي لا تتطور، لأنها "توفّر مسار ترحيل سريعاً".
هذه المرة لا يوجد هدف مماثل. فبعبارة Microsoft، Cloud Services "تتعلق بنشر التطبيقات كأجهزة افتراضية. والشيفرة التي تكتبها مرتبطة ارتباطاً وثيقاً بمثيل الجهاز الافتراضي". شيفرتك تعرف أنها تعمل داخل دور. تقرأ الإعدادات من الدور، وتجد مساحة القرص عبر الدور، وتحصل على الشهادات التي يثبّتها الدور، وتشغّل سكربتات الإعداد بصلاحيات المسؤول قبل بدء الدور. وكل ذلك يجب استبداله.
وأمر آخر قبل أن تقرأ الإرشادات الرسمية. فإشعار الإيقاف والأسئلة الشائعة لدى Microsoft يسمّيان وجهة واحدة، هي Service Fabric managed cluster. أما صفحة النظرة العامة فتسرد خمس وجهات، ومصفوفة قرار الترحيل لدى Microsoft نفسها تقارن سبعاً. Service Fabric خيار افتراضي، لا شرط، وهو الخيار الخاطئ لكثير من أدوار الويب.
الوجهات، ومتى تناسب كل منها
لا يلزم أن تنتهي أدوار الويب والعامل في المكان نفسه. اختر وجهة لكل دور.
App Service (Windows). أقرب شيء إلى دور الويب لتطبيق ASP.NET. فمثيلات Windows تأتي مثبَّتاً عليها إصدارات .NET Framework المدعومة، فتعمل Web Forms وMVC 5 دون إعادة كتابة. ويمكن أن تلحقها أدوار العامل في صورة WebJobs، التي تعمل "في المثيل نفسه الذي يعمل عليه تطبيق الويب" دون تكلفة إضافية. والحد هو الجهاز نفسه: توجّه Microsoft التطبيقات التي تحتاج إلى مكونات COM، أو الوصول إلى السجل (registry)، أو مثبّتات MSI إلى Managed Instance، فلا مكان لمهام بدء التشغيل ذات الصلاحيات المرتفعة في الخطة القياسية.
App Service Managed Instance. مبنية لتطبيقات الويب القديمة على Windows. وبحسب نظرة Microsoft العامة، فهي "متاحة عموماً لتطبيقات الويب على Windows في مناطق مختارة"، ومقتصرة على خطتي Pv4 وPmv4، مع .NET Framework 3.5 و4.8 مثبَّتين مسبقاً، وسكربتات تثبيت PowerShell تستطيع تسجيل مكونات COM، وكتابة مفاتيح السجل، وتشغيل مثبّتات MSI، وإعداد IIS. وهذا يغطي معظم ما كانت تفعله مهام بدء التشغيل ذات الصلاحيات المرتفعة. والقيود: تطبيقات الويب فقط (لا WebJobs)، ولا حاويات، وEntra ID والهوية المُدارة فقط (لا انضمام إلى نطاق، ولا NTLM، ولا Kerberos)، ووقت كتابة هذا المقال كانت المنطقة الأوروبية الوحيدة المدرجة هي North Europe.
Container Apps. جيدة لأدوار العامل بعد انتقالها إلى .NET الحديثة: توسّع مدفوع بالطوابير، ومهام مجدولة ومهام تُطلقها الأحداث، وتقليص إلى الصفر. لكن متطلبات الحاويات تقول إن "صور الحاويات المبنية على Linux (linux/amd64) مطلوبة". فالشيفرة المبنية على .NET Framework لا تعمل هناك حتى تُنقل.
Azure Kubernetes Service. تشغّل حاويات Windows Server في مجموعات عُقد Windows، فيمكن وضع دور مبني على .NET Framework في حاوية ونقله. وتقيّم مصفوفة القرار تعقيد الترحيل وعبء التشغيل فيها كليهما بأنه مرتفع. وهي تناسبك إن كنت تشغّل Kubernetes بالفعل، لا كأول عنقود لتطبيق قديم واحد.
Virtual Machine Scale Sets. تصفها المصفوفة بأنها "أقرب إلى نموذج Cloud Services، وتوفّر نقلاً أسهل كما هو". تستعيد الجهاز الافتراضي، ومعه التحديثات الأمنية، وبناء الصور، وإعداد IIS الذي كان الدور يتولاه عنك.
Service Fabric managed cluster. الوجهة التي تسمّيها Microsoft. أدوار العامل تنتقل إليها بسلاسة. أما أدوار الويب فكثيراً لا: فـ Service Fabric "لا تدعم IIS"، ودليل التحويل يسرد ASP.NET Web Forms كغير مدعومة، والمسار هو التحويل إلى ASP.NET Core MVC. ويضيف دليل الترحيل إلى Service Fabric أن العناقيد المُدارة "لا تدعم الحاويات حالياً"، فالتطبيق المعتمد على IIS يحتاج إلى عنقود تقليدي، بأعباء تشغيل أكبر.
جدول القرار
| يبدو دورك هكذا | الوجهة المرجحة | أين يذهب العمل |
|---|---|---|
| دور ويب بـ ASP.NET Web Forms أو MVC 5، ومهام بدء التشغيل بسيطة أو معدومة | App Service (Windows) | الإعدادات، والشهادات، وخط النشر |
| دور ويب تثبّت مهام بدء تشغيله مكونات COM أو مثبّتات MSI أو مفاتيح سجل | App Service Managed Instance | إعادة كتابة مهام بدء التشغيل كسكربتات تثبيت؛ والتحقق من المنطقة والخطة |
| دور عامل على .NET Framework يستعلم دورياً من طابور، بحمل متوسط | WebJob بجانب تطبيق الويب | استبدال RoleEntryPoint بمضيف تطبيق سطر أوامر |
| دور عامل مستعد لنقله إلى .NET الحديثة | Container Apps | النقل نفسه، ثم صورة حاوية |
| أدوار كثيرة، وفريق يشغّل Kubernetes بالفعل | AKS مع مجموعات عُقد Windows | الصور، وتشغيل العنقود |
| اعتماديات أصلية ثقيلة، ولا رغبة في تغيير الشيفرة | VM Scale Sets | تحديث نظام التشغيل وصيانة الصور، بشكل دائم |
| نظام يغلب عليه العمال، وطبقة الويب على ASP.NET Core بالفعل | Service Fabric managed cluster | تعلّم المنصة؛ لا IIS، ولا حاويات |
ما الذي يتغير في الشيفرة
ابحث في الحل (solution) عن Microsoft.WindowsAzure.ServiceRuntime. كل ملف يستورده مدرج في القائمة.
RoleEntryPoint
دور العامل صنف يرث RoleEntryPoint ويعيد تعريف OnStart وRun وOnStop. وإن عادت Run، يُعاد تدوير المثيل. وتدمج Service Fabric الثلاثة في RunAsync واحدة يجب أن تتوقف "حين يُرسَل إشعار CancellationToken الخاص بالدالة RunAsync". وعلى App Service أو داخل حاوية، يصبح المنطق نفسه تطبيق سطر أوامر أو خدمة خلفية مستضافة بحلقة ورمز إلغاء.
الجزء الذي يفوت الناس هو الإيقاف. كانت OnStop تمنحك لحظة لإنهاء الرسالة التي بين يديك. تأكد من أن المضيف الجديد يمرر إشارة الإلغاء، وأن الرسالة المتروكة في منتصف المعالجة آمنة إن عولجت مرتين.
وكثيراً ما يكون لأدوار الويب صنف مماثل أيضاً، عادة WebRole.cs. فإن كانت OnStart فيه تفعل أي شيء (تعديلات IIS، أو تسخين ذاكرة التخزين المؤقت)، فاعرف ما هو قبل حذفه.
RoleEnvironment
تقرأ RoleEnvironment.GetConfigurationSettingValue("Key") الإعدادات من ملف .cscfg. ولا شيء خارج Cloud Services يوفّرها. قبل نقل أي شيء، غلّف كل استدعاء بواجهة إعدادات صغيرة واحدة، ثم وجّه تلك الواجهة إلى إعدادات التطبيق أو متغيرات البيئة أو Key Vault على المضيف الجديد. إنه أرخص تغيير في المشروع، ويجعل الباقي قابلاً للاختبار على حاسوب محمول.
ثلاثة استخدامات أخرى يجب البحث عنها:
RoleEnvironment.Changed، الذي كان يطبّق تغييرات الإعدادات دون إعادة تشغيل. لدى Service Fabric حدث مكافئ. وفي غيرها، افترض أن تغيير الإعداد يعيد تشغيل العملية واختبر أثر ذلك على العمل الجاري.RoleEnvironment.CurrentRoleInstanceالمستخدم لاختيار مثيل واحد للعمل المجدول. تعمل WebJobs المُطلَقة (triggered) على مثيل واحد؛ أما المستمرة (continuous) فتعمل على كل المثيلات ما لم تُقيَّد. قرّر صراحة.- فروع
RoleEnvironment.IsAvailableوIsEmulated. هذه تفصل مسار "السحابة" عن المسار "المحلي"، وأحدهما على وشك أن يصبح شيفرة ميتة.
.cscfg و.csdef
يحمل ملف .cscfg الإعدادات لكل بيئة، وأعداد المثيلات، وبصمات الشهادات. ويحمل ملف .csdef نقاط النهاية، وحجم الجهاز الافتراضي، والتخزين المحلي، ومهام بدء التشغيل، ومخازن الشهادات، وأحياناً عدة مواقع IIS داخل دور ويب واحد. راجع الملفين سطراً بسطر ودوّن أين يعيش كل مدخل بعد الترحيل: إعداد تطبيق، أو مرجع في Key Vault، أو شيفرة بنية تحتية، أو لا مكان. ونقاط النهاية الداخلية التي تتيح للأدوار استدعاء بعضها مباشرة تحتاج إلى بديل، إما عنوان خدمة وإما طابور.
الشهادات
فرضت extended support بالفعل نقل الشهادات إلى Key Vault، فهذا الجزء من عمل 2024 يؤتي ثماره. ما يتغير هو طريقة عثور الشيفرة عليها. فملف .csdef يثبّت الشهادات في مخزن مسمى، غالباً LocalMachine. وعلى App Service بنظام Windows، يجعلها الإعداد WEBSITE_LOAD_CERTIFICATES متاحة في Current User\My. والشيفرة التي تفتح مخزن LocalMachine لا تجد شيئاً، ويفشل أول استدعاء يحتاج إلى الشهادة. وفي حاويات Linux، حمّلها من Key Vault عند بدء التشغيل بدلاً من ذلك.
مهام بدء التشغيل
افتح Startup.cmd. هنا تعيش المفاجآت، وتعمل عادة بـ executionContext="elevated": خطوط لتوليد ملفات PDF، أو مكون COM، أو وحدة إعادة كتابة لـ IIS، أو تعديل في السجل من أجل TLS. ولكل سطر ثلاثة مصائر ممكنة: لم يعد مطلوباً، أو ينتقل إلى سكربت تثبيت على Managed Instance، أو يُدمج في صورة حاوية أو جهاز افتراضي.
التخزين المحلي
مورد LocalStorage في ملف .csdef، المقروء عبر RoleEnvironment.GetLocalResource، كان يمنح كل مثيل قرصاً للملفات المؤقتة. استخدم مجلد الملفات المؤقتة في المنصة للملفات المؤقتة فعلاً. وكل ما يجب أن يبقى بعد إعادة التشغيل، بما في ذلك الملفات التي افترض أحدهم أنها دائمة، يذهب إلى Blob Storage.
Web Forms
هذا هو القرار الذي يقود الباقي. فـ Web Forms مبنية على System.Web وليس لها إصدار في ASP.NET Core، فنقل تطبيق Web Forms إلى Service Fabric أو Container Apps يعني إعادة كتابة واجهة المستخدم. أما App Service، وManaged Instance، وحاوية Windows، أو scale set فكلها تستطيع تشغيله دون تغيير. انقله كما هو واجعل التحديث مشروعاً مستقلاً بميزانيته الخاصة. فإعادة كتابة واجهة المستخدم لا مكان لها على المسار الحرج لموعد إيقاف.
الباقي
يصبح تبديل VIP بين خدمتين سحابيتين فتحات نشر (deployment slots) على App Service أو مراجعات (revisions) على Container Apps. والسجلات المرسلة عبر امتداد التشخيص (WAD) تحتاج إلى وجهة جديدة، عادة Application Insights. ولا توفّر App Service القياسية ولا Container Apps سطح مكتب بعيداً؛ أما Managed Instance فتسمح به عبر Azure Bastion، للتشخيص فقط.
خطة من ستة أشهر
بالعد التنازلي من 31 مارس 2027، مع عطلات ديسمبر في المنتصف.
أكتوبر: الحصر واختيار الوجهة. اسرد كل نشر على extended support. ولكل دور، سجّل إصدار .NET Framework، وهل هو Web Forms أم MVC، وكل استدعاء لـ RoleEnvironment، وكل مهمة بدء تشغيل، ومورد تخزين محلي، وشهادة، ونقطة نهاية. ثم افحص الجزء غير المريح: هل تستطيع بناء الحزمة المنشورة من الشيفرة المصدرية التي لديك؟ مع الأنظمة التي بنتها وكالات، يكون الجواب أحياناً لا، وأكتوبر هو الشهر المناسب لاكتشاف ذلك. واختر وجهة لكل دور.
نوفمبر: دور واحد من البداية إلى النهاية. أضف غلاف الإعدادات، واكتب البيئة المستهدفة كشيفرة بنية تحتية، وشغّل دوراً واحداً (عادة أبسط عامل) في بيئة اختبار مع السجلات والشهادات وخط النشر.
ديسمبر ويناير: نقل الباقي. استبدل نقاط الدخول، ومهام بدء التشغيل، والتخزين المحلي. واختبر حمل بيئة مرحلية (staging) ببيانات تشبه بيانات الإنتاج: فقد لا تضاهي WebJob أو حاوية إنتاجية جهاز افتراضي مخصص لدور.
فبراير: التشغيل المتوازي. شغّل البيئة الجديدة على حركة حقيقية. وبالنسبة للعمال الذين يتشاركون طابوراً مع الأدوار القديمة، إما أن تجعل المعالجة متساوية الأثر (idempotent) أولاً، وإما أن توقف العمال القدامى قبل تشغيل الجدد.
بداية مارس: الانتقال. بدّل DNS مع هامش زمني كافٍ. أبقِ النشر القديم متوقفاً لكن سليماً لأسبوع أو اثنين، ثم احذفه. ولا تجدول الانتقال في الأسبوع الأخير من مارس: فالانتقال الفاشل حينها لا فرصة ثانية له.
وإن كنت ستبدأ في يناير بدلاً من ذلك، فأسقط التحديث تماماً. اختر الوجهة التي تحتاج إلى أقل تغيير في الشيفرة (App Service، أو Managed Instance، أو scale sets)، وانتقل، وأعد الهيكلة بعد ذلك.
ما الذي ليس واضحاً
تقول Microsoft إن الخدمة "ستُوقف بالكامل" وإن الترحيل مطلوب "لتجنب انقطاع الخدمة". ولا تقول الصفحات التي قرأناها ما الذي سيحدث لنشر لا يزال يعمل في 1 أبريل 2027. لا تخطط لاكتشاف ذلك. ومن المرجح أيضاً أن تتغير مناطق Managed Instance وخططها خلال الأشهر المقبلة، فتأكد منها عند اتخاذ القرار، لا من هذا المقال.
أين تحصل على المساعدة
نتسلّم تطبيقات بناها آخرون، ونفهم كيف تعمل، وننقلها: الحصر، والوجهة لكل دور، وتغييرات RoleEnvironment ومهام بدء التشغيل، والانتقال. ويغطي عملنا في صيانة الأنظمة القديمة تطبيقات .NET Framework وWeb Forms؛ وإن كان فريقك هو من يتولى الترحيل ويحتاج إلى أيدٍ إضافية، فاطّلع على تعزيز الفريق.
إن كان لديك نشر على Cloud Services وموعد بعد ستة أشهر، راسلنا على office@c9group.dev.