Ansible में unreachable hosts को कैसे ignore करें
Ansible में unreachable hosts और failed tasks के बीच का अंतर समझें। ignore_unreachable, serial और max_fail_percentage का सही उपयोग करके अपनी playbooks को बेहतर बनाएँ।
Unreachable host एक failed task नहीं है
Ansible में unreachable hosts को ignore करने के लिए आप ignore_unreachable: true सेट करते हैं, और यह switch काम करता है। महत्वपूर्ण यह जानना है कि इसका उपयोग कब करना है, क्योंकि Ansible दो अलग-अलग समस्याओं को दो अलग-अलग तरीकों से संभालता है। एक task जो host पर चला और error return किया, वह failure है। एक host जिससे Ansible connect ही नहीं हो सका, वह unreachable है। ignore_errors केवल पहले मामले को कवर करता है। ignore_unreachable केवल दूसरे मामले को कवर करता है।
Play recap में अंतर यहाँ दिया गया है।
PLAY RECAP *********************************************************************
web1 : ok=7 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web2 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0Ansible ने web1 से connect किया और सात tasks चलाए। web2 में unreachable=1 और failed=0 दिखाई देते हैं, जिसका अर्थ है कि उस पर कुछ भी नहीं चला। Ansible को connection कभी नहीं मिला, इसलिए इसने host को play से हटा दिया और बाकी काम जारी रखा। यदि वह play security update install कर रहा था, तो आपके servers में से एक में वह update नहीं है।
होस्ट के अनरीचेबल (unreachable) होने के कारण
अनरीचेबल का अर्थ है कि किसी भी मॉड्यूल के होस्ट तक पहुँचने से पहले ही कनेक्शन विफल हो गया। यहाँ पढ़ने के लिए कोई मॉड्यूल आउटपुट नहीं होता, केवल एक कनेक्शन त्रुटि होती है, और यह उस पहले टास्क पर दिखाई देती है जो मशीन से संपर्क करता है।
fatal: [web2]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 203.0.113.20 port 22: Connection refused", "unreachable": true}msg फ़ील्ड में वास्तविक कारण होता है। आप इनका सामना करेंगे:
Connection refused: TCP कनेक्शन अस्वीकार कर दिया गया, जिसका अर्थ है कि उस पोर्ट पर कुछ भी लिसन (listen) नहीं कर रहा है। sshd बंद है, या SSH को किसी अन्य पोर्ट पर ले जाया गया है और आपकी इन्वेंट्री अभी भी 22 दिखा रही है।Connection timed out: किसी ने भी उत्तर नहीं दिया। कोई फ़ायरवॉल पैकेट ड्रॉप कर रहा है, या सर्वर बंद है। प्रत्येक प्रयास में पूरा कनेक्शन टाइमआउट लगता है, जो डिफ़ॉल्ट रूप से 10 सेकंड है।Host key verification failed.:~/.ssh/known_hostsमें मौजूद की (key) उस की से मेल नहीं खाती जो सर्वर ने प्रस्तुत की है। एक रीबिल्ट VPS अपना IP एड्रेस बरकरार रखता है और उसे एक नई होस्ट की मिलती है, इसलिए रीइंस्टॉल के बाद यह अपेक्षित है, लेकिन किसी अन्य समय पर यह गंभीर है।Permission denied (publickey): SSH ने उत्तर दिया और आपकी की को अस्वीकार कर दिया। पोर्ट ठीक है, इसलिए यह प्रमाणीकरण (authentication) की समस्या है, आमतौर पर गलतansible_userया ऐसी की जो लोड नहीं की गई है।Timeout (12s) waiting for privilege escalation prompt: कनेक्शन काम कर गया लेकिनbecomeविफल रहा। sudo एक ऐसे पासवर्ड की प्रतीक्षा कर रहा है जो कभी नहीं मिलता।
पायथन इंटरप्रेटर का न होना वह कारण है जिसकी लोग इस सूची में अपेक्षा करते हैं, लेकिन यह इसमें नहीं आता है। SSH कनेक्ट हो जाता है, इसलिए होस्ट रीचेबल है। मॉड्यूल के पास फिर चलाने के लिए कुछ नहीं होता:
fatal: [db1]: FAILED! => {"changed": false, "module_stdout": "/bin/sh: 1: /usr/bin/python3: not found\r\n", "msg": "The module failed to execute correctly, you probably need to set the interpreter", "rc": 127}वह लाइन FAILED! कहती है और रीकैप इसे failed के अंतर्गत गिनता है, इसलिए ignore_unreachable इसे कभी नहीं छुएगा। उस होस्ट के लिए ansible_python_interpreter सेट करें, या उस पर python3 इंस्टॉल करें।
Play में unreachable hosts को कैसे अनदेखा करें
Task स्तर पर, keyword module के बगल में स्थित होता है:
- name: Read the package list, and do not stop if the host is down
ansible.builtin.command: dpkg -l
register: packages
changed_when: false
ignore_unreachable: truePlay स्तर पर यह play के हर task के लिए default सेट करता है, और एक single task इसे वापस बदल सकता है:
- name: Opportunistic fleet maintenance
hosts: all
ignore_unreachable: true
tasks:
- name: This runs, cannot connect, and the play carries on
ansible.builtin.ping:
- name: This one still ends the play for a host that is down
ansible.builtin.ping:
ignore_unreachable: falseअंदरूनी तौर पर क्या बदलता है, यह जानना उपयोगी है। ignore_unreachable सेट होने पर, host को play से हटाया नहीं जाता है, इसलिए बाद का हर task फिर से connect करने की कोशिश करता है और उसी तरह विफल हो जाता है। इनमें से प्रत्येक प्रयास connection timeout तक प्रतीक्षा करता है, जो कि 10 सेकंड है जब तक कि आप ansible.cfg में timeout को न बदलें। एक मृत सर्वर के खिलाफ बीस task वाला play रनटाइम में लगभग 200 सेकंड जोड़ देता है और log में बीस लाल लाइनें बना देता है।
इसलिए एक बार जाँचें, फिर उस host को सफाई से रोक दें:
- name: Opportunistic fleet maintenance
hosts: all
gather_facts: false
tasks:
- name: Check that the host answers before doing any work
ansible.builtin.ping:
register: reachable
ignore_unreachable: true
- name: End the play for this host if it never answered
ansible.builtin.meta: end_host
when: reachable.unreachable | default(false)
- name: Gather facts now that the connection is known good
ansible.builtin.setup:
- name: Refresh the package index
ansible.builtin.apt:
update_cache: true
become: trueयह हर task के बजाय प्रति मृत host एक connection प्रयास है। Ansible 2.8 में जोड़ा गया end_host, वर्तमान host के लिए play को बिना failed मार्क किए समाप्त कर देता है। unreachable key registered result पर केवल तभी मौजूद होती है जब connection विफल हो जाता है, इसलिए default(false) उस हर host पर condition को वैध रखता है जिसने उत्तर दिया। Fact gathering को play स्तर पर बंद रखा जाता है क्योंकि implicit Gathering Facts task अन्यथा वह task होगा जो टूटे हुए connection का सामना करेगा, और आप चाहते हैं कि वह आपका अपना ping हो।
ignore_unreachable एक play keyword और एक task keyword है। इसे playbook में वहां रखें जहां कोई पाठक इसे देख सके, न कि role के अंदर, क्योंकि यह तय करता है कि किन hosts को रन के दौरान छोड़ा जा सकता है। Playbooks और roles के बीच का विभाजन इस बात को कवर करता है कि इस तरह की सेटिंग का स्वामित्व किस layer के पास होना चाहिए।
ignore_errors का उपयोग यहाँ गलत क्यों है
Ansible documentation इस सीमा के बारे में स्पष्ट है। ignore_errors "यह केवल तब काम करता है जब task चल सके और 'failed' का मान लौटाए। यह Ansible को undefined variable errors, connection failures, execution issues (उदाहरण के लिए, missing packages), या syntax errors को अनदेखा करने के लिए बाध्य नहीं करता है।"
Connection failure कभी भी failed: true के साथ task result नहीं बनता है। यह एक अलग flag के रूप में आता है, और Ansible सबसे पहले उस flag पर कार्य करता है: host unreachable list में चला जाता है और play से बाहर हो जाता है। एक play के सभी बारह tasks पर ignore_errors: true लगा दें, तब भी एक closed SSH port वाला host पहले task पर ही रुक जाएगा। यह इस क्षेत्र में सबसे आम भ्रम है, और अपने पुराने playbooks में इसे grep करना उचित है, विशेष रूप से उन्हें जो VPS पर पहली playbook लिखना सीखने के दौरान लिखी गई थीं।
दबाने से पहले डिबग करें
दबाव (suppression) जो स्थायी हो जाता है, उसी के कारण फ्लीट में विचलन (drift) आता है, क्योंकि जिस होस्ट तक कोई नहीं पहुँच सकता, उसे कोई पैच भी नहीं कर रहा होता है। पहले इस क्रम का पालन करें। यहाँ दी गई प्रत्येक कमांड केवल डेटा पढ़ती है।
ansible web2 -i inventory.ini -m ansible.builtin.ping -oएक होस्ट पर एक मॉड्यूल चलाता है और एक लाइन प्रिंट करता है।- उसी कमांड में
-vvvvजोड़ें। Ansible उस पूर्ण ssh कमांड को प्रिंट करता है जिसे वह बनाता है, जिसमें टारगेट यूजर, पोर्ट, प्राइवेट की और उसके द्वारा पास किए गए विकल्प शामिल होते हैं। - उस ssh कमांड को स्वयं
-vके साथ चलाएं। यदि सामान्य ssh अंदर नहीं जा सकता है, तो समस्या Ansible के नीचे है और कोई भी playbook कीवर्ड इसे ठीक नहीं करेगा। msgस्ट्रिंग को पढ़ें और ऊपर दी गई सूची से उसका मिलान करें।Connection refusedऔरConnection timed outदो अलग-अलग स्थानों की ओर इशारा करते हैं, एक SSH सर्विस की ओर और दूसरा नेटवर्क पाथ की ओर।Host key verification failed.के लिए, देखें कि आपनेssh-keygen -F web2.example.comके साथ क्या स्टोर किया है। यदि सर्वर को फिर से बनाया गया था, तो पुराने एंट्री कोssh-keygen -R web2.example.comके साथ हटा दें और प्रोवाइडर कंसोल से जांचने के बाद नई की को स्वीकार करें।ansible.cfgमेंhost_key_checking = Falseसेट करने से एरर तो हट जाता है, लेकिन वह चेक भी हट जाता है जो आपको यह बताता कि उस एड्रेस पर अब कोई अलग मशीन जवाब दे रही है।Permission denied (publickey)के लिए, पुष्टि करें कि Ansible के अनुसार उसे क्या उपयोग करना चाहिए।ansible-inventory -i inventory.ini --host web2प्रभावी वेरिएबल्स को प्रिंट करता है, जिसमेंansible_userऔरansible_portशामिल हैं।- यदि SSH काम करता है लेकिन मॉड्यूल नहीं, तो
ansible web2 -m ansible.builtin.raw -a 'command -v python3 || echo none'के साथ इंटरप्रेटर की जांच करें।rawमॉड्यूल शेल के माध्यम से एक कमांड चलाता है और उसे टारगेट पर python की आवश्यकता नहीं होती है।
केवल इसके बाद ही होस्ट को अनदेखा करना एक आदत के बजाय एक निर्णय बनता है।
रीकैप में unreachable को अलग से गिना जाता है और CI अक्सर इसे छोड़ देता है
ansible-playbook सफलता पर 0, कम से कम एक होस्ट विफल होने पर 2, और कम से कम एक होस्ट के unreachable होने पर 4 का exit code देता है। ये दोनों मान सोर्स में बिट फ्लैग हैं, इसलिए यदि किसी रन में एक होस्ट विफल होता है और एक unreachable रहता है, तो यह 6 का exit code देता है। ansible कमांड भी समान कोड लौटाती है। अगस्त 2026 में इनकी जांच ansible-core सोर्स के आधार पर की गई थी।
अब ignore_unreachable: true सेट करें और उसी मृत होस्ट के विरुद्ध सात टास्क वाला प्ले चलाएं:
PLAY RECAP *********************************************************************
web1 : ok=7 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web2 : ok=7 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=7web2 में unreachable=0 और सात टास्क ok रिपोर्ट होते हैं, और रन 0 के साथ समाप्त होता है। जब यह कीवर्ड सेट होता है, तो Ansible उस होस्ट के लिए dark काउंटर के बजाय ok और ignored काउंटरों को बढ़ाता है, जो कि वही काउंटर है जो unreachable कॉलम को भरता है। लाल रंग की UNREACHABLE! लाइनें अभी भी प्रिंट होती हैं, इसलिए लॉग सटीक रहता है जबकि रीकैप और exit code भ्रामक होते हैं।
एक CI जॉब जो केवल $? की जांच करती है, वह इस रन को सफल मान लेगी, और इसके सारांश में कहीं भी यह नहीं दिखेगा कि किसी मशीन तक कभी पहुंचा ही नहीं गया। रीचेबिलिटी चेक को प्ले से पहले एक अलग स्टेप बनाएं:
ansible all -i inventory.ini -m ansible.builtin.ping -oयह प्रति होस्ट एक लाइन प्रिंट करता है और यदि कोई होस्ट unreachable है तो 4 का exit code देता है। इससे पाइपलाइन को विफल होने के लिए एक आधार मिलता है और लॉग में होस्ट के नाम भी मिल जाते हैं। ping को टारगेट पर एक कार्यशील Python इंटरप्रेटर की आवश्यकता होती है, इसलिए यह केवल कनेक्शन से अधिक चीजों की पुष्टि करता है, जो आमतौर पर आप चाहते भी हैं। इसके बाद playbook को ignore_unreachable के साथ चलाएं ताकि जो होस्ट चालू हैं, उनमें बदलाव लागू हो सकें।
any_errors_fatal और max_fail_percentage का बैच पर प्रभाव
ये दो कीवर्ड तय करते हैं कि फ्लीट के किसी हिस्से में समस्या आने पर क्या होगा, और ये unreachable hosts के साथ अलग-अलग व्यवहार करते हैं।
any_errors_fatal: true unreachable host पर प्रतिक्रिया देता है। Ansible बैच के बाकी hosts पर वर्तमान task पूरा करता है, और फिर उस बैच के हर host के लिए play को रोक देता है। इसका उपयोग तब करें जब रन केवल तभी सार्थक हो जब वह पूरी तरह सफल हो, जैसे कि coordinated schema change के मामले में।
max_fail_percentage: 30 unreachable host पर प्रतिक्रिया नहीं देता है। यह चेक failed hosts की संख्या को बैच के आकार से विभाजित करता है, और unreachable hosts को एक अलग सूची में रखा जाता है, इसलिए वे उस संख्या को कभी प्रभावित नहीं करते। दस hosts में से चार unreachable होने पर भी max_fail_percentage: 10 के तहत रन जारी रहता है, जबकि दो hosts के task fail होने पर play रुक जाता है। डॉक्यूमेंटेशन एक और सावधानी जोड़ता है: "निर्धारित प्रतिशत से अधिक होना चाहिए, उसके बराबर नहीं।" serial: 4 के साथ, चार में से दो failures के बाद रुकने का मतलब है 50 के बजाय 49 लिखना।
एक स्थिति ऐसी है जहाँ unreachable hosts अपने आप रन को रोक देते हैं। यदि बैच का हर host failed या unreachable है, तो Ansible के पास काम करने के लिए कुछ नहीं बचता और वह NO MORE HOSTS LEFT के साथ play को समाप्त कर देता है।
serial: पूरे फ्लीट में बदलाव लागू करना
- name: Rolling nginx config update
hosts: webservers
serial: 2
max_fail_percentage: 25
tasks:
- name: Deploy the site config
ansible.builtin.template:
src: site.conf.j2
dest: /etc/nginx/conf.d/site.conf
owner: root
mode: "0644"
become: true
notify: Reload nginx
handlers:
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
become: trueserial: 2 पूरे play को दो hosts पर चलाता है, उसे पूरा करता है, और फिर अगले दो पर शुरू करता है। serial: "25%" समूह के आकार के साथ स्केल होता है। एक सूची, serial: [1, 5, 10], canary आकार है: पहले एक host, फिर पाँच, फिर दस, और बचे हुए सभी hosts अंतिम बैच आकार के अनुसार चलते हैं। max_fail_percentage को प्रति बैच मापा जाता है, इसलिए ये दोनों एक साथ काम करते हैं। यदि पहली मशीन विफल होती है, तो चालीस मशीनों के खराब होने से पहले ही run रुक जाता है। यही वह चीज है जो एक कंट्रोल मशीन से Linux सर्वर के फ्लीट को मैनेज करना को एक ही command से सुरक्षित बनाती है।
अनपहुँच योग्य (unreachable) hosts को कब अनदेखा करें और कब नहीं
अवसरवादी (opportunistic) कार्यों के लिए उन्हें अनदेखा करें। यदि कोई host down है, तो उसे छोड़ देने से fact collection run या hourly drift check में कोई नुकसान नहीं होता, क्योंकि अगली बार वह host मिल जाएगा। वहाँ ignore_unreachable: true play level सही विकल्प है, जिसे ping step के साथ जोड़ने से छूटे हुए नाम ऐसी जगह दिखाई देंगे जहाँ कोई व्यक्ति उन्हें पढ़ सके।
Security patch run के लिए उन्हें कभी अनदेखा न करें। इस run का महत्व इस गारंटी में है कि हर host पर fix लागू हो चुका है। unreachable स्थिति को दबाने (suppress) से "एक सर्वर अभी भी असुरक्षित है" जैसी चेतावनी छिप जाती है और परिणाम 'clean green' दिखाई देने लगता है। जो host दो सप्ताह से unreachable है, सबसे अधिक संभावना यही है कि वह सुरक्षा के मामले में काफी पीछे है। उस run को exit 4 के साथ समाप्त होने दें और किसी व्यक्ति को इसकी जाँच करने दें।
दोनों स्थितियों में एक नियम लागू होता है: प्रक्रिया को रुकने से रोकें, लेकिन रिकॉर्ड को कभी न छिपाएं। यदि कोई host skip हुआ है, तो recap में, CI log में या monitoring alert में इसका उल्लेख होना चाहिए। Ansible को केवल उन्हीं कुछ सेकंड्स के लिए पता होता है कि host मौजूद है जब उस पर कोई play चल रहा होता है, इसलिए यह जानने के लिए कि कोई सर्वर मंगलवार से down है, यह एक खराब माध्यम है। यह कार्य monitoring का है, और Zabbix install करने वाला एक Ansible playbook एक दोपहर में पूरे fleet का दृश्य प्रदान कर सकता है।
FAQ
Ansible में ignore_errors और ignore_unreachable के बीच क्या अंतर है?
ignore_errors: true उस task पर लागू होता है जो host पर चला और विफल रहा, जैसे कि किसी command का non-zero exit code देना। ignore_unreachable: true उस host पर लागू होता है जिससे Ansible connect नहीं हो सका, जहाँ कोई भी module कभी चला ही नहीं। ये task result के अलग-अलग fields को पढ़ते हैं, और इनमें से कोई भी दूसरे मामले को कवर नहीं करता है। Ansible documentation में कहा गया है कि ignore_errors "Ansible को undefined variable errors, connection failures, execution issues (उदाहरण के लिए, missing packages), या syntax errors को अनदेखा करने के लिए नहीं कहता है", और एक बंद SSH port एक connection failure है।
क्या ignore_unreachable host को play recap से छिपा देता है?
वास्तव में, हाँ। इस keyword के सेट होने पर, Ansible उस host को unreachable के अंतर्गत गिनना बंद कर देता है और उसे प्रति task एक बार ok और ignored के रूप में गिनता है, और फिर run 0 exit code के साथ समाप्त हो जाता है। fatal: [host]: UNREACHABLE! लाइनें अभी भी print होती हैं, इसलिए log सटीक रहता है, भले ही recap और exit code सटीक न हों। ignored column पर नज़र रखें, या ansible all -m ansible.builtin.ping -o को एक अलग step के रूप में चलाएँ ताकि एक unreachable host अभी भी कहीं न कहीं non-zero exit code उत्पन्न करे।
जब कोई host unreachable होता है तो ansible-playbook क्या exit code लौटाता है?
यह 4 लौटाता है। कम से कम एक failed host वाला run 2 लौटाता है, और ये दोनों मान bit flags हैं, इसलिए एक run जिसमें failure और unreachable host दोनों हों, वह 6 लौटाता है। एक सफल run 0 लौटाता है। इन codes की जाँच अगस्त 2026 में ansible-core source के आधार पर की गई थी। ignore_unreachable: true सेट करने से 4 हट जाता है, यही कारण है कि जो pipeline केवल exit code की जाँच करती है, वह एक skipped machine को नहीं देख पाती है।
मैं उस host के लिए play के बाकी हिस्से को कैसे skip करूँ जिसने कभी जवाब नहीं दिया?
पहले task को ansible.builtin.ping बनाएँ जिसमें ignore_unreachable: true और register: reachable हो, फिर उसके बाद when: reachable.unreachable | default(false) condition के तहत ansible.builtin.meta: end_host का उपयोग करें। end_host उस host के लिए play को बिना failed मार्क किए समाप्त कर देता है। play पर gather_facts: false सेट करें ताकि आपका ping वह task हो जो broken connection का सामना करे। इस pattern के बिना dead host play में बना रहता है, और हर बाद वाला task फिर से connection timeout का इंतज़ार करता है।
क्या मुझे security patch run के दौरान unreachable hosts को ignore करना चाहिए?
नहीं। एक patch run इसलिए किया जाता है क्योंकि यह आपको गारंटी देता है कि हर host पर update हो गया है, और unreachable hosts को ignore करने से वह गारंटी एक green recap में बदल जाती है। run को 4 के साथ exit होने दें, उन hosts के नाम पढ़ें जिन्होंने जवाब नहीं दिया, और उन्हें ठीक करें। suppression केवल बार-बार होने वाले opportunistic runs के लिए है जहाँ अगला pass छूटी हुई चीज़ों को पकड़ लेगा।