首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
Kubernetes IP Masquerade Agent 用户指南
Kubernetes云管理控制器
Kubernetes安全地清空一个节点
Kubernetes保护集群
Kubernetes调试DNS问题
Kubernetes改变默认 StorageClass
Kubernetes更改PersistentVolume的回收策略
Kubernetes关键插件Pod的调度保证
Kubernetes静态加密Secret数据
Kubernetes开发云控制器管理器
Kubernetes控制节点上的CPU管理策略
Kubernetes控制节点上的拓扑管理策略
Kubernetes名字空间演练
Kubernetes配置API对象配额
启用/禁用 Kubernetes API
Kubernetes迁移多副本的控制面
Kubernetes升级集群
Kubernetes声明网络策略
Kubernetes使用CoreDNS进行服务发现
Kubernetes使用KMS驱动进行数据加密
使用Kubernetes API访问集群
Kubernetes使用NUMA感知的内存管理器
Kubernetes通过名字空间共享集群
Kubernetes通过配置文件设置Kubelet参数
为Kubernetes运行etcd集群
Kubernetes为节点发布扩展资源
Kubernetes限制存储使用量
Kubernetes验证已签名容器镜像
以非root用户身份运行Kubernetes节点组件
在Kubernetes集群中使用NodeLocal DNSCache
在Kubernetes集群中使用sysctl
Kubernetes在集群中使用级联删除
在运行中的集群上重新配置节点的 kubelet
Kubernetes自定义DNS服务
Kubernetes自动扩缩集群DNS服务
当前位置:
首页>>
技术小册>>
Kubernetes中文教程(五)
小册名称:Kubernetes中文教程(五)
这篇文章提供了一些关于 DNS 问题诊断的方法。 你的集群必须使用了 CoreDNS 或者其前身,`kube-dns`。 ### 创建一个简单的 Pod 作为测试环境 此示例在 `default` 名字空间创建 Pod。 服务的 DNS 名字解析取决于 Pod 的名字空间。 详细信息请查阅 [Pod 与 Service 的 DNS]。 使用上面的清单来创建一个 Pod: ```shell kubectl apply -f https://k8s.io/examples/admin/dns/dnsutils.yaml ``` ``` pod/dnsutils created ``` 验证其状态: ```shell kubectl get pods dnsutils ``` ``` NAME READY STATUS RESTARTS AGE dnsutils 1/1 Running 0 <some-time> ``` 一旦 Pod 处于运行状态,你就可以在该环境里执行 `nslookup`。 如果你看到类似下列的内容,则表示 DNS 是正常运行的。 ```shell 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` 命令执行失败,请检查下列内容: ### 先检查本地的 DNS 配置 查看 resolv.conf 文件的内容 (阅读[定制 DNS 服务] 和 后文的[已知问题] ,获取更多信息) ```shell 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 options ndots:5 ``` 下列错误表示 CoreDNS (或 kube-dns)插件或者相关服务出现了问题: ```shell 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' ``` 或者 ```shell kubectl exec -i -t dnsutils -- nslookup kubernetes.default ``` 输出为: ``` Server: 10.0.0.10 Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local nslookup: can't resolve 'kubernetes.default' ``` ### 检查 DNS Pod 是否运行 使用 `kubectl get pods` 命令来验证 DNS Pod 是否运行。 ```shell 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 的日志信息: ```shell 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 服务是否已经启用。 ```shell kubectl get svc --namespace=kube-system ``` 输出为: ``` NAME TYPE CLUSTER-IP EXTERNAL-IP PORT 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 的端点是否公开了。 ```shell kubectl get endpoints kube-dns --namespace=kube-system ``` ``` NAME ENDPOINTS AGE kube-dns 10.180.3.17:53,10.180.3.17:53 1h ``` 如果你没看到对应的端点,请阅读 [调试服务]的端点部分。 若需要了解更多的 Kubernetes DNS 例子,请在 Kubernetes GitHub 仓库里查看 [cluster-dns 示例]。 ### DNS 查询有被接收或者执行吗? 你可以通过给 CoreDNS 的配置文件(也叫 Corefile)添加 `log` 插件来检查查询是否被正确接收。 CoreDNS 的 Corefile 被保存在一个叫 `coredns` 的 里,使用下列命令来编辑它: ```shell kubectl -n kube-system edit configmap coredns ``` 然后按下面的例子给 Corefile 添加 `log`。 ```yaml 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 必须能够列出 和 相关的资源来正确解析服务名称。 示例错误消息: ``` 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`: ```shell kubectl describe clusterrole system:coredns -n kube-system ``` 预期输出: ``` PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- nodes [] [] [get] endpoints [] [] [list watch] namespaces [] [] [list watch] pods [] [] [list watch] services [] [] [list watch] endpointslices.discovery.k8s.io [] [] [list watch] ``` 如果缺少任何权限,请编辑 ClusterRole 来添加它们: ```shell kubectl edit clusterrole system:coredns -n kube-system ``` EndpointSlices 权限的插入示例: ``` ... - apiGroups: - discovery.k8s.io resources: - endpointslices verbs: - list - watch ... ``` ### 你的服务在正确的名字空间中吗? 未指定名字空间的 DNS 查询仅作用于 Pod 所在的名字空间。 如果 Pod 和服务的名字空间不相同,则 DNS 查询必须指定服务所在的名字空间。 该查询仅限于 Pod 所在的名字空间: ```shell kubectl exec -i -t dnsutils -- nslookup <service-name> ``` 指定名字空间的查询: ```shell kubectl exec -i -t dnsutils -- nslookup <service-name>.<namespace> ``` 要进一步了解名字解析,请查看 [Pod 与 Service 的 DNS]。 ## 已知问题 有些 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.3 或更早版本作为你的基础镜像,DNS 可能会由于 Alpine 中 一个已知的问题导致无法正常工作。 请查看[这里]获取更多信息。 ## - 参阅[自动扩缩集群中的 DNS 服务]. - 阅读 [Pod 与 Service 的 DNS]
上一篇:
Kubernetes保护集群
下一篇:
Kubernetes改变默认 StorageClass
该分类下的相关小册推荐:
Kubernetes中文教程(三)
Kubernets合辑3-kubernetes介绍
Kubernets合辑4-kubernetes入门
Kubernetes合辑1-安装Kubernetes
Kubernets合辑12-配置中心
Kubernets合辑9-资源约束
Kubernets合辑13-集群监控
Kubernets合辑5-Pod控制器
Kubernets合辑15-持续部署
云原生-K8S入门实战
Kubernets合辑6-服务发现
Kubernets合辑11-持续集成