在 Kubernetes 中,DNS 名称被分配给 Pod 和服务,以便通过名称而不是 IP 地址进行通信。
集群内DNS解析默认使用的域名为cluster.local
,可以根据需要自定义。Service 的 DNS 名称遵循<service-name>.<namespace>.svc.cluster.local
格式,而Pod 的 DNS 名称遵循<pod-ip-address-replace-dot-with-hyphen>.<namespace>.pod.cluster.local
格式。
CoreDNS 的运行基于名为Corefile
的配置文件,该文件指定 DNS 服务器应如何运行并响应传入请求。
Kubernetes:DNS
DNS解析
在 Kubernetes 中,分配给 Pod 和服务的DNS 名称用集群内的名称解析,允许Pod 和服务通过名称而不是 IP 地址相互通信。
行万里路,此处相逢,共话云原生之道。 偶逗趣事,明月清风,与君同坐。
默认域名:cluster.local
在 Kubernetes 中,cluster.local
是集群内用于 DNS 解析的默认域名。当对同一命名空间内的服务或 Pod 进行 DNS 查询时,Kubernetes DNS 服务会将命名空间和cluster.local
后缀附加到名称中,以形成完全限定域名 (FQDN)。虽然它是默认域名,但如果需要,可以自定义使用不同的域名。
Service的 DNS 名称
Kubernetes 中服务的 DNS 名称遵循以下格式:
Service的 DNS 名称
<service-name>.<namespace>.svc.cluster.local
service-name
的是Service的名称,而namespace
表示Service运行的命名空间。
例如,如果一个名为的服务my-service
正在my-namespace
命名空间中运行,则相应的 DNS 名称将为:
my-service.my-namespace.svc.cluster.local
Pod 的 DNS 名称
Kubernetes 中 Pod 的 DNS 名称遵循以下格式:
Pod 的 DNS 名称
<pod-ip-address-replace-dot-with-hyphen>.<namespace>.pod.cluster.local
pod-ip-address-replace-dot-with-hyphen
是 Kubernetes 分配给 Pod 的 IP 地址,其中点由连字符替换。namespace
是Pod 运行所在的命名空间。
例如,如果具有10.1.2.3
IP 地址的 Pod在my-namespace
命名空间中运行,则其 DNS 名称将为:
10-1-2-3.my-namespace.pod.cluster.local
使用 DNS 名称进行 Pod 和服务交互
同一命名空间中的 Pod 和服务
当 Pod 和 Services 位于同一命名空间时,你可以使用服务名称而不是完全限定域名 (FQDN)通过查询访问 Services。
同一命名空间中的 Pod 和服务
不同命名空间中的 Pod 和服务
当 Kubernetes 中 Pod 和 Service 位于不同的命名空间时,需要同时指定Service 名称和命名空间,才能从 Pod 访问 Service。
不同命名空间中的 Pod 和服务
CoreDNS
在引入 CoreDNS 之前,Kubernetes 使用kube-dns作为默认的 DNS 解决方案。DNS 服务器处理集群中服务和 Pod 的 DNS 请求。根据Kubernetes 官方文档,从 1.11 版本开始,推荐使用 CoreDNS 作为默认 DNS 解决方案,并默认与 kubeadm 一起安装。
配置文件:核心文件
Corefile 是一个文本文件,指定 DNS 服务器应如何操作和响应传入请求。
核心文件示例:
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
集群的顶级域名在Kubernetes 插件配置中指定为“ cluster.local ” 。该插件还配置为使用 in-addr.arpa
和 ip6.arpa
域处理 IPv4 和 IPv6 地址的反向 DNS 查找。
要了解有关 Corefile 及其语法的更多信息,请参阅CoreDNS Manual或CoreDNS ConfigMap options中提供的官方文档。
CoreDNS 指标
DNS服务器将记录存储在其数据库中并使用该数据库回答域名查询。如果 DNS 服务器没有此数据,它会尝试从其他 DNS 服务器寻找解决方案。
DNS 解析是任何应用程序的基本要求,因此你需要确保其正常工作。我们建议查看dns-debugging-resolution故障排除指南,并确保你的 CoreDNS 已配置并正确运行。
默认情况下,当你配置集群时,你应该始终有一个仪表板来观察关键的 CoreDNS 指标。为了获取 CoreDNS 指标,你应该在 CoreDNS 配置中启用Prometheus 插件。
下面的示例配置使用prometheus
插件启用从 CoreDNS 实例收集指标。
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods verified
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
以下是我们建议在你的仪表板中包含的关键指标。如果你使用 Prometheus、DataDog、Kibana 等,你可能会发现可以使用来自社区/提供商的仪表板模板。
- • 缓存命中百分比:使用 CoreDNS 缓存响应的请求的百分比
- • DNS 请求延迟 - CoreDNS:CoreDNS 处理 DNS 请求所花费的时间 - 上游服务器:处理转发到上游的 DNS 请求所花费的时间
- • 转发到上游服务器的请求数
- • 请求的错误代码 - NXDomain:不存在的域 - FormErr:DNS 请求中的格式错误 - ServFail:服务器故障 - NoError:无错误,已成功处理请求
- • CoreDNS 资源使用情况:服务器消耗的不同资源,如内存、CPU 等。
我们使用 DataDog 进行特定应用程序监控。以下只是我使用 DataDog 构建的用于分析的示例仪表板。
CoreDNS 指标
减少 DNS 搜索
当我们开始深入了解应用程序如何向 CoreDNS 发出请求时,我们观察到大多数出站请求是通过应用程序发送到外部 API 服务器的。
这通常是 resolv.conf 在应用程序部署 Pod 中的外观。
nameserver 10.100.0.10
search kube-namespace.svc.cluster.local svc.cluster.local cluster.local us-west-2.compute.internal
options ndots:5
如果你了解 Kubernetes 如何尝试解析 FQDN,就知道它会尝试在不同级别进行 DNS 查找。
考虑到上述 DNS 配置,当 DNS 解析器向 CoreDNS 服务器发送查询时,它会尝试考虑搜索路径来搜索域。
如果我们正在寻找域名 boktube.io,它将进行以下查询,并在最后一个查询中收到成功的响应。
botkube.io.kube-namespace.svc.cluster.local <= NXDomain
botkube.io.svc.cluster.local <= NXDomain
boktube.io.cluster.local <= NXDomain
botkube.io.us-west-2.compute.internal <= NXDomain
botkube.io <= NoERROR
由于我们进行了太多的外部查找,因此我们收到了大量针对 DNS 搜索的 NXDomain 响应。为了优化这一点,我们spec.template.spec.dnsConfig
在 Deployment 对象中进行了自定义。变化是这样的:
dnsPolicy: ClusterFirst
dnsConfig:
options:
- name: ndots
value: "1"
通过上述更改,pod 上的resolve.conf 发生了更改。仅针对外部域执行搜索。这减少了对 DNS 服务器的查询数量。这也有助于减少应用程序的 5xx 错误。你可以在下图中注意到 NXDomain 响应计数的差异。
减少 DNS 搜索
对于这个问题,一个更好的解决方案是Kubernetes 1.18+ 引入的节点级缓存。
定制 CoreDNS
我们可以通过插件来定制CoreDNS。Kubernetes 支持不同类型的工作负载,标准 CoreDNS 配置可能无法满足你的所有需求。CoreDNS 有几个插件。根据你在集群上运行的工作负载类型(假设相互通信的应用程序或在 Kubernetes 集群外部交互的独立应用程序),你尝试解析的 FQDN 类型可能会有所不同。
假设你在特定的公共/私有云中运行 Kubernetes,并且大多数 DNS 支持的应用程序都在同一云中。在这种情况下,CoreDNS 还提供特定的云相关或通用插件,可用于扩展 DNS 区域记录。
是否在 Kubernetes 集群中运行适当数量的 CoreDNS 实例是需要做出决定的关键因素之一。建议运行至少两个 CoreDNS 服务器实例,以更好地保证 DNS 请求得到服务。根据所服务的请求数量、请求性质、集群上运行的工作负载数量以及集群大小,你可能需要添加额外的 CoreDNS 实例或为集群配置 HPA。