SSD Nodes Learn 🎉 VPS من $5.50/شهر
الأدلة Matt Connorبقلم Matt Connor

لقطات VPS أم النسخ الاحتياطية أم الاستنساخ؟

افهم الفرق بين لقطة VPS والنسخة الاحتياطية والاستنساخ: ما الذي يستعيده كل خيار، ولماذا قد تفقد اللقطة مع الخادم، وما الذي تصلحه قبل تشغيل النسخة المستنسخة.

ما هي اللقطة والنسخة الاحتياطية والاستنساخ فعلياً

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

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

لماذا لا تُعدّ لقطة VPS نسخة احتياطية

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

  • يُعلَّق الحساب، أو تفشل عملية الدفع، أو يسرق شخص بيانات تسجيل الدخول.
  • يحذف شخص أو برنامج نصي يملك صلاحية الوصول إلى API المثيل. لدى كثير من المزوّدين، يؤدي حذف المثيل إلى حذف لقطاته معه. اقرأ السلوك الموثّق لدى مزوّد الخدمة قبل افتراض خلاف ذلك.
  • تتعرض المنطقة لمشكلة، وتصبح كل مواردها غير قابلة للوصول في الوقت نفسه.
  • يعثر شيء يعمل بصلاحية root على رمز API الخاص بمزوّد الخدمة الذي تركته في /root، ويحذف اللقطات قبل أن يعبث بالقرص.

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

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

لماذا قد تؤدي لقطة لقاعدة بيانات قيد التشغيل إلى استعادة معطوبة

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

تتعامل معظم مكونات المنظومة مع ذلك. يعيد ext4 وXFS تشغيل سجل المعاملات عند تركيب نظام الملفات، لذلك يبدأ نظام الملفات بصورة سليمة. ويعيد PostgreSQL تشغيل سجل الكتابة المسبقة عند البدء، ويظهر ذلك في السجل:

LOG:  database system was not properly shut down; automatic recovery in progress

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

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

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

sudo -u postgres pg_dumpall --clean --file=/var/backups/pg-$(date +%F).sql
sudo mysqldump --single-transaction --routines --all-databases > /var/backups/mysql-$(date +%F).sql

يوفّر --single-transaction تفريغاً متسقاً لجداول InnoDB من دون حجب عمليات الكتابة، لأن التفريغ يعمل ضمن معاملة واحدة بمستوى عزل القراءة القابلة للتكرار. ولا يشمل ذلك جداول MyISAM، التي تحتاج إلى قفل أو إلى إيقاف الخادم. تحقّق من أن التفريغ غير فارغ وغير مبتور قبل الوثوق به: ينتهي tail -n 1 /var/backups/mysql-$(date +%F).sql في ملف mysqldump مكتمل بتعليق Dump completed.

إذا كان لديك مجلد بيانات منفصل، يمكنك تجميده لعدد الثواني التي تحتاجها اللقطة:

sudo fsfreeze -f /srv
# take the snapshot from your provider's panel or API
sudo fsfreeze -u /srv

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

النصف الخارجي: restic أو Borg

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

sudo apt update && sudo apt install -y restic
sudo sh -c 'umask 077; head -c 24 /dev/urandom | base64 > /root/.restic-pass'
sudo chmod 600 /root/.restic-pass
sudo cat /root/.restic-pass

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

export RESTIC_REPOSITORY="s3:https://s3.example.com/vps-backups"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
sudo -E restic init
sudo -E restic backup /etc /srv /var/backups
sudo -E restic snapshots

يحتفظ sudo -E بهذه المتغيرات، لأن root يحصل من دونه على بيئة نظيفة، ويُبلغ restic بأن موقع المستودع غير محدد. يجب أن يعرض restic snapshots عملية التشغيل التي أجريتها للتو، مع المضيف والمسارات الخاصة بها. تحقّق من المستودع نفسه وفق جدول زمني، واقرأ بعض البيانات منه بدلاً من الاكتفاء بفحص بنيته:

sudo -E restic check --read-data-subset=5%
sudo -E restic restore latest --target /tmp/restore-check
sudo -E restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

النسخة الاحتياطية التي لم تُختبر ليست سوى تخمين. استعدها إلى VPS مختلف مرة واحدة على الأقل، وقِس المدة، وسجّلها، لأن هذا الرقم هو هدف الاستعادة الفعلي لديك. يُعد Borg خياراً موثوقاً آخر، ويخزّن مستودعه عبر SSH بدلاً من تخزين الكائنات؛ وتتناول مقارنة restic وBorgBackup المفاضلات بين الخيارين.

ما الذي يجب إصلاحه قبل أن يقترب VPS مستنسخ من بيئة الإنتاج

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

أعد إنشاء مفاتيح مضيف SSH. تحمل النسخة المستنسخة ملفات /etc/ssh/ssh_host_* الخاصة بالخادم الأصلي، لذلك يعرض الخادمان هوية المضيف نفسها. ويمكن لأي شخص يسيطر على أحدهما انتحال هوية الآخر أمام كل عميل قبل ذلك المفتاح، ولا يعرض SSH أي تحذير، لأن المفتاح هو المفتاح الذي يتوقعه العميل.

sudo rm -f /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart ssh
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

يكتب ssh-keygen -A مفتاحاً جديداً لكل نوع يتوقعه البرنامج الخدمي. يجب أن يختلف البصمة الناتجة عن الأمر الأخير عن البصمة الموجودة على الخادم الأصلي. تستمر جلستك الحالية بعد إعادة التشغيل، لأن إعادة تشغيل sshd لا تغلق الاتصالات القائمة. نفّذ ذلك قبل أن يتصل أي شخص بالنسخة المستنسخة. إذا أجلت هذه الخطوة، فسيحصل كل عميل وثق بالمفتاح الموروث مسبقاً على WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!، وعليه تشغيل ssh-keygen -R <host> أولاً.

أعد ضبط معرّف الجهاز. يُعد /etc/machine-id معرّفاً فريداً ينشئه systemd مرة واحدة عند الإقلاع الأول، وترثه النسخة المستنسخة.

sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
sudo reboot

إفراغ /etc/machine-id يخبر systemd بإنشاء قيمة جديدة عند الإقلاع التالي، ولذلك تفرغ الملف بدلاً من حذفه. يتسبب تكرار المعرّف في تعطّل أمرين. في الصور التي تحصل على عنوانها عبر DHCP، يشتق systemd-networkd معرّف عميل DHCP من معرّف الجهاز افتراضياً، لذلك تطلب النسختان تأجيراً بالمعرّف نفسه، ويمنحهما الخادم العنوان نفسه. كما يضيف journald معرّف الجهاز إلى كل إدخال، لذلك يسجّل جامع السجلات المركزي الخادمين ضمن جهاز واحد. شغّل cat /etc/machine-id بعد إعادة التشغيل، وتأكد من تغيّر القيمة.

غيّر اسم المضيف.

sudo hostnamectl set-hostname web-02
grep 127.0.1.1 /etc/hosts

يكتب hostnamectl قيمة /etc/hostname ويطبّق الاسم فوراً. لكنه لا يعدّل /etc/hosts، لذلك عدّل سطر 127.0.1.1 ليتطابق معه. إذا تجاوزت هذه الخطوة، فلن يُحل الاسم الجديد إلى أي وجهة، لذلك تنتظر كل استدعاءات sudo بحثاً فاشلاً وتطبع sudo: unable to resolve host web-02: Name or service not known.

دوّر كل بيانات الاعتماد المضمّنة في الصورة. تحتوي النسخة المستنسخة على أسرار الخادم الأصلي، وأصبح بإمكان جهازين التصرف بوصفهما الخادم الأصلي. راجع ملفات authorized_keys الخاصة بـSSH، ورموز واجهات provider وDNS البرمجية، وملفات .env الخاصة بالتطبيقات، وكلمات مرور قواعد البيانات، والمفاتيح الخاصة لـTLS، ورموز تسجيل agents المراقبة، وكلمة مرور مستودع restic. يعثر الأمر التالي على معظمها:

sudo grep -rIlE 'PASSWORD|SECRET|TOKEN|API_KEY' /etc /srv /opt /home 2>/dev/null
sudo find / -name '.env' -not -path '/proc/*' -not -path '/sys/*' 2>/dev/null

إذا كانت النسخة المستنسخة نسخة اختبار لن تقدم network traffic، فألغِ الأسرار بدلاً من تدويرها. خادم staging يحتفظ برمز API حي خاص بالإنتاج هو خادم إنتاج مع تحديثات أقل جودة.

أوقف المهام التي تعمل الآن مرتين. يؤدي تشغيل الخادمين لـcrontab نفسه إلى الوصول إلى الأنظمة الخارجية نفسها في الدقيقة نفسها.

systemctl list-timers --all
sudo crontab -l
sudo ls -l /etc/cron.d /etc/cron.daily

تستحق حالة restic شرحاً مفصلاً، لأنها تفسد سياسة الاحتفاظ لديك بدلاً من أن تفشل بوضوح فقط. يضع restic اسم المضيف على كل snapshot، ويطبّق restic forget --keep-daily 7 سياسته لكل مضيف. تُعامل آلتان تسجلان اسم المضيف نفسه باعتبارهما مضيفاً واحداً، لذلك قد تأتي snapshots اليومية السبع كلها من النسخة المستنسخة، بينما تُحذف snapshots الخاصة بالخادم الأصلي. أصلح اسم المضيف قبل أول تشغيل للنسخ الاحتياطي، أو أوقف المؤقت على النسخة المستنسخة. حالة certbot أبسط: يؤدي تجديد خادمين للأسماء نفسها إلى بلوغ حد معدل شهادات duplicate لدى جهة إصدار الشهادات، ويفشل التشغيل الخاسر برسالة تفيد بإصدار عدد كبير من الشهادات مسبقاً لمجموعة الأسماء نفسها تماماً. كما لا يمكن لنسخة مستنسخة ما زال نطاقها يشير إلى الخادم الأصلي اجتياز تحدي HTTP، لذلك عطّل التجديد عليها.

تعامل مع agent المراقبة. تتعرّف معظم agents إلى نفسها باستخدام اسم المضيف أو ملف ID يُكتب عند التثبيت، لذلك تدمج agentان تعملان باسم مضيف واحد مقاييسهما في سلسلة واحدة. عندها تعرض مخططات CPU قيماً لم تنتجها أي آلة منفردة، وتتذبذب التنبيهات. أوقف agent على النسخة المستنسخة وأزله، أو أعد تسجيله باسم المضيف الجديد باستخدام الإجراء الموثق لدى المورّد.

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

ip -br addr
sudo grep -r addresses /etc/netplan/

امسح حالة cloud-init إذا أصبحت هذه النسخة قالباً.

sudo cloud-init clean --logs

يزيل ذلك حالة cloud-init الموجودة تحت /var/lib/cloud، لذلك ينفّذ الإقلاع التالي وحدات الإقلاع الأول مرة أخرى، بما في ذلك إنشاء مفاتيح مضيف SSH عند عدم وجودها. توفّر بعض الإصدارات أيضاً راية لإعادة ضبط معرّف الجهاز. شغّل cloud-init clean --help على صورتك لمعرفة ما يدعمه إصدارك، بدلاً من الاعتماد على قائمة رايات من مصدر آخر.

متى تستخدم كل خيار

التراجع عن ترقية محفوفة بالمخاطر: أنشئ لقطة. أنشئها قبل التغيير بدقائق، ثم نفّذ الترقية واستعد الصورة إذا حدث خطأ. يؤدي الاسترداد إلى حذف كل عملية كتابة تمت منذ إنشاء اللقطة، لذلك أفرغ قاعدة البيانات أولاً على الخادم الذي يستقبل حركة مرور فعلية، وحدد بدقة النافذة الزمنية التي ستفقدها. بالنسبة إلى do-release-upgrade على جهاز يمكنك إخراجه من الخدمة لمدة عشر دقائق، تكون اللقطة هي الخطة كاملة.

الانتقال إلى خطة أكبر: انشر نسخة مطابقة. أنشئ النسخة المطابقة من لقطة على الخطة الأكبر، وراجع قائمة الهوية أعلاه، ثم اختبرها على عنوان IP مستقل قبل نقل أي حركة مرور إليها. خفّض قيمة TTL لـDNS قبل يوم حتى يكون التحويل سريعاً، وأبقِ الخادم الأصلي قيد التشغيل إلى أن يستقبل الخادم الجديد حركة مرور فعلية لفترة كافية. تأكد أولاً من أن الخطة الأكبر أسرع فعلاً بالنسبة إلى عبء العمل لديك، باستخدام طريقة قياس الأداء نفسها على الخادمين، لأن زيادة عدد vCPUs على عتاد أكثر انشغالاً لا تعني دائماً ترقية.

إنشاء قالب: أنشئ لقطة لجهاز منظّف. ثبّت خادماً واحداً وعزّزه أمنياً، ثم أزل كل ما يميّزه قبل إنشاء صورته. لا تترك host keys، واجعل machine ID فارغاً، ولا تترك authorized_keys شخصية أو بيانات اعتماد، ونظّف cloud-init. بعد ذلك أنشئ لقطة. تنشئ كل instance منشورة منها هويتها الخاصة عند الإقلاع الأول، لذلك لا تعود قائمة التحقق أعلاه مجرد قائمة تحقق. اربطها بـالدقائق العشر الأولى القياسية على VPS جديد حتى يتضمن القالب العمل الذي كنت ستكرره بخلاف ذلك.

FAQ

هل تُعدّ لقطة VPS نسخة احتياطية؟

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

هل أحتاج إلى إيقاف قاعدة البيانات قبل إنشاء لقطة؟

ليس دائماً، لكن يجب أن تقبل طبيعة النتيجة. تكون لقطة المزوّد متسقة بعد التعطل، أي إن الصورة تطابق الحالة التي سيبدو عليها القرص بعد انقطاع الطاقة. يتعافى PostgreSQL وInnoDB من ذلك عند البدء، ويسجّل PostgreSQL database system was not properly shut down; automatic recovery in progress أثناء العملية. لا يُضمن التعافي عندما تمتد بياناتك على وحدتي تخزين أُخذت لقطتاهما في لحظتين مختلفتين، أو عندما يكتب تطبيق البيانات من دون fsync. اكتب pg_dumpall أو mysqldump --single-transaction على القرص أولاً، حتى تحتوي الصورة على ملف واحد تعرف أنه متسق.

لماذا يتعارك خادمان مستنسخان على عنوان IP نفسه؟

لأنهما يشتركان في /etc/machine-id. في الصور التي تستخدم DHCP، ينشئ systemd-networkd معرّف عميل DHCP من معرّف الجهاز افتراضياً، لذلك يطلب كلا المستنسخين عقد إيجار بصفتهما العميل نفسه، ويعرض خادم DHCP العنوان نفسه لكليهما. اقتطع /etc/machine-id إلى صفر بايت، وأزل /var/lib/dbus/machine-id، وأنشئ رابطاً رمزياً له يعيده إلى /etc/machine-id، ثم أعد التشغيل لكي ينشئ systemd قيمة جديدة. والسبب الشائع الآخر هو وجود عنوان ثابت مكتوب في /etc/netplan/، وقد نسخه المستنسخ حرفياً؛ تحقّق باستخدام ip -br addr.

ما أسرع طريقة للتحقق من أن المستنسخ آمن لوضعه في الإنتاج؟

قارن أربعة أمور مع الخادم الأصلي. شغّل ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub على كليهما وتأكد من اختلاف البصمات. شغّل cat /etc/machine-id على كليهما وتأكد من اختلاف القيم. ثم شغّل hostnamectl status وتأكد من أن الاسم جديد وقابل للحل، حتى لا يصدر sudo تحذيراً. بعد ذلك شغّل systemctl list-timers --all وأوقف كل مؤقت يتصل بنظام مشترك، مثل النسخ الاحتياطي أو تجديد الشهادات أو وكيل المراقبة، إلى أن تحدد أي جهاز سيتولى تلك المهمة.