headless Service 的 DNS 到底返回什么?StatefulSet 的 Pod 为什么有固定的域名?没就绪的 Pod 会出现在 DNS 里吗?这篇用 nslookup 在真集群里把这些问题的答案都查出来。
普通 Service cip(10.96.204.228):nslookup cip → ['10.96.204.228'] headless Service hl:nslookup hl → ['10.244.1.83', '10.244.1.84', '10.244.2.120'](是否恰好是三个 Pod IP:True) 连续查 4 次 hl 的返回顺序(只显示 IP 最后一段):[['83', '120', '84'], ['83', '84', '120'], ['83', '120', '84'], ['120', '84', '83']](CoreDNS 默认会打乱 A 记录的顺序,客户端拿到的第一个不固定) kubectl get svc hl:hl ClusterIP None <none> 80/TCP 2s
普通 Service cip 的 A 记录只有一个,就是 ClusterIP;headless Service hl(clusterIP: None,kubectl get svc 里 CLUSTER-IP 显示 None)返回的是全部三个 Pod IP。连续查 4 次,顺序每次不同(CoreDNS 默认打乱),所以客户端不要依赖第一个。没有虚拟 IP,也就没有 kube-proxy 做的负载均衡——选哪个由客户端决定。
web-0.hl.k62.svc.cluster.local → ['10.244.1.83'](Pod IP 10.244.1.83) web-1.hl.k62.svc.cluster.local → ['10.244.1.84'](Pod IP 10.244.1.84) web-2.hl.k62.svc.cluster.local → ['10.244.2.120'](Pod IP 10.244.2.120) 删掉 web-1 并等它重建:IP 10.244.1.84 → 10.244.1.85;web-1.hl 现在解析为 ['10.244.1.85'](名字不变,IP 跟着变) 普通 Service 没有这种名字:nslookup web-1.cip → ['(无记录)']
StatefulSet 的 serviceName 指向这个 headless Service,Pod 的 hostname 是 web-N、subdomain 是 hl,于是每个 Pod 有自己的 A 记录 web-N.hl.k62.svc.cluster.local。删掉 web-1 重建,IP 从 10.244.1.84 变成 10.244.1.85,同一个域名现在解析到新 IP。普通 Service 没有这种名字,查 web-1.cip.… 得不到记录。(注意 busybox 的 nslookup 对带点的短名字不展开 search 域,实验里用了完整域名。)
让 web-2 的就绪探针失败(把 index.html 移走):hl 返回 2 个地址 ['83', '85'];web-2 的 IP 末段是 120
web-2.hl 单独解析:['(无记录)']
给 hl 加 publishNotReadyAddresses: true:hl 返回 3 个地址 ['120', '83', '85'];web-2.hl → ['10.244.2.120'](没就绪的 Pod 也出现了)让 web-2 的就绪探针失败后,hl 的 A 记录从 3 个变成 2 个,web-2 自己的域名也查不到。给 Service 加 publishNotReadyAddresses: true,3 个地址回来了,web-2.hl.… 也能解析——数据库集群成员互相发现时要用它,因为成员还没就绪时就得先互相找到。
nslookup -type=SRV _http._tcp.hl.k62.svc.cluster.local:3 条;例:['0 33 80 web-0.hl.k62.svc.cluster.local', '0 33 80 web-2.hl.k62.svc.cluster.local'] 普通 Service:SRV _http._tcp.cip → ['0 100 80 cip.k62.svc.cluster.local'](指向 Service 自身的名字,端口 80)
nslookup -type=SRV _http._tcp.hl.k62.svc.cluster.local 返回 3 条,每条指向一个 Pod 的名字和端口(0 33 80 web-0.hl.…);普通 Service 只有 1 条,指向 Service 自己(0 100 80 cip.k62.svc.cluster.local)。前缀里的 _http 是 Service 端口的名字,_tcp 是协议。