Skip to content

第 3 讲|域名和 DNS

IP 地址(尤其是 IPv4 的 203.0.113.10、IPv6 的 2001:db8::8a2e:370:7334)不便于人类记忆。域名是为了让用户可以用易记的名称(如 www.example.com)访问服务而设计的中间层。但机器之间通信仍然使用 IP——浏览器拿到域名后,需要查询该名称对应的 IP,这一过程称为 DNS(Domain Name System)解析

DNS 不只用于公网网站。公司内部平台、云 VPC 内的服务、Kubernetes 里的 Service,背后都是同一套域名解析机制。本讲先讲清楚域名的结构、DNS 的查询过程、记录类型、TTL 的作用,然后展开内网 DNS 的应用场景和常见解析异常的判定。

一、域名的层级结构

域名按层级组织,从右往左层级越来越细。以 www.example.com 为例:

域名从根到主机名的层级结构

层级管理者
com顶级域(TLD)ICANN 等国际机构
example.com主域名(Second-level Domain)域名注册者(公司/个人)
www子域名(Sub-domain)主域名所有者自行控制

顶级域分两类:

  • 通用顶级域(gTLD):.com.org.net.io.app
  • 国家代码顶级域(ccTLD):.cn.jp.uk.de

主域名所有者可以在自己的主域名下创建任意子域名,按业务用途拆分。常见的拆分方式:

子域名用途
www官网
api后端 API
static / cdn静态资源/CDN
m移动版网站
admin管理后台(应限制内网或 VPN 访问)
mail邮件服务
grafana / prometheus监控平台
harbor / nexus镜像/制品仓库

看到一个陌生的域名时,从子域名前缀通常能大致判断指向的服务类型,这对快速理解故障范围有帮助。

二、递归 DNS 与权威 DNS

DNS 系统有两类核心角色:

权威 DNS

最终保存域名解析记录、对外回答"该域名对应什么"的服务器。每个主域名都有自己的权威 DNS。在云厂商控制台或域名注册商管理后台配置的解析记录,就是写入权威 DNS。

  • 阿里云解析、腾讯云 DNS、AWS Route53、Cloudflare 都属于权威 DNS 服务商
  • 改解析记录,本质是改权威 DNS 上的配置

递归 DNS

替客户端完成完整查询过程的中间服务器。客户端不会自己从根 DNS 开始一路查到底——递归 DNS 帮你完成这件事并返回最终结果。

  • 系统配置中 /etc/resolv.conf 里的 nameserver,通常就是递归 DNS
  • 8.8.8.8(Google)、1.1.1.1(Cloudflare)、114.114.114.114(国内通用)、运营商 DNS、公司内网 DNS,都属于递归 DNS

完整查询过程

递归 DNS 负责跑腿,权威 DNS 负责给最终答案

权威 DNS 与递归 DNS 的分工对运维的影响

  • 修改解析记录 — 在权威 DNS(控制台)操作,通常立即生效
  • 生效全网范围 — 不取决于权威 DNS,而取决于各级递归 DNS 的缓存何时过期——这正是 TTL 的作用,下一节展开

三、DNS 记录类型

DNS 不只能返回 IP,还有多种记录类型对应不同的解析需求:

类型含义典型用途
AIPv4 地址大多数业务域名
AAAAIPv6 地址IPv6 网络
CNAME别名,指向另一个域名接入 CDN、域名跳转
MX邮件服务器域名邮件投递
TXT任意文本域名所有权验证、SPF/DKIM 反垃圾邮件、ACME 证书申请
NS该域名的权威 DNS 服务器子域委派
SOA域起始授权域的元数据,自动生成
SRV服务记录指定服务的主机名+端口,LDAP/SIP 等场景

业务方日常接触最多的是 AAAAACNAME 三种。

CDN 接入场景下的 CNAME 链

接入 CDN 的业务域名几乎都使用 CNAME 而非 A 记录。原因:

  • CDN 厂商的边缘节点 IP 动态分配,根据用户位置就近返回
  • 业务方无法预测 IP、不可能写死

典型解析链:

查询: www.example.com
权威 DNS: CNAME → example.com.cdn-provider.net
查询: example.com.cdn-provider.net
CDN 权威 DNS: A → 北京用户得到 203.0.113.42,上海用户得到 198.51.100.13

dig 工具可以完整看到这条链路:

bash
$ dig www.example.com

;; ANSWER SECTION:
www.example.com.        300  IN  CNAME  example.com.cdn-provider.net.
example.com.cdn-provider.net. 60 IN A   203.0.113.42

CNAME 的限制

主域名(zone apex)不能配 CNAME——example.com 本身只能配 A,不能 CNAME 到其他域名。这是 RFC 规定,部分场景下需要主域名也走 CDN,但又不允许 CNAME,云厂商提供了 ALIAS 或 ANAME 记录作为变通方案(在 DNS 层做隐式 CNAME 解析)。

四、TTL 与缓存

DNS 查询结果会在多个层级被缓存:浏览器、操作系统、路由器、运营商 DNS、上游 DNS。TTL(Time To Live)就是告诉这些缓存"这条记录可以保留多久"——单位是秒。

TTL 决定 DNS 缓存多久过期

例如 TTL = 300,意味着查询到这条记录后,300 秒内的重复查询使用缓存,300 秒后必须重新查询。

TTL 长短的取舍

TTL 范围优点缺点
长(3600s ~ 86400s)查询少,权威 DNS 负载低切换 IP 时缓存等待时间长
短(60s ~ 300s)切换快,几分钟全网生效查询量大,权威 DNS 压力大

业务正常运行期间,TTL 可以配置稍长(3600s 即 1 小时)以减少查询压力。

IP 切换前的标准操作:提前调低 TTL

域名迁移或主备切换前的标准操作:

  1. 提前 1-2 天把 TTL 调低(例如从 3600 改为 60-300 秒)
  2. 等待原 TTL 完全过期(各级缓存都已使用新 TTL)
  3. 执行 A 记录的 IP 切换
  4. 观察 1-2 天确认稳定后,把 TTL 恢复正常值

这个流程的关键价值:新 IP 出问题时,回滚的等待时间从数小时缩短到几分钟

缓存清理

修改解析记录后,某些位置仍解析到旧 IP,通常是缓存未过期。手动清理本地缓存:

bash
# Linux (systemd-resolved)
systemd-resolve --flush-caches
resolvectl flush-caches

# Linux (nscd)
service nscd restart

# macOS
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

# Windows
ipconfig /flushdns

# 浏览器:大多数浏览器需要重启或访问 chrome://net-internals/#dns

上游递归 DNS 的缓存无法用客户端命令清理,只能等待 TTL 自然过期——这正是 TTL 决定全网生效时间的体现。

五、内网 DNS

DNS 在内网场景中的应用范围远超公网。公司内部、云 VPC、Kubernetes 集群内都广泛使用 DNS。

内网 DNS 用服务名解耦后端 IP

内网 DNS 的典型场景

场景域名示例
公司内部 GitLabgitlab.company.local
云 VPC 内的 MySQLmysql.internal.example.com
K8s Serviceapi.default.svc.cluster.local
K8s Podpod-name.namespace.pod.cluster.local

内网 DNS 的核心价值:解耦 IP 与服务

服务的 IP 在生产环境中频繁变化:

  • 数据库主备切换 → IP 切换
  • Kubernetes Pod 重建 → IP 变化
  • 应用扩缩容 → 新增/减少 IP

通过 DNS 解耦后,业务代码使用稳定的域名访问,IP 变化对应用透明。Kubernetes 是这种解耦最彻底的实现——一个 Service 名背后的 Pod IP 可能一天变几次,应用始终用同一个域名,完全无感知。

Kubernetes 内的 DNS 解析机制

K8s 集群内的 DNS 由 CoreDNS 提供,服务名按固定格式构成:

<service-name>.<namespace>.svc.cluster.local

例如 default namespace 下的 api Service,完整域名是 api.default.svc.cluster.local。同 namespace 内的 Pod 可以省略部分,直接用 api(由 search domain 自动补全)。

内网 DNS 故障的判定

应用日志中出现:

lookup api.default.svc.cluster.local: no such host

判定路径:

bash
# 1. Service 是否存在
kubectl get svc -n default api

# 2. Service 的 Endpoints 是否有 Pod
kubectl get endpoints -n default api

# 3. CoreDNS 是否正常
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=50

# 4. 从有问题的 Pod 内部直接 DNS 查询
kubectl exec -it <pod> -- nslookup api.default.svc.cluster.local

具体的网络 DNS 故障类型与处理方式,在 第 14 讲 网络诊断与排错 的 DNS 章节展开。

六、DNS 解析异常的判定信号

DNS 出问题时通常表现为以下几种结果:

结果含义大概率原因
NXDOMAIN域名不存在域名拼写错误、记录未配置、域名已过期
SERVFAILDNS 服务器内部错误上游权威 DNS 故障、网络断、DNSSEC 校验失败
REFUSEDDNS 服务器拒绝回答防火墙拦截、DNS 服务器配置限制查询来源
解析到旧 IP缓存未过期TTL 还有效或本机 hosts 写死
不同地区解析到不同 IP智能调度CDN、GeoDNS、运营商缓存差异

NXDOMAIN 不一定是故障

某些应用启动时会探测多个候选域名(例如 DNS search 自动补全后的多个 FQDN),部分候选返回 NXDOMAIN 是正常的。日志中出现少量 NXDOMAIN 不必紧张,真正需要警觉的是:

  • 业务核心域名出现 NXDOMAIN
  • 多个域名同时 SERVFAIL
  • 解析耗时从毫秒级突然升到秒级

后两种情况通常意味着 DNS 链路本身出了问题,排查方向是上游 DNS 服务器、网络连通性、CoreDNS 健康状态。

DNS 解析慢的判定

应用偶尔出现"启动后第一次请求慢几秒,后续正常",大概率是 DNS 解析慢:

bash
time dig @<本机配置的 DNS> example.com

正常本地 DNS 响应应当在 100ms 以内。如果接近 1 秒甚至几秒,说明本地或上游 DNS 性能有问题。处理方式:

  • 在本机部署 dnsmasq / systemd-resolved / unbound 做本地缓存,避免每次都查上游
  • 应用层启用 DNS 缓存(JVM 的 networkaddress.cache.ttl、Python 的 socket 缓存)
  • 检查 /etc/resolv.conf 中的 options 参数:timeout 默认 5 秒过长,可调到 1-2 秒;attempts 默认 2 次过多,可调到 1
bash
# /etc/resolv.conf
options timeout:2 attempts:1 rotate

rotate 让多个 nameserver 轮询使用,避免第一个 DNS 慢时所有查询都先等它超时。

七、查 DNS 的常用工具

工具用途
dig直接查权威 DNS,显示完整结果(推荐)
nslookup简化的查询工具,输出较简略
host进一步简化的工具
getent hosts走系统 NSS,模拟应用的真实解析路径
bash
# 标准查询
dig www.example.com

# 指定 DNS 服务器查询
dig @8.8.8.8 www.example.com
dig @1.1.1.1 www.example.com

# 查特定记录类型
dig www.example.com A
dig example.com MX
dig example.com NS
dig example.com TXT

# 从根域名开始递归追踪
dig +trace example.com

# 反向解析(IP → 域名)
dig -x 8.8.8.8

# 只输出最终 IP(脚本化)
dig +short www.example.com

# 走系统 NSS(包括 /etc/hosts),模拟应用看到的解析
getent hosts www.example.com

diggetent hosts 必须对比看

应用看到的解析结果走的是系统 NSS(nsswitch.conf 中通常是 files dns,先查 /etc/hosts 再查 DNS),dig 直接绕过 hosts 查 DNS。两者结果不一致时,几乎都是 /etc/hosts 写死了旧记录:

bash
# 修改的是 DNS,但应用一直访问旧 IP——常见根因是 /etc/hosts
grep example.com /etc/hosts
cat /etc/nsswitch.conf | grep ^hosts

判定流程:dig 出来对、getent hosts 出来不对 → 几乎一定是 hosts 或 NSS 顺序问题。这是 DNS 排查中最常见的认知陷阱。