如我们在 前一篇文章 中所述,CoreDNS 可在 Kubernetes 集群中用于替代 Kube-DNS 进行服务发现。由于 CoreDNS 架构的灵活性,CoreDNS 能够实现一些有意义的用例。在本篇博客中,我们将演示如何解决一个常见问题 - 为你的服务创建自定义 DNS 条目。
这里有几种不同的可能性
- 创建一个外部名称别名
- 将服务动态添加到另一个域,无需运行其他服务器
- 在群集域中添加任意条目
CoreDNS 可以解决所有这些用例。我们从第一种非常常见的情况开始。在这种情况下,你希望能够为给定服务使用相同的名称,无论是在集群内还是外部访问该服务。例如,在使用绑定到该名称的 TLS 证书时,这一点很有用。
假设我们有一个服务,foo.default.svc.cluster.local
,它作为 foo.example.com
供外部客户端使用。也就是说,在集群外部进行查找时,foo.example.com
将解析到负载均衡器 VIP - 服务的外部 IP 地址。在集群内部,它将解析为相同的内容,因此在此内部使用此名称将导致流量转发 - 通过外部 IP 从集群外部转出,然后又转入。相反,我们希望它解析为内部 ClusterIP,避免转发。
为在 CoreDNS 中实现此目的,我们将使用 rewrite
插件。此插件可以在将查询向下发送到链中的任何后端进行应答之前修改查询。回想一下在上一篇博客中使用的 Corefile
(CoreDNS 配置文件)
.:53 {
errors
log
health
kubernetes cluster.local 10.0.0.0/24
forward . /etc/resolv.conf
cache 30
}
为获得所需的行为,我们只需要添加一条重写规则,将 foo.example.com
映射到 foo.default.svc.cluster.local
.:53 {
errors
log
health
rewrite name foo.example.com foo.default.svc.cluster.local
kubernetes cluster.local 10.0.0.0/24
forward . /etc/resolv.conf
cache 30
}
通过 kubectl edit
或 kubectl apply
将其添加到 ConfigMap
后,我们必须让 CoreDNS 知道 Corefile
已更改。你可以向它发送一个 SIGUSR1
以通知它以正常方式重新加载 - 也就是说,不会中断服务
$ kubectl exec -n kube-system coredns-980047985-g2748 -- kill -SIGUSR1 1
运行我们的测试 pod,我们可以看到该方法有效
$ kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
If you don't see a command prompt, try pressing enter.
/ # host foo
foo.default.svc.cluster.local has address 10.0.0.72
/ # host foo.example.com
foo.example.com has address 10.0.0.72
/ # host bar.example.com
Host bar.example.com not found: 3(NXDOMAIN)
/ #
这就解决了第一个问题。
第二个问题也一样容易解决。这里,我们只需要能够在与集群所在域不同的区域中提供 DNS 条目。由于 CoreDNS 是一个通用的 DNS 服务器,除了 kubernetes
插件外,还有很多其他方式可以提供区域。为了简便,我们将使用 file
插件和另一个 ConfigMap
条目来满足此用例。但是,你可以使用 etcd
插件将服务直接存储在 etcd 实例中,也可以使用 auto
插件管理一组区域(与 git-sync 一起使用时非常好)。
要创建新的区域,我们需要修改我们一直在使用的 coredns.yaml
,以便在 pod 中创建附加文件。为此,我们必须通过向 Corefile
添加 file
行,以及为区域文件添加另一个键 example.db
来编辑 ConfigMap
。
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.: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
}
example.db: |
; example.org test file
example.org. IN SOA sns.dns.icann.org. noc.dns.icann.org. 2015082541 7200 3600 1209600 3600
example.org. IN NS b.iana-servers.net.
example.org. IN NS a.iana-servers.net.
example.org. IN A 127.0.0.1
a.b.c.w.example.org. IN TXT "Not a wildcard"
cname.example.org. IN CNAME www.example.net.
service.example.org. IN SRV 8080 10 10 example.org.
我们还需要编辑 Pod
模板规范的 volumes
部分
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
- key: example.db
path: example.db
一旦我们使用 kubectl apply -f
应用此修改,就会创建一个新的 CoreDNS pod,因为卷中的文件是新的。以后对该文件的更改将不需要创建新的 pod,而只需要像之前一样 graceful restart。我们来看一下
$ kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools
If you don't see a command prompt, try pressing enter.
/ # host foo
foo.default.svc.cluster.local has address 10.0.0.72
/ # host foo.example.com
foo.example.com has address 10.0.0.72
/ # host example.org
example.org has address 127.0.0.1
/ #
完美!现在,我们可以编辑该 ConfigMap
,并随时发送 SIGUSR1
来添加 example.org
条目。当然,正如前面提到的,我们还可以使用 etcd
后端,避免修改 ConfigMap
和发送信号的麻烦。
这会给我们带来最后一个问题。可以使用 kubernetes
插件中对 fallthrough
的新支持来解决该问题。此功能已添加到最近发布的 CoreDNS 版本 007 中 - 我们将尽快发布另一篇博文,说明如何使用它。