Ansible कहता है शुरू हो गया, पर WireGuard अब भी पुरानी कॉन्फ़िग से चल रहा है
state: started पहले से चल रही यूनिट को छेड़ता नहीं, इसलिए फिर से लिखी गई wg0.conf कभी लागू नहीं होती। बदलाव के लिए handler जोड़ें और फिर लाइव डिवाइस की फ़ाइल से तुलना करें।
playbook का रन हरे रंग में खत्म होता है, WireGuard यूनिट सक्रिय है, handshake काम करता है, और नया peer फिर भी कहीं नहीं पहुँचता। सर्वर को कल की कॉन्फ़िग पर चलते देखना और playbook को सफलता बताते देखना खास तरह की झुंझलाहट है, क्योंकि आउटपुट में कुछ भी गलत नहीं है। Ansible ने ठीक वही किया जो कहा गया था: उसने सुनिश्चित किया कि यूनिट शुरू हो, और यूनिट पहले से शुरू थी। फिर से लिखी गई कॉन्फ़िग फ़ाइल लागू करना अलग काम है, और वह तभी होता है जब कुछ सेवा से कहे कि उसे दोबारा पढ़े।
देखें कि दूसरा रन वास्तव में क्या बताता है
बदली हुई कॉन्फ़िग के साथ playbook दो बार चलाएँ और सारांश की तुलना करें। दूसरे रन में यूनिट कार्य ok दिखना चाहिए, changed नहीं, क्योंकि पहले से चल रही सेवा को डिज़ाइन से ही अछूता छोड़ा जाता है। यही सही ढंग से काम करती idempotence है, और यही कारण है कि नई फ़ाइल कभी kernel तक नहीं पहुँचती।
diff आउटपुट के साथ जाँच रन जोड़ें ताकि दिखे कि कौन-से कार्य किसी चीज़ को छुएँगे।
ansible-playbook -i inventory site.yml --check --diff
systemctl show wg-quick@wg0 -p ActiveEnterTimestamp -p NRestarts
stat -c '%y %n' /etc/wireguard/wg0.confतीन टाइमस्टैम्प एक भी लॉग पंक्ति पढ़ने से पहले कहानी बता देते हैं। अगर कॉन्फ़िग फ़ाइल उस क्षण से नई है जब यूनिट सक्रिय हुई, तो चल रहा इंटरफ़ेस पुरानी फ़ाइल से बना है, और आगे के सभी लक्षण वहीं से आते हैं।
यह Ansible की खराबी नहीं है। यही व्यवहार हर उस कॉन्फ़िगरेशन प्रबंधन उपकरण में दिखता है जो «सुनिश्चित करो कि यह चल रहा है» को «सुनिश्चित करो कि यह यही चला रहा है» से अलग करता है। यह अंतर तब तक नुकताचीनी लगता है जब तक यह आपकी एक दोपहर न ले ले।
शुरू होना एक स्थिति है, पुनःलोड नहीं
state: started यूनिट के बारे में एक शर्त बताता है। यह वादा नहीं करता कि सेवा अपने इनपुट दोबारा पढ़ेगी, और यह नहीं जान सकता कि जो फ़ाइल उसने कभी खोली नहीं वह बदल गई है। wg-quick परिनियोजन में इनपुट में इंटरफ़ेस कॉन्फ़िग, पते, रूट, DNS प्रविष्टियाँ और कोई भी post-up हुक शामिल होते हैं।
इसलिए अद्यतन फ़ाइल में नया peer, अलग पता या बदला हुआ रूटिंग निर्देश हो सकता है जबकि लाइव इंटरफ़ेस पुराना सेट ही परोसता रहता है। handshake फिर भी सफल होता है क्योंकि लोड की गई कुंजियाँ और एंडपॉइंट अब भी मान्य हैं। यही विफलता को देखना कठिन बनाता है, और इसीलिए लोग टाइमस्टैम्प जाँचने से पहले एक घंटा DNS के पीछे भागते हैं।
मॉड्यूल के दो और विकल्पों को अक्सर समाधान समझा जाता है। daemon_reload systemd से यूनिट फ़ाइलें दोबारा पढ़वाता है, जो WireGuard कॉन्फ़िग फ़ाइल के लिए अप्रासंगिक है। state: reloaded यूनिट से उसकी रीलोड क्रिया चलाने को कहता है, और वह आपकी ज़रूरत पूरी करती है या नहीं यह पूरी तरह यूनिट पर निर्भर है। इनमें से कोई भी यह जानने का विकल्प नहीं है कि चल रही प्रक्रिया ने वास्तव में कौन-से इनपुट पढ़े।
फ़ाइल स्थापित करें, फिर handler को सूचित करें
idempotence बनाए रखते हुए बदलाव लागू करने का तरीका सामान्य है: फ़ाइल लिखने वाला कार्य handler को सूचित करता है, और handler तभी चलता है जब फ़ाइल वास्तव में बदली हो। बिना संपादन के दूसरा रन कुछ नहीं करता, और आप यही चाहते हैं।
- name: write the interface configuration
ansible.builtin.template:
src: wg0.conf.j2
dest: /etc/wireguard/wg0.conf
owner: root
mode: "0600"
notify: apply wg0
- name: ensure the interface unit is enabled
ansible.builtin.systemd_service:
name: wg-quick@wg0
enabled: true
state: started
- name: apply wg0
listen: apply wg0
ansible.builtin.systemd_service:
name: wg-quick@wg0
state: restartedhandler प्ले के अंत में चलते हैं, उन कार्यों के बाद जिन्होंने उन्हें सूचित किया, इसलिए उसी प्ले का बाद वाला कार्य अब भी पुराना इंटरफ़ेस देख सकता है। अगर क्रम महत्वपूर्ण है, तो नई कॉन्फ़िग पर निर्भर कार्य से पहले meta: flush_handlers से handler स्पष्ट रूप से खाली करें।
restart का उपयोग करें, reload का नहीं, जब तक यूनिट की रीलोड क्रिया सत्यापित न कर लें। अपस्ट्रीम wg-quick यूनिट एक का समर्थन करती है और WireGuard कॉन्फ़िग सिंक करती है, पर पते, रूट, DNS या हुक की सेटिंग दोबारा नहीं चलाती। इसलिए रूट निर्देश जोड़ने के बाद reload सफल दिखता है और कुछ नहीं बदलता।
लाइव डिवाइस की फ़ाइल से तुलना करें
इस वर्ग की गलतियाँ बंद करने वाली जाँच kernel के पास जो है और फ़ाइल जो कहती है, उनकी तुलना है। दो कमांड तुलनीय आउटपुट देते हैं, और अंतर ही विचलन है।
sudo wg showconf wg0
sudo wg-quick strip wg0
sudo diff <(sudo wg showconf wg0) <(sudo wg-quick strip wg0)wg showconf निजी कुंजी सहित लाइव डिवाइस छापता है, इसलिए उस आउटपुट को रहस्य मानें और टिकट में चिपकाएँ नहीं। wg-quick strip केवल wg-quick-विशिष्ट कुंजियाँ हटाकर फ़ाइल छापता है, और इसीलिए दोनों की तुलना हो सकती है।
peer सूची में अंतर का मतलब है कि फ़ाइल कभी लागू नहीं हुई। केवल उन कुंजियों या एंडपॉइंट में अंतर जिनके बदलने की अपेक्षा थी, का मतलब है कि किसी ने उसे आंशिक रूप से लागू किया। कोई अंतर न होने का मतलब है कि कॉन्फ़िग वर्तमान है और गड़बड़ी कहीं और है, जो अपने आप में उपयोगी परिणाम है।
पुनःआरंभ की कीमत जानबूझकर चुकाएँ
इंटरफ़ेस पुनःआरंभ करने से टनल टूटती है, और अगर वह टनल आपका प्रशासनिक सत्र ले जा रही है, तो पुनःआरंभ उसी सत्र को समाप्त कर देता है जिसने इसे माँगा था। handler को बदलाव-विंडो के पीछे रखें, या playbook ऐसे प्रबंधन पथ से चलाएँ जो इंटरफ़ेस के पुनःआरंभ पर निर्भर न हो।
यही कीमत लोगों को reload की ओर धकेलती है। यह उचित सहज ज्ञान है, और तब सही बन जाता है जब आप जानते हैं कि reload वास्तव में कौन-से बदलाव लागू करता है। अपस्ट्रीम wg-quick यूनिट पर peer और कुंजी बदलावों के लिए यह पर्याप्त है; पतों, रूटिंग और हुक के लिए नहीं। इसे एक बार साफ कर लेना बदलाव-विंडो में खोजने से सस्ता है।
systemd_service मॉड्यूल का दस्तावेज़ started, restarted और reloaded के बीच का अंतर समझाता है, और हरे सारांश से अनुमान लगाने के बजाय एक बार पढ़ना बेहतर है। इस पूरी चर्चा की जड़ वही एक अंतर है।