【问题标题】:How to use second host in a group when host 1 fails in ansible?当主机1在ansible中失败时如何使用组中的第二台主机?
【发布时间】:2020-11-09 15:36:14
【问题描述】:

我有一个包含 500 多个组的清单,每个组有 2 个主机,1 个是主要的,另一个是次要的。在我的剧本中,我正在做两件事。一是获取无法访问的主机列表,二是在主服务器中执行命令。

我的库存示例:(就像这样,我有 500 多个来自 set1...set500 的组)

[set1]
host1set1 setup=primary
host2set1 setup=secondary
[set1:vars]
setidentifier=set1

我能够收集无法访问的主机列表并在主服务器中执行命令。 现在,我想知道只有当我的主服务器无法访问时,如何在辅助服务器中执行命令。

  - delegate_to: localhost
    command: ping -c1 "{{ hostvars[inventory_hostname].ansible_host|default(inventory_hostname) }}"
    register: ping
    ignore_errors: true
    become: false

  - set_fact:
     available: "{{ ping.rc == 0 }}"

  - lineinfile:
      dest: "/tmp/available.txt"
      line: "{{ hostvars[inventory_hostname]. }} : {{ inventory_hostname }}"
      regexp: "Host: {{ inventory_hostname }}"
      create: true
    delegate_to: localhost
    become: false
    when: "{{ hostvars[inventory_hostname].available }} == False"

  - shell: date
    register: dateout
    when: "setup is search('primary')"

只有当我的主服务器无法访问时,我才需要在辅助服务器中执行shell任务(我提到日期命令仅供参考,我还有其他事情要做。)。

有人可以在这里阐明一下我该怎么做吗?

【问题讨论】:

    标签: ansible yaml devops ansible-2.x


    【解决方案1】:

    仅在组中的单个主机上执行任务 - 尝试使用 run_once: true 执行 ansible 任务,详细参考 cab 可以找到 here

    如果您知道 master 是可访问的,您可以为组中的剩余主机设置一个变量 fact(如 execute_on_secondary = False),并将其用于任务的block 中的 when 条件

    - set_fact:
        execute_on_secondary: False
      delegate_to: "{{ item }}"
      with_items: "{{ play_hosts }}"
      run_once: yes
      when: ## condition for when primary is reachable ##
    
    - block:
        # tasks here
      when: setup == "primary" or execute_on_secondary
    

    下面的方法很简单。在业务关键系统上使用之前对其进行测试。

    - hosts: all
      serial: 2
      tasks:
        - set_fact: ## same as above ##
          run_once: yes
        - block:
            # tasks here
          when: setup == "primary" or execute_on_secondary    
    

    【讨论】:

    • 这只能对一组运行不是吗?如果我一次为所有 500 个组运行此作业(对我的整个库存),这将只在一个组中运行,因为我们正在使用 run_once 对吗?
    • @Rajesh 如果您在 playbook 文件中使用 - hosts: allrun_once 将使该任务仅在 all 组中的单个主机上运行(ansible 不会逐组处理任务,它处理一个名为all 的特殊组,默认情况下包含清单中的所有主机)。为了更清楚地说明这一点,请尝试在 playbook 中使用 debug 模块打印 {{ groups }} 变量值(不要忘记在此处使用 run_once,否则,该变量将被打印 500 次)。
    • @Rajesh 一个简单的 hack 可以工作 - 如果每个 host_group 只有 2 个主机条目(一个主机和一个辅助),您可以在 playbook 中使用 serial: 2 来获得所需的结果。请参阅我上面回答的第二部分。
    【解决方案2】:

    首先 Ping 组。无法访问的主机将被排除在未来的播放之外:

    这是我的库存:

    [groupA]
    AnsibleTower ansible_host=192.168.124.8
    [groupB]
    jaxsat ansible_host=192.168.124.111
    rhel7.5 ansible_host=192.168.124.4
    

    现在,这是没有 ping 的剧本:

    ---
    - hosts: groupB
      gather_facts: no
      connection: ssh
      tasks:
      - name: Run hostname command
        command: /bin/hostname
        register: result
        run_once: yes 
    
      - name: Show result
        debug:
          var: result
        run_once: yes 
    

    因为jaxsat 关闭而失败:

    $ ansible-playbook -i inventory/ test_one_only.yml
    
    PLAY [groupB] **********************************************************************************
    
    TASK [Run hostname command] ********************************************************************
    Tuesday 21 July 2020  13:40:38 -0400 (0:00:00.064)       0:00:00.064 ********** 
    fatal: [jaxsat]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.124.111 port 22: No route to host\r\n", "unreachable": true}
     [WARNING]: Failure using method (v2_runner_on_unreachable) in callback plugin
    (<ansible.plugins.callback.mail.CallbackModule object at 0x7f95688fbf10>): [Errno 111]
    Connection refused
    
    
    NO MORE HOSTS LEFT *****************************************************************************
        to retry, use: --limit @/home/jack/Ansible/TEST/test_one_only.retry
    
    PLAY RECAP *************************************************************************************
    jaxsat                     : ok=0    changed=0    unreachable=1    failed=0   
    
    Tuesday 21 July 2020  13:40:42 -0400 (0:00:03.218)       0:00:03.283 ********** 
    =============================================================================== 
    Run hostname command -------------------------------------------------------------------- 3.22s
    Playbook run took 0 days, 0 hours, 0 minutes, 3 seconds
    

    现在,我添加ping

    ---
    - hosts: groupB
      gather_facts: no
      connection: ssh
      tasks:
      - name: ping all hosts
        ping:
    
      - name: Run hostname command
        command: /bin/hostname
        register: result
        run_once: yes 
    
      - name: Show result
        debug:
          var: result
        run_once: yes 
    

    并且jaxsat 没有在其他任务上尝试过:

    $ ansible-playbook -i inventory/ test_one_only.yml
    
    PLAY [groupB] **********************************************************************************
    
    TASK [ping all hosts] **************************************************************************
    Tuesday 21 July 2020  13:42:12 -0400 (0:00:00.057)       0:00:00.057 ********** 
    ok: [rhel7.5]
    fatal: [jaxsat]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.124.111 port 22: No route to host\r\n", "unreachable": true}
     [WARNING]: Failure using method (v2_runner_on_unreachable) in callback plugin
    (<ansible.plugins.callback.mail.CallbackModule object at 0x7f07f21ad850>): [Errno 111]
    Connection refused
    
    
    TASK [Run hostname command] ********************************************************************
    Tuesday 21 July 2020  13:42:15 -0400 (0:00:03.217)       0:00:03.275 ********** 
    changed: [rhel7.5]
    
    TASK [Show result] *****************************************************************************
    Tuesday 21 July 2020  13:42:15 -0400 (0:00:00.348)       0:00:03.623 ********** 
    ok: [rhel7.5] => {
        "result": {
            "changed": true, 
            "cmd": [
                "/bin/hostname"
            ], 
            "delta": "0:00:00.001530", 
            "end": "2020-07-21 13:42:15.921749", 
            "failed": false, 
            "rc": 0, 
            "start": "2020-07-21 13:42:15.920219", 
            "stderr": "", 
            "stderr_lines": [], 
            "stdout": "localhost.localdomain.localdomain", 
            "stdout_lines": [
                "localhost.localdomain.localdomain"
            ]
        }
    }
        to retry, use: --limit @/home/jack/Ansible/TEST/test_one_only.retry
    
    PLAY RECAP *************************************************************************************
    jaxsat                     : ok=0    changed=0    unreachable=1    failed=0   
    rhel7.5                    : ok=3    changed=1    unreachable=0    failed=0   
    
    Tuesday 21 July 2020  13:42:15 -0400 (0:00:00.037)       0:00:03.661 ********** 
    =============================================================================== 
    ping all hosts -------------------------------------------------------------------------- 3.22s
    Run hostname command -------------------------------------------------------------------- 0.35s
    Show result ----------------------------------------------------------------------------- 0.04s
    Playbook run took 0 days, 0 hours, 0 minutes, 3 seconds
    

    【讨论】:

    • 感谢您的评论。您已在您的剧本中手动指定该剧本在 hostB 上运行。我该怎么做 ?我有 500 多个组,我无法手动将组添加到 playbook 中,对吗?
    • 不是 HOSTB,而是 GROUPB。无论如何,我假设您对不同的组有不同的任务。 (否则,为什么他们在不同的组?)
    • 所有组的任务都相同。但是库存是这样定义的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    相关资源
    最近更新 更多