CoreDNS 详解:Kubernetes 集群的"服务发现引擎"

This article is extracted from the chat log with AI. Please identify it with caution.

(注:自 Kubernetes 1.11 起,CoreDNS 已取代 KubeDNS 成为默认 DNS 服务)

什么是 CoreDNS?#

CoreDNS 是 Kubernetes 集群中的核心 DNS 服务,它为集群内的所有 Pod 和 Service 提供名称解析功能。简单来说,CoreDNS 是 Kubernetes 服务发现机制的基石,它将 Service 名称(如 my-service.default.svc.cluster.local)解析为对应的 ClusterIP,使得应用无需硬编码 IP 地址即可相互发现和通信。

作为云原生计算基金会 (CNCF) 毕业项目,CoreDNS 以其插件化架构高性能灵活性成为现代 Kubernetes 集群的标准 DNS 解决方案。没有 CoreDNS,微服务架构将难以实现,因为服务将无法通过名称相互发现。

CoreDNS 在 Kubernetes 中的核心角色#

1. 服务发现的"目录管理员"#

  • 为每个 Service 创建 DNS 记录
  • 支持 A 记录(IPv4)、AAAA 记录(IPv6)和 SRV 记录
  • 自动生成层次化域名:<service>.<namespace>.svc.<cluster-domain>

2. 服务解析的"翻译官"#

  • 将逻辑服务名称转换为实际 IP 地址
  • 为 Headless Service 提供 Pod IP 列表(而非 ClusterIP)
  • 支持服务端口发现(SRV 记录)

3. 集群网络的"连接器"#

  • 集成外部 DNS 服务(如公司内部 DNS 或云 DNS)
  • 为 Pod 提供默认搜索域,简化名称查询
  • 处理跨命名空间的服务发现

CoreDNS 的架构与工作原理#

1. CoreDNS 组件架构#

graph LR
A[Pod] -->|DNS 查询| B(CoreDNS Pod)
B --> C[插件链]
C --> D[kubernetes 插件]
C --> E[forward 插件]
C --> F[cache 插件]
D -->|查询| G[API Server]
E -->|转发| H[上游 DNS]
F -->|缓存结果| I[内存缓存]

CoreDNS 采用插件链架构,请求按顺序通过多个插件处理:

  1. kubernetes 插件:处理集群内部 Service 和 Pod 的 DNS 查询
  2. forward 插件:将外部域名查询转发到上游 DNS 服务器
  3. cache 插件:缓存查询结果,提高性能
  4. autopath 插件:优化 Pod 的 DNS 查询路径
  5. prometheus 插件:暴露监控指标

2. DNS 查询流程#

当 Pod 查询 my-service.default.svc.cluster.local 时:

  1. Pod 的 DNS 请求发送到 CoreDNS 服务(通常为 10.96.0.10)
  2. CoreDNS 检查查询是否匹配集群域(cluster.local)
  3. kubernetes 插件向 API Server 查询 Service 信息
  4. 获取 Service 的 ClusterIP 或 Endpoint IP 列表
  5. 返回 DNS 响应(A 记录或 SRV 记录)
  6. 结果被 cache 插件缓存,以加速后续相同查询

3. DNS 记录类型与示例#

记录类型示例解析结果用途
A 记录my-service.default.svc.cluster.local10.96.45.10Service ClusterIP
A 记录 (Headless)my-headless-svc.default.svc.cluster.local10.244.1.5, 10.244.2.6直接返回 Pod IP
SRV 记录_http._tcp.my-service.default.svc.cluster.local80 my-service.default.svc.cluster.local服务端口发现
PTR 记录10.244.1.510-244-1-5.my-pod.default.pod.cluster.local反向 DNS 查找

CoreDNS 的配置与部署#

1. Corefile 配置#

CoreDNS 使用名为 Corefile 的配置文件,定义插件链和行为:

# CoreDNS 配置示例 (/etc/coredns/Corefile)
.:53 {
    errors  # 错误日志
    health {  # 健康检查端点
        lameduck 5s
    }
    ready  # 就绪检查端点
    kubernetes cluster.local in-addr.arpa ip6.arpa {
        pods insecure  # 允许 Pod 反向查找
        fallthrough in-addr.arpa ip6.arpa  # 未匹配时继续处理
        ttl 30  # 缓存 TTL
    }
    prometheus :9153  # 指标端口
    forward . /etc/resolv.conf {  # 转发外部查询
        max_concurrent 1000
    }
    cache 30  # 缓存所有记录 30 秒
    loop  # 检测转发循环
    reload  # 自动重载配置
    loadbalance  # 负载均衡 DNS 响应
}

2. 关键配置参数#

参数说明推荐值
podsPod DNS 模式insecure (允许 Pod 反向查找)
ttlDNS 记录 TTL30s (平衡性能与更新速度)
cache缓存时间30s
max_concurrent最大并发转发查询1000
fallthrough未匹配时继续处理in-addr.arpa ip6.arpa
lameduck健康检查延迟5s

3. 部署清单示例#

# CoreDNS Deployment 示例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
    spec:
      serviceAccountName: coredns
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name: coredns
        image: coredns/coredns:1.8.6
        resources:
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
          readOnly: true
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8181
          initialDelaySeconds: 10
          timeoutSeconds: 3
          periodSeconds: 10
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
# CoreDNS Service 示例
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  annotations:
    prometheus.io/port: "9153"
    prometheus.io/scrape: "true"
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.96.0.10  # 通常为 kube-apiserver 配置中的 clusterDNS
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
  - name: metrics
    port: 9153
    protocol: TCP

CoreDNS 的高级功能#

1. 自定义 DNS 策略#

Pod 可以通过 dnsPolicy 字段定制 DNS 行为:

apiVersion: v1
kind: Pod
metadata:
  name: custom-dns
spec:
  dnsPolicy: "None"  # 忽略集群 DNS 设置
  dnsConfig:
    nameservers:
      - 1.1.1.1
      - 8.8.8.8
    searches:
      - ns1.svc.cluster.local
      - my-namespace.svc.cluster.local
      - svc.cluster.local
      - cluster.local
    options:
      - name: ndots
        value: "5"
      - name: timeout
        value: "2"
  • Default:继承节点的 DNS 配置
  • ClusterFirst(默认):使用集群 DNS,回退到上游 DNS
  • ClusterFirstWithHostNet:HostNetwork Pod 的 ClusterFirst
  • None:完全自定义 DNS 配置

2. 高级插件扩展#

插件功能使用场景
rewrite重写 DNS 查询和响应兼容旧版应用,重定向查询
template基于模板生成响应动态生成 DNS 记录
k8s_external处理外部服务暴露集群服务到外部 DNS
file从区域文件提供 DNS静态 DNS 记录
log详细查询日志调试和审计
whoami返回客户端信息调试客户端连接

示例:重写规则(兼容旧版 DNS 名称)

.:53 {
    kubernetes cluster.local in-addr.arpa ip6.arpa
    rewrite name exact legacy-app.default.svc.cluster.local my-app.default.svc.cluster.local
    forward . /etc/resolv.conf
    cache 30
}

3. 自动路径优化 (Autopath)#

CoreDNS 的 autopath 插件显著提高 DNS 查询效率:

传统查询流程(无 autopath):

1. my-service (失败)
2. my-service.default.svc.cluster.local (成功)

优化后流程(有 autopath):

1. my-service.default.pod.cluster.local (由 Pod IP 推断的搜索域)
2. my-service.default.svc.cluster.local (成功)
  • 减少 50%+ 的 DNS 查询
  • 降低 CoreDNS 负载
  • 加快应用启动时间

CoreDNS 与其它组件的关系#

1. 与 kube-proxy 和 Service#

graph LR
A[Pod] -->|查询 my-service| B(CoreDNS)
B -->|返回 10.96.45.10| A
A -->|连接 10.96.45.10:80| C[kube-proxy]
C -->|路由到| D[Pod 1]
C -->|路由到| E[Pod 2]
C -->|路由到| F[Pod 3]
  • CoreDNS 负责名称→IP 解析
  • kube-proxy 负责 IP→Pod 负载均衡
  • 两者协同实现完整服务发现

2. 与 kubelet#

  • kubelet 配置每个 Pod 的 /etc/resolv.conf
  • 设置 nameserver 为 CoreDNS Service IP
  • 配置搜索域(search domains)和选项(如 ndots)

典型 /etc/resolv.conf

nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

3. 与外部 DNS 系统集成#

graph LR
A[Pod] -->|内部查询| B(CoreDNS)
A -->|外部查询 example.com| B
B -->|内部域 cluster.local| C[kubernetes 插件]
B -->|外部域 example.com| D[forward 插件]
D --> E[上游 DNS 8.8.8.8]
D --> F[企业 DNS 10.0.0.10]
  • 支持条件转发(基于域名)
  • 可配置多个上游 DNS 服务器
  • 支持 DNS over TLS (DoT) 和 DNS over HTTPS (DoH)

CoreDNS 的监控与故障排除#

1. 关键监控指标#

指标说明健康阈值
请求率每秒 DNS 查询数根据集群规模而定
错误率失败查询比例< 1%
延迟DNS 响应时间 P99< 100ms
缓存命中率缓存响应比例> 80%
内存使用每实例内存消耗< 100Mi/1000 请求/秒

Prometheus 查询示例

# 错误率
sum(rate(coredns_dns_request_errors_total[5m])) / sum(rate(coredns_dns_requests_total[5m]))

# P99 延迟
histogram_quantile(0.99, sum(rate(coredns_dns_request_duration_seconds_bucket[5m])) by (le))

# 缓存命中率
sum(rate(coredns_cache_hits_total[5m])) / (sum(rate(coredns_cache_hits_total[5m])) + sum(rate(coredns_cache_misses_total[5m])))

2. 常用诊断命令#

# 检查 CoreDNS Pod 状态
kubectl get pods -n kube-system -l k8s-app=kube-dns

# 检查 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns

# 从测试 Pod 查询 DNS
kubectl run -it --rm --restart=Never --image=busybox:1.28 dns-test -- nslookup kubernetes.default

# 检查 CoreDNS 配置
kubectl get configmap -n kube-system coredns -o yaml

# 检查指标
curl http://<coredns-pod-ip>:9153/metrics

# 检查 DNS 配置
kubectl exec <pod-name> -- cat /etc/resolv.conf

# 高级调试(启用详细日志)
kubectl edit configmap -n kube-system coredns
# 添加 log 插件到 Corefile

3. 常见问题与解决方案#

问题现象可能原因诊断命令解决方案
DNS 解析超时CoreDNS 资源不足kubectl top pods -n kube-system增加 CPU/内存限制
间歇性解析失败节点 DNS 配置冲突cat /etc/resolv.conf (节点上)修复节点 resolv.conf
无法解析外部域名上游 DNS 配置错误kubectl exec <pod> -- nslookup google.com检查 forward 插件配置
SRV 记录缺失未正确配置端口kubectl get svc <service> -o yaml确保 Service 有命名端口
高延迟缓存未命中率高curl http://<coredns-pod>:9153/metrics | grep cache增加缓存 TTL
DNS 污染重复部署 CoreDNSkubectl get svc -n kube-system kube-dns清理重复部署

最佳实践#

  1. 资源规划

    resources:
      requests:
        cpu: "100m"
        memory: "70Mi"
      limits:
        cpu: "200m"
        memory: "170Mi"
    • 每 1000 个 Pod 预留 0.25 CPU 和 100Mi 内存
    • 根据查询模式调整(突发查询需要更多 CPU)
  2. 高可用配置

    • 部署至少 2 个副本,分布在不同节点
    • 配置 PodDisruptionBudget 防止同时驱逐
    • 使用反亲和性避免单点故障
    affinity:
      podAntiAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: k8s-app
              operator: In
              values: ["kube-dns"]
          topologyKey: "kubernetes.io/hostname"
  3. 性能优化

    • 启用 autopath 减少查询次数
    • 适当增加缓存 TTL(30-60 秒)
    • 为频繁访问的服务设置更长 TTL
    • 限制最大并发查询防止拒绝服务
  4. 安全加固

    • 限制 CoreDNS 权限(最小权限 ServiceAccount)
    • 禁用不必要的插件(如 whoami 仅在调试时启用)
    • 配置只读根文件系统
    • 限制 Pod 到必要的命名空间
  5. 多集群 DNS 策略

    • 为不同环境(dev/staging/prod)使用不同集群域
    • 通过 stubDomains 配置跨集群服务发现
    • 使用 CoreDNS federation 插件(实验性)实现全局服务发现
  6. 可观察性增强

    • 集成 Prometheus 和 Grafana 仪表板
    • 配置详细错误日志(仅在调试时)
    • 设置 DNS 查询延迟和错误率告警
    • 采样记录慢查询

一个简单类比#

想象 Kubernetes 集群是一座庞大的智能城市:

  • CoreDNS 是城市的中央查询服务中心(类似电话簿+导航系统)
  • Service 是城市中的公共服务设施(如"中央医院"、“消防局”)
  • Pod 是设施内的具体服务窗口(如"中央医院-急诊室"、“中央医院-门诊”)
  • DNS 查询 是市民的服务请求(“我需要去医院”)

中央查询服务中心(CoreDNS)的工作方式:

  1. 接收请求:市民(Pod)询问"中央医院在哪里?"
  2. 查询数据库:服务中心查询城市数据库(API Server)
  3. 提供地址:返回"中央医院位于第5区,坐标10.96.45.10"
  4. 智能路由:如果是急诊,直接提供最近的急诊窗口地址(Headless Service)
  5. 外部查询:对于"国家图书馆"等外部设施,转接给国家级查询中心(上游 DNS)

当城市扩张时(新服务部署):

  • 无需通知每个市民新设施位置
  • 市民只需记住设施名称
  • 查询服务中心自动更新数据库
  • 所有查询立即指向正确位置

CoreDNS 作为 Kubernetes 服务发现的核心,是微服务架构得以实现的隐形支柱。它将复杂的网络位置抽象为简单的名称,使开发者能够专注于业务逻辑而非网络细节。通过合理配置和监控 CoreDNS,可以显著提升集群的服务发现效率和可靠性,为大规模分布式应用提供坚实基础。

在云原生世界中,CoreDNS 不仅是 DNS 服务器,更是连接所有服务的神经系统。随着服务网格(如 Istio)和多集群架构的普及,CoreDNS 的角色将更加关键,成为连接混合云和多云环境的统一服务发现层。掌握 CoreDNS 的工作原理和优化技巧,是构建生产级 Kubernetes 集群的必备技能。

本文共 3616 字,创建于 Dec 31, 2025

相关标签: Kubernetes, ByAI