Ansible:如何将字典列表合并为嵌套字典以构建Bind反向解析PTR记录
Ansible:如何将字典列表合并为嵌套字典以构建Bind反向解析PTR记录
嘿,我看你已经用Ansible的read_csv模块把包含IP和主机名的CSV文件转换成字典列表了,现在要搞Bind的反向PTR记录对吧?这事儿不难,我给你一步步拆解实现方法。
先明确需求:反向解析的结构逻辑
Bind的PTR记录是基于IP的反向网段来组织的,比如IP 10.32.1.32,对应的反向区域是1.32.10.in-addr.arpa,而具体的记录是32 IN PTR host1.。所以我们需要把原始的字典列表,转换成以反向区域名为键,以「最后一段IP:主机名」为子字典的嵌套结构。
第一步:把字典列表转换成嵌套字典
我们可以用set_fact结合循环来构建这个嵌套字典。假设你从read_csv得到的列表变量叫csv_host_list,直接用下面的任务就行:
- name: 构建PTR记录的嵌套字典 set_fact: ptr_records: "{{ ptr_records | default({}) | combine({ reversed_zone: { last_octet: item.hostname } }, recursive=True) }}" loop: "{{ csv_host_list }}" vars: ip_parts: "{{ item.ip.split('.') }}" # 生成反向区域名:把IP前3段倒序,加上in-addr.arpa reversed_zone: "{{ ip_parts[2] }}.{{ ip_parts[1] }}.{{ ip_parts[0] }}.in-addr.arpa" # 取IP的最后一段作为PTR记录的前缀 last_octet: "{{ ip_parts[3] }}"
执行完这个任务后,ptr_records的结构会变成这样:
{ "1.32.10.in-addr.arpa": { "32": "host1" }, "6.50.10.in-addr.arpa": { "71": "host2" } }
同一个反向区域的记录会自动合并到同一个子字典里,非常方便。
第二步:用嵌套字典生成Bind配置
有了这个嵌套字典,接下来就可以用template模块生成Bind的区域配置和区域文件了。
首先写一个Jinja2模板文件(比如命名为ptr_zones.j2):
# 生成反向区域的全局配置 {% for zone, records in ptr_records.items() %} zone "{{ zone }}" { type master; file "/etc/bind/zones/db.{{ zone }}"; }; {% endfor %} # 生成每个区域的具体记录文件(这里可以拆分到单独模板,或者直接写在一起) {% for zone, records in ptr_records.items() %} $TTL 86400 @ IN SOA ns1.yourdomain.com. admin.yourdomain.com. ( {{ ansible_date_time.epoch }} ; 用时间戳做自动递增的序列号 3600 ; Refresh 1800 ; Retry 604800 ; Expire 86400 ) ; Negative Cache TTL @ IN NS ns1.yourdomain.com. {% for octet, hostname in records.items() %} {{ octet }} IN PTR {{ hostname }}.yourdomain.com. {% endfor %} {% endfor %}
然后在Ansible任务里调用这个模板,生成配置文件:
- name: 生成Bind PTR区域配置 template: src: ptr_zones.j2 dest: /etc/bind/named.conf.local.d/ptr_records.conf mode: 0644 notify: 重启Bind服务 # 记得定义重启Bind的handler handlers: - name: 重启Bind服务 service: name: bind9 state: restarted
几个实用小提醒
- 如果你的CSV里只有短主机名(比如
host1而不是host1.yourdomain.com),一定要在模板里补上域名后缀,不然PTR记录会无效 - 序列号用
ansible_date_time.epoch可以自动递增,避免手动修改的麻烦 - 确保Bind的区域文件路径(比如
/etc/bind/zones/)存在,权限设置正确,Bind进程能读取
备注:内容来源于stack exchange,提问作者Matt Wagner
相关产品推荐
相关产品推荐

