我可以使用下面的 ansible 剧本列出
unreachable
服务器。
---
- name: "Play 1-Find the details here {{ source_host }} & {{ dest_host }}"
hosts: localhost
any_errors_fatal: True
serial: 1
vars:
source_host: "{{ hostvars[inventory_hostname]['serverlist_input'] }}"
gather_facts: no
tasks:
- add_host:
name: "{{ item | trim }}"
groups: source_node
printback_rec: "{{ hostvars[inventory_hostname]['printback_input'] }}"
with_items:
- "{{ source_host.split(',') }}"
- set_fact:
rec_group_names: 'source_node'
- name: Check unreachable hosts
hosts: "{{ hostvars['localhost']['rec_group_names'] }}"
gather_facts: true
any_errors_fatal: false
tasks:
- name: Print group names
debug:
msg: "GROUP NAME TO BE TESTED: {{ group_names }}"
- name: Perform ping in Template
ping:
- block:
- debug:
var: ansible_play_hosts_all
- debug:
var: ansible_play_hosts
- set_fact:
down: "{{ ansible_play_hosts_all|difference(ansible_play_hosts) }}"
- debug:
var: down
run_once: true
- name: "Display unreachable hosts one at a time {{ startlogstring | default('start:') }}"
debug:
msg: "Unreachable Host: {{ item }}"
loop: "{{ ansible_play_hosts_all | difference(ansible_play_hosts) }}"
run_once: true
- fail:
msg: "Exiting play if target hosts are unreachable"
when: ansible_play_hosts_all != ansible_play_hosts
run_once: true
- name: Play 2- Configure Source nodes
hosts: source_node
gather_facts: false
any_errors_fatal: false
debugger: never
ignore_unreachable: yes
vars:
ansible_ssh_common_args: '-o ConnectTimeout=2'
tasks:
# - name: Detect unreachable hosts
# import_playbook: "{{ playbook_dir }}/generictask_templates/logunreachablehost.yml"
- name: Perform ping
ping:
所需输出:
PLAY [Play 1-Find the details here {{ source_host }} & {{ dest_host }}] ********
TASK [Reset Github logs] *******************************************************
changed: [localhost] => (item=precheck.log)
TASK [add_host] ****************************************************************
ok: [localhost] => (item=remotehost4)
ok: [localhost] => (item=remotehost3)
ok: [localhost] => (item=remotehost2)
ok: [localhost] => (item=remotehost1)
TASK [set_fact] ****************************************************************
ok: [localhost]
PLAY [Check unreachable hosts] *************************************************
TASK [Gathering Facts] *********************************************************
fatal: [remotehost1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname remotehost1: Name or service not known", "unreachable": true}
[WARNING]: Platform sunos on host remotehost3 is using the discovered Python
interpreter at /usr/bin/python3.9, but future installation of another Python
interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.12/reference_appendices/interpreter_discovery.html for more information.
ok: [remotehost3]
[WARNING]: Platform linux on host remotehost4 is using the discovered Python
interpreter at /usr/local/bin/python3.9, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.12/reference_appendices/interpreter_discovery.html for more information.
ok: [remotehost4]
[WARNING]: Platform linux on host remotehost2 is using the discovered Python
interpreter at /usr/local/bin/python3.9, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.12/reference_appendices/interpreter_discovery.html for more information.
ok: [remotehost2]
TASK [Print group names] *******************************************************
ok: [remotehost4] => {
"msg": "GROUP NAME TO BE TESTED: ['source_node']"
}
TASK [Perform ping in Template] ************************************************
ok: [remotehost3]
ok: [remotehost4]
ok: [remotehost2]
TASK [debug] *******************************************************************
ok: [remotehost4] => {
"ansible_play_hosts_all": [
"remotehost4",
"remotehost3",
"remotehost2",
"remotehost1"
]
}
TASK [debug] *******************************************************************
ok: [remotehost4] => {
"ansible_play_hosts": [
"remotehost4",
"remotehost3",
"remotehost2"
]
}
TASK [set_fact] ****************************************************************
ok: [remotehost4]
TASK [debug] *******************************************************************
ok: [remotehost4] => {
"down": [
"remotehost1"
]
}
TASK [Display unreachable hosts one at a time start:] ***************
ok: [remotehost4] => (item=remotehost1) => {
"msg": "Unreachable Host: remotehost1"
}
TASK [fail] ********************************************************************
fatal: [remotehost4]: FAILED! => {"changed": false, "msg": "Exiting play if target hosts are unreachable"}
NO MORE HOSTS LEFT *************************************************************
PLAY RECAP *********************************************************************
remotehost4 : ok=11 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
remotehost2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
remotehost1 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
remotehost3 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这是我的要求。
我希望创建一个可重复使用的模板
include_tasks
或 import_playbook
,我可以将任何 <groups>
传递给 hosts:
,它将帮助我记录该 unreachable
的所有 group_name
服务器。
目的是在其他游戏中重用此模板/剧本来记录
unreachable
服务器。
我尝试了以下方法,但它不起作用并且出现错误:
第 1 步:创建名为“{{ playbook_dir }}/templates/logunreachable.yml”的可重用剧本,并从先前成功运行中复制相同的逻辑,无需任何更改:
cat {{ playbook_dir }}/templates/logunreachable.yml
- name: Check unreachable hosts
hosts: "{{ hostvars['localhost']['rec_group_names'] }}"
gather_facts: true
any_errors_fatal: false
tasks:
- name: Print group names
debug:
msg: "GROUP NAME TO BE TESTED: {{ group_names }}"
run_once: true
- name: Perform ping in Template
ping:
- block:
- debug:
var: ansible_play_hosts_all
- debug:
var: ansible_play_hosts
- set_fact:
down: "{{ ansible_play_hosts_all|difference(ansible_play_hosts) }}"
- debug:
var: down
run_once: true
- name: "Display unreachable hosts one at a time {{ startlogstring | default('are-inject-start:') }}"
debug:
msg: "Unreachable Host: {{ item }}"
loop: "{{ ansible_play_hosts_all | difference(ansible_play_hosts) }}"
run_once: true
- fail:
msg: "Exiting play if target hosts are unreachable"
when: ansible_play_hosts_all != ansible_play_hosts
run_once: true
在主剧本中,我
import
上述剧本并期望与以前类似的输出:
呼叫者剧本:
---
- name: "Play 1-Find the details here {{ source_host }} & {{ dest_host }}"
hosts: localhost
any_errors_fatal: True
serial: 1
vars:
source_host: "{{ hostvars[inventory_hostname]['serverlist_input'] }}"
gather_facts: no
tasks:
- add_host:
name: "{{ item | trim }}"
groups: source_node
printback_rec: "{{ hostvars[inventory_hostname]['printback_input'] }}"
with_items:
- "{{ source_host.split(',') }}"
- set_fact:
rec_group_names: 'source_node'
- name: Play 2- Configure Source nodes
hosts: source_node
gather_facts: false
any_errors_fatal: false
debugger: never
ignore_unreachable: yes
vars:
ansible_ssh_common_args: '-o ConnectTimeout=2'
tasks:
- name: Detect unreachable hosts
import_playbook: "{{ playbook_dir }}/generictask_templates/logunreachablehost.yml"
- name: Perform ping
ping:
但是,输出并不像以前那样:
输出:
PLAY [Play 1-Find the details here {{ source_host }} & {{ dest_host }}] ********
TASK [Reset Github logs] *******************************************************
changed: [localhost] => (item=precheck.log)
TASK [add_host] ****************************************************************
ok: [localhost] => (item=remotehost4)
ok: [localhost] => (item=remotehost3)
ok: [localhost] => (item=remotehost2)
ok: [localhost] => (item=remotehost1)
TASK [set_fact] ****************************************************************
ok: [localhost]
PLAY [Play 2- Configure Source nodes] ******************************************
TASK [Detect unreachable hosts] ************************************************
fatal: [remotehost1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname remotehost1: Name or service not known", "skip_reason": "Host remotehost1 is unreachable", "unreachable": true}
[WARNING]: Platform sunos on host remotehost3 is using the discovered Python
interpreter at /usr/bin/python3.9, but future installation of another Python
interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.12/reference_appendices/interpreter_discovery.html for more information.
fatal: [remotehost3]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3.9"}, "changed": false, "module_stderr": "Shared connection to remotehost3 closed.\\r\\n", "module_stdout": "", "msg": "MODULE FAILURE\\nSee stdout/stderr for the exact error", "rc": 0}
[WARNING]: Platform linux on host remotehost2 is using the discovered Python
interpreter at /usr/local/bin/python3.9, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.12/reference_appendices/interpreter_discovery.html for more information.
fatal: [remotehost2]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/local/bin/python3.9"}, "changed": false, "module_stderr": "Shared connection to remotehost2 closed.\\r\\n", "module_stdout": "", "msg": "MODULE FAILURE\\nSee stdout/stderr for the exact error", "rc": 0}
[WARNING]: Platform linux on host remotehost4 is using the discovered Python
interpreter at /usr/local/bin/python3.9, but future installation of another
Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible-
core/2.12/reference_appendices/interpreter_discovery.html for more information.
fatal: [remotehost4]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/local/bin/python3.9"}, "changed": false, "module_stderr": "Shared connection to remotehost4 closed.\\r\\n", "module_stdout": "", "msg": "MODULE FAILURE\\nSee stdout/stderr for the exact error", "rc": 0}
TASK [Perform ping] ************************************************************
fatal: [remotehost1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: Could not resolve hostname remotehost1: Name or service not known", "skip_reason": "Host remotehost1 is unreachable", "unreachable": true}
PLAY RECAP *********************************************************************
remotehost4 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
remotehost2 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
remotehost1 : ok=0 changed=0 unreachable=2 failed=0 skipped=2 rescued=0 ignored=0
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
remotehost3 : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
您能否建议一个解决方案,让我可以通过
hosts: <groupnamme>
并且工作流程可以帮助列出所有无法访问的主机。
目的是在其他游戏中重用此模板/剧本来记录无法访问的服务器。
ignore_unreachable
关键字,可以自动跳过无法访问的主机并继续执行而不会失败。此外,Ansible 会在所有后续播放中自动跳过它们。无法访问的主机列表将显示在播放回顾中。
考虑以下最小的可重现示例:
# inventory.yaml
---
all:
vars:
ansible_python_interpreter: auto_silent
ansible_connection: local
printback_input: what is this? # this variable is in fact not used
hosts:
localhost:
rec_group_names: source_node
source_node:
hosts:
remotehost1:
ansible_connection: ssh
ansible_host: example.com
remotehost[2:4]:
# playbook.yaml
---
- name: Test with unreachable hosts
gather_facts: false # you can gather facts as well, but this is faster is you don't need them
hosts: all
tasks:
- name: Perform ping
ping:
输出(为了简洁起见,我启用了 YAML 标准输出回调):
Alexanders-Mini:78050414 alexander$ ansible-playbook playbook.yaml -i inventory.yaml
PLAY [Test with unreachable hosts 1] **********************************************************************************************************************************************************************
TASK [Perform ping 1] *************************************************************************************************************************************************************************************
ok: [remotehost2]
ok: [remotehost3]
ok: [remotehost4]
fatal: [remotehost1]: UNREACHABLE! =>
changed: false
msg: 'Failed to connect to the host via ssh: ssh: connect to host example.com port
22: Operation timed out'
unreachable: true
PLAY [Test with unreachable hosts 2] **********************************************************************************************************************************************************************
TASK [Perform ping 2] *************************************************************************************************************************************************************************************
ok: [remotehost3]
ok: [remotehost2]
ok: [remotehost4]
PLAY RECAP ************************************************************************************************************************************************************************************************
remotehost1 : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
remotehost2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
remotehost3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
remotehost4 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
现在,如果您仍然想在单独的 playbook 中将无法访问的主机列为变量,同时临时传递主机列表。实际上,在您当前的实现中存在三个错误阻止了这一点:
hostvars
只是因为 Ansible 不知道应该在哪些主机上运行该游戏;--extra-vars
;localhost
上运行此游戏。所有这些都阻碍了剧本的可重用性。
因此,要解决所有问题,您需要将主机添加到同一剧本中的清单中,但在
localhost
上单独播放,并在 ping
主机上运行 all
(如果未定义该普通变量) 。顺便说一句,您不需要将它们添加两次,因此我正在检查它们是否已存在于库存中。我还添加了控制事实收集的能力:
# detect_and_list_unreachable_hosts.yaml
---
- name: Add the hosts to the inventory if they are missing
hosts: localhost
gather_facts: false
tasks:
- name: Add the list of hosts to the custom group
add_host:
name: "{{ item | trim }}"
groups: "{{ target_group | default ('source_node') }}"
loop: "{{ target_hosts.split(',') }}"
when:
- target_hosts is defined and target_hosts
- groups['source_node'] is defined and item not in item not in groups['source_node'
or item not in groups
- name: List the unreachable hosts
hosts: "{{ test_hosts | default('all') }}"
gather_facts: "{{ gather_facts_on_test_hosts | default('false') }}"
tasks:
- name: Ping the hosts
ping:
- name: Log the ping results
debug:
var: ansible_play_hosts_all | difference(ansible_play_hosts)
此剧本将在任何情况下工作:有或没有额外的变量,有或没有预定义清单,清单中有或没有本地主机,清单中有或没有目标主机。
您还可以添加
failed_when
条件,或者调用 assert
或 fail
模块来在有无法访问的主机时停止执行。
要将其与任何其他剧本一起使用,只需将其添加为第一个剧本即可:
# playbook.yaml
---
- name: Detect the unreachable hosts
import_playbook: detect_and_list_unreachable_hosts.yaml
# subsequent plays go here
如果您不想使用额外的变量,您可以随时将
vars
添加到该导入中:
# playbook.yaml
---
- name: Detect the unreachable hosts
import_playbook: detect_and_list_unreachable_hosts.yaml
vars:
target_hosts: "{{ some_other_hosts }}"
# or simply hardcode:
# target_hosts: remotehost5,remotehost6