ansible_default_ipv4.address IP 地址范围

ansible_default_ipv4.address IP 地址范围

我正在编写的剧本可以在多个环境中运行,并且每个环境都在不同的子网上。

我正在编写一个条件块,只有当主机 IP 处于我在条件中指定的范围内时,该块才会运行

例如

如果ansible_default_ipv4.address位于以下 IP 之一

  • 192.168.4.41 或 192.168.4.42 或 192.168.4.81 或 192.168.4.82
  • 192.168.5.41 或 192.168.5.42 或 192.168.5.81 或 192.168.5.82
  • 192.168.6.41 或 192.168.6.42 或 192.168.6.81 或 192.168.6.82
  • ... 等等

我可以逐个添加每个 IP,但这似乎效率低下、重复性强,并且会使剧本冗长。有没有办法在条件中添加范围?

此外,如果可能的话,我如何强制仅在 GroupA 或 GroupB 或 GroupC 服务器上运行?

答案1

从技术上讲,您的示例中没有 IP 范围,只有不同子网上的离散 IP 地址。

在这种情况下,我会列出我想要使用的前缀和后缀,并使用product筛选映射join筛选

prefixes:
  - 192.168.4
  - 192.168.5
  - 192.168.6
suffixes:
  - 41
  - 42
  - 82
all_ips: "{{ prefixes | product(suffixes) | map('join', '.') }}"

当展开时

    "all_ips": [
        "192.168.4.41",
        "192.168.4.42",
        "192.168.4.82",
        "192.168.5.41",
        "192.168.5.42",
        "192.168.5.82",
        "192.168.6.41",
        "192.168.6.42",
        "192.168.6.82"
    ]

然后您可以在条件中使用该表达式:

when: ansible_default_ipv4.address in all_ips

现在,如果我理解正确的话,您希望特定子网上的每组 IP 都成为特定组的标记。您可以在剧本中动态地执行此操作。下面是一个例子,让您了解全局概念。我只对其进行了部分测试,因此可能会有一些遗留的拼写错误(如果很明显,请告诉我或编辑答案)。请注意,该prefixes变量与上面的变量略有不同,以适应所需的组声明。

- name: gather facts from all host and create dynamic groups
  hosts: all
  
  vars:
    prefixes:
      192.168.4: dyn_group_A
      192.168.5: dyn_group_B
      192.168.6: dyn_group_C

    suffixes:
      - 41
      - 42
      - 82

    all_ips: "{{ prefixes.keys() | product(suffixes) | map('join', '.') }}"

  tasks:
    - name: tag needed targets with a fact
      vars:
        host_prefix: "{{ (ansible_default_ipv4.address | split('.'))[:3] | join('.') }}"
      ansible.builtin.set_fact:
        my_dyn_group: "{{ prefixes[host_prefix] }}"
      when: ansible_default_ipv4.address in all_ips

    - name: create overall and specific dynamic groups from tagged targets
      ansible.builtin.add_host:
        name: "{{ item.inventory_hostname }}"
        groups:
          - dyn_group_overall
          - "{{ item.my_dyn_group }}"
      loop: "{{ ansible_play_hosts | map('extract', hostvars) | selectattr('my_dyn_group', 'defined') }}"
      loop_control:
        label: "{{ item.inventory_hostname }}"

    - name: a single task that would play on all valid hosts and skip on others
      ansible.builtin.debug:
        msg: "I would run on {{ inventory_hostname }}"
      when: inventory_hostname in groups['dyn_group_overall']

    - name: a single task that would run only on group B hosts and skip on others
      ansible.builtin.debug:
        msg: "I would run on {{ inventory_hostname }}"
      when: inventory_hostname in groups['dyn_group_B']

# Note that limiting a task by condition to a group
# in a wider targeted play as above is usually not a good practice.
# It is much more efficient on most occasion to target
# the needed group in a specific play

- name: tasks to be played on all matched hosts
  hosts: dyn_group_overall
  # Facts are already gathered above so skip it
  gather_facts: false

  tasks:
    - ansible.builtin.debug:
        msg: This will only play on targeted host

- name: tasks to be played on hosts in group C
  hosts: dyn_group_C
  gather_facts: false

  tasks:
    - ansible.builtin.debug:
        msg: This will only play on hosts in group C

相关内容