SSD Nodes Learn 🎉 VPS $5.50/माह से
गाइड Matt Connorलेखक: Matt Connor

VPS Snapshot, Backup और Clone में क्या अंतर है?

VPS Snapshot को बैकअप क्यों नहीं माना जाता है और इनमें से किसे कब चुनें? इस लेख में जानिए कि कैसे Snapshot, Backup और Clone अलग-अलग तरह से डेटा सुरक्षा और रिकवरी में मदद करते हैं।

Snapshot, backup और clone वास्तव में क्या हैं

VPS snapshot आपके सर्वर की एक disk image है, जिसे आपका provider अपने infrastructure पर आपके account के भीतर रखता है। Backup आपके डेटा की एक स्वतंत्र प्रति (copy) है जिसे आप कहीं और restore कर सकते हैं, जिसके लिए आपको उस provider की सहायता की आवश्यकता नहीं होती जिसने मूल डेटा रखा था। Clone एक snapshot से deploy किया गया नया instance है, इसलिए यह मूल सर्वर की सटीक प्रति के रूप में शुरू होता है, जिसमें उसकी identity भी शामिल होती है।

ये अलग-अलग समस्याओं का समाधान करते हैं। Snapshot एक खराब upgrade को कुछ ही मिनटों में वापस (roll back) कर देता है, लेकिन यह account बंद होने की स्थिति में कोई मदद नहीं करता। Backup तब भी सुरक्षित रहता है जब provider सेवा बंद कर दे, और इसे restore करने में अधिक समय लगता है क्योंकि आपको पहले मशीन को फिर से बनाना पड़ता है। Clone आपको एक ही चरण में दूसरा चलता हुआ सर्वर देता है, और यह आपको ऐसी दो मशीनें भी देता है जो खुद को एक ही मशीन मानती हैं।

VPS snapshot बैकअप क्यों नहीं है

समस्या image की गुणवत्ता नहीं, बल्कि failure domain है। Snapshot आपके provider के storage platform पर स्थित होता है, आमतौर पर उसी region में जहाँ से वह सर्वर आया है, और हमेशा उसी account के भीतर। एक ही घटना सर्वर और उसके snapshot दोनों को नष्ट कर सकती है।

  • account suspend हो जाता है, payment विफल हो जाती है, या कोई login credentials चुरा लेता है।
  • कोई व्यक्ति या script जिसे API access प्राप्त है, instance को delete कर देता है। कई providers पर, instance delete करने से उसके snapshots भी delete हो जाते हैं। कुछ भी मानने से पहले अपने provider के documented व्यवहार को पढ़ें।
  • region में कोई बड़ी समस्या आती है और उसमें मौजूद सब कुछ एक साथ unreachable हो जाता है।
  • सर्वर पर root के रूप में चल रहा कोई process /root में छोड़े गए provider API token को ढूंढ लेता है, और disk को छूने से पहले ही snapshots को हटा देता है।

बैकअप वह copy है जो इन चारों स्थितियों में सुरक्षित रहती है। इसकी परीक्षा एक ही प्रश्न है: यदि आज दोपहर आपका provider account अस्तित्व में न रहे, तो आप क्या restore कर पाएंगे, और उसे कहाँ restore करेंगे? जो भी इस प्रश्न पर विफल हो जाए, वह केवल एक rollback tool है। Snapshot लेना जारी रखें, क्योंकि कुछ भी इससे तेज restore नहीं होता। फिर एक दूसरी copy ऐसे storage पर रखें जिसे आपका provider नियंत्रित न करता हो।

पुराना नियम अभी भी लागू होता है: data की तीन copies, दो प्रकार के storage पर, जिनमें से एक platform से बाहर हो। एक provider snapshot और साथ में अलग infrastructure पर restic backup repository इसे दो हिस्सों में पूरा करते हैं।

चलते हुए डेटाबेस का स्नैपशॉट लेने पर वह खराब क्यों हो सकता है

प्रोवाइडर स्नैपशॉट ब्लॉक डिवाइस की एक निश्चित समय की कॉपी बनाता है। यह आपके एप्लिकेशन को पहले रुकने के लिए नहीं कहता है, और यह पेज कैश (page cache) में मौजूद किसी भी डेटा को नहीं देख सकता है। इसलिए, यह इमेज अधिक से अधिक 'क्रैश-कंसिस्टेंट' (crash-consistent) होती है। यह बिल्कुल वैसा ही दिखता है जैसे कि बिजली का तार अचानक खींच लेने पर डिस्क की स्थिति होती है।

अधिकांश स्टैक इसे संभाल लेते हैं। ext4 और XFS माउंट होने पर अपने जर्नल को रीप्ले (replay) करते हैं, जिससे फाइलसिस्टम चालू हो जाता है। PostgreSQL स्टार्टअप पर अपने राइट-अहेड लॉग (write-ahead log) को रीप्ले करता है, और लॉग में यह जानकारी होती है:

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

InnoDB भी ऐसा ही करता है और स्टार्टअप के दौरान अपनी क्रैश रिकवरी लाइनें प्रिंट करता है। वह रिकवरी डेटाबेस के डिजाइन के अनुसार ही काम करती है, इसलिए शांत PostgreSQL या MySQL का सिंगल-वॉल्यूम स्नैपशॉट आमतौर पर ठीक से रिस्टोर हो जाता है।

ऐसी स्थितियाँ जहाँ क्रैश-कंसिस्टेंट होना पर्याप्त नहीं है, वे वास्तविक हैं और नुकसान पहुँचा सकती हैं। यदि आपका डेटा दो वॉल्यूम में फैला है, तो रूट डिस्क और अलग डेटा डिस्क का स्नैपशॉट अलग-अलग समय पर लिया जाता है। इस कारण डेटा फाइलें और लॉग डायरेक्टरी एक-दूसरे से मेल नहीं खाते और रिकवरी के पास रीप्ले करने के लिए कुछ भी सही नहीं होता। कोई भी फाइल जिसे एप्लिकेशन fsync को कॉल किए बिना लिखता है, जैसे कि आधा प्राप्त हुआ अपलोड या क्यू फाइल (queue file), वह ट्रंकेटेड (truncated) होकर वापस आ सकती है। एप्लिकेशन जो कुछ भी मेमोरी में रखता है और टाइमर पर फ्लश करता है, वह इमेज में मौजूद नहीं होता है।

इसलिए स्नैपशॉट लेने से पहले डिस्क पर एक डंप लिखें। तब इमेज में एक ऐसी फाइल होगी जिसके बारे में आप जानते हैं कि वह आंतरिक रूप से सुसंगत (internally consistent) है, चाहे लाइव डेटा फाइलें किसी भी स्थिति में हों।

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 टेबल्स का एक सुसंगत डंप देता है, क्योंकि डंप एक 'रिपीटेबल-रीड' (repeatable-read) ट्रांजेक्शन के भीतर चलता है। यह MyISAM टेबल्स को कवर नहीं करता है, जिन्हें लॉक या सर्वर को रोकने की आवश्यकता होती है। भरोसा करने से पहले जांच लें कि डंप खाली या ट्रंकेटेड तो नहीं है: पूर्ण mysqldump पर tail -n 1 /var/backups/mysql-$(date +%F).sql एक Dump completed टिप्पणी के साथ समाप्त होता है।

यदि आपके पास एक अलग डेटा वॉल्यूम है, तो आप इसे उन कुछ सेकंड के लिए फ्रीज कर सकते हैं जिनकी स्नैपशॉट को आवश्यकता होती है:

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

केवल डेटा वॉल्यूम को ही फ्रीज करें। कभी भी / को फ्रीज न करें। एक फ्रीज किया हुआ रूट फाइलसिस्टम बॉक्स पर हर राइट ऑपरेशन को ब्लॉक कर देता है, जिसमें वह शेल भी शामिल है जिसका उपयोग आप अनफ्रीज कमांड टाइप करने के लिए करेंगे। इससे आप खुद को ही लॉक कर लेंगे और आपको हार्ड रिसेट का इंतजार करना पड़ेगा।

ऑफसाइट हिस्सा: restic या Borg

स्नैपशॉट बैकअप का तेज़ हिस्सा है। ऑफसाइट कॉपी वह हिस्सा है जो आपके प्रोवाइडर के विफल होने पर भी सुरक्षित रहता है। restic एक अच्छा डिफ़ॉल्ट विकल्प है क्योंकि यह डेटा को डुप्लीकेट होने से रोकता है (deduplicate), क्लाइंट-साइड एन्क्रिप्ट करता है, और S3-compatible ऑब्जेक्ट स्टोरेज, SFTP या किसी साधारण डायरेक्टरी में डेटा लिख सकता है। यहाँ ऑफसाइट टारगेट के रूप में स्टोरेज VPS का उपयोग करना अच्छा रहता है, क्योंकि बैकअप रिपॉजिटरी को IOPS के बजाय अधिक क्षमता (capacity) की आवश्यकता होती है।

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 रिपॉजिटरी को इसके बिना नहीं खोला जा सकता और इसे रिकवर करने का कोई रास्ता नहीं है। यदि पासवर्ड की एकमात्र कॉपी उसी सर्वर पर थी जिसे आपने अभी खो दिया है, तो बैकअप केवल एन्क्रिप्टेड शोर (encrypted noise) बनकर रह जाएगा।

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 की तुलना में बताए गए हैं।

cloned VPS को production में लाने से पहले क्या ठीक करें

Clone एक सटीक प्रतिलिपि होती है। यही इसकी खूबी है और यही समस्या भी। जो चीजें मूल सर्वर को विशिष्ट बनाती हैं, वे सब इसमें भी आ जाती हैं, और डुप्लिकेट होने पर टकराव होता है।

SSH host keys को फिर से जनरेट करें। Clone में मूल सर्वर की /etc/ssh/ssh_host_* फाइलें होती हैं, इसलिए दो सर्वर एक ही host identity प्रस्तुत करते हैं। जो कोई भी एक सर्वर को नियंत्रित करता है, वह उस key को स्वीकार करने वाले किसी भी client के सामने दूसरे सर्वर का रूप धारण कर सकता है। SSH कोई चेतावनी नहीं देता, क्योंकि key वही है जिसकी client अपेक्षा कर रहा था।

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 daemon द्वारा अपेक्षित हर प्रकार की नई key लिखता है। अंतिम command से प्राप्त fingerprint मूल सर्वर से अलग होना चाहिए। आपका वर्तमान session restart के बाद भी बना रहता है, क्योंकि sshd को restart करने से स्थापित connections बंद नहीं होते। इसे clone से किसी के भी connect होने से पहले करें। यदि आप इसे बाद के लिए छोड़ते हैं, तो जिस भी client ने पहले से ही पुरानी key पर भरोसा किया है, उसे WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! मिलेगा और उसे पहले ssh-keygen -R <host> चलाना होगा।

Machine ID को reset करें। /etc/machine-id एक विशिष्ट पहचानकर्ता है जिसे systemd पहली बार boot होने पर एक बार जनरेट करता है, और clone इसे विरासत में प्राप्त कर लेता है।

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 को अगले boot पर नया मान जनरेट करने के लिए कहता है, इसीलिए आप फाइल को delete करने के बजाय truncate करते हैं। डुप्लिकेट होने पर दो चीजें खराब होती हैं। जिन images में DHCP द्वारा address मिलता है, उनमें systemd-networkd डिफ़ॉल्ट रूप से machine ID से ही DHCP client identifier प्राप्त करता है। इसलिए दोनों clones एक ही client के रूप में lease मांगते हैं और सर्वर उन्हें एक ही address दे देता है। साथ ही, journald हर entry पर machine ID की मुहर लगाता है, इसलिए एक केंद्रीय log collector दोनों सर्वरों को एक ही मशीन के रूप में दर्ज करता है। Reboot के बाद cat /etc/machine-id चलाएं और पुष्टि करें कि मान बदल गया है।

Hostname बदलें।

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

hostnamectl /etc/hostname में लिखता है और नाम को तुरंत लागू करता है। यह /etc/hosts को नहीं छूता, इसलिए 127.0.1.1 लाइन को तदनुसार edit करें। यदि आप ऐसा नहीं करते हैं, तो नया नाम कहीं भी resolve नहीं होगा, और हर sudo call failed lookup पर रुक जाएगी और sudo: unable to resolve host web-02: Name or service not known प्रिंट करेगी।

Image में मौजूद हर credential को rotate करें। Clone में मूल सर्वर के secrets होते हैं, और अब दो मशीनें मूल सर्वर की तरह काम कर सकती हैं। SSH authorized_keys फाइलों, provider और DNS API tokens, application .env फाइलों, database passwords, TLS private keys, monitoring enrolment tokens, और restic repository password को बदलें। यह command उनमें से अधिकांश को ढूंढ लेगी:

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

यदि clone एक test copy है जो कभी traffic serve नहीं करेगी, तो rotate करने के बजाय उन्हें revoke करें। एक staging box जिसमें live production API token हो, वह खराब patching वाला एक production box ही है।

उन jobs को बंद करें जो अब दो बार चल रही हैं। एक ही crontab चलाने वाले दो सर्वर एक ही मिनट में एक ही external system को hit करते हैं।

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

restic का उदाहरण देना जरूरी है, क्योंकि यह केवल error देने के बजाय आपके retention को खराब करता है। restic हर snapshot को host name के साथ tag करता है, और restic forget --keep-daily 7 अपनी policy प्रति host लागू करता है। एक ही host name रिपोर्ट करने वाली दो मशीनों को एक ही host माना जाता है, इसलिए सात "daily" snapshots clone से आ सकते हैं जबकि मूल सर्वर के snapshots हटा दिए जाते हैं। पहला backup चलने से पहले hostname ठीक करें, या clone पर timer को रोक दें। certbot का मामला सरल है: एक ही नाम को renew करने वाले दो सर्वर certificate authority की duplicate certificate rate limit को hit करते हैं, और बाद वाला run बहुत अधिक certificates जारी होने की error के साथ fail हो जाता है। जिस clone का domain अभी भी मूल सर्वर की ओर point कर रहा है, वह वैसे भी HTTP challenge पास नहीं कर सकता, इसलिए वहां renewal को disable कर दें।

Monitoring agent को संभालें। अधिकांश agents hostname या install के समय लिखी गई ID फाइल से पहचान करते हैं, इसलिए एक ही host के रूप में रिपोर्ट करने वाले दो agents अपने metrics को एक ही series में मिला देते हैं। CPU graphs ऐसे मान दिखाते हैं जो किसी एक मशीन ने पैदा नहीं किए होते, और alerts बार-बार बजते हैं। Clone पर agent को रोकें और हटा दें, या अपने vendor की documented प्रक्रिया का उपयोग करके इसे नए hostname के तहत फिर से enrol करें।

मूल सर्वर के address के लिए network configuration की जाँच करें। यदि image में netplan में static address है, तो clone एक ऐसा IP claim करता है जो दूसरी मशीन का है।

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

यदि यह clone एक template बनने वाला है, तो cloud-init state को clear करें।

sudo cloud-init clean --logs

यह /var/lib/cloud के तहत cloud-init की state को हटा देता है, जिससे अगला boot फिर से first-boot modules चलाता है, जिसमें SSH host keys को जनरेट करना भी शामिल है यदि वे मौजूद न हों। कुछ versions machine ID को reset करने के लिए flag भी देते हैं। कहीं और से मिली flag सूची पर भरोसा करने के बजाय यह देखने के लिए कि आपकी image क्या support करती है, अपनी image पर cloud-init clean --help चलाएं।

कब किसका उपयोग करें

जोखिम भरे अपग्रेड को रोल बैक करना: स्नैपशॉट लें। बदलाव करने से कुछ मिनट पहले स्नैपशॉट लें, अपग्रेड चलाएं, और यदि कुछ गलत हो जाए तो इमेज को रिस्टोर करें। रिस्टोर करने से स्नैपशॉट के बाद के सभी राइट्स हट जाते हैं, इसलिए लाइव ट्रैफिक वाले सर्वर पर पहले डेटाबेस का डंप लें और यह स्पष्ट रखें कि आप कितना डेटा खो देंगे। ऐसे do-release-upgrade के लिए जिसे आप दस मिनट के लिए ऑफलाइन कर सकते हैं, स्नैपशॉट ही पूरी योजना है।

बड़े प्लान पर माइग्रेट करना: क्लोन डिप्लॉय करें। स्नैपशॉट से बड़े प्लान पर क्लोन बनाएं, ऊपर दी गई पहचान सूची (identity list) पर काम करें, और ट्रैफिक मूव करने से पहले इसे इसके अपने IP पर टेस्ट करें। कटओवर को तेज करने के लिए DNS TTL को एक दिन पहले कम कर दें, और जब तक नया बॉक्स वास्तविक ट्रैफिक न संभाल ले, तब तक मूल सर्वर को चालू रखें। पहले यह पुष्टि करें कि क्या बड़ा प्लान वास्तव में आपके वर्कलोड के लिए तेज है, इसके लिए दोनों सर्वरों पर समान बेंचमार्क विधि का उपयोग करें, क्योंकि अधिक व्यस्त हार्डवेयर पर अधिक vCPU हमेशा अपग्रेड नहीं होते हैं।

टेम्पलेट बनाना: एक साफ मशीन का स्नैपशॉट लें। एक सर्वर इंस्टॉल और हार्डन करें, फिर इमेज लेने से पहले हर अद्वितीय चीज़ को हटा दें। कोई host keys नहीं, एक खाली machine ID, कोई व्यक्तिगत authorized_keys नहीं, कोई क्रेडेंशियल्स नहीं, और cloud-init साफ किया हुआ। उसका स्नैपशॉट लें। इससे डिप्लॉय किया गया प्रत्येक इंस्टेंस पहली बूट पर अपनी पहचान खुद बनाता है, इसलिए ऊपर दी गई चेकलिस्ट अब चेकलिस्ट नहीं रहती। इसे नए VPS पर शुरुआती दस मिनट के मानक कार्यों के साथ जोड़ें ताकि टेम्पलेट में वह काम पहले से शामिल हो जिसे आप अन्यथा बार-बार दोहराते।

FAQ

क्या VPS snapshot एक backup है?

नहीं, क्योंकि यह उसी सर्वर के साथ failure domain साझा करता है जिससे इसे लिया गया है। Snapshot आपके provider के storage पर, आपके account में, आमतौर पर उसी region में रहता है। Account suspension, चोरी हुई API key, या गलती से instance delete होने पर सर्वर और उसके snapshots एक ही बार में हट सकते हैं। कई providers पर instance delete करने से उसके snapshots भी design के अनुसार delete हो जाते हैं। Snapshot आपके पास उपलब्ध सबसे तेज़ rollback है, इसलिए इन्हें लेते रहें, और एक दूसरी encrypted copy ऐसी infrastructure पर रखें जिसे आपका provider control न करता हो।

क्या snapshot लेने से पहले मुझे अपना database रोकना होगा?

हमेशा नहीं, लेकिन आपको यह स्वीकार करना होगा कि आपको क्या मिलता है। Provider snapshot crash-consistent होता है, जिसका अर्थ है कि image वैसी ही दिखती है जैसी बिजली कटने के बाद disk दिखती। PostgreSQL और InnoDB start होने पर इससे recover हो जाते हैं, और PostgreSQL ऐसा करते समय database system was not properly shut down; automatic recovery in progress log करता है। जब आपका data दो अलग-अलग volumes पर फैला हो जिन्हें अलग-अलग समय पर snapshot किया गया हो, या जब कोई application fsync के बिना write करती हो, तो recovery की गारंटी नहीं होती। पहले disk पर pg_dumpall या mysqldump --single-transaction लिखें, ताकि image में एक ऐसी file हो जिसके बारे में आप जानते हों कि वह consistent है।

दो cloned servers एक ही IP address के लिए क्यों लड़ते हैं?

क्योंकि वे /etc/machine-id साझा करते हैं। DHCP का उपयोग करने वाली images पर, systemd-networkd डिफ़ॉल्ट रूप से machine ID से अपना DHCP client identifier बनाता है। इसलिए दोनों clones एक ही client के रूप में lease मांगते हैं और DHCP server दोनों को एक ही address offer करता है। /etc/machine-id को zero bytes पर truncate करें, /var/lib/dbus/machine-id को हटाएँ, इसे वापस /etc/machine-id पर symlink करें, और reboot करें ताकि systemd एक नया value generate करे। दूसरा सामान्य कारण /etc/netplan/ में लिखा static address है, जिसे clone ने ज्यों का त्यों copy कर लिया है; ip -br addr के साथ जाँचें।

यह जाँचने का सबसे तेज़ तरीका क्या है कि clone production में डालने के लिए सुरक्षित है?

Original के मुकाबले चार चीजों की तुलना करें। दोनों पर ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub चलाएँ और पुष्टि करें कि fingerprints अलग हैं। दोनों पर cat /etc/machine-id चलाएँ और पुष्टि करें कि values अलग हैं। hostnamectl status चलाएँ और पुष्टि करें कि नाम नया है और resolve होता है, ताकि sudo चेतावनी न दे। फिर systemctl list-timers --all चलाएँ और साझा system से बात करने वाले हर timer को रोक दें, जैसे कि backups, certificate renewal, या monitoring agent, जब तक कि आप यह तय न कर लें कि कौन सी machine उस काम की मालिक है।