在ansible中处理无法访问的主机

Handle unreachable host in ansible

我正在写一个剧本,作为它的最后一个任务,将各种“摘要”写入本地主机上的文件。

这是 yaml:

---
- name: Summary
  hosts: all
  tasks:
    - name: Register Ip Addr
      command: "hostname -i"
      register: ip_addr

    - name: Write to file on localhost
      shell: |
          echo {{ ip_addr.stdout }} >> ./summary.txt
      delegate_to: localhost

  post_tasks:
    - name: Post Task
      shell:
        cat ./summary.txt
      register: cat_out
      delegate_to: localhost
      run_once: True

    - name: Output cat out
      debug:
        msg: "{{ cat_out.stdout }}"
      delegate_to: localhost
      run_once: True

这是我用于清单的主机文件。

[control]
ubuntu-c

[centos]
centos[1:3]

[ubuntu]
ubuntu[1:3]

[linux:children]
centos
ubuntu

当我 运行 它时,我得到了这个 ...

ansible@ubuntu-c:~/summary$ ansible-playbook -i hosts  summary.yaml 

PLAY [Summary] ******************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************
ok: [ubuntu1]
ok: [centos1]
ok: [centos2]
ok: [centos3]
ok: [ubuntu2]
ok: [ubuntu3]
fatal: [ubuntu-c]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ansible@ubuntu-c: Permission denied (publickey,password).", "unreachable": true}

TASK [Register Hostname] ********************************************************************************************************************
changed: [ubuntu2]
changed: [ubuntu1]
changed: [centos1]
changed: [centos2]
changed: [centos3]
changed: [ubuntu3]

TASK [Write to file on localhost] ***********************************************************************************************************
changed: [centos1 -> localhost]
changed: [centos2 -> localhost]
changed: [centos3 -> localhost]
changed: [ubuntu1 -> localhost]
changed: [ubuntu2 -> localhost]
changed: [ubuntu3 -> localhost]

TASK [Post Task] ****************************************************************************************************************************
changed: [centos1 -> localhost]

TASK [Output cat out] ***********************************************************************************************************************
ok: [centos1 -> localhost] => {
    "msg": "172.20.0.6\n172.20.0.5\n172.20.0.7\n172.20.0.8\n172.20.0.3\n172.20.0.4"
}

PLAY RECAP **********************************************************************************************************************************
centos1                    : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos2                    : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos3                    : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu-c                   : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu1                    : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu2                    : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu3                    : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

ansible@ubuntu-c:~/summary$ cat summary.txt 
172.20.0.6
172.20.0.5
172.20.0.7
172.20.0.8
172.20.0.3
172.20.0.4

我希望能够在输出中说明无法访问的主机 ubuntu-c,以便 summary.txt 看起来像这样:

ansible@ubuntu-c:~/summary$ cat summary.txt 
172.20.0.6
172.20.0.5
172.20.0.7
ubuntu-c (unreachable)
172.20.0.8
172.20.0.3
172.20.0.4

更新:根据 Jack 的建议,我现在有了这本剧本:

ansible@ubuntu-c:~/summary$ cat summary.yaml
---
- name: Summary
  hosts: all
  # gather_facts: False
  tasks:

    - name: Register Hostname
      command: "hostname -i"
      register: echo_hostname
      ignore_unreachable: True
      ignore_errors: True

  post_tasks:

    - name: Show template 
      pause:
        seconds: 1
        prompt: | 
          {% for host in vars['ansible_play_hosts_all'] %}
            "{{ host }}"{% if not loop.last %},{% endif %}
            {% if hostvars[host]['echo_hostname'] is defined %}
              {{ hostvars[host]['echo_hostname']['stdout'] }}
            {% else %}
               "{{ host }} unreachable."
            {% endif %}
          {% endfor %}
          "-------------"
          "end of file"
      delegate_to: localhost
      run_once: True

当我运行剧本...

ansible@ubuntu-c:~/summary$ ansible-playbook -i hosts  summary.yaml 
...

PLAY [Summary] ******************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************
ok: [ubuntu1]
ok: [centos1]
ok: [centos2]
ok: [centos3]
ok: [ubuntu2]
ok: [ubuntu3]
fatal: [ubuntu-c]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ansible@ubuntu-c: Permission denied (publickey,password).", "unreachable": true}

TASK [Register Hostname] ********************************************************************************************************************
changed: [ubuntu2]
changed: [ubuntu1]
changed: [centos2]
changed: [centos1]
changed: [centos3]
changed: [ubuntu3]

TASK [Show template] ************************************************************************************************************************
Pausing for 1 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
[Show template]
  "ubuntu-c",       "ubuntu-c unreachable."
    "centos1",      172.20.0.6
    "centos2",      172.20.0.8
    "centos3",      172.20.0.5
    "ubuntu1",      172.20.0.7
    "ubuntu2",      172.20.0.3
    "ubuntu3"      172.20.0.4
  "-------------"
"end of file"
:
ok: [centos1 -> localhost]

PLAY RECAP **********************************************************************************************************************************
centos1                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu-c                   : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu1                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

我刚刚完成了这样一个剧本。我先做了一个连接测试,但忽略了无法访问的主机:

- name: ping hosts
  ping:
  register: connection_test
  ignore_errors: yes
  ignore_unreachable: yes

然后我使用 Jinja 模板创建一个包含连接信息的文件:

- name: Create start notification
  template:
    src: start_notification.j2
    dest: "{{ role_path }}/files/start_notification.html"
    mode: 0644
    backup: yes
  run_once: yes
  delegate_to: localhost
  become: no

然后我把那些主机从游戏中移除:

- name: Remove failed and unreachable hosts from play_hosts
  meta: end_host
  when: connection_test.unreachable is defined or connection_test.rc != 0

您的模板将遍历 play_hosts,其中包括无法访问的模板,检查 connection_test 的值,并相应地报告。

编辑:示例 Jinja2 模板:

{% for target in play_hosts %}
{% if hostvars[target].connection_test.unreachable is defined %}
  {% set test_result = "UNREACHABLE: " + hostvars[target].connection_test.msg %}
{% else %}
  {% set test_result = "CONNECTION TEST SUCCEEDED" %}
{% endif %}
        <TR>
                <TD nowrap>{{ target }}</TD>
                <TD>{{ test_result }}</TD>
        </TR>
{% endfor %}