Cloned VPS में duplicate machine-id कैसे ठीक करें
Cloned VPS में /etc/machine-id समान होने से DHCP lease में संघर्ष हो सकता है। इसे सुरक्षित रूप से regenerate करने और golden image के लिए truncate करने की पूरी प्रक्रिया यहाँ जानें।
/etc/machine-id क्या है, और इसका डुप्लीकेट होना क्यों मायने रखता है
एक cloned VPS उसी /etc/machine-id के साथ बूट होता है जो उस सर्वर का था जिससे उसे clone किया गया था, और यह मान केवल एक ही installation का होना चाहिए। इसका समाधान चार commands हैं: फाइल को खाली करें, यदि D-Bus की कॉपी एक वास्तविक फाइल है तो उसे हटा दें, regenerate करें, और reboot करें। reboot वह चरण है जिसे लोग छोड़ देते हैं, और यही वह चरण है जिससे बदलाव प्रभावी होता है।
/etc/machine-id में एक newline-terminated, lowercase, 32-character वाली hexadecimal string होती है। डिकोड करने पर, यह 16-byte (128-bit) का मान है। machine-id(5) manual page इसे गोपनीय बताता है और कहता है कि इसे नेटवर्क पर expose नहीं किया जाना चाहिए, क्योंकि जो भी इसे पढ़ता है वह बाद में आपकी मशीन को फिर से पहचान सकता है। इसे सिस्टम इंस्टॉल होने पर एक बार लिखा जाता है, और उसके बाद कोई भी चीज इसे बदलती नहीं है।
यहाँ तीन identifiers के बीच भ्रम होता है, इसलिए उन्हें अलग करना उचित है। hostname एक label है जिसे आप चुनते हैं और किसी भी समय बदल सकते हैं। /sys/class/dmi/id/product_uuid में DMI (desktop management interface) product UUID हाइपरवाइजर से आता है और इसे केवल root ही पढ़ सकता है। machine ID तीसरा identifier है: ऑपरेटिंग सिस्टम इसे generate करता है, और बॉक्स पर मौजूद हर user इसे पढ़ सकता है।
मशीन ID को वास्तव में कौन पढ़ता है
DHCP client identifier. यह सबसे बड़ी समस्या है। systemd.network(5) में ClientIdentifier= को [DHCPv4] सेक्शन के अंतर्गत डिफ़ॉल्ट रूप से duid पर सेट किया गया है, जो IAID और DUID (DHCP unique identifier) से बना एक RFC 4361 क्लाइंट ID भेजता है। networkd.conf(5) डिफ़ॉल्ट DUID प्रकार को vendor के रूप में प्रलेखित करता है, जहाँ DUID मान को वेंडर आइडेंटिफ़ायर (systemd) के रूप में 43793 का उपयोग करके और मशीन ID की हैश की गई सामग्री से उत्पन्न किया जाता है। DHCPv6 भी इसी DUID का उपयोग करता है। एक ही मशीन ID वाले दो क्लोन का हैश एक ही DUID बनाता है, और यदि वे एक ही इंटरफ़ेस नाम रखते हैं, तो वे बाइट-आइडेंटिकल क्लाइंट आइडेंटिफ़ायर भेजते हैं। इसके बाद DHCP सर्वर दो के बजाय एक ही क्लाइंट देखता है और दोनों मशीनों को एक ही लीज (lease) प्रदान करता है। इसका लक्षण यह है कि IP एड्रेस दो सर्वरों के बीच घूमता रहता है, या जब भी दूसरा सर्वर रिन्यू करता है, तो पहला सर्वर अपना एड्रेस खो देता है।
journald. जर्नल फाइलें /var/log/journal/<machine-id>/ में रहती हैं। डायरेक्टरी का नाम सीधे ID के आधार पर रखा जाता है। यदि आप दो क्लोन के जर्नल एक ही कलेक्टर पर भेजते हैं, तो वे एक ही डायरेक्टरी में जमा हो जाते हैं और एक ही होस्ट के रूप में पढ़े जाते हैं।
D-Bus. /var/lib/dbus/machine-id वह स्थान है जहाँ से इस फाइल फॉर्मेट की शुरुआत हुई थी। Debian और Ubuntu पर यह /etc/machine-id के लिए एक सिम्बॉलिक लिंक (symlink) है। कुछ सिस्टम पर यह एक अलग वास्तविक फाइल होती है जिसमें इसकी अपनी कॉपी होती है, और वह कॉपी नीचे दी गई प्रक्रिया में एक जाल (trap) है।
Per-host agents. मॉनिटरिंग एजेंट, लाइसेंस चेक, इन्वेंट्री टूल और बैकअप क्लाइंट अक्सर मशीन ID को अपने डिफ़ॉल्ट होस्ट आइडेंटिफ़ायर के रूप में उपयोग करते हैं, क्योंकि यह स्थिर होता है और इसके लिए किसी कॉन्फ़िगरेशन की आवश्यकता नहीं होती। दो सर्वरों द्वारा एक ही पहचान रिपोर्ट करने का अर्थ है कि मेट्रिक्स की एक ही सीरीज मर्ज हो जाती है, या एक ही लाइसेंस सीट दो मशीनों को कवर करती है। यह जाँचें कि आपका एजेंट अपना होस्ट ID कैसे प्राप्त करता है, बजाय इसके कि आप यह मान लें कि वह होस्टनेम का उपयोग करता है।
यह कैसे पता करें कि आपके पास डुप्लीकेट है
दोनों सर्वर पर इसे चलाएं और आउटपुट की तुलना करें।
cat /etc/machine-id
ls -l /var/lib/dbus/machine-id
sudo cat /sys/class/dmi/id/product_uuidcat /etc/machine-id
दो लाइव सर्वर पर समान machine IDs होने का मतलब है कि एक को दूसरे से clone किया गया है। यदि आप एक ही कमांड पसंद करते हैं, तो hostnamectl अपने Machine ID: लाइन पर समान मान प्रिंट करता है।
ls -l का परिणाम अगला कदम तय करता है। एक symlink इस तरह दिखता है:
lrwxrwxrwx 1 root root 15 Aug 21 09:12 /var/lib/dbus/machine-id -> /etc/machine-idls -l /etc/machine-id
-rw-r--r-- से शुरू होने वाली लाइन का मतलब है कि यह एक वास्तविक फाइल है जिसमें पुरानी ID की अपनी कॉपी मौजूद है। आपको इसे हटाना होगा, क्योंकि systemd-machine-id-setup कुछ भी करने से पहले इसे पढ़ता है।
product UUID भी मायने रखता है। systemd-machine-id-setup(1) रैंडम जनरेशन पर वापस जाने से पहले KVM UUID का उपयोग करता है, इसलिए यदि आपके प्रदाता ने दोनों clones को समान SMBIOS (system management BIOS) UUID दिया है, तो regenerate करने पर आपको दो बार समान machine ID मिलेगी। दोनों बॉक्स पर अलग-अलग product UUID होने का मतलब है कि आपको यहाँ चिंता करने की कोई आवश्यकता नहीं है।
Cloned VPS पर machine ID को रीजेनरेट करना
क्रम महत्वपूर्ण है। systemd-machine-id-setup(1) के अनुसार, यदि सिस्टम के लिए पहले से ही एक वैध D-Bus machine ID कॉन्फ़िगर है, तो वह D-Bus machine ID कॉपी हो जाती है और /etc/machine-id को इनिशियलाइज़ करने के लिए उपयोग की जाती है। यदि आप एक वास्तविक /var/lib/dbus/machine-id को वहीं रहने देते हैं, तो आप उसी मान को फिर से जनरेट कर लेंगे जिसे आप हटाना चाह रहे थे।
sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id # only if ls -l showed a real file
sudo systemd-machine-id-setup
sudo ln -sf /etc/machine-id /var/lib/dbus/machine-id
cat /etc/machine-idसबसे पहले फ़ाइल को ट्रंकेट करना आवश्यक है, क्योंकि यह टूल केवल तभी कार्य करता है जब फ़ाइल गायब हो या खाली हो; यदि फ़ाइल में पहले से ही एक वैध ID मौजूद है, तो यह कुछ नहीं करता है। systemd-machine-id-setup स्टैंडर्ड एरर पर रिपोर्ट करता है कि उसने क्या किया है। KVM VPS पर आप आमतौर पर यह देखेंगे:
Initializing machine ID from KVM UUID.Initializing machine ID from random generator. वह संदेश है जो तब आता है जब कोई हाइपरवाइज़र UUID उपलब्ध नहीं होता है। दोनों में से कोई भी परिणाम ठीक है, बशर्ते cat /etc/machine-id अब दूसरे सर्वर से अलग मान प्रिंट करे।
सिमलिंक (symlink) D-Bus और systemd को एक ही मान पर रखता है। यदि आप एक अलग वास्तविक फ़ाइल पसंद करते हैं, तो इसके बजाय sudo dbus-uuidgen --ensure चलाएँ: यह फ़ाइल के मौजूद न होने पर एक नए UUID के साथ फ़ाइल बनाता है। यदि dbus इंस्टॉल नहीं है, तो /var/lib/dbus डायरेक्टरी बिल्कुल नहीं होगी, ln, No such file or directory के साथ विफल हो जाएगा, और आप उन दोनों लाइनों को छोड़ सकते हैं।
उसके बाद रीबूट करें।
sudo rebootरीबूट क्यों अनिवार्य है
हर वह process जिसने पुराना मान (value) पहले ही पढ़ लिया है, वह अभी भी उसी का उपयोग कर रही है। sd_id128_get_machine() calling process के भीतर ID को cache कर लेता है, इसलिए एक चलता हुआ daemon कभी यह नहीं देख पाता कि फ़ाइल बदल गई है। journald ने पहले ही /var/log/journal/<old-id>/system.journal को open कर रखा है और उसमें डेटा जोड़ना जारी रखता है। systemd-networkd ने शुरू होते समय अपना DUID निर्धारित कर लिया था और वह हर renewal पर पुराना client identifier भेजना जारी रखता है, जो आमतौर पर वही विफलता है जिसे आप ठीक करने का प्रयास कर रहे हैं। D-Bus ने भी स्टार्टअप पर ही अपना ID पढ़ लिया था। आप सेवाओं को एक-एक करके restart कर सकते हैं, लेकिन आप किसी एक को छोड़ देंगे, और PID 1 भी पुराना मान ही रखे हुए है।
रीबूट के बाद, दोनों हिस्सों की जाँच करें:
cat /etc/machine-id
ls /var/log/journal//var/log/journal/ में अब नई ID के नाम से एक दूसरा directory है, और नए entries वहीं जाते हैं। सामान्य journalctl केवल वर्तमान मशीन की directory को पढ़ता है, इसलिए आपका pre-clone इतिहास डिफ़ॉल्ट दृश्य से गायब हो जाता है। यह अभी भी डिस्क पर मौजूद है: journalctl --merge हर journal directory को पढ़ता है, जिसमें पुरानी वाली भी शामिल है। जब आप सुनिश्चित हो जाएं कि आपको उन logs की आवश्यकता नहीं है, तो पुरानी directory को हटा दें।
यही कारण है कि आप इस प्रक्रिया का पूर्वाभ्यास (rehearse) container में नहीं कर सकते। एक container host kernel को साझा करता है और कभी भी अपना PID 1 बूट नहीं करता है, और रीबूट ही इस पूरी प्रक्रिया का मुख्य उद्देश्य है। इसका परीक्षण उसी तरह करें जैसे यह production में होता है: एक VM को clone करें, commands चलाएं, रीबूट करें, और फिर source मशीन के साथ ID की तुलना करें।
Clone करने के बाद नहीं, snapshot लेने से पहले truncate करें
एक-एक करके clone को ठीक करना काम करता है। image को ठीक करना बेहतर है, क्योंकि खराब snapshot से restore किया गया हर सर्वर वही मान (value) ले लेता है। template को shut down करने से पहले इसे अपना अंतिम कार्य बनाएँ।
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 shutdown -h nowफाइल को खाली करें। उसे delete न करें। machine-id(5) कई मशीनों पर उपयोग की जाने वाली images के लिए एक खाली फाइल की अनुशंसा करता है, क्योंकि एक खाली फाइल मौजूद होने पर image को read-only मोड में उपयोग करते समय वास्तविक फाइल के ऊपर एक temporary फाइल को bind-mount किया जा सकता है। एक read-only /etc पर, boot के समय generate होने वाली ID उस temporary फाइल में रहती है, और filesystem के writable होने पर systemd-machine-id-setup --commit उसे लिख देता है।
योजना बनाने के लिए एक दुष्प्रभाव: एक unpopulated machine ID अगले boot को first boot के रूप में चिह्नित करती है, इसलिए ConditionFirstBoot=yes ले जाने वाली units उस boot पर चलती हैं और उसके बाद के हर boot पर छोड़ दी जाती हैं। template बनाने से पहले देखें कि आपकी image grep -rl ConditionFirstBoot /usr/lib/systemd/system/ के साथ क्या run करेगी।
एक template और एक snapshot अलग-अलग objects हैं, और यह अंतर तय करता है कि identity copy होगी या नहीं। template एक build artifact है जिसे आप जानबूझकर तैयार करते हैं, जबकि snapshot एक चल रहे सर्वर की point-in-time copy है और यह अपने डेटा के साथ उस सर्वर की identity को भी ले जाता है।
क्लाउड इमेजेस इसे सही तरीके से क्यों करती हैं और आपका स्नैपशॉट क्यों नहीं
डिस्ट्रिब्यूशन क्लाउड इमेजेस को क्लोन करने के लिए बनाया जाता है, इसलिए वे बिना machine ID के आती हैं और पहली बार बूट होने पर यह भर जाती है। cloud-init में इसके लिए एक निर्धारित चरण मौजूद है। cloud-init clean --machine-id, systemd सिस्टम पर /etc/machine-id को uninitialized स्ट्रिंग पर सेट करता है, और cloud-init CLI संदर्भ इसे गोल्डन इमेज को क्लोन करते समय सर्वोत्तम अभ्यास (best practice) मानता है, ताकि उस इमेज के अगले बूट पर एक अद्वितीय machine ID जनरेट हो सके।
आपके द्वारा लिया गया स्नैपशॉट एक अलग स्थिति है। जब आपने स्नैपशॉट पर क्लिक किया था, तब फाइल पहले से ही भरी हुई थी, इसलिए उससे रिस्टोर किए गए प्रत्येक सर्वर में वही एक वैल्यू रहती है, और रिस्टोर प्रक्रिया में इसे हटाने का कोई प्रावधान नहीं होता। यह चलते हुए सर्वर को नए VPS पर ले जाने जैसी ही समस्या है, जहाँ कॉपी बिल्कुल सटीक होती है और identity वह हिस्सा है जिसे आप कॉपी नहीं करना चाहते थे।
क्लोन और क्या-क्या कॉपी करता है
- SSH host keys.
/etc/ssh/ssh_host_*भी कॉपी हो जाता है, इसलिए दोनों सर्वर क्लाइंट्स को एक ही फिंगरप्रिंट दिखाते हैं। उन फाइलों को हटा दें औरsudo ssh-keygen -Aचलाएं, या Debian और Ubuntu परsudo dpkg-reconfigure openssh-serverका उपयोग करें। इसके बाद आपके क्लाइंट्स को बदले हुए होस्ट की (host key) के बारे में चेतावनी मिलेगी, जो कि सही व्यवहार है। - होस्टनाम (Hostname). इसे
sudo hostnamectl set-hostname app02के साथ सेट करें, फिर जांचें कि/etc/hostsअभी भी नए नाम को रिजॉल्व करता है या नहीं। - स्टेटिक नेटवर्क कॉन्फ़िगरेशन. स्टेटिक आईपी वाले सर्वर का क्लोन नेटवर्क से जुड़ते ही मूल सर्वर के साथ आईपी टकराव (collision) पैदा करेगा। क्लोन को नेटवर्क से जोड़ने से पहले
/etc/netplan/पढ़ें। - घड़ी (Clock). रिस्टोर किया गया स्नैपशॉट उसी समय से शुरू होता है जो स्नैपशॉट लेते समय था। रिस्टोर किए गए VPS पर समय का बड़ा अंतर TLS सर्टिफिकेट वैलिडेशन को तोड़ देता है और टाइम सिंक होने तक लॉग के क्रम को अस्त-व्यस्त कर देता है।
क्लोन पर भी नए VPS के लिए पहले दस मिनट की चेकलिस्ट को पूरा करें। क्लोन किया गया सर्वर अपने स्रोत सर्वर के यूजर अकाउंट्स, SSH कीज़, फायरवॉल रूल्स और शेड्यूल किए गए जॉब्स को इनहेरिट कर लेता है, और इनमें से किसी की भी उस काम के लिए समीक्षा नहीं की गई होती जो क्लोन को करना है।
FAQ
क्या /etc/machine-id बदलने के बाद मुझे reboot करना होगा?
हाँ। Processes machine ID को एक बार पढ़कर उसे cache कर लेती हैं, इसलिए नया मान पहले से चल रही किसी भी प्रक्रिया तक नहीं पहुँचता। journald पुराने ID के नाम वाली journal directory में लिखना जारी रखता है, और DHCP client पुराने मान से प्राप्त client identifier भेजना जारी रखता है, जो आमतौर पर इसे बदलने का मुख्य कारण होता है। व्यक्तिगत services को restart करने से उनमें से कुछ ठीक हो जाती हैं, लेकिन PID 1 भी पुराना मान ही रखता है। Reboot करें, फिर cat /etc/machine-id के साथ और दूसरे सर्वर से तुलना करके इसकी पुष्टि करें।
क्या /etc/machine-id और hardware UUID एक ही हैं?
नहीं। /sys/class/dmi/id/product_uuid में DMI product UUID hypervisor से आता है और इसे केवल root ही पढ़ सकता है। Machine ID को operating system द्वारा generate किया जाता है और यह एक साधारण file में रहता है जिसे कोई भी user पढ़ सकता है। इनका संबंध एक दिशा में होता है: KVM guest पर, जब copy करने के लिए कोई D-Bus ID नहीं होती, तो systemd-machine-id-setup hypervisor UUID से एक नई machine ID seed करता है। यदि दो clones का product UUID एक ही है, तो वे एक ही machine ID को फिर से generate करेंगे, इसलिए परिणाम पर भरोसा करने से पहले उस file की भी तुलना करें।
क्या मुझे /etc/machine-id को delete कर देना चाहिए या खाली छोड़ना चाहिए?
Image तैयार करते समय इसे खाली छोड़ दें। machine-id(5) एक खाली file को प्राथमिकता देता है, क्योंकि जब image read-only /etc के साथ चलती है, तो systemd इसके ऊपर एक temporary file को bind-mount कर सकता है। Writable system पर file को delete करना काम करता है और कुछ clone scripts ऐसा ही करती हैं, लेकिन खाली file एक सुरक्षित default है। Cloud-init इसी उद्देश्य के लिए file में uninitialized शब्द लिखता है।
मेरे दो cloned servers को एक ही DHCP address क्यों मिला?
क्योंकि दोनों ने एक ही client identifier भेजा। systemd-networkd DHCPv4 के लिए default रूप से ClientIdentifier=duid का उपयोग करता है, और default DUID /etc/machine-id के hash से बनता है। इसलिए, समान machine IDs उन clones पर समान identifiers उत्पन्न करते हैं जिनके interface names भी समान हैं। DHCP server उस identifier का मिलान करता है, दोनों requests को एक ही client मानता है, और एक ही lease प्रदान करता है। प्रत्येक box को अपनी machine ID दें और दोनों को reboot करें। यदि server अभी भी पुराना address दे रहा है, तो DHCP server पर ही stale lease को clear करें।