1. Kubernetes DNS 名称解析的核心价值
在容器化部署环境中,服务发现是维持微服务架构正常运转的生命线。传统基于IP的直接访问方式在动态调度的Pod面前完全失效——当一个Pod由于节点故障被重新调度时,它的IP地址会发生改变。2014年Google开源的Kubernetes项目通过内置DNS服务完美解决了这个痛点。
CoreDNS作为Kubernetes默认的DNS服务器(自1.13版本起替代kube-dns),会持续监听API Server中Service和Pod的变化。当你在集群内创建名为web-svc的Service时,CoreDNS会自动生成web-svc.default.svc.cluster.local这样的完整域名记录。这种机制使得无论后端Pod如何漂移,前端应用只需通过固定域名即可访问服务,实现了服务访问与底层基础设施的解耦。
2. Kubernetes DNS 的架构实现细节
2.1 CoreDNS 的工作流程
CoreDNS在Kubernetes中以Deployment形式运行,通常包含两个副本Pod确保高可用。其核心配置文件Corefile通过ConfigMap挂载,默认配置包含以下关键段:
.:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance }这段配置声明了CoreDNS如何处理不同域名的查询请求。其中kubernetes cluster.local插件是关键,它告诉CoreDNS需要监听Kubernetes中cluster.local域下的资源变更。当收到web-svc.default.svc.cluster.local这样的查询时,处理流程如下:
- 客户端向集群DNS(10.96.0.10)发起DNS查询
- CoreDNS检查查询域名是否匹配
cluster.local后缀 - 若匹配则查询API Server获取对应Service的ClusterIP
- 返回包含ClusterIP的DNS响应给客户端
2.2 域名记录生成规则
Kubernetes自动生成以下几种类型的DNS记录:
- Service记录:
<service>.<ns>.svc.cluster.local解析到Service的ClusterIP - Pod记录:
<pod-ip>.<ns>.pod.cluster.local将Pod IP转换为DNS可解析名称(需显式启用) - Headless Service记录:当Service没有ClusterIP时,直接解析到后端Pod IP列表
一个生产集群中典型的解析示例如下:
# 查询default命名空间下的nginx服务 nslookup nginx.default.svc.cluster.local Server: 10.96.0.10 Address: 10.96.0.10#53 Name: nginx.default.svc.cluster.local Address: 10.96.152.103 # 查询kube-system命名空间下的kube-dns服务 nslookup kube-dns.kube-system.svc.cluster.local Server: 10.96.0.10 Address: 10.96.0.10#53 Name: kube-dns.kube-system.svc.cluster.local Address: 10.96.0.103. 自定义DNS配置实战
3.1 修改集群DNS参数
Kubernetes允许通过修改kubelet参数调整Pod的DNS配置,关键参数包括:
--cluster-dns:DNS服务IP列表(逗号分隔)--cluster-domain:集群域名后缀(默认为cluster.local)
这些参数需要在kubelet启动时指定,修改后需要重启kubelet服务生效。例如在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf中添加:
Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10,192.168.1.1 --cluster-domain=company.lan"3.2 Pod级别的DNS策略
在Pod的YAML定义中,可以通过dnsPolicy字段指定不同的DNS策略:
apiVersion: v1 kind: Pod metadata: name: custom-dns-pod spec: containers: - name: nginx image: nginx dnsPolicy: "None" dnsConfig: nameservers: - 8.8.8.8 searches: - ns1.svc.company.lan - my.dns.search.suffix options: - name: ndots value: "2" - name: edns0支持的政策类型包括:
Default:继承节点上的DNS配置ClusterFirst:优先使用集群DNS(默认值)ClusterFirstWithHostNet:主机网络模式下的特殊策略None:完全自定义DNS配置
4. 常见问题排查指南
4.1 DNS查询超时问题
当Pod内出现nslookup: can't resolve 'kubernetes.default'错误时,建议按照以下步骤排查:
检查CoreDNS Pod状态:
kubectl -n kube-system get pods -l k8s-app=kube-dns正常应显示两个Running状态的Pod。
验证Service端点:
kubectl -n kube-system get ep kube-dns输出应包含CoreDNS Pod的IP和端口。
检查kubelet配置:
ps aux | grep kubelet | grep cluster-dns确认
--cluster-dns参数指向正确的DNS服务IP。测试DNS连通性: 在问题Pod中执行:
dig +short kubernetes.default.svc.cluster.local @10.96.0.10如果无响应,检查网络插件是否阻止了53端口的UDP通信。
4.2 ndots参数引发的性能问题
Kubernetes默认设置ndots:5,这意味着任何包含至少5个点的域名都会先尝试直接解析,失败后才走搜索域。例如查询api会依次尝试:
api.default.svc.cluster.local. api.svc.cluster.local. api.cluster.local. api.对于需要频繁访问外部服务的Pod,建议调整此参数:
dnsConfig: options: - name: ndots value: "2"5. 高级配置与优化实践
5.1 自定义Hosts文件注入
某些场景下需要为Pod注入特定的hosts记录,可以通过hostAliases字段实现:
apiVersion: v1 kind: Pod metadata: name: hostaliases-pod spec: hostAliases: - ip: "192.168.1.100" hostnames: - "foo.local" - "bar.local" containers: - name: cat-hosts image: busybox command: - cat args: - "/etc/hosts"5.2 使用NodeLocal DNSCache
在大规模集群中,为每个节点部署本地DNS缓存可以显著降低CoreDNS负载。NodeLocal DNSCache以DaemonSet形式运行,监听节点上的169.254.20.10地址。部署步骤:
下载部署清单:
wget https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml修改配置中的变量:
- name: __PILLAR__LOCAL__DNS__ value: "169.254.20.10" - name: __PILLAR__DNS__SERVER__ value: "10.96.0.10"应用配置:
kubectl apply -f nodelocaldns.yaml
5.3 外部域名分流策略
通过CoreDNS的forward插件可以实现内外网域名分流解析。例如将公司内部域名转发到私有DNS,其他查询走公共DNS:
corp.local:53 { errors cache 30 forward . 10.10.0.100 10.10.0.101 } .:53 { errors cache 30 forward . /etc/resolv.conf }6. 监控与日志分析
6.1 CoreDNS监控指标
CoreDNS默认暴露Prometheus指标在9153端口,关键指标包括:
coredns_dns_request_count_total:DNS请求总数coredns_dns_request_duration_seconds:请求处理耗时coredns_panic_count_total:崩溃次数
建议设置以下告警规则:
- alert: CoreDNSHighLatency expr: histogram_quantile(0.99, sum(rate(coredns_dns_request_duration_seconds_bucket[1m])) by (le)) > 1 for: 5m labels: severity: warning annotations: summary: "CoreDNS high latency detected" description: "DNS 99th percentile latency is {{ $value }} seconds"6.2 日志分析技巧
启用CoreDNS的log插件可以记录详细查询日志:
.:53 { log errors health kubernetes cluster.local { pods verified } }典型日志分析场景:
# 统计查询量最多的域名 kubectl logs -n kube-system coredns-xxxx | grep -o 'query:.*' | sort | uniq -c | sort -nr # 查找NXDOMAIN响应 kubectl logs -n kube-system coredns-xxxx | grep -w NXDOMAIN # 跟踪特定客户端的查询 kubectl logs -n kube-system coredns-xxxx | grep 'client 10.244.1.23'7. 安全加固建议
7.1 DNS劫持防护
为防止中间人攻击篡改DNS响应,建议:
启用CoreDNS的
dnstap插件记录完整流量:dnstap tcp://127.0.0.1:6000 full配置网络策略限制DNS查询源:
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-dns-access namespace: kube-system spec: podSelector: matchLabels: k8s-app: kube-dns policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: project: my-app ports: - protocol: UDP port: 53
7.2 资源限制配置
为CoreDNS设置合理的资源限制防止资源耗尽:
resources: limits: memory: 512Mi cpu: 1000m requests: memory: 128Mi cpu: 100m同时建议启用HPA自动扩缩容:
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: coredns-hpa namespace: kube-system spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: coredns minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70