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 关联情况纳入集群监控,避免服务发现中断。

相关推荐
小熊美家熊猫系统31 分钟前
电子合同技术实现与合规实践
java·开发语言·分布式
云烟成雨TD31 分钟前
Agent Scope Java 2.x 系列【3】从零构建 ReActAgent
java·人工智能·agent
一只叫煤球的猫40 分钟前
ThreadForge 源码解读二:一个 Task 从 submit 到完成,内部到底发生了什么?
java·后端·面试
阿狸猿1 小时前
论微服务架构及其应用
java·微服务·架构
程序员黑豆2 小时前
Java中的字符串【AI全栈开发】
java
namexingyun2 小时前
开源前端生态如何成为 AI UI 生成的“燃料“:shadcn/ui、Tailwind CSS、Storybook 技术价值全解剖
java·前端·人工智能·python·ui·开源·ai编程
终将老去的穷苦程序员2 小时前
基于SpringBoot的餐饮管理系统
java·spring boot·后端
心之伊始2 小时前
Spring AI Tool Calling 实战:让 Java Agent 调用本地 Bean 工具方法
java·spring boot·agent·spring ai·tool calling
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第110题】【并发篇】第10题:CAS 存在哪些问题?
java·开发语言·面试
瀚高PG实验室3 小时前
java中间件无法连接数据库
java·数据库·中间件·瀚高数据库