在 Kubernetes 语境里,CoreDNS 常被压缩成一句很实用的话:它就是集群的 DNS 服务器。这句话当然成立,入口也足够清楚,不过它把项目内部最值得理解的那层设计盖住了。[1][2][4] CoreDNS 手册写得很直接,这台服务器几乎所有能力都通过插件组织起来,而并非焊接成一块单体二进制。[2] 配置文档随后又补上一条极关键的规则:Corefile 里的书写顺序,并不决定插件执行顺序;真正的链路顺序来自 plugin.cfg,也就是说,配置文件看上去很灵活,实际始终落在一张预编译插件图的边界里。[3]

把这个前提带进 CNCF 的 Understanding CoreDNS in Kubernetes,整场视频会一下子变得更清楚。[1] 它真正有用的地方,不在于重复一遍 DNS 基础,也不在于演示几条 Kubernetes 命令。更深的一层在于,讲者不断把 CoreDNS 拉回“有边界的运行时”这个位置。某一组插件只对特定命名空间拥有权威回答能力,一些配套插件围绕这块权威区添加行为,区外的名字则被明确送去别处处理。[1][3][4][5]

今天的官方文档仍然支持这种读法。手册用插件组合来定义 CoreDNS。[2] 配置页解释 server block、directives 与编译期插件顺序。[3] kubernetes 插件页面则说明,这个插件会 watch Kubernetes 对象,并只对自己被配置为权威的 zone 回答;当查询落到这条边界之外,forwarding 或 fallthrough 才接手。[4] 顺着视频与这些文档一起读,我更愿意把 CoreDNS 看成一套边界非常清楚的插件运行时,而并非一个会自动吞下所有命名问题的“集群 DNS 盒子”。[1][3][4]

带着这个视角回看视频,很多行为都会重新长出解释力。watch 循环不再像一团背景机制,上游解析器的交接也不再像附带功能,pod 回答模式与编译期插件顺序则一起说明,CoreDNS 从一开始就不打算把自己做成一层没有边界的动态脚本环境。[1][2][3][4]

配图说明:题图使用 John Belamaric 的真实 GitHub 头像。这个选择合适,因为本文围绕的是维护者对 CoreDNS 内部机制与操作边界的讲解。最重要的视觉锚点,是解释系统的人,而并非通用服务器照片或人为拼接的 DNS 示意图。[6]

大约从 4:19 开始,“集群 DNS” 很快就被重新说成了 “CoreDNS 里的 Kubernetes service discovery”

视频前段最值得停一下的地方,是讲者提到 CoreDNS 对 Kubernetes service discovery 的原生支持,并说明它后来成了 Kubernetes 1.13 的默认 DNS 服务器。[1] 这句话看上去像背景介绍,实际已经把项目位置说得更准了一步。关键点不在于 CoreDNS 恰好跑在 Kubernetes 旁边,关键点在于,Kubernetes 命名这一层是通过一个明确的插件式发现面落进 CoreDNS 里的。[1][4]

kubernetes 插件页面用更冷静的语言说的是同一件事。这个插件实现 Kubernetes DNS-Based Service Discovery 规范,可以替代 kube-dns,并对自己被配置负责的 zone 提供权威回答。[4] 这已经比“CoreDNS 知道整个集群的所有名字”要收得更紧。它知道的,是这组 zone 与对象类型之内的那部分命名事实。手册对 CoreDNS 的总定义又把原因补齐了:插件才是 DNS function 的单位,所以 Kubernetes 支持属于由插件定义出来的一块回答表面。[2]

这正是视频前段最有价值的地方。它让 Kubernetes 里的 CoreDNS 不再只是“默认组件”那种平铺描述。CoreDNS 并非天然等于那只 DNS Pod,它更像一台插件化 DNS 服务器,而 Kubernetes 刚好是其中最重要的一块权威数据来源。[1][2][4]

大约从 8:32 与 13:58 开始,架构把 watch 到的集群状态与上游递归解析分得很开

下一段真正把结构讲开的地方,出现在讲者说明 CoreDNS 会连接 Kubernetes API、watch Services、Pods 与 Endpoints,回答属于集群内部的名字,再把边界外的查询转交给上游解析器的时候。[1] 这几分钟几乎把整个操作模型说完了,因为它明确指出了“事实从哪里来”。集群内服务发现来自 watch;集群外命名则被有意交给别人处理。[1][4]

文档与视频在这里几乎完全重合。kubernetes 插件页面说明,插件可以在集群内连接 API,也可以连接远端 API server,还明确写出 stubDomainsupstreamNameservers 是通过 forward 插件实现的。[4] 同一页还说,这个插件在一个 server block 里只能使用一次。这条规则的分量很大,因为它提醒你,这块权威回答面从设计上就要保持可读,而并非在一个逻辑服务器里无限复制。[4] 配置文档从另一侧把这种克制固定下来:一个 server block 定义的是一条面向某个 zone 范围的插件链路,并非一团随时变形的运行时脚本。[3]

这也是 forwarding 在这场视频里如此重要的原因。它并非服务发现之后顺手带上的补丁功能,它就是边界本身。CoreDNS 没有假装 Kubernetes 是通用命名权威。它只对 cluster-local 的知识负责,再把其余查询交给上游 DNS。这个边界一旦记牢,很多排障问题都会自动变简单:一个名字要么属于被 watch 的集群 zone,要么已经越过边界,落到 forwarding 路径里去了。[1][4]

大约从 22:55 开始,kubernetes 插件的几个选项把 CoreDNS 最严格的地方直接摊开了

视频后段 John Belamaric 讲到 kubernetes 插件几个常见选项的时候,这套“有边界的运行时”判断第一次完全落地。[1] 他解释了 service 子域、独立的 pod 命名空间,以及 kube-dns 过去那种“只要看起来像 IP 地址就回一个结果”的宽松做法。接着视频指出,CoreDNS 给出了更严格的模式,运维者可以把 pod 回答完全关掉,也可以要求系统只在目标 pod 真实存在于该 namespace 时才给出结果。[1]

当前文档把这些模式写得很清楚。pods disabled 会返回 NXDOMAINpods insecure 会直接回显请求里的 IP;pods verified 只有在对应 pod 真正存在时才回答,同时它也会付出更高的内存成本,因为 CoreDNS 需要维护针对全部 pod 的 watch。[4] 页面还列出了 endpoint_pod_namesnoendpoints、namespace 过滤、label 过滤,以及默认 5 秒 TTL 这些行为。[4] 这些都属于把“权威回答范围”收紧或放宽、并把成本写在明处的操作做法。

所以这段视频最重要的地方,并不只是“这里有几个 knob 可以调”。它更像是在说明,CoreDNS 认为什么样的 DNS 行为值得被信任。kube-dns 那种宽松回应方式当然方便,不过 CoreDNS 更希望运维者明确表态:你究竟要便利,还是要可验证的回答与可见的资源成本。[1][4]

大约从 26:17 开始,最后一道边界才出现:连插件灵活性本身也受编译期秩序约束

整场视频最锋利的一个时刻,出现在讲者提醒观众:默认镜像会把一组插件编译进去,这些插件并非运行后再动态装载的,连它们的顺序也在编译期就定下来了。[1] CoreDNS 配置文档把这一点写得没有歧义:Corefile 中插件的书写顺序,不决定执行顺序;真正的顺序由 plugin.cfg 决定。[3]

这条规则很容易被忽略,不过它恰好是把整个系统收拢起来的力量。CoreDNS 之所以显得极其灵活,是因为 Corefile 很短,插件目录又很大。[2][5] 插件页把 in-tree 模块列成一张近乎菜单式的目录,这种感觉会更强。[5] 视频与文档放在一起读,就会发现这份灵活性其实一直在边界里。CoreDNS 并非一套可以在运行时任意重排内部结构的自由环境。它是一套边界非常鲜明的运行时:编译出来的插件图先定义可强制执行范围,Corefile 再在这个范围里选择并配置具体行为。[1][3][5]

这也是这支视频今天仍值得看的原因。它把 CoreDNS 讲得很老实。Kubernetes 服务发现来自 watch 状态,不来自魔法。集群外命名通过上游解析器处理,不落在集群权威里。pod 回答模式是一种策略选择,带着明确代价。连那套著名的插件模型,也始终受编译期顺序约束,好让请求路径保持可预测。[1][2][3][4][5] 一旦沿着这些边界去理解 CoreDNS,它就不再只是 Kubernetes 默认件,而会显露出更准确的形状:一套有边界、有权威范围、有编译期秩序的插件运行时。

来源

  1. CNCF,《Understanding CoreDNS in Kubernetes - John Belamaric, Google & Cricket Liu, Francois Tur, Infoblox》,YouTube 视频,发布于 2018 年 12 月 16 日。
  2. CoreDNS Manual,《What is CoreDNS?》——以插件为中心定义服务器与 DNS function。
  3. CoreDNS Manual,《Configuration》——Corefile 结构、server block,以及通过 plugin.cfg 确定编译期插件顺序的规则。
  4. CoreDNS documentation,《kubernetes plugin》——zone 权威范围、watch 行为、pod 模式、TTL 默认值与 forwarding 说明。
  5. CoreDNS documentation,《Plugins》——in-tree 插件目录与当前项目插件表面。
  6. GitHub,《johnbelamaric》——本文配图来源页面。