在上一篇文章中,介绍了三个在kubernetes中自定义 DNS 条目的不同用例
- 为外部名称添加别名
- 动态将服务添加到另一个域中,而不用运行其他服务器
- 在群集域中添加任意的条目
在该文章中,我们介绍了前两种用例。在本篇文章中,我们将展示如何使用kubernetes插件的fallthrough
选项,以满足第三种用例。
要了解其工作原理,我们首先需要了解 CoreDNS 如何处理请求。这在之前的查询路由 一文中有所介绍,但在这里我们将更加深入地进行讨论。
我们都知道 CoreDNS 会链接插件。但这到底是什么意思呢?为了了解其含义,我们将会剖析一个 Corefile 以及了解如何将其转换成 CoreDNS 内部元素,然后我们将讨论查询是如何通过这些内部元素进行路由的。
考虑一下这个 Corefile
coredns.io:5300 {
file /etc/coredns/zones/coredns.io.db
}
example.io:53 {
errors
log
file /etc/coredns/zones/example.io.db
}
example.net:53 {
file /etc/coredns/zones/example.net.db
}
.:53 {
errors
log
health
rewrite name foo.example.com foo.default.svc.cluster.local
kubernetes cluster.local 10.0.0.0/24
file /etc/coredns/example.db example.org
forward . /etc/resolv.conf
cache 30
}
请注意,此文件中有两个不同的端口:5300 和 53。在内部,每个端口都会产生一个dnsserver.Server
。尽管有四个服务器块(节),但我们只获得两个实际的服务器。CoreDNS 将收集与同一端口相关的所有服务器块并将它们合并到同一dnsserver.Server
中。服务器将多路复用端口上的查询,并根据区域将它们传递到不同的插件链中。它会为该区域选择最具体的匹配服务器块。如果没有匹配的服务器块,则返回SERVFAIL
。这在下图中以可视化的方式进行了展示。
因此,任何特定的查询都会经过一个插件链。插件的顺序在在构建时由plugin.cfg
文件决定,尽管有一些讨论关于在运行时修改该顺序。这就是为什么即使cache
出现在服务器块的末尾,它也不是插件链的结尾。
请注意,在 .:53
服务器块中,我们定义了 health
插件,但它不会出现在图表中。这是由于有一些不同类型的插件。“常规”插件执行请求处理,并出现在插件链中。不过,有一些插件只修改服务器或服务器块的配置。由于它们不包含任何请求时逻辑,因此不会插入到插件链中。工作原理类似于此类插件的一些插件包括:health
、tls
、startup
、shutdown
和 root
插件。
您可以将执行请求时处理的插件分为两组:以某种方式操作请求的插件以及后端插件。后端插件提供了区域和记录数据的不同来源。etcd
、file
和 kubernetes
插件都是后端的范例。
操作请求但不是后端的插件(即,它们不是区域数据的来源)通常会在执行逻辑后将查询传递至下一个插件。例如,rewrite
插件对请求进行更改,然后将其传递出去。在从后续插件返回结果时,它将问题部分还原为原来的样子(以便客户端不会抱怨),但会保留响应并将其传递回客户端。
给定的任何后端通常都是其区域的最后依托对象 - 它会返回结果或为查询返回 NXDOMAIN。不过,有时候这不是期望的行为,因此一些插件支持 fallthrough
选项。当启用 fallthrough
时,如果未找到记录,插件不会返回 NXDOMAIN,而是会将请求向下传递到该链中。接下来在该链中的后端有机会处理该请求。
返回我们最初对 Kubernetes 中这三个用例的讨论,我们现在可以了解我们如何使用 fallthrough
达到第三个用例。记起这篇博文中的初始 Corefile 的
.:53 {
errors
log
health
kubernetes cluster.local 10.0.0.0/24
forward . /etc/resolv.conf
cache 30
}
这涉及处理群集中 DNS 服务发现的标准。第三个用例是向现有集群域添加任意条目。为此,我们要定义另一个用于处理 cluster.local
区域的后端,并在 kubernetes
插件中配置 fallthrough
选项。对于非常动态的条目,我们可用到 etcd
插件。但为了演示目的,使用 file
插件更简单一些,因此我们这么做了。
由于在 plugin.cfg
中kubernetes
位于 file
之前,在 kubernetes
中使用 fallthrough
会导致 file
处理 kubernetes
无法处理的任何查询。这意味着我们需要像之前在博客中处理第二个用例一样拥有一个区域文件作为我们的 ConfigMap 的一部分。不过,在这种情况下,不像配置不同的区域(在另一篇博客中为 example.org
),file
插件被配置为使用 cluster.local
域
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
log
health
kubernetes cluster.local 10.0.0.0/24 {
fallthrough
}
file /etc/coredns/cluster.db cluster.local
forward . /etc/resolv.conf
cache 30
}
cluster.db: |
cluster.local. IN SOA ns.dns.cluster.local. hostmaster.cluster.local. 2015082541 7200 3600 1209600 3600
something.cluster.local. IN A 10.0.0.1
otherthing.cluster.local. IN CNAME google.com.
记住将 cluster.db
文件添加到容器模板的 config-volume
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
- key: cluster.db
path: cluster.db
最后,发信号给 CoreDNS 让它优雅地重新加载(每个正在运行的容器)
$ kubectl -n kube-system exec coredns-461002909-7mp96 -- kill -SIGUSR1 1
现在让我们尝试一下新的 DNS 记录。
$ kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
If you don't see a command prompt, try pressing enter.
/ # host kubernetes
kubernetes.default.svc.cluster.local has address 10.0.0.1
/ # host something
something.cluster.local has address 10.0.0.1
/ # host otherthign
Host otherthign not found: 3(NXDOMAIN)
/ # host otherthing
otherthing.cluster.local is an alias for google.com.
google.com has IPv6 address 2607:f8b0:4005:805::200e
google.com mail is handled by 30 alt2.aspmx.l.google.com.
google.com mail is handled by 50 alt4.aspmx.l.google.com.
google.com mail is handled by 40 alt3.aspmx.l.google.com.
google.com mail is handled by 20 alt1.aspmx.l.google.com.
google.com mail is handled by 10 aspmx.l.google.com.
/ #
我们可以看到如果输入了错误的名称,我们仍然像期望的那样接收 NXDOMAIN。但是,正确的名称会解析为区域文件中的记录。因此,我们现在拥有了一种在集群域中创建自定义条目的方法。
在标准 CoreDNS 版本中,kubernetes
插件位于 file
和 etcd
之前。这意味着它获取处理查询的优先权。如果你愿意,可以重新构建 CoreDNS 以更改该顺序 - 如果想查看如何执行该操作,可以看看 Miek 在 如何将插件添加到 CoreDNS 中的文章。