1 2 3 4 5 作者:李晓辉 微信联系:Lxh_Chat 联系邮箱: 939958092@qq.com
收集和处理⽹络信息概述 在使用 Ansible 自动化配置网络信息时,有很多过滤器和查找插件可以帮你收集和处理网络信息。配合从受管主机收集的事实,它们能派上大用场。
比如,标准模块 ansible.builtin.setup
,会在每个 Play 的开头自动运行,帮你从每台受管主机搜罗各种与网络相关的数据。而其中的 ansible_facts['interfaces']
,实际上是系统里所有网络接口名称的列表。通过这个列表,你可以深入了解系统里每个网络接口的具体信息。
以下是常用的网络相关的facts:
事实名称 描述 ansible_facts[‘dns’][‘nameservers’] 用于由受管主机(包括在 min 子集中)进行名称解析的 DNS 名称服务器。 ansible_facts[‘domain’] 受管主机的域。 ansible_facts[‘all_ipv4_addresses’] 受管主机上配置的所有 IPv4 地址。 ansible_facts[‘all_ipv6_addresses’] 受管主机上配置的所有 IPv6 地址。 ansible_facts[‘fqdn’] 受管主机的完全限定域名(DNS 名称)。 ansible_facts[‘hostname’] 非限定主机名,即 FQDN 中第一个句点之前的字符串。
我们来看一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 --- - name: 收集并显示网络信息 hosts: all gather_facts: yes tasks: - name: 显示受管主机的 IPv4 地址 debug: msg: "所有 IPv4 地址: {{ ansible_facts['all_ipv4_addresses'] }} " - name: 显示受管主机的 IPv6 地址 debug: msg: "所有 IPv6 地址: {{ ansible_facts['all_ipv6_addresses'] }} " - name: 显示 DNS 名称服务器 debug: msg: "DNS 名称服务器: {{ ansible_facts['dns']['nameservers'] }} " - name: 显示主机名 debug: msg: "主机名: {{ ansible_facts['hostname'] }} "
ipaddr 过滤器 ansible.utils.ipaddr
是一个非常强大的过滤器,可用于处理 IP 地址相关的任务,比如验证、转换、比较 IP 地址或子网等等。
要使用 ansible.utils.ipaddr
过滤器,必须安装 netaddr
Python 模块。在 红帽8 以上,可以通过安装 python3-netaddr
软件包来满足此依赖。
查找 IP 地址 如果值是 IP 地址,则过滤器返回 IP 地址。 如果值不是 IP 地址,则过滤器返回 false
1 2 3 4 5 6 7 8 9 10 11 --- - name: 测试 ansible.utils.ipaddr 过滤器 hosts: localhost tasks: - name: 验证一个有效的 IP 地址 debug: msg: "{{ '192.168.1.1' | ansible.utils.ipaddr }} " - name: 验证一个无效的 IP 地址 debug: msg: "{{ 'not_an_ip' | ansible.utils.ipaddr }} "
查找网络掩码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 --- - name: 查找合格的子网掩码 hosts: localhost gather_facts: no vars: netmask_data: - "255.255.255.0" - "255.255.0.0" - "255.0.0.0" - "invalid_netmask" - "255.255.128.0" tasks: - name: 筛选出有效的子网掩码 debug: msg: > 合格的子网掩码是: {{ netmask_data | select('ansible.utils.ipaddr', 'netmask') | list }}
查找主机地址 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 --- - name: Filter host IPs from a list and display them hosts: localhost vars: listips: - 192.168 .1 .1 - 192.168 .1 .0 - 192.168 .1 .255 - 10.0 .0 .1 - 172.16 .0 .1 tasks: - name: Filter host IPs from the list ansible.builtin.set_fact: host_ips: "{{ listips | ansible.utils.ipaddr('host') }} " - name: Display the filtered host IPs ansible.builtin.debug: msg: "Host IPs: {{ host_ips }} "
查找网络范围 过滤掉不是有效⽹络规格的值,必要时将⼦⽹掩码转换为 CIDR 前缀
1 2 3 4 5 6 7 8 9 10 11 - name: Get Network Information Using ansible.utils.ipaddr hosts: localhost gather_facts: no tasks: - name: Define IP address and subnet set_fact: ip_address: "192.168.1.100/24" - name: Extract network information debug: msg: "The network of {{ ip_address }} is {{ ip_address | ansible.utils.ipaddr('net') }} "
运行结果:
1 2 3 4 TASK [Extract network information ] ************** ok: [localhost ] => { "msg": "The network of 192.168.1.100/24 is 192.168.1.0/24" }
判断CIDR位数 ansible.utils.ipaddr('prefix')
过滤器用于获取 IP 地址的 CIDR 前缀长度 (即子网掩码的位数)。例如,192.168.1.100/24
的前缀是 24
,2001:db8::1/64
的前缀是 64
。
IPv4 和 IPv6 都适用 。
prefix
提取 CIDR 的子网掩码位数,例如:
192.168.1.100/24
→ 24
2001:db8::1/64
→ 64
8.8.8.8/32
→ 32
(单个主机)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - name: Get CIDR prefix length using ansible.utils.ipaddr hosts: localhost gather_facts: no tasks: - name: Define IP addresses with CIDR set_fact: ip_list: - "192.168.1.100/24" - "10.0.0.5/16" - "172.16.30.4/12" - "2001:db8::1/64" - "8.8.8.8/32" - name: Extract prefix length debug: msg: "IP: {{ item }} , Prefix Length: {{ item | ansible.utils.ipaddr('prefix') }} " loop: "{{ ip_list }} "
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 TASK [Extract prefix length ] ************************ ok: [localhost ] => (item=192.168.1.100/24) => { "msg": "IP: 192.168.1.100/24, Prefix Length: 24" } ok: [localhost ] => (item=10.0.0.5/16) => { "msg": "IP: 10.0.0.5/16, Prefix Length: 16" } ok: [localhost ] => (item=172.16.30.4/12) => { "msg": "IP: 172.16.30.4/12, Prefix Length: 12" } ok: [localhost ] => (item=2001:db8::1/64) => { "msg": "IP: 2001:db8::1/64, Prefix Length: 64" } ok: [localhost ] => (item=8.8.8.8/32) => { "msg": "IP: 8.8.8.8/32, Prefix Length: 32" }
判断IP是否是私有IP ansible.utils.ipaddr('private')
过滤器用于判断一个 IP 地址是否属于 私有 IP 地址 (RFC1918 内网地址:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - name: Check if IP address is private hosts: localhost gather_facts: no tasks: - name: Define IP addresses set_fact: ip_list: - "192.168.1.100" - "10.0.0.5" - "172.16.30.4" - "8.8.8.8" - name: Check if each IP is private debug: msg: "{{ item }} is private: {{ item | ansible.utils.ipaddr('private') }} " loop: "{{ ip_list }} "
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 TASK [Check if each IP is private ] *************** ok: [localhost ] => (item=192.168.1.100) => { "msg": "192.168.1.100 is private: True" } ok: [localhost ] => (item=10.0.0.5) => { "msg": "10.0.0.5 is private: True" } ok: [localhost ] => (item=172.16.30.4) => { "msg": "172.16.30.4 is private: True" } ok: [localhost ] => (item=8.8.8.8) => { "msg": "8.8.8.8 is private: False" }
判断是否为公网IP ansible.utils.ipaddr('public')
过滤器用于判断一个 IP 地址是否是 公网 IP 地址 (即不属于 RFC1918 私有 IP 段)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - name: Check if IP address is public hosts: localhost gather_facts: no tasks: - name: Define IP addresses set_fact: ip_list: - "192.168.1.100" - "10.0.0.5" - "172.16.30.4" - "8.8.8.8" - "1.1.1.1" - name: Check if each IP is public debug: msg: "{{ item }} is public: {{ item | ansible.utils.ipaddr('public') }} " loop: "{{ ip_list }} "
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 TASK [Check if each IP is public ] *************** ok: [localhost ] => (item=192.168.1.100) => { "msg": "192.168.1.100 is public: False" } ok: [localhost ] => (item=10.0.0.5) => { "msg": "10.0.0.5 is public: False" } ok: [localhost ] => (item=172.16.30.4) => { "msg": "172.16.30.4 is public: False" } ok: [localhost ] => (item=8.8.8.8) => { "msg": "8.8.8.8 is public: True" } ok: [localhost ] => (item=1.1.1.1) => { "msg": "1.1.1.1 is public: True" }
ipwrap 过滤器 对 IPv4 地址 ,ipwrap
不会做任何修改 。 对 IPv6 地址 ,ipwrap
会添加方括号 [ ]
,确保在 URL 或某些配置文件(如 nginx.conf
)中解析时不会出错。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - name: Wrap IP addresses using ansible.utils.ipwrap hosts: localhost gather_facts: no tasks: - name: Define IP addresses set_fact: ip_list: - "192.168.1.100" - "10.0.0.5" - "172.16.30.4" - "8.8.8.8" - "2001:db8::1" - name: Apply ipwrap filter debug: msg: "Original: {{ item }} , Wrapped: {{ item | ansible.utils.ipwrap }} " loop: "{{ ip_list }} "
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 TASK [Apply ipwrap filter ] ************************ ok: [localhost ] => (item=192.168.1.100) => { "msg": "Original: 192.168.1.100, Wrapped: 192.168.1.100" } ok: [localhost ] => (item=10.0.0.5) => { "msg": "Original: 10.0.0.5, Wrapped: 10.0.0.5" } ok: [localhost ] => (item=172.16.30.4) => { "msg": "Original: 172.16.30.4, Wrapped: 172.16.30.4" } ok: [localhost ] => (item=8.8.8.8) => { "msg": "Original: 8.8.8.8, Wrapped: 8.8.8.8" } ok: [localhost ] => (item=2001:db8::1) => { "msg": "Original: 2001:db8::1, Wrapped: [2001:db8::1]" }
举个例子:
如果你需要生成一个 Nginx 配置,其中服务器监听 IPv6 地址:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - name: Generate Nginx config with IPv6 support hosts: localhost gather_facts: no tasks: - name: Define server IP set_fact: server_ip: "2001:db8::1" - name: Create Nginx config copy: dest: "/tmp/nginx.conf" content: | server { listen 80; listen [{{ server_ip | ansible.utils.ipwrap }}]:80; server_name example.com; }
这样 listen [2001:db8::1]:80;
语句就能正确解析,而不会因为 :
符号导致错误。
格式化⽹络信息输出 获取前几个地址 获取 IP 网络的前 X 个可用 IP 地址
1 2 3 4 5 6 7 8 9 10 11 - name: Get first 5 available IPs from a subnet hosts: localhost gather_facts: no tasks: - name: Define subnet set_fact: subnet: "192.0.2.0/24" - name: Extract first 5 available IPs debug: msg: "{{ subnet | ansible.utils.ipaddr(5) }} "
获取所有可用地址 ansible.utils.ipaddr('range_usable')
过滤器用于获取 子网中的所有可用 IP 地址 ,即去掉 网络地址和广播地址 后的 IP 地址范围。
1 2 3 4 5 6 7 8 9 10 11 - name: Get all usable IPs in a subnet hosts: localhost gather_facts: no tasks: - name: Define subnet set_fact: subnet: "192.0.2.0/29" - name: Get usable IP range debug: msg: "{{ subnet | ansible.utils.ipaddr('range_usable') }} "
运行结果
1 2 3 4 5 6 7 8 9 10 11 TASK [Get usable IP range ] ************************* ok: [localhost ] => { "msg": [ "192.0.2.1" , "192.0.2.2" , "192.0.2.3" , "192.0.2.4" , "192.0.2.5" , "192.0.2.6" ] }
判断IP是否属于某网段 ansible.utils.network_in_usable
过滤器用于判断 某个 IP 地址是否在指定的子网范围内,并且是可用的主机地址 (即 不是网络地址、广播地址或其他保留地址 )。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - name: Check if an IP is usable in a subnet hosts: localhost gather_facts: no tasks: - name: Define subnet and IPs set_fact: subnet: "192.0.2.0/29" test_ips: - "192.0.2.0" - "192.0.2.1" - "192.0.2.6" - "192.0.2.7" - name: Check if IPs are usable debug: msg: "IP {{ item }} usable: {{ subnet | ansible.utils.network_in_usable(item) }} " loop: "{{ test_ips }} "
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 TASK [Check if IPs are usable ] ************************* ok: [localhost ] => (item=192.0.2.0) => { "msg": "IP 192.0.2.0 usable: False" } ok: [localhost ] => (item=192.0.2.1) => { "msg": "IP 192.0.2.1 usable: True" } ok: [localhost ] => (item=192.0.2.6) => { "msg": "IP 192.0.2.6 usable: True" } ok: [localhost ] => (item=192.0.2.7) => { "msg": "IP 192.0.2.7 usable: False" }
获取下一个地址是什么 ansible.utils.ipaddr('next_usable')
过滤器用于 获取下一个可用的主机 IP 地址 ,即跳过 网络地址、广播地址 ,并返回 下一个可用 IP 。
1 2 3 4 5 6 7 8 9 10 11 - name: Get next usable IP hosts: localhost gather_facts: no tasks: - name: Define an IP with subnet set_fact: ip_with_subnet: "192.0.2.5/24" - name: Get the next usable IP debug: msg: "{{ ip_with_subnet | ansible.utils.ipaddr('next_usable') }} "
运行结果
1 2 3 4 TASK [Get the next usable IP ] ************************* ok: [localhost ] => { "msg": "192.0.2.6" }
cidr_merge 过滤器 ansible.utils.cidr_merge
过滤器用于 合并多个 CIDR 子网 ,将它们优化成更少、更大的子网范围。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - name: Merge multiple CIDR subnets hosts: localhost gather_facts: no tasks: - name: Define CIDR subnets set_fact: cidr_list: - "192.168.1.0/25" - "192.168.1.128/25" - "192.168.2.0/24" - "192.168.3.0/24" - "10.0.0.0/8" - "10.1.0.0/16" - name: Merge subnets debug: msg: "{{ cidr_list | ansible.utils.cidr_merge }} "
运行结果
1 2 3 4 5 6 7 8 9 TASK [Merge subnets ] ************************* ok: [localhost ] => { "msg": [ "10.0.0.0/8" , "192.168.1.0/24" , "192.168.2.0/24" , "192.168.3.0/24" ] }
更多网络过滤器用法,请点击Using the ipaddr filter