3、DNS与域名解析:内网DNS搭建(Bind9)、域名规划、泛域名解析、服务发现基础

3.1 内网DNS的核心作用

在服务目录平台中,DNS(Domain Name System)是基础设施的“电话簿”。内网DNS将可读的域名(如 api.srv.local)映射为容器或物理机的IP地址,是服务发现、流量路由和运维自动化的基础。相比公网DNS,内网DNS需要更高的解析速度、更灵活的域名规划以及支持泛域名解析。

关键指标: 内网DNS解析延迟应控制在 5ms 以内,缓存命中率需达到 95% 以上,以保障微服务调用的低延迟。

3.2 域名规划:分层命名体系

合理的域名规划是内网DNS可维护性的基石。建议采用“三级域名 + 环境标签”的命名体系:

层级 示例 说明
顶级域 .local 内网专用顶级域,避免与公网冲突
二级域(服务域) srv.local 承载所有微服务域名
三级域(服务名) api.srv.local 具体服务名称,如API网关、用户服务
环境标签(前缀) dev.api.srv.local 区分开发、测试、生产环境
域名规划最佳实践:
  • 环境隔离: 使用 dev、test、prod 作为前缀,避免跨环境域名污染。
  • 服务版本: 在域名中嵌入版本号(如 v2.api.srv.local),支持蓝绿部署。
  • 避免下划线: 域名中仅使用字母、数字和连字符(-),确保兼容性。

3.3 Bind9 内网DNS搭建

Bind9(Berkeley Internet Name Domain)是业界最成熟的开源DNS服务器。以下是在 Ubuntu 22.04 上搭建内网DNS的完整步骤:

3.3.1 安装与基础配置

# 安装 Bind9
sudo apt update
sudo apt install bind9 bind9utils bind9-doc -y

# 检查版本
named -v

# 启动并设置开机自启
sudo systemctl enable named
sudo systemctl start named

3.3.2 主配置文件(named.conf)

编辑 /etc/bind/named.conf,定义内网区域:

// 全局选项
options {
    directory "/var/cache/bind";
    recursion yes;                 // 允许递归查询
    allow-query { any; };         // 允许所有内网客户端查询
    allow-query-cache { any; };
    forwarders {
        8.8.8.8;                  // 上游DNS(公网转发)
        114.114.114.114;
    };
    dnssec-validation auto;
    listen-on { any; };           // 监听所有内网接口
    listen-on-v6 { none; };
};

// 内网正向解析区域
zone "srv.local" {
    type master;
    file "/etc/bind/db.srv.local";
    allow-update { none; };
};

// 内网反向解析区域(可选)
zone "168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/db.192.168";
};

3.3.3 区域数据文件

创建正向解析文件 /etc/bind/db.srv.local:

$TTL    604800
@       IN      SOA     ns1.srv.local. admin.srv.local. (
                        2025031001   ; Serial
                        604800       ; Refresh
                        86400        ; Retry
                        2419200      ; Expire
                        604800 )     ; Negative Cache TTL

; 名称服务器
@       IN      NS      ns1.srv.local.
@       IN      NS      ns2.srv.local.

; 名称服务器IP
ns1     IN      A       192.168.1.10
ns2     IN      A       192.168.1.11

; 服务域名(A记录)
api     IN      A       192.168.1.100
user    IN      A       192.168.1.101
order   IN      A       192.168.1.102

; 别名(CNAME)
www     IN      CNAME   api.srv.local.
注意: 每次修改区域文件后,必须递增 Serial 号(建议使用日期+序号格式),否则从DNS服务器不会同步更新。

3.3.4 启动与验证

# 检查配置文件语法
sudo named-checkconf

# 检查区域文件语法
sudo named-checkzone srv.local /etc/bind/db.srv.local

# 重启服务
sudo systemctl restart named

# 测试解析(在客户端)
nslookup api.srv.local 192.168.1.10
dig @192.168.1.10 user.srv.local

3.4 泛域名解析:通配符与动态服务发现

泛域名解析(Wildcard DNS)允许一个DNS记录匹配所有子域名。在微服务架构中,泛域名可以大幅减少DNS记录数量,是实现服务发现的基础。

3.4.1 泛域名配置

在区域文件中添加一条 * 记录:

; 泛域名解析:所有未定义的子域名都指向API网关
*       IN      A       192.168.1.200

此时,any-service.srv.local 都会解析到 192.168.1.200(API网关),网关再根据路径或Header进行路由。

3.4.2 泛域名 vs 精确记录

特性 精确记录 泛域名记录
配置复杂度 每个服务需单独添加 一条记录覆盖所有
灵活性 高(可指定不同IP) 低(所有流量指向同一IP)
适用场景 核心服务、固定IP 动态服务、开发环境
缓存效率 高(精确匹配) 中(通配符匹配)
推荐策略: 核心服务(如API网关、配置中心)使用精确记录;动态微服务使用泛域名 + 网关路由,实现“一次配置,全局生效”。

3.5 服务发现基础:DNS-SD与SRV记录

DNS服务发现(DNS-SD,RFC 6763)利用SRV记录和TXT记录,让客户端自动发现服务的端口、协议和元数据。

3.5.1 SRV记录格式

_service._protocol.srv.local.  IN  SRV  priority weight port target

示例:

_grpc._tcp.api.srv.local.  IN  SRV  10  5  50051 node1.srv.local.
_grpc._tcp.api.srv.local.  IN  SRV  10  5  50051 node2.srv.local.
_http._tcp.web.srv.local.  IN  SRV  10  10 8080  web-node.srv.local.

3.5.2 服务发现流程

  1. 查询SRV记录: 客户端请求 _grpc._tcp.api.srv.local,获取目标主机和端口。
  2. 查询A记录: 解析目标主机(如 node1.srv.local)的IP地址。
  3. 查询TXT记录(可选): 获取服务版本、权重、健康状态等元数据。
  4. 建立连接: 客户端根据IP+端口发起gRPC/HTTP请求。
DNS服务发现流程(SRV记录) 客户端 DNS服务器 服务节点1 192.168.1.101:50051 服务节点2 192.168.1.102:50051 ① 查询 _grpc._tcp.api ② 返回 node1:50051, node2:50051 ③ 查询 node1.srv.local A记录 ④ 返回 192.168.1.101 ⑤ 建立gRPC连接 说明: SRV记录让客户端无需硬编码端口,实现负载均衡和故障转移。TXT记录可携带版本、权重等元数据。

3.6 内网DNS架构:高可用与转发策略

生产环境必须部署多台DNS服务器,避免单点故障。典型架构如下:

内网DNS高可用架构 客户端 微服务 容器/Pod 主DNS (Master) 192.168.1.10 从DNS (Slave1) 192.168.1.11 从DNS (Slave2) 192.168.1.12 上游DNS 8.8.8.8 / 114.114.114.114 区域传输 (AXFR) 区域传输 (AXFR) DNS查询 转发(非权威查询) 高可用策略: 客户端配置多个DNS服务器(如 192.168.1.10、192.168.1.11),主DNS故障时自动切换到从DNS。

3.7 与Kubernetes DNS集成

在Kubernetes环境中,CoreDNS作为集群DNS,与内网Bind9协同工作:

  • 集群内部: CoreDNS解析 *.svc.cluster.local,将Service名称解析为Cluster IP。
  • 集群外部: CoreDNS通过 forward 插件将非集群域名转发到内网Bind9(如 srv.local)。
  • 统一管理: 所有微服务域名(如 api.srv.local)在Bind9中集中管理,Kubernetes Pod通过 ndots 配置决定搜索域。
# CoreDNS Corefile 配置示例
.:53 {
    errors
    health
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure
        fallthrough in-addr.arpa ip6.arpa
    }
    forward . 192.168.1.10 192.168.1.11 {
        max_concurrent 1000
    }
    cache 30
    loop
    reload
    loadbalance
}
集成要点:
  • Bind9负责 全局内网域名(如 srv.local),CoreDNS负责 集群内部域名(如 svc.cluster.local)。
  • 在Pod的 /etc/resolv.conf 中设置 search srv.local svc.cluster.local,实现短域名访问。
  • 泛域名 *.srv.local 指向API网关,实现新服务的自动接入。

3.8 安全与运维

维度 措施 说明
访问控制 allow-query + ACL 限制只有内网网段(如 192.168.0.0/16)可以查询
区域传输 allow-transfer 仅允许从DNS服务器(如 192.168.1.11、192.168.1.12)发起区域传输
日志审计 channel + category 记录所有DNS查询日志,便于故障排查和安全审计
缓存清理 rndc flush 修改区域文件后,使用 rndc reload 或 rndc flush 清除缓存
监控告警 Prometheus + Bind9 Exporter 监控查询量、错误率、缓存命中率,设置告警阈值
安全警告: 切勿将内网DNS服务器暴露到公网。使用 listen-on { 192.168.0.0/16; }; 限制监听接口,并配置防火墙规则(如 iptables)仅允许内网流量。

3.9 本章小结