如何用Ansible实现DNS配置的自动化管理?

来源:CDN教程作者:梁博渊头衔:网络博主
导读:本期聚焦于梁博渊创作的《如何用Ansible实现DNS配置的自动化管理?》,敬请观看详情。手工修改named配置文件、逐台重启DNS服务的方式既容易出错又难以追溯,当服务器数量达到几十台时,配置漂移问题会越来越明显。本文介绍如何利用Ansible将BIND和dnsmasq的DNS配置纳入自动化管理,内容包括批量分发zone文件并校验语法、用模板渲染不同环境的解析记录、通过handler实现配置变更后的自动reload、以及利用幂等性保证重复执行结果一致。文章还给出了roles的组织结构和常用模块的写法示例,帮助运维人员把DNS变更从手工操作变成可审计、可回滚的代码化流程。

DNS解析服务看起来简单,实际维护起来却相当琐碎。每新增一台服务器要加A记录,每个业务域名要配CNAME,改完还得手动检查语法、重启服务、验证解析结果。一旦机器多了、环境多了,手工操作几乎必然出现配置不一致的情况。把DNS配置交给Ansible管理,是解决这类问题比较成熟的思路:配置以文件形式存放,变更通过剧本下发,执行结果幂等可重复,整个过程天然留有审计记录。

如何用Ansible实现DNS配置的自动化管理?

为什么DNS配置适合用Ansible管理

DNS配置本质上是纯文本文件的集合,zone文件、named.conf、resolv.conf,全部都是可以模板化的内容,这正是Ansible最擅长的领域。用copytemplate模块下发文件,用service模块控制named服务,用command模块调用named-checkzone做语法校验,整条链路都能被playbook覆盖。

另一个重要原因是幂等性。手工改配置时,重复执行同一次修改可能导致重复的记录条目;而Ansible的任务在设计良好的情况下,无论执行多少遍,最终状态都一致。这对于DNS这种基础服务尤为关键——一条重复或错乱的记录可能影响整个业务的域名解析。

此外,playbook本身可以作为配置的历史档案。每次变更走Git提交,出问题时能快速定位是哪次提交引入的,回滚也只是checkout到上一个版本再执行一次,比手工改回配置可靠得多。

基础实现:批量分发zone文件并自动reload

先看一个最直接的场景:管理BIND的正向解析zone文件。我们用template模块渲染zone内容,并在文件变化时触发reload。目录结构建议按role组织:

roles/
  dns/
    tasks/main.yml
    handlers/main.yml
    templates/db.ippipp.com.j2
    files/named.conf.options

tasks中的核心任务如下:

- name: 安装BIND
  ansible.builtin.package:
    name: bind9
    state: present

- name: 下发zone配置文件
  ansible.builtin.template:
    src: db.ippipp.com.j2
    dest: /etc/bind/db.ippipp.com
    owner: root
    group: bind
    mode: '0644'
  notify: reload bind

- name: 确保named运行中
  ansible.builtin.service:
    name: named
    state: started
    enabled: true

handler写在handlers/main.yml中,注意handler只在被notify且任务实际产生变更时才执行:

- name: reload bind
  ansible.builtin.service:
    name: named
    state: reloaded

这里有个容易踩的坑:不要用state: restarted代替reloaded。BIND重启会清空缓存,reload则只重新加载配置,对线上服务更友好。另外,模板文件中的序列号必须每次变更时递增,否则主从同步不会生效,后面会讲如何用Jinja2自动处理。

模板化与环境变量分离

不同环境的解析记录通常有差异,比如测试环境的api域名指向测试机房,生产环境指向另一组IP。如果为每个环境维护一份独立的zone文件,后续合并维护成本很高。正确做法是用一个模板加多份变量文件。

模板文件db.ippipp.com.j2中,解析记录从变量读取:

$TTL 3600
@ IN SOA ns1.ippipp.com. admin.ippipp.com. (
     {{ serial }} ; Serial
     3600      ; Refresh
     900       ; Retry
     604800    ; Expire
     86400 )   ; Minimum

@   IN NS  ns1.ippipp.com.
ns1 IN A   {{ nameserver_ip }}
{% for host in web_servers %}
{{ host.name }} IN A {{ host.ip }}
{% endfor %}

变量按环境存放:

# group_vars/prod.yml
nameserver_ip: 10.0.1.53
web_servers:
  - { name: web01, ip: 10.0.1.11 }
  - { name: web02, ip: 10.0.1.12 }

# group_vars/test.yml
nameserver_ip: 192.168.1.53
web_servers:
  - { name: web01, ip: 192.168.1.11 }

序列号推荐用Ansible在渲染时自动生成,例如用执行时间戳:

- name: 设置序列号
  ansible.builtin.set_fact:
    serial: "{{ lookup('pipe', 'date +%Y%m%d01') }}"

这样每次发版变更,序列号自然变化,从节点同步就能正常触发,不需要人工记得改数字。

变更前校验:避免把错误配置推上线

DNS配置出错影响面大,语法校验必须在reload之前完成。BIND自带两个很好用的工具:named-checkconf检查主配置,named-checkzone检查zone文件。可以在playbook中加入校验步骤,校验失败则中止执行:

- name: 校验zone文件语法
  ansible.builtin.command: named-checkzone ippipp.com /etc/bind/db.ippipp.com
  register: zone_check
  changed_when: false

- name: 校验失败则中止
  ansible.builtin.fail:
    msg: "zone文件语法错误,请检查"
  when: zone_check.rc != 0

更优雅的做法是利用template模块的validate参数,在文件落地前就完成校验,校验失败文件不会写入目标路径:

- name: 下发并校验zone文件
  ansible.builtin.template:
    src: db.ippipp.com.j2
    dest: /etc/bind/db.ippipp.com
    validate: "named-checkzone ippipp.com %s"

注意validate中的%s代表临时文件路径,这个机制能保证线上永远不存在一份语法错误的配置文件。对于客户端的resolv.conf,如果只是简单场景,也可以直接用template分发;如果需要保留手工添加的条目,则要考虑用lineinfile做增量修改,避免覆盖管理员临时加的排查用记录。

轻量场景:用dnsmasq做内网解析

并非所有场景都需要上BIND。内网几十台机器、只需要一些自定义域名映射时,dnsmasq更轻便。它的配置同样适合Ansible管理,核心是维护一份hosts条目列表:

- name: 渲染dnsmasq自定义解析
  ansible.builtin.template:
    src: dnsmasq.addresses.conf.j2
    dest: /etc/dnsmasq.d/addresses.conf
  notify: restart dnsmasq

模板中循环生成address记录:

{% for item in dns_entries %}
address=/{{ item.domain }}/{{ item.ip }}
{% endfor %}

dnsmasq改配置后需要restart而非reload,这一点和BIND不同,写handler时别搞混。另外dnsmasq可以作为缓存服务器,把上游DNS指向公共解析,内网查询延迟能明显下降,这部分配置也可以一并用Ansible统一分发。

小结与实践建议

把DNS配置纳入Ansible管理后,日常加一条解析记录的流程变成:修改变量文件、提交Git、执行playbook、观察变更报告,全程几十秒完成且可追溯。实践中有几点经验值得注意:第一,zone文件权限要收紧,避免被普通用户读取到内网拓扑;第二,主从架构下先推从节点再推主节点,可以减少解析抖动;第三,重要变更前用--check模式做 dry run,先看diff再实际执行。

如果团队规模较大,还可以在此基础上接入CI流水线,把playbook的执行交给流水线触发,变更走审批流程,DNS这个基础设施组件就真正实现了代码化、可审计的运维方式。

AnsibleDNS配置自动化运维修改时间:2026-09-10 06:34:40

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260910/53872.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。