编辑
2023-05-22
运维
00
请注意,本文编写于 485 天前,最后修改于 485 天前,其中某些信息可能已经过时。

目录

1.1 部署环境要求
1.1.1 节点信息
1.1.2 节点要求
1.2 部署 BIND Master
1.2.1 创建 BIND Master Role
1.2.2 创建 BIND Master Playbook
1.2.3 安装 BIND Master
1.3 部署 BIND Slave
1.3.1 创建 BIND Slave Role
1.3.2 创建 BIND Slave Playbook
1.3.3 安装 BIND Slave
1.4 设置节点使用 DNS 服务
1.5 总结

DNS (Domain Name Server) 提供了域名/主机名到 IP 地址的正反向解析功能,是保障网络服务能够正常使用的重要基础设施。几乎每次网络连接都是从 DNS 解析开始的,比如访问 Web 页面、发送电子邮件等等,都需要将域名解析为 IP 地址。

实现 DNS 的服务有很多,BIND 是 Unix/Linux 操作系统首选的 DNS 服务器,对于建设私有 DNS,BIND 无疑是一个好选择。本文将通过以下主题介绍 BIND,并演示在 Rocky Linux 9 上自动化完成 BIND 主从架构的部署:

  • 部署环境要求
  • 部署 BIND Master
  • 部署 BIND Slave
  • 配置客户端
  • 总结

1.1 部署环境要求

BIND 主从部署过程的自动化是通过 Ansible 实现的,因此需要 Ansible 控制节点,BIND 使用主从架构,因此需要 BIND Master 节点和 BIND Slave 节点,共需要三个节点。

1.1.1 节点信息

三个节点分别为 2 核 CPU、2 G 内存的虚拟机。

Ansible 托管节点的信息已经在 “自动化部署 NTP 服务” 一文做过介绍,这里略过。Ansible Inventory hosts 文件内容如下:

[automate] automate-host.aiops.red [ntp] ntp1.server.aiops.red [dnsmaster] dns1-host.aiops.red [dnsslave] dns2-host.aiops.red

BIND Master 节点信息:

# IP:10.211.55.16 # NETMASK:255.255.255.0 # 主机名:dns1-host.aiops.red # 系统版本:Rocky Linux release 9.0

BIND Slave 节点信息:

# IP:10.211.55.17 # NETMASK:255.255.255.0 # 主机名:dns2-host.aiops.red # 系统版本:Rocky Linux release 9.0

1.1.2 节点要求

Ansible 控制节点通过主机名访问 DNS 主从节点,在 DNS 部署完成前,需要在 Ansible 控制节点的 /etc/hosts 文件中做主机名与 IP 地址的绑定:

sudo vim /etc/hosts

image-20230522165709475

为了实现部署过程的自动化,Ansible 控制节点需要通过 aiops 用户 (或其他有免密 sudo 权限的普通用户) 免密登录 DNS 主从节点,并可以免密执行 sudo 命令。在之后的小结中,会使用名为 set_authorized_key 的 Ansible Role 配置免密登录。

1.2 部署 BIND Master

BIND (Berkeley Internet Name Domain) 是由 ISC (Internet Systems Consortium) 开发和维护的开源软件,为不同操作系统实现 DNS 协议。

在本节中,介绍通过一组 Ansible Roles 完成 BIND Master 的安装与配置。

1.2.1 创建 BIND Master Role

创建 bind_master Role,并进入 bind_master/ Role 目录:

ansible-galaxy role init --init-path ~/roles/ bind_master cd ~/roles/bind_master/

image-20230522165714143

tasks/main.yml 文件中,定义安装 BIND Master 需要的 task,文件内容如下:

--- # tasks file for bind_master - name: install bind packages task ansible.builtin.dnf: name: - bind - bind-utils state: present - name: started dns service task ansible.builtin.systemd: name: named.service state: started enabled: true - name: turn on dns service in the firewall task ansible.builtin.firewalld: service: dns permanent: true immediate: true state: enabled - name: generate named.conf file from template task ansible.builtin.template: src: "{{ item.src }}" dest: "{{ item.dest }}" owner: root group: named loop: - { src: named_master.conf.j2, dest: /etc/named.conf } - { src: named.conf.master.j2, dest: /etc/named.conf.master } - { src: domain_name.j2, dest: "/var/named/{{ domain_name }}" } - { src: arpa.j2, dest: "/var/named/{{ arpa }}.in-addr.arpa" } notify: restart dns service handlers

第一个 task 安装 BIND 软件包,bind 包提供了 BIND 的主程序 namedbind-utils 包提供了查询 DNS 信息的命令 (host、dig、nslookup)。

第二个 task 启动 named.service 服务,并将其设置为开机启动。

第三个 task 在 firewalld 防火墙中开启 dns service,以供客户端访问。

第四个 task 通过模板文件生成四个配置文件,并在文件有变化时,通过 notify 通知 “restart dns service handlers” 执行。

handlers/main.yml 文件的内容如下:

--- # handlers file for bind_master - name: restart dns service handlers ansible.builtin.systemd: name: named.service state: restarted

在接到通知后,重启 named.service 服务。

在模板配置文件中用到了几个变量,定义在了 defaults/main.yml 文件中:

--- # defaults file for bind_master allow_network: 10.211.55.0/24 arpa: 55.211.10 domain_name: aiops.red master_ip: 10.211.55.16 slave_ip: 10.211.55.17

这几个变量的值需要被使用者重新定义,因此把它们定义在了 defaults/main.yml 文件中。

1.2.2 创建 BIND Master Playbook

~/playbooks/ 目录下创建用于存放部署 BIND Master 的 Playbook 及模板文件的目录,并切换到 deploy_bind_master/

mkdir -p ~/playbooks/deploy_bind_master/templates/ cd ~/playbooks/deploy_bind_master/

image-20230522165722721

templates/ 目录中创建模板文件。模板文件可以存放在 Role 的 templates/ 目录下,也可以存放在 Playbook 的 templates/ 目录下,如果两个位置分别存储了模板文件,Playbook 会覆盖 Role。

templates/named_master.conf.j2 文件生成 named 的主配置文件,内容如下:

options { listen-on port 53 { 127.0.0.1; {{ master_ip }}; }; listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; secroots-file "/var/named/data/named.secroots"; recursing-file "/var/named/data/named.recursing"; allow-query { localhost; {{ allow_network }}; }; recursion yes; dnssec-validation yes; managed-keys-directory "/var/named/dynamic"; geoip-directory "/usr/share/GeoIP"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; include "/etc/crypto-policies/back-ends/bind.config"; }; logging { channel default_debug { file "data/named.run"; severity dynamic; }; }; zone "." IN { type hint; file "named.ca"; }; include "/etc/named.rfc1912.zones"; include "/etc/named.root.key"; include "/etc/named.conf.master";

文件用到了 master_ipallow_network 变量。master_ip 定义了 named 进程监听的 IP 地址;allow_network 定义了允许使用该 DNS 进行查询的网段。

文件末尾包含了 /etc/named.conf.master 文件,该文件由 templates/named.conf.master.j2 模板文件生成,内如如下:

zone "{{ domain_name }}" { type master; allow-transfer { {{ slave_ip }}; }; also-notify { {{ slave_ip }}; }; file "/var/named/{{ domain_name }}"; }; zone "{{ arpa }}.in-addr.arpa" { type master; allow-transfer { {{ slave_ip }}; }; also-notify { {{ slave_ip }}; }; file "/var/named/{{ arpa }}.in-addr.arpa"; };

zone 定义资源记录区,domain_name 是要托管的域名。allow-transfer 定义了将 Master DNS 上的区域文件内容复制到哪些 Slave DNS 上,以提供容错性。

templates/domain_name.j2 模板文件用于生成 zone 配置文件,内容如下:

$TTL 1h @ IN SOA {{ domain_name}}. root.{{ domain_name }}. ( 2022112101 ; Serial YYYYMMDDnn 24h ; Refresh 2h ; Retry 28d ; Expire 2d ) ; Minimum TTL ;Name Servers @ IN NS dns1-host @ IN NS dns2-host ;Mail Servers @ IN MX 0 mail1-host ;Other Servers dns1-host IN A 10.211.55.16 dns2-host IN A 10.211.55.17 mail1-host IN A 10.211.55.5 ntp1-host IN A 10.211.55.19 ;Canonical Names ntp1.server IN CNAME ntp1-host

templates/arpa.j2 生成 zone 反向区域文件,定义 PTR 记录,内容如下:

$TTL 1h @ IN SOA {{ arpa }}.in-addr.arpa root.{{ domain_name }}. ( 2022111801 ; Serial YYYYMMDDnn 24h ; Refresh 2h ; Retry 28d ; Expire 2d ) ; Minimum TTL ;Name Servers @ IN NS dns1-host @ IN NS dns2-host ;Other Servers dns1-host IN A 10.211.55.16 dns2-host IN A 10.211.55.17 ;PTR Records 16 IN PTR dns1-host 17 IN PTR dns2-host 5 IN PTR mail1 19 IN PTR ntp1-host

正反向区域文件中,分别添加了几个解析。

创建 deploy_bind_master.yaml Playbook 文件,内容如下:

#!/usr/bin/env ansible-playbook --- - name: deploy bind master server play hosts: dnsmaster become: true gather_facts: false roles: - set_authorized_key - change_hostname - upgrade_packages - bind_master ...

Playbook 文件中使用了四个 Role。

set_authorized_key Role 将 Ansible 控制节点的 aiops 用户的公钥拷贝到托管节点的指定用户,以配置免密登录。执行该 Role 时,需要 -k 选项,提供远程用户密码。

在该 Role 中定义了两个文件。

set_authorized_key/tasks/main.yml 内容如下:

--- # tasks file for set_authorized_key - name: initialization ssh key task ansible.builtin.authorized_key: comment: aiops user public key user: "{{ item }}" key: "{{ lookup('file', '/home/{{ local_user }}/.ssh/id_rsa.pub') }}" loop: "{{ remote_users }}"

set_authorized_key/defaults/main.yml 内容如下:

--- # defaults file for set_authorized_key local_user: aiops remote_users: - aiops

local_user 变量为 Ansible 控制节点的用户;remote_users 变量为托管节点的用户。

change_hostname Role 根据 Inventory hosts 中的名称设置托管节点的主机名,change_hostname/tasks/main.yml 文件内容如下:

--- # tasks file for change_hostname - name: change host name task ansible.builtin.shell: cmd: hostnamectl set-hostname "{{ inventory_hostname }}"

upgrade_packages Role 更新 dnf 包,类似在操作系统上执行 dnf upgrade -y 命令。如果有软件包更新,则重启操作系统。upgrade_packages/tasks/main.yml 文件的内容如下:

--- # tasks file for upgrade_packages - name: upgrade packages task ansible.builtin.dnf: update_cache: true name: "*" state: latest register: upgradeResult - name: reboot system task reboot: when: upgradeResult.changed

在 “Linux 9 自动化部署 NTP 服务” 一文中,对 Role 的创建做过介绍。

1.2.3 安装 BIND Master

执行 deploy_bind_master.yaml Playbook,安装并配置 BIND Master 节点:

ansible-playbook deploy_bind_master.yaml -k

image-20230522165732456

1.3 部署 BIND Slave

Slave 节点提高了服务的可用性。

1.3.1 创建 BIND Slave Role

创建 bind_slave Role,并进入 bind_slave/ Role 目录:

ansible-galaxy role init --init-path ~/roles/ bind_slave cd ~/roles/bind_slave

image-20230522165737219

tasks/main.yml 文件中,定义安装 BIND Slave 的 task,内容如下:

--- # tasks file for bind_slave - name: install bind packages task ansible.builtin.dnf: name: - bind - bind-utils state: present - name: started dns service task ansible.builtin.systemd: name: named.service state: started enabled: true - name: set selinux to allow data synchronization from master task ansible.builtin.shell: cmd: setsebool -P named_write_master_zones on - name: generate configuration files task ansible.builtin.template: src: "{{ item.src }}" dest: "{{ item.dest }}" owner: root group: named loop: - { src: named_slave.conf.j2, dest: /etc/named.conf } - { src: named.conf.slave.j2, dest: /etc/named.conf.slave } notify: restart dns service handlers

编辑 handlers/main.yml 文件,内容如下:

--- # handlers file for bind_slave - name: restart dns service handlers ansible.builtin.systemd: name: named.service state: restarted

defaults/main.yml 中设置变量:

--- # defaults file for bind_slave allow_network: 10.211.55.0/24 arpa: 55.211.10 domain_name: aiops.red master_ip: 10.211.55.16 slave_ip: 10.211.55.17

Slave 中用到的变量与 Master 相同。

1.3.2 创建 BIND Slave Playbook

~/playbooks/ 目录下创建用于存放部署 BIND Slave 的 Playbook 及模板文件的目录,并切换到 deploy_bind_slave/

mkdir -p ~/playbooks/deploy_bind_slave/templates cd ~/playbooks/deploy_bind_slave/

image-20230522165743252

BIND Slave Role 用到了named_slave.conf.j2named.conf.slave.j2 两个模板文件,这两个文件存放在 ~/playbooks/deploy_bind_slave/templates/ 目录下。

named_slave.conf.j2 内容如下:

options { listen-on port 53 { 127.0.0.1; {{ slave_ip }}; }; listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; secroots-file "/var/named/data/named.secroots"; recursing-file "/var/named/data/named.recursing"; allow-query { localhost; {{ allow_network }}; }; recursion yes; dnssec-validation yes; managed-keys-directory "/var/named/dynamic"; geoip-directory "/usr/share/GeoIP"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; /* https://fedoraproject.org/wiki/Changes/CryptoPolicy */ include "/etc/crypto-policies/back-ends/bind.config"; }; logging { channel default_debug { file "data/named.run"; severity dynamic; }; }; zone "." IN { type hint; file "named.ca"; }; include "/etc/named.rfc1912.zones"; include "/etc/named.root.key"; include "/etc/named.conf.slave";

named.conf.slave.j2 文件内容如下:

zone "{{ domain_name }}" { type slave; masters { {{ master_ip }}; }; file "/var/named/{{ domain_name }}"; }; zone "{{ arpa }}.in-addr.arpa" { type slave; masters { {{ master_ip }}; }; file "/var/named/{{ arpa }}.in-addr.arpa"; };

创建 deploy_bind_slave.yaml Playbook 文件,内容如下:

#!/usr/bin/env ansible-playbook --- - name: deploy bind slave server play hosts: dnsslave become: true gather_facts: false roles: - set_authorized_key - change_hostname - upgrade_packages - bind_slave ...

1.3.3 安装 BIND Slave

执行 deploy_bind_slave.yaml Playbook,安装并配置 BIND Slave 节点:

ansible-playbook deploy_bind_slave.yaml -k

image-20230522165749598

1.4 设置节点使用 DNS 服务

DNS 主从节点已部署完成,接下来设置主机使用新建的 DNS 服务。

在 Ansible 控制节点上执行以下命令,为 /etc/resolv.conf 文件生成新内容:

sudo nmcli c m eth0 ipv4.dns-search aiops.red ipv4.dns 10.211.55.17,10.211.55.16

image-20230522165754416

执行 restart_eth.sh 脚本,重启网卡连接,使配置生效。restart_eth.sh 脚本内容如下:

#!/bin/bash sudo nmcli c down eth0 sudo nmcli c up eth0

执行脚本:

sh restart_eth.sh

image-20230522165758726

eth0 需要修改成正确的网卡接口。

查看 /etc/resolv.conf 文件的内容,可以看到,nameserver 地址已经配置为主从 DNS 的地址:

image-20230522165802990

aiops.red zone 添加了几个 A 记录以及解析 ntp1.server 的 CNAME 记录。删除 /etc/hosts 文件中包含 ntp1.server.aiops.red 的条目,然后访问该地址,以验证 DNS 的域名解析功能:

ping -c 1 ntp1.server.aiops.red dig ntp1.server.aiops.red

image-20230522165806565

从输出可以看出,ntp1.server.aiops.red 域名是通过 DNS Slave 解析的。

可以编写一个 Ansible task,将 /etc/resolv.conf 文件拷贝到其他主机,使其他主机也能使用已部署的 DNS 服务解析域名。

1.5 总结

本文介绍了在 Rocky Linux 9 及其他基于 RPM 的 Linux 发行版上,使用 Ansible 自动化部署主从架构的 DNS 服务。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Gustav

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!