الهجرة بسرعة إلى حاويات الويب والبيانات المنفصلة

:warning: تحذير: إذا لم تكن مرتاحًا للعمل كمسؤول أنظمة Linux، ولا تملك خبرة في حاويات Docker، فإن الانتقال إلى نشر متعدد الحاويات سيسبب لك صعوبات. وسيتعين على الموظفين والمتطوعين هنا أن يطلبوا منك العودة إلى نشر منفرد لحاوية واحدة يُدار بالكامل بواسطة سكربت launcher.

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

الطريقة الموصى بها للانتقال من نشر حاوية واحدة إلى نشر متعدد الحاويات هي في جوهرها:

  • قم بنسخ احتياطي لمنصة Discourse الخاصة بك
  • احذف كل شيء
  • ابدأ من الصفر مع نشر متعدد الحاويات
  • استعد النسخة الاحتياطية

إذا كان موقعك كبيرًا ويستغرق ساعات للاستعادة، كما هو الحال معي، فقد تتساءل عما إذا كانت هناك طريقة أسرع. لا داعي للتفكير أكثر! لقد انتقلت من نشر منفرد إلى نشر بثلاث حاويات (ويب، بيانات، وريدز) في وقت أقل مما يستغرقه عادةً الأمر ./launcher rebuild app لهذا الموقع. (12 دقيقة من وقت التوقف الكلي، بينما قد يستغرق إعادة بناء التطبيق أحيانًا أكثر من 30 دقيقة.) بناءً على تجربتي، أنصح بالاحتفاظ بـ Redis مع Postgres في حاوية data واحدة في المستقبل.

إذا قمت بذلك، فإنك تتحمل المسؤولية عن معرفة متى تحتاج إلى إعادة بناء الحاويات الأخرى الخاصة بك (البيانات، وإذا كنت غبيًا مثلي وقمت بفصل Redis، فإن Redis أيضًا). لن تحصل بعد الآن على ترقيات مجانية لكل شيء باستخدام ./launcher rebuild app — إذا لم تكن تملك الموارد اللازمة لإدارة هذه العملية، فاستخدم نشرًا منفردًا، أو اشترِ خدمة Discourse المستضافة.

الاختبار

لا تستخدم هذه العملية للانتقال إلى حاويات متعددة ما لم تفهم، بعد قراءتها، أيضًا كيفية الانتقال بسرعة من حاويات متعددة إلى حاوية واحدة. إذا لم يكن ذلك واضحًا لك بعد قراءة هذا المنشور، فإن هذا المنشور يمثل تقنية متقدمة للغاية (أي لا يمكن تمييزها عن السحر)، ومن الممكن ألا تتعرف أيضًا على ما إذا كانت هذه العملية قد تعطلت في منتصف الطريق، مما قد يؤدي إلى الحصول على نسخة معطلة من Discourse لا تتعرف عليها إلا في وقت لاحق. إذا حدث ذلك، فستكون مضطرًا للاحتفاظ بالقطعتين التاليتين. كما يقولون: «من كسر، دفع»!

النسخ الاحتياطي

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

قم بتنزيل النسخة الاحتياطية الخاصة بك. تتضمن الأوامر أدناه نقل ملفات داخل بيانات Discourse، وإذا ارتكبت خطأً، فقد تكون قد حذفت نسختك الاحتياطية. لذا قم بتنزيلها. وإذا لم تتضمن نسختك الاحتياطية الملفات المرفوعة (uploads)، فقم بنسخها احتياطيًا أيضًا. فهي موجودة أيضًا في المكان الذي ستقوم فيه بنقل الملفات.

بجدية، قم بالنسخ الاحتياطي.

عندما قمت بذلك، قمت أولاً بعمل نسخة احتياطية، ثم قمت بنسخ احتياطي للنظام عن بُعد، قبل أن أذهب إلى أي خطوة أخرى.

إعداد تكوين متعدد الحاويات جديد

ستحتاج على الأقل إلى containers/web_only.yml و containers/data.yml، وإذا كنت ترغب أيضًا في فصل Redis، فستحتاج إلى containers/redis.yml. ابدأ بنسخ samples/data.ymlsamples/redis.yml اختياريًا) إلى مجلد containers/.

إذا كنت تنشر Redis بشكل منفصل، فقم بإزالة قالب Redis من أعلى ملف containers/data.yml. (ولكن لا تفعل ذلك دون سبب وجيه؛ فهذا مجرد عمل إضافي.)

لديك طريقتان لإنشاء web_only.yml.

  1. انسخ samples/web_only.yml إلى containers/؛ ثم قارن كلا الملفين بـ containers/app.yml، مع الحفاظ على أي تكوين لـ Postgres في params: في ملف containers/data.yml الجديد
  • انسخ أي params: لـ Postgres من containers/app.yml إلى containers/data.yml
  • أنشئ كلمة مرور فريدة لاستبدال SOME_SECRET
  1. أو، انسخ containers/app.yml إلى containers/web_only.yml وقارنها بـ samples/web_only.yml
  • احذف أي إشارات إلى قوالب Postgres و Redis
  • احذف قسم params: بالكامل الذي يحتوي فقط على إعدادات Postgres
  • أضف قسم links:، حرفيًا من samples/web_only.yml أو معدلاً (انظر أدناه) إذا كنت تنشر Redis في حاوية منفصلة
  • أضف قسم قاعدة البيانات من samples/web_only.yml وأنشئ كلمة مرور فريدة لاستبدال SOME_SECRET
  • غيّر تعريفات الأحجام (volumes) من standalone إلى web_only

إليك قسم links: الذي يجب استخدامه إذا كنت تفصل Redis إلى حاوية خاصة به بدلاً من استخدام الافتراضي المعقول المتمثل في دمجه مع Postgres في حاوية البيانات:

# استخدم مفتاح 'links' لربط الحاويات معًا، أي استخدام علم Docker --link.
links:
  - link:
      name: data
      alias: data
  - link:
      name: redis
      alias: redis

لا حاجة لربط redis إذا كنت تجمع حاويتي Redis و Postgres في حاوية بيانات واحدة؛ هذا只是为了 إظهار ما يجب عليك فعله.

إليك نسخة من إعدادات Postgres الحالية في env في samples/data.yml التي ستحتاج إلى تغيير SOME_SECRET فيها:

  ## TODO: قم بتكوين الاتصال بقواعد البيانات
  DISCOURSE_DB_SOCKET: ''
  #DISCOURSE_DB_USERNAME: discourse
  DISCOURSE_DB_PASSWORD: SOME_SECRET
  DISCOURSE_DB_HOST: data
  ## إذا كنت تستخدم حاوية بيانات+ريدز واحدة، فسيكون التالي "data"
  DISCOURSE_REDIS_HOST: redis

لاحظ أنه بالنسبة للنشر العادي (وليس متعدد المواقع)، لن تحتاج إلى تعديل أي سطور أخرى. DISCOURSE_DB_SOCKET مخصص لـ Unix domain socket لـ Postgres، وليس رقم منفذ.

إليك مثال على التغيير في تعريف الأحجام في نهاية web_only.yml الذي ستحتاج إلى استخدامه إذا قمت بنسخه من app.yml بدلاً من samples/web_only.yml:

@@ -75,10 +80,10 @@
 ## حاوية Docker عديمة الحالة؛ يتم تخزين جميع البيانات في /shared
 volumes:
   - volume:
-      host: /var/discourse/shared/standalone
+      host: /var/discourse/shared/web_only
       guest: /shared
   - volume:
-      host: /var/discourse/shared/standalone/log/var-log
+      host: /var/discourse/shared/web_only/log/var-log
       guest: /var/log

الآن، اضبط نفس كلمة المرور السرية التي استخدمتها في containers/web_only.yml في containers/data.yml بدلاً من SOME_SECRET.

الآن أنت جاهز للانتقال.

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

حاويات منفصلة للبيانات (Postgres) و Redis:

cd /var/discourse

./launcher stop app
cd  shared
mkdir data
mkdir redis
mv standalone/postgres_* data/
mv standalone/redis_data/ redis/
mv standalone web_only
mkdir -p data/log/var-log
mkdir -p redis/log/var-log

cd ..

./launcher destroy app

./launcher bootstrap data
./launcher bootstrap redis
./launcher start redis
./launcher start data

./launcher bootstrap web_only
./launcher start web_only

حاوية بيانات مدمجة لـ Postgres+Redis:

cd /var/discourse

./launcher stop app
cd  shared
mkdir data
mv standalone/postgres_* data/
mv standalone/redis_data/ data/
mv standalone web_only
mkdir -p data/log/var-log

cd ..

./launcher destroy app

./launcher bootstrap data
./launcher start data

./launcher bootstrap web_only
./launcher start web_only

لاحظ أيضًا أنه إذا قمت بإعداد nginx الخارجي سابقًا، فستحتاج إلى تغيير مسار proxy_pass ليتوافق مع موقع web_only الجديد؛ على سبيل المثال من http://unix:/var/discourse/shared/standalone/nginx.http.sock: إلى http://unix:/var/discourse/shared/web_only/nginx.http.sock:

بالنسبة لي، على آلة افتراضية (VM) ذات نواتين وذاكرة 4 جيجابايت وموقع بنسخ احتياطية بحجم 600 ميجابايت دون تنزيلات، أسفر هذا الإجراء عن 12 دقيقة من وقت التوقف. قد تختلف تجربتك.

لاحظ أن كل ما سبق حتى الآن لا يقوم بتحديث launcher. قد لا تكون محدثًا. (على سبيل المثال، قمت بتشغيل هذا بعد توفر تحديث Postgres 12، ولكن قبل أن أطبقه. تركتني هذه العملية بـ Postgres 10. ثم كان الشيء التالي الذي قمت به هو إعادة بناء تطبيق البيانات، الذي قام بتحديث launcher وأخبرني بنجاح بـ عملية تحديث Postgres 12.)

ما يجب فعله في التحديثات المستقبلية

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

./launcher stop web_only
./launcher rebuild data # و/أو redis
./launcher rebuild web_only

لاحظ أنه إذا قمت بإعادة بناء حاوية data (أو postgres، أو redis)، فستحتاج إلى إنشاء حاوية ويب جديدة لإعادة ربطها بحاوية البيانات الجديدة. يمكنك القيام بذلك إما بإعادة بناء web_only، أو، إذا كنت لا تعتقد أنك بحاجة إلى إعادة بنائها، فإن الأمر ./launcher destroy web_only; ./launcher start web_only سيفي بالغرض (وإذا حصلت على خطأ يتعلق بـ “حاوية بيانات مفقودة” أو ما شابه، فهذا هو ما تحتاج إلى فعله).

ومع ذلك، عندما لا يحتاج Postgres ولا Redis إلى تحديث، فإن عدم الحاجة إلى إعادة بناء هذه الحاويات يكون أسرع بكثير، ومعظم إعادة بناء التطبيقات هي مجرد ./launcher rebuild web_only.

بدلاً من ذلك، للحصول على وقت توقف أقل (يُبلغ عنه بشكل مختلف بين 15 ثانية و 2 دقيقة):

./launcher bootstrap web_only
./launcher destroy web_only && ./launcher start web_only

مرة أخرى، من خلال الانتقال إلى نشر متعدد الحاويات، فإن تتبع متى يكون ذلك مناسبًا أصبح الآن من مسؤوليتك. ستحصل على إشعارات في لوحة التحكم للمدير حول التحديثات، ولكنها ستطبق فقط على حاوية web_only. لن يخبرك أحد متى تحتاج إلى تحديث Postgres أو Redis. إذا قمت بذلك، اقرأ فئة الإعلانات قبل كل ترقية إصدار تقوم بها، واقرأ ملاحظات الإصدار لكل إصدار جديد تترقى إليه أو من خلاله. أي، إذا قمت بتخطي تحديث إصدار، فلا تتخطى قراءة ملاحظات الإصدار للإصدار الذي قمت بتخطي تحديثه إليه. (فكر في إعداد مراقبة لملاحظات الإصدار، أو اشتراك قارئ التغذية الخاص بك في https://meta.discourse.org/tag/release-notes.rss للبقاء على اطلاع دائم.)

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

مراجعة النسخ الاحتياطي

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

راجع تنفيذ النسخ الاحتياطي عن بُعد للتأكد من أنه سيقوم بنسخ الملفات المرفوعة في /var/discourse/shared/web_only بدلاً من /var/discourse/shared/standalone حتى تحافظ على تحديث نسخك الاحتياطية في تنفيذك متعدد الحاويات الجديد.

22 إعجابًا

مرحباً، mcdanlj! أنا جديد هنا. أجد أن discourse لديه طريقتان للنشر، إحداهما هي الوضع المستقل لـ app.yml، والأخرى هي طريقتك وهي فصل قاعدة البيانات وذاكرة التخزين المؤقت redis إلى وضع متعدد الحاويات لـ web-only.yml و data.yml و redis.yml. ولكن في نفس الوقت، أجد أيضاً أنه يمكن توصيل app.yml بـ redis وقاعدة البيانات عن طريق تعديل المعلمات DISCOURSE_DB_HOST و DISCOURSE_REDIS_HOST، فلماذا نحتاج إلى تقسيم app.yml إلى web-only.yml و data.yml و redis.yml؟

إذا كان لديك قاعدة بيانات و Redis موجودتان بالفعل (على سبيل المثال، RDS و ElastiCache، أو قمت بإنشائهما بنفسك بطريقة أخرى)، فلن تحتاج إلى إنشاء نسختك الخاصة.

لاحظ أن كل Discourse يحتاج إلى Redis خاص به.

إعجاب واحد (1)

شكراً جاي على شرحك اللطيف! لكنني ما زلت مرتبكاً. من برنامج تعليمي لـ Falco لاحظت أنه من السهل استخدام قواعد بيانات RDS و Elasticache الخاصة بـ AWS دون الحاجة إلى تكوين web-only.yml و data.yml و redis.yml. برنامج تعليمي لـ Falco يعدل فقط المعلمات في app.yml. لكن برنامج mcdanlj التعليمي مختلف. هل هذا لأنه لديه منتدى كبير جداً؟ لذلك لا يمكنه استخدام الطريقة البسيطة التي يوفرها Falco؟

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

في الغالب، يجب عليك استخدام أي منهما يبدو منطقيًا لك.

إعجاب واحد (1)

شكراً جزيلاً! ربما يكون الحاوية الواحدة هي أفضل طريقة بالنسبة لي :rofl: لم أدرك الفرق بين خادم قاعدة بيانات rds وخادم قاعدة بيانات خاص بي قبل أن تخبرني :joy:

إعجاب واحد (1)

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

لهذا السبب بدأت بـ:

:grinning:

إعجابَين (2)

شكراً لك يا mcdanlj! برنامجك التعليمي رائع وقد تعلمت الكثير من المعرفة منه. قررت اختيار الإعداد الافتراضي البسيط المكون من حاوية واحدة. نعم، لقد قمت بتشغيله :rofl:

إعجابَين (2)