Kubernetes DNS 完全指南:服务发现核心机制与实践

Kubernetes DNS 完全指南:服务发现核心机制与实践

一、Kubernetes DNS 核心概述

1. 基本定位
  • 内置特性:Kubernetes 1.3+ 版本默认集成 DNS 服务,通过集群插件自动部署(包含 DNS Pod 和 Service)。

  • 核心作用:为集群内的 Service、Pod 提供域名解析能力,替代手动配置 IP 地址,实现灵活的服务发现。

  • 工作原理 :kubelet 通过 --cluster-dns 标志告知容器 DNS 服务 IP,容器通过该 IP 解析集群内域名;同时通过 --cluster-domain 配置集群默认域(默认 cluster.local)。

2. 核心优势
  • 无需修改应用代码,兼容传统 DNS 解析逻辑。

  • 自动同步 Service/Pod 变更,IP 动态变化时无需手动更新配置。

  • 支持跨命名空间解析,简化多团队协作部署。

二、DNS 命名规则与解析模式

1. 域名生成规则

集群内所有资源的 DNS 域名遵循统一格式,核心结构为:

复制代码
[资源名称].[命名空间].[资源类型].cluster.local
  • 默认搜索列表:Pod 的 DNS 配置会自动包含「自身命名空间 + 集群默认域」,简化短域名解析。

  • 示例说明:

    • 命名空间 bar 中的 Service foo,在同命名空间可通过 foo 解析,跨命名空间(如 quux)需通过 foo.bar 解析。
2. 支持的 DNS 记录类型
(1)Service 相关记录
记录类型 适用场景 域名格式 解析结果
A 记录 普通 Service(带 ClusterIP) my-svc.my-namespace.svc.cluster.local Service 的 ClusterIP
A 记录 无头服务(Headless Service,无 ClusterIP) my-svc.my-namespace.svc.cluster.local 关联的所有 Pod IP 列表(轮询负载均衡)
SRV 记录 命名端口的 Service _port-name._port-protocol.my-svc.my-namespace.svc.cluster.local 端口号 + 对应域名(普通 Service)或多个 Pod 端口 + 域名(无头服务)
(2)Pod 相关记录
  • 默认 A 记录 (启用后):pod-ip-address.my``-namespace.pod.cluster.local(如 1-2-3-4.default.pod.cluster.local)。

  • 自定义主机名 / 子域名 :通过 PodSpec 的 hostnamesubdomain 字段配置,生成格式为 [hostname].[subdomain].[namespace].svc.cluster.local 的域名,需配合无头服务使用:

    示例:Pod 自定义域名配置

    apiVersion: v1

    kind: Service

    metadata:

    name: default-subdomain # 无头服务(clusterIP: None)

    spec:

    selector:

    复制代码
     name: busybox

    clusterIP: None

    ports:

    • name: foo

      port: 1234


    apiVersion: v1

    kind: Pod

    metadata:

    name: busybox1

    labels:

    name: busybox

    spec:

    hostname: busybox-1 # 自定义主机名

    subdomain: default-subdomain # 关联无头服务

    containers:

    • image: busybox

      command: ["sleep", "3600"]

      name: busybox

最终 Pod 域名:busybox-1.default-subdomain.default.svc.cluster.local

三、DNS 服务使用与验证

1. 快速验证 DNS 可用性
步骤 1:创建测试 Pod
yaml 复制代码
# busybox.yaml

apiVersion: v1

kind: Pod

metadata:

name: busybox

namespace: default

spec:

containers:

- image: busybox

 command: ["sleep", "3600"]

 name: busybox

restartPolicy: Always
复制代码
$ kubectl create -f busybox.yaml

$ kubectl get pods busybox  # 等待 STATUS 为 Running
步骤 2:执行 DNS 解析测试
复制代码
# 解析集群默认 Service(kubernetes.default)

$ kubectl exec -ti busybox -- nslookup kubernetes.default

# 成功输出示例:

Server:    10.0.0.10  # DNS Service IP

Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes.default

Address 1: 10.0.0.1  # kubernetes Service 的 ClusterIP
2. 查看 Pod DNS 配置

Pod 的 DNS 配置存储在 /etc/resolv.conf 中,可通过以下命令查看:

复制代码
$ kubectl exec busybox -- cat /etc/resolv.conf

# 典型输出(包含搜索路径和 DNS 服务器):

search default.svc.cluster.local svc.cluster.local cluster.local

nameserver 10.0.0.10  # 集群 DNS Service IP

options ndots:5
  • search:解析短域名时的搜索路径,按顺序匹配命名空间和集群域。

  • ndots:5:当域名中.数量少于 5 时,优先使用搜索路径拼接解析。

四、DNS 常见问题排查

当 DNS 解析失败时,按以下步骤逐步排查:

1. 基础配置检查
  • 验证 Pod 的 /etc/resolv.conf 是否包含正确的 nameserver(集群 DNS IP)和 search 路径。

  • 确认目标 Service/Pod 已创建,且命名空间、名称无拼写错误。

2. DNS 组件状态检查
复制代码
# 1. 检查 DNS Pod 是否运行(kube-system 命名空间)

$ kubectl get pods --namespace=kube-system -l k8s-app=kube-dns

# 预期输出:3/3 Ready(包含 kubedns、dnsmasq、healthz 三个容器)

# 2. 检查 DNS Service 是否存在

$ kubectl get svc --namespace=kube-system kube-dns

# 预期输出:CLUSTER-IP 为 10.0.0.10(默认),PORT(S) 为 53/UDP,53/TCP

# 3. 检查 DNS Endpoints 是否正常(关联 DNS Pod IP)

$ kubectl get ep kube-dns --namespace=kube-system

# 预期输出:ENDPOINTS 包含 DNS Pod 的 IP:53
3. 日志排查

查看 DNS Pod 日志,定位错误原因(如连接 apiserver 失败、配置错误等):

复制代码
# 查看 kubedns 容器日志

$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c kubedns

# 查看 dnsmasq 容器日志

$ kubectl logs --namespace=kube-system $(kubectl get pods --namespace=kube-system -l k8s-app=kube-dns -o name) -c dnsmasq
  • 日志级别说明:W(警告)、E(错误)、F(失败)需重点关注。
4. 已知问题与规避方案
  • Linux libc 限制 :最多支持 3 个 nameserver 和 3 个 search 记录,超出部分会被截断。可通过 Node 部署 dnsmasq 扩展 nameserver,或使用 kubelet 的 --resolv-conf 自定义配置文件。

  • Alpine 镜像兼容问题 :Alpine 3.3 及更早版本 DNS 解析异常,需升级镜像或手动安装 bind-tools

  • Pod 继承 Node DNS :默认情况下,Pod 会继承 Node 的 DNS 配置,若需自定义,可通过 kubelet 的 --resolv-conf 标志指定配置文件(设为 "" 表示不继承)。

五、高级配置与扩展

1. 自定义集群域名

通过 kubelet 的 --cluster-domain 标志修改集群默认域(默认 cluster.local),例如:

复制代码
# kubelet 启动参数

--cluster-domain=my-cluster.local

修改后,Service 域名格式变为 my-svc.my-namespace.svc.my``-cluster.local

2. 无头服务(Headless Service)DNS 配置

无头服务无 ClusterIP,DNS 解析直接返回关联 Pod IP,适用于:

  • 客户端需自主实现负载均衡。

  • 需通过域名直接访问单个 Pod(如状态 ful 应用)。

3. 跨集群 DNS 解析(Federation)

Kubernetes 支持集群联邦(Federation),通过 DNS 服务实现跨集群 Service 发现,需部署联邦插件并配置跨集群 DNS 转发规则,具体参考 集群联邦官方文档

六、总结与最佳实践

  1. 优先使用短域名 :同命名空间直接使用 Service 名称解析(如 my-nginx),跨命名空间使用 服务名.命名空间(如 my-nginx.prod)。

  2. 避免硬编码 IP:所有集群内服务访问均通过 DNS 域名,适配 Pod 动态扩缩容和 IP 变更。

  3. 启用 Pod 域名解析 :如需通过域名访问特定 Pod,配置 hostnamesubdomain 并关联无头服务。

  4. 定期检查 DNS 状态:将 DNS Pod 运行状态、Endpoints 关联情况纳入集群监控,避免服务发现中断。

相关推荐
逻辑驱动的ken2 小时前
Java高频面试考点场景题14
java·开发语言·深度学习·面试·职场和发展·求职招聘·春招
阿冰冰呀2 小时前
互联网大厂Java求职面试实录:谢飞机的“水货”之路
java·mybatis·dubbo·springboot·线程池·多线程·hashmap
水无痕simon2 小时前
1.单机部署Nacos1.3.2
java
米高梅狮子3 小时前
05.Kubernetes Volume和Kubernetes ConfigMap
云原生·容器·kubernetes
Java小生不才4 小时前
spring AI文生图
java·人工智能·spring ai
苍煜5 小时前
ThreadPoolExecutor线程池终极全解:同步异步判定+SpringBoot生产实战
java·开发语言·spring boot
c++之路5 小时前
C++ 动态内存
java·jvm·c++
2301_800976939 小时前
数据库的基本操作后续
java·数据库·sql
SECS/GEM9 小时前
SECS/GEM如何实现越南现场自定义消息
java·服务器·数据库