💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
本人主要分享计算机核心技术:系统维护、数据库、网络安全、自动化运维、容器技术、云计算、人工智能、运维开发、算法结构、物联网、JAVA 、Python、PHP、C、C++等。
不同类型针对性训练,提升逻辑思维,剑指大厂,非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。
Kubernetes的域名解析方案CoreDNS
1. CoreDNS与Kubernetes
1.1 CoreDNS简介
CoreDNS 是一个灵活可扩展的 DNS 服务器,可以作为 Kubernetes 集群 DNS。与 Kubernetes 一样,CoreDNS 项目由 CNCF 托管。
借助CoreDNS 服务器,可以将 Kubernetes 服务名称解析为相应的 IP 地址。支持正向查找(A 和 AAAA 记录)、端口发现(SRV 记录)、反向 IP 地址发现(PTR 记录)等。
通过替换现有集群部署中的 kube-dns,或者使用 kubeadm 等工具来为你部署和升级集群,可以在你的集群中使用 CoreDNS 而非 kube-dns。
1.2 CoreDNS 插件架构
CoreDNS是一种灵活、可扩展的 DNS 服务器,借助插件架构,允许用户根据需求自定义功能。与其他 DNS 服务器BIND、Knot、PowerDNS不同,CoreDNS 非常灵活,几乎所有功能都交给插件去实现。
默认的 CoreDNS 安装中包含了大约 30 个插件,还可以编译许多外部插件到 CoreDNS 中,以扩展其功能。
CoreDNS 的插件架构使其具有很强的可扩展性。每个插件负责处理特定类型的 DNS 请求或提供特定的功能。例如:
-
kubernetes 插件:用于解析 Kubernetes 服务和 Pod 的 DNS 名称。
-
hosts 插件:用于从 hosts 文件中解析名称。
-
file 插件:用于从区域文件中解析名称。
1.3 版本配套情况
Kubernetes从1.09版本开始支持CoreDNS作为集群的DNS应用。在 Kubernetes 1.21 版本中,kubeadm 移除了对将 kube-dns
作为 DNS 应用的支持;在 kubeadm
v1.31,CoreDNS是支持的唯一的集群 DNS 应用。
当你使用 kubeadm
升级使用 kube-dns
的集群时,你还可以执行到 CoreDNS 的迁移。在这种场景中,kubeadm
将基于 kube-dns
ConfigMap 生成 CoreDNS 配置("Corefile"), 保存存根域和上游名称服务器的配置。
Kubernetes 中的 CoreDNS 版本 页面记录了 kubeadm 安装的 Kubernetes 版本和 CoreDNS 版本配套关系。以下是部分内容:
Kubernetes Version | CoreDNS version installed by kubeadm | Changes in CoreDNS from previous release to Kubernetes |
v1.30 | v1.11.1 | |
v1.29 | v1.11.1 | |
v1.28 | v1.10.1 | |
v1.27 | v1.10.1 | |
v1.26 | v1.9.3 | |
v1.25 | v1.9.3 | |
v1.24 | v1.8.6 | |
v1.23 | v1.8.6 | https://github.com/coredns/coredns/blob/master/notes/coredns-1.8.5.md https://github.com/coredns/coredns/blob/master/notes/coredns-1.8.6.md |
v1.22 | v1.8.4 | https://github.com/coredns/coredns/blob/master/notes/coredns-1.8.1.md https://github.com/coredns/coredns/blob/master/notes/coredns-1.8.2.md https://github.com/coredns/coredns/blob/master/notes/coredns-1.8.3.md https://github.com/coredns/coredns/blob/master/notes/coredns-1.8.4.md ---NOTE--- CoreDNS must be granted list and watch access to EndpointSlices |
v1.21 | v1.8.0 | https://github.com/coredns/coredns/blob/master/notes/coredns-1.7.1.md https://github.com/coredns/coredns/blob/master/notes/coredns-1.8.0.md ---DEPRECATIONS--- The transfer option in the kubernetes plugin has been removed. Zone transfers can be enabled with the new transfer plugin. |
v1.20 | v1.7.0 | |
... | ... | ... |
v1.09 | v1.0.1 | The v1.0.1 was the first version of CoreDNS to be shipped with Kubernetes. |
1.4 CoreDNS在kubernetes下的工作原理
CoreDNS 在 Kubernetes 中作为一个 Deployment 运行,通常会部署两个或多个副本以确保高可用性。它主要通过以下步骤工作:
-
启动与配置:CoreDNS 读取 ConfigMap 配置文件,根据配置启动相应的插件。
-
监听 DNS 请求:CoreDNS 监听来自 Kubernetes 集群内部的 DNS 请求。
-
解析 DNS 请求:根据请求的类型,CoreDNS 调用相应的插件进行解析。例如,对于
kube-dns
插件,CoreDNS 会查询 Kubernetes API 服务器以获取服务的 IP 地址。 -
返回解析结果:将解析结果返回给请求方。
2. 理解CoreDNS配置
下面是由kubeadm附带的CoreDNS配置,保存在kubernetes集群名为coredns
的configmap中:
[root@k8s ~]# kubectl -n kube-system get configmap coredns -oyaml
apiVersion: v1
data:
Corefile: |
.: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 {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
creationTimestamp: "2024-06-11T14:02:11Z"
name: coredns
namespace: kube-system
resourceVersion: "250"
uid: 3b716ad5-50a7-4d87-9178-a47797b91c8a
.:53
: 这里的 .
表示 CoreDNS 处理所有域名请求(根域名),53
是 CoreDNS 监听的端口号(标准 DNS 端口)。
Corefile 部分是 CoreDNS 的配置。这份配置基于以下 CoreDNS 插件:
-
errors:
errors
插件会将错误信息输出到 标准输出。当 DNS 请求过程中发生错误时,该插件会将错误日志记录下来,方便调试和排错。 -
health:
health
插件提供了一个 HTTP 健康检查接口,默认监听地址是http://localhost:8080/health
,提供 CoreDNS 的健康报告。kubelet
会定期检查 CoreDNS 的健康状况,确定其是否正常运行。lameduck
是一个新增加的选项。它指定在 CoreDNS 被标记为不健康后,CoreDNS 在关闭之前仍然会继续响应请求的时间(这里是 5 秒)。这允许在 CoreDNS 实例停止或被替换时,已有的请求有一个缓冲期可以继续完成,而不会立即中断。 -
ready:
ready
插件用于确保在 CoreDNS 完全准备好处理 DNS 请求之前,不会将其标记为可用,在端口 8181 上提供的一个 HTTP 端点, 当所有能够表达自身就绪的插件都已就绪时,在此端点返回 200 OK。这在启动时非常有用,确保其他服务只有在 CoreDNS 完全加载所有配置并处于健康状态时,才会开始依赖它的解析服务。 -
kubernetes:
kubernetes
插件是 CoreDNS 的核心部分,它为 Kubernetes 集群提供 DNS 服务,基于服务和 Pod 的 IP 来应答 DNS 查询。。-
kubernetes
插件根据 Kubernetes 的服务和 Pod 的 IP 地址解析 DNS 查询。 -
cluster.local
是默认的 Cluster Domain(集群域名),即服务的默认后缀,比如foo.default.svc.cluster.local
。 -
in-addr.arpa
和ip6.arpa
处理反向 DNS 查询(将 IP 地址解析为域名)。 -
pods insecure
选项表示为了向后兼容 kube-dns。 -
fallthrough
选项用于指定如果某个域没有被 CoreDNS 处理,则将该请求传递给下一个 DNS 解析插件处理。 -
ttl
选项用于定制响应的 TTL。默认值是 5 秒钟。TTL 的最小值可以是 0 秒钟, 最大值为 3600 秒。将 TTL 设置为 0 可以禁止对 DNS 记录进行缓存。
-
-
prometheus:
prometheus
插件用于暴露 CoreDNS 的指标,供 Prometheus 监控系统收集。CoreDNS 的度量指标值以 Prometheus 格式(也称为 OpenMetrics)在http://localhost:9153/metrics
上提供。 -
forward:不在 Kubernetes 集群域内的任何查询都将转发到预定义的解析器 (
/etc/resolv.conf
)。max_concurrent 1000
指定了forward
插件在处理 DNS 查询时的最大并发请求数,这里设置为 1000。这个选项可以限制 CoreDNS 向上游 DNS 服务器同时发出的请求数量,避免因为过多的并发查询导致上游服务器超载或 DNS 查询超时。 -
cache:
cache
插件用于启用前端缓存,以提高 DNS 查询的响应速度并减少对上游 DNS 服务器的依赖。即当 DNS 请求命中缓存时,会直接返回缓存结果,而不再进行外部查询。这里配置 30 秒的DNS 解析缓存生存时间(TTL),TTL 控制了客户端的 DNS 缓存持续时间,TTL 较短意味着 DNS 解析会更频繁地更新,而较长的 TTL 可以减少解析请求的频率,但可能会延迟变更的生效。 -
loop:
loop
插件用于检测和防止 DNS 循环(DNS 循环是指 DNS 请求在多级 DNS 服务器之间不断循环而无法得到解析结果的情况)。如果发现死循环,则中止 CoreDNS 进程。 -
reload:
reload
插件允许 CoreDNS 在 Corefile 文件内容发生变更时自动重新加载配置。当你对 Corefile 文件进行修改后,不需要重启 CoreDNS 进程,它会自动应用新的配置。编辑 ConfigMap 配置后,请等待两分钟,以使更改生效。 -
loadbalance: 这是一个轮转式 DNS 负载均衡器, 它在应答中随机分配 A、AAAA 和 MX 记录的顺序。这对分散流量到多个后端服务特别有用。
此外,在较老版本中,DNS转发配置还可能见到upstream
和proxy
配置。
# kubectl -n kube-system get configmap coredns -oyaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local 10.96.0.0/12 {
pods insecure
upstream /etc/resolv.conf
}
prometheus :9153
proxy . /etc/resolv.conf
cache 30
}
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-21T12:55:15Z
name: coredns
namespace: kube-system
resourceVersion: "161"
selfLink: /api/v1/namespaces/kube-system/configmaps/coredns
uid: 30bf0882-e64e-11e7-baf6-0cc47a8055d6
在较新的版本中,上述功能已经被forward
插件替代。
3. CoreDNS功能验证
在CoreDNS部署运行正常后,测试Kubernetes内部域名的解析功能:
[root@k8s ~]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 80d
harbor harbor-core ClusterIP 10.101.2.50 <none> 80/TCP 47d
harbor harbor-database ClusterIP 10.99.23.171 <none> 5432/TCP 47d
harbor harbor-jobservice ClusterIP 10.99.108.96 <none> 80/TCP 47d
harbor harbor-portal ClusterIP 10.99.110.218 <none> 80/TCP 47d
harbor harbor-redis ClusterIP 10.103.117.94 <none> 6379/TCP 47d
harbor harbor-registry ClusterIP 10.104.89.36 <none> 5000/TCP,8080/TCP 47d
harbor harbor-trivy ClusterIP 10.107.222.192 <none> 8080/TCP 47d
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 80d
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.102.9.117 <none> 8000/TCP 76d
kubernetes-dashboard kubernetes-dashboard NodePort 10.97.21.53 <none> 443:31930/TCP 76d
# 在节点上使用dig命令解析kubernetes服务,指定dns为kube-dns
[root@k8s ~]# dig @10.96.0.10 kubernetes.default.svc.cluster.local +noall +answer
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.16 <<>> @10.96.0.10 kubernetes.default.svc.cluster.local +noall +answer
; (1 server found)
;; global options: +cmd
kubernetes.default.svc.cluster.local. 30 IN A 10.96.0.1
# 解析 kubernetes-dashboard服务
[root@k8s ~]# dig @10.96.0.10 kubernetes-dashboard.kubernetes-dashboard.svc.cluster.local +noall +answer
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7_9.16 <<>> @10.96.0.10 kubernetes-dashboard.kubernetes-dashboard.svc.cluster.local +noall +answer
; (1 server found)
;; global options: +cmd
kubernetes-dashboard.kubernetes-dashboard.svc.cluster.local. 30 IN A 10.97.21.53
# 在容器内部解析集群服务域名
[root@k8s ~]# kubectl run -i --tty --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default.svc.cluster.local
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: kubernetes.default.svc.cluster.local
Address: 10.96.0.1
pod "debug" deleted
可以看到通过dig指定kube-dns解析集群内的svc,可以获取到svc对应的IP。
4. 使用CoreDNS配置外部域名解析
4.1 使用 CoreDNS 配置存根域和上游域名服务器
CoreDNS 能够使用 forward 插件配置存根域和上游域名服务器,这样对于非Kubernetes集群的域名访问,可以将解析任务交给上游域名服务器。示例如下:
如果集群操作员在 "10.150.0.1" 处运行了 Consul 域服务器, 且所有 Consul 名称都带有后缀 .consul.local
。要在 CoreDNS 中对其进行配置, 集群管理员可以在 CoreDNS 的 ConfigMap 中创建加入以下字段。
consul.local:53 {
errors
cache 30
forward . 10.150.0.1
}
要显式强制所有非集群 DNS 查找通过特定的域名服务器(位于 172.16.0.1),可将 forward
指向该域名服务器,而不是 /etc/resolv.conf
。
forward . 172.16.0.1
最终的包含默认的 Corefile
配置的 ConfigMap 如下所示:
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . 172.16.0.1
cache 30
loop
reload
loadbalance
}
consul.local:53 {
errors
cache 30
forward . 10.150.0.1
}
说明:
CoreDNS 不支持 FQDN 作为存根域和域名服务器(例如 "ns.foo.com")。转换期间,CoreDNS 配置中将忽略所有的 FQDN 域名服务器。
4.2 配置hosts解析
CoreDNS 的 hosts
插件用于将域名解析指向固定的 IP 地址,类似于操作系统中的 /etc/hosts
文件。该插件允许将域名解析存储在 CoreDNS 的配置中,以便在 CoreDNS 收到相应的查询时,直接返回这些 IP 地址,而无需再向上游 DNS 服务器请求解析。
hosts
插件配置示例
以下是一个简单的 Corefile
示例,展示了如何配置 hosts
插件:
.:53 {
errors
health
hosts /etc/coredns/hosts {
ttl 60
fallthrough
}
kubernetes cluster.local in-addr.arpa ip6.arpa
prometheus :9153
forward . 8.8.8.8
cache 30
reload
loadbalance
}
解释:
-
hosts /etc/coredns/hosts
:指定一个外部的 hosts 文件(类似于
/etc/hosts
),该文件中包含域名与 IP 地址的静态映射。例如:192.168.1.10 example.com 192.168.1.20 another-example.com
CoreDNS 会读取此文件,并根据文件中的映射返回相应的 IP 地址。
-
ttl 60
: 指定返回的 DNS 记录的生存时间(TTL),这里设置为 60 秒。也就是说,客户端可以在 60 秒内缓存这个解析结果。 -
fallthrough
: 如果查询的域名不在hosts
文件中,将继续传递给下一个插件处理,比如kubernetes
或forward
插件。如果不加这个选项,未匹配到的查询会被丢弃。
内联配置 hosts
hosts
插件也可以直接在 Corefile 中定义静态域名解析,不依赖于外部的 hosts
文件:
.:53 {
errors
health
hosts {
192.168.1.10 example.com
192.168.1.20 another-example.com
fallthrough
}
kubernetes cluster.local in-addr.arpa ip6.arpa
prometheus :9153
forward . 8.8.8.8
cache 30
reload
loadbalance
}
5. CoreDNS的安装、迁移及升级
5.1 安装 CoreDNS
如果是较新版本的kubeadm
部署的Kubernetes
环境,默认就会使用CoreDNS作为默认DNS方案。有关手动部署或替换 kube-dns,请参阅 CoreDNS 网站。
5.2 迁移到CoreDNS
在 Kubernetes 1.21 版本中,kubeadm 移除了对将 kube-dns 作为 DNS 应用的支持。对于 kubeadm v1.31,所支持的唯一的集群 DNS 应用是 CoreDNS。
当你使用 kubeadm 升级使用 kube-dns 的集群时,你还可以执行到 CoreDNS 的迁移。在这种场景中,kubeadm 将基于 kube-dns ConfigMap 生成 CoreDNS 配置("Corefile"), 保存存根域和上游名称服务器的配置。
5.3 升级 CoreDNS
如果你只想升级 CoreDNS 或使用自己的定制镜像,也可以手动升级 CoreDNS。参看指南和演练 文档了解如何平滑升级。在升级你的集群过程中,请确保现有 CoreDNS 的配置("Corefile")被保留下来。
如果使用 kubeadm
工具来升级集群,则 kubeadm
可以自动处理保留现有 CoreDNS 配置这一事项。
如果使用 kubeadm 工具来升级集群,则 kubeadm 可以自动处理保留现有 CoreDNS 配置这一事项。
6. DNS 问题排查
如果DNS解析遇到问题,可以参考下面的流程进行troubshooting,内容参考自调试 DNS 问题 | Kubernetes。
6.1 创建一个简单的 Pod 作为测试环境(可选)
创建一个Pod用作测试环境。
# admin/dns/dnsutils.yaml
apiVersion: v1
kind: Pod
metadata:
name: dnsutils
namespace: default
spec:
containers:
- name: dnsutils
image: registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3
command:
- sleep
- "infinity"
imagePullPolicy: IfNotPresent
restartPolicy: Always
说明:
此示例在
default
名字空间创建 Pod。DNS 名字解析取决于 Pod 的名字空间。详细信息请查阅 Pod 与 Service 的 DNS。
使用上面的清单来创建一个 Pod:
kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml
pod/dnsutils created
验证其状态:
kubectl get pods dnsutils
NAME READY STATUS RESTARTS AGE
dnsutils 1/1 Running 0 <some-time>
一旦 Pod 处于运行状态,你就可以在该环境里执行 nslookup
。如果你看到类似下列的内容,则表示 DNS 是正常运行的。
kubectl exec -i -t dnsutils -- nslookup kubernetes.default
输出为:
Server: 10.0.0.10
Address 1: 10.0.0.10
Name: kubernetes.default
Address 1: 10.0.0.1
如果 nslookup
命令执行失败,按照下面的思路进行排查。
6.2 排查思路
这里以上面创建的jessie-dnsutils作为示例说明一下排查思路,实践中可根据自己的环境对有问题的应用进行排查。
先检查本地的 DNS 配置
查看 resolv.conf 文件的内容:
kubectl exec -ti dnsutils -- cat /etc/resolv.conf
验证 search 和 nameserver 的配置是否与下面的内容类似 (注意 search 根据不同的云提供商可能会有所不同):
search default.svc.cluster.local svc.cluster.local cluster.local google.internal c.gce_project_id.internal
nameserver 10.0.0.10 # 10.0.0.10为kube-dns的svc cluster-ip
options ndots:5
下列错误表示 CoreDNS (或 kube-dns)插件或者相关服务出现了问题:
kubectl exec -i -t dnsutils -- nslookup kubernetes.default
输出为:
Server: 10.0.0.10
Address 1: 10.0.0.10
nslookup: can't resolve 'kubernetes.default'
提示无法解析'kubernetes.default
。
检查 DNS Pod 是否运行
使用 kubectl get pods
命令来验证 DNS Pod 是否运行。
kubectl get pods --namespace=kube-system -l k8s-app=kube-dns
输出为:
NAME READY STATUS RESTARTS AGE
...
coredns-7b96bf9f76-5hsxb 1/1 Running 0 1h
coredns-7b96bf9f76-mvmmt 1/1 Running 0 1h
...
说明:
对于 CoreDNS 和 kube-dns 部署而言,标签
k8s-app
的值都应该是kube-dns
。
如果你发现没有 CoreDNS Pod 在运行,或者该 Pod 的状态是 failed 或者 completed, 那可能这个 DNS 插件在你当前的环境里并没有成功部署,你将需要手动去部署它。
检查 DNS Pod 里的错误
使用 kubectl logs
命令来查看 DNS 容器的日志信息。
如查看 CoreDNS 的日志信息:
kubectl logs --namespace=kube-system -l k8s-app=kube-dns
下列是一个正常运行的 CoreDNS 日志信息:
.:53
2018/08/15 14:37:17 [INFO] CoreDNS-1.2.2
2018/08/15 14:37:17 [INFO] linux/amd64, go1.10.3, 2e322f6
CoreDNS-1.2.2
linux/amd64, go1.10.3, 2e322f6
2018/08/15 14:37:17 [INFO] plugin/reload: Running configuration MD5 = 24e6c59e83ce706f07bcc82c31b1ea1c
查看是否日志中有一些可疑的或者意外的消息。
检查是否启用了 DNS 服务
使用 kubectl get service
命令来检查 DNS 服务是否已经启用。
kubectl get svc --namespace=kube-system
输出为:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
...
kube-dns ClusterIP 10.0.0.10 <none> 53/UDP,53/TCP 1h
...
说明
不管是 CoreDNS 还是 kube-dns,这个服务的名字都会是
kube-dns
。
如果你已经创建了 DNS 服务,或者该服务应该是默认自动创建的但是它并没有出现, 请阅读调试服务 来获取更多信息。
DNS 的端点公开了吗?
你可以使用 kubectl get endpoints
命令来验证 DNS 的端点是否公开了。
kubectl get endpoints kube-dns --namespace=kube-system
NAME ENDPOINTS AGE
kube-dns 10.180.3.17:53,10.180.3.17:53 1h
如果你没看到对应的端点,请阅读 调试服务的端点部分。
DNS 查询有被接收或者执行吗?
你可以通过给 CoreDNS 的配置文件(也叫 Corefile)添加 log
插件来检查查询是否被正确接收。CoreDNS 的 Corefile 被保存在一个叫 coredns
的 ConfigMap 里,使用下列命令来编辑它:
kubectl -n kube-system edit configmap coredns
然后按下面的例子给 Corefile 添加 log
。
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
log
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
保存这些更改后,你可能会需要等待一到两分钟让 Kubernetes 把这些更改应用到 CoreDNS 的 Pod 里。
接下来,发起一些查询并依照前文所述查看日志信息,如果 CoreDNS 的 Pod 接收到这些查询, 你将可以在日志信息里看到它们。
下面是日志信息里的查询例子:
.:53
2018/08/15 14:37:15 [INFO] CoreDNS-1.2.0
2018/08/15 14:37:15 [INFO] linux/amd64, go1.10.3, 2e322f6
CoreDNS-1.2.0
linux/amd64, go1.10.3, 2e322f6
2018/09/07 15:29:04 [INFO] plugin/reload: Running configuration MD5 = 162475cdf272d8aa601e6fe67a6ad42f
2018/09/07 15:29:04 [INFO] Reloading complete
172.17.0.18:41675 - [07/Sep/2018:15:29:11 +0000] 59925 "A IN kubernetes.default.svc.cluster.local. udp 54 false 512" NOERROR qr,aa,rd,ra 106 0.000066649s
CoreDNS 是否有足够的权限?
CoreDNS 必须能够列出 service 和 endpoint 相关的资源来正确解析服务名称。
示例错误消息:
2022-03-18T07:12:15.699431183Z [INFO] 10.96.144.227:52299 - 3686 "A IN serverproxy.contoso.net.cluster.local. udp 52 false 512" SERVFAIL qr,aa,rd 145 0.000091221s
首先,获取当前的 ClusterRole system:coredns
:
kubectl describe clusterrole system:coredns -n kube-system
预期输出:
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
endpoints [] [] [list watch]
namespaces [] [] [list watch]
pods [] [] [list watch]
services [] [] [list watch]
endpointslices.discovery.k8s.io [] [] [list watch]
如果缺少任何权限,请编辑 ClusterRole 来添加它们:
kubectl edit clusterrole system:coredns -n kube-system
EndpointSlices 权限的插入示例:
...
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- list
- watch
...
你的服务在正确的名字空间中吗?
未指定名字空间的 DNS 查询仅作用于 Pod 所在的名字空间。如果 Pod 和服务的名字空间不相同,则 DNS 查询必须指定服务所在的名字空间。
该查询仅限于 Pod 所在的名字空间:
kubectl exec -i -t dnsutils -- nslookup <service-name>
指定名字空间的查询:
kubectl exec -i -t dnsutils -- nslookup <service-name>.<namespace>
要进一步了解名字解析,请查看 Pod 与 Service 的 DNS。
6.3 已知问题
有些 Linux 发行版本(比如 Ubuntu)默认使用一个本地的 DNS 解析器(systemd-resolved)。systemd-resolved
会用一个存根文件(Stub File)来覆盖 /etc/resolv.conf
内容, 从而可能在上游服务器中解析域名产生转发环(forwarding loop)。这个问题可以通过手动指定 kubelet 的 --resolv-conf
标志为正确的 resolv.conf
(如果是 systemd-resolved
, 则这个文件路径为 /run/systemd/resolve/resolv.conf
)来解决。kubeadm 会自动检测 systemd-resolved
并对应的更改 kubelet 的命令行标志。
Kubernetes 的安装并不会默认配置节点的 resolv.conf
文件来使用集群的 DNS 服务,因为这个配置对于不同的发行版本是不一样的。这个问题应该迟早会被解决的。
Linux 的 libc(又名 glibc)默认将 DNS nameserver
记录限制为 3, 而 Kubernetes 需要使用 1 条 nameserver
记录。这意味着如果本地的安装已经使用了 3 个 nameserver
,那么其中有些条目将会丢失。要解决此限制,节点可以运行 dnsmasq
,以提供更多 nameserver
条目。你也可以使用 kubelet 的 --resolv-conf
标志来解决这个问题。
如果你使用 Alpine 3.17 或更早版本作为你的基础镜像,DNS 可能会由于 Alpine 的设计问题而无法工作。在 musl 1.24 版本之前,DNS 存根解析器都没有包括 TCP 回退, 这意味着任何超过 512 字节的 DNS 调用都会失败。请将你的镜像升级到 Alpine 3.18 或更高版本。