本文讨论在尝试从 Microsoft Azure Kubernetes 服务 (AKS) 群集建立出站连接时,如何排查从 Pod 内部(而不是从辅助角色节点)发生的域名系统(DNS)解析失败问题。
先决条件
Kubernetes kubectl 工具或类似的工具连接到群集。 若要使用 Azure CLI 安装 kubectl,请运行 az aks install-cli 命令。
用于处理包的 apt-get 命令行工具。
用于 DNS 查找的 主机 命令行工具。
systemctl 命令行工具。
背景
对于 DNS 解析,Pod 会将请求发送到 kube-system
命名空间中的 CoreDNS 容器。
如果 DNS 查询用于内部组件(例如服务名称),则 CoreDNS Pod 会自行响应。 但是,如果请求适用于外部域,CoreDNS Pod 会将请求发送到上游 DNS 服务器。
上游 DNS 服务器基于运行 Pod 的工作节点的 resolv.conf 文件获取。 resolv.conf 文件 (/run/systemd/resolve/resolv.conf) 将根据运行工作器节点的虚拟网络的 DNS 设置更新 。
故障排除清单
若要从 Pod 中排查 DNS 问题,请使用以下部分中的说明。
步骤 1:排查 Pod 中的 DNS 故障
可以使用 kubectl 命令从 Pod 中排查 DNS 问题,如以下步骤所示:
验证 CoreDNS Pod 是否正在运行:
kubectl get pods -l k8s-app=kube-dns -n kube-system
检查 CoreDNS 容器组是否超负荷运行。
$ kubectl top pods -n kube-system -l k8s-app=kube-dns NAME CPU(cores) MEMORY(bytes) coredns-dc97c5f55-424f7 3m 23Mi coredns-dc97c5f55-wbh4q 3m 25Mi
验证托管 CoreDNS Pod 的节点是否未过度使用。 此外,获取托管 CoreDNS Pod 的节点:
kubectl get pods -n kube-system -l k8s-app=kube-dns -o jsonpath='{.items[*].spec.nodeName}'
检查这些节点的使用情况:
kubectl top nodes
验证 CoreDNS Pod 的日志:
kubectl logs -l k8s-app=kube-dns -n kube-system
注释
若要查看更多调试信息,请启用 CoreDNS 中的详细日志。 若要在 CoreDNS 中启用详细日志记录,请参阅 AKS 中的 CoreDNS 自定义疑难解答。
步骤 2:创建测试“Pod”以运行命令
如果 DNS 解析失败,请执行以下步骤:
在集群中启动一个测试 Pod。
kubectl run -it --rm aks-ssh --namespace <namespace> --image=debian:stable
测试 Pod 运行时,你将获得对 Pod 的访问权限。
运行以下命令安装所需的包:
apt-get update -y apt-get install dnsutils -y
验证 resolv.conf 文件是否具有正确的条目:
cat /etc/resolv.conf search default.svc.cluster.local svc.cluster.local cluster.local 00idcnmrrm4edot5s2or1onxsc.bx.internal.cloudapp.net nameserver 10.0.0.10 options ndots:5
host
使用命令确定 DNS 请求是否正在路由到上游服务器:$ host -a microsoft.com Trying "microsoft.com.default.svc.cluster.local" Trying "microsoft.com.svc.cluster.local" Trying "microsoft.com.cluster.local" Trying "microsoft.com.00idcnmrrm4edot5s2or1onxsc.bx.internal.cloudapp.net" Trying "microsoft.com" Trying "microsoft.com" ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62884 ;; flags: qr rd ra; QUERY: 1, ANSWER: 27, AUTHORITY: 0, ADDITIONAL: 5 ;; QUESTION SECTION: ;microsoft.com. IN ANY ;; ANSWER SECTION: microsoft.com. 30 IN NS ns1-39.azure-dns.com. ... ... ns4-39.azure-dns.info. 30 IN A 13.107.206.39 Received 2121 bytes from 10.0.0.10#53 in 232 ms
检查 Pod 中的上游 DNS 服务器,以确定 DNS 解析是否正常工作。 例如,对于 Azure DNS,请运行以下 nslookup 命令:
$ nslookup microsoft.com 168.63.129.16 Server: 168.63.129.16 Address: 168.63.129.16#53 ... ... Address: 20.81.111.85
步骤 3:在显式指定上游 DNS 服务器时,检查 DNS 请求是否正常工作
如果在显式指定上游 DNS 服务器时来自 Pod 的 DNS 请求正常工作,请验证以下条件:
检查是否存在 CoreDNS 的自定义 ConfigMap:
kubectl describe cm coredns-custom -n kube-system
如果存在自定义 ConfigMap,请验证配置是否正确。 有关详细信息,请参阅 使用 Azure Kubernetes 服务自定义 CoreDNS。
检查网络策略是否阻止用户数据报协议 (UDP) 端口 53 上的流量流向命名空间中的
kube-system
CoreDNS Pod。检查 CoreDNS Pod 是否位于不同的节点池(系统节点池)。 如果是,请检查网络安全组(NSG)是否与阻止 UDP 端口 53 上的流量的系统节点池相关联。
检查虚拟网络最近是否已更新以添加新的 DNS 服务器。
如果发生虚拟网络更新,请检查是否也发生了以下事件之一:
- 节点已重启。
- 节点中的网络服务已重启。
若要使 DNS 设置中的更新生效,必须重启节点上的网络服务和 CoreDNS Pod。 若要重启网络服务或 Pod,请使用以下方法之一:
重启节点。
扩展新节点。 (新节点将具有更新的配置。
在节点中重启网络服务,然后重启 CoreDNS Pod。 执行以下步骤:
建立与节点的SSH连接。 有关详细信息,请参阅连接到 Azure Kubernetes 服务 (AKS) 群集节点以进行维护或故障排除。
从节点内部重启网络服务:
systemctl restart systemd-networkd
检查设置是否已更新:
cat /run/systemd/resolve/resolv.conf
重启网络服务后,使用 kubectl 重启 CoreDNS Pod:
kubectl delete pods -l k8s-app=kube-dns -n kube-system
检查是否在虚拟网络 DNS 设置中指定了多个 DNS 服务器。
如果在 AKS 虚拟网络中指定了多个 DNS 服务器,则会发生以下序列之一:
AKS 节点将请求作为序列的一部分发送到上游 DNS 服务器。 在此序列中,请求将发送到虚拟网络中配置的第一个 DNS 服务器(如果 DNS 服务器可访问且正在运行)。 如果第一个 DNS 服务器无法访问且未响应,则请求将发送到下一个 DNS 服务器。
AKS 节点使用 解析程序 命令将请求发送到 DNS 服务器。 可以在 AKS 节点中的 /run/systemd/resolve/resolve.conf 中找到此解析程序的配置文件。
是否存在多个服务器? 在这种情况下,解析程序库按列出的顺序对其进行查询。 (使用的策略是首先尝试一个名称服务器。如果查询超时,则尝试下一个,依此类推,直到名称服务器列表用尽。然后,查询将继续尝试连接至名称服务器,直到达到最大重试次数为止。)
CoreDNS 使用 转发 插件将请求发送到上游 DNS 服务器。 此插件使用随机算法来选择上游 DNS 服务器。 在此序列中,请求可以转到虚拟网络中提及的任何 DNS 服务器。 例如,你可能会收到以下输出:
$ kubectl describe cm coredns -n kube-system Name: coredns Namespace: kube-system Labels: addonmanager.kubernetes.io/mode=Reconcile k8s-app=kube-dns kubernetes.io/cluster-service=true Annotations: <none> Data ==== Corefile: ---- .:53 { errors ready health kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa } prometheus :9153 forward . /etc/resolv.conf # Here! cache 30 loop reload loadbalance import custom/*.override } import custom/*.server BinaryData ==== Events: <none>
在 CoreDNS
forward
插件中,policy
指定用于选择上游服务器的策略。 下表中定义了这些策略。策略名称 DESCRIPTION random
实现随机上游选择的策略。 此策略是默认策略。 round_robin
基于轮循机制排序选择主机的策略。 sequential
基于顺序排序选择主机的策略。 如果 AKS 虚拟网络包含多个 DNS 服务器,则来自 AKS 节点的请求可能会转到第一个 DNS 服务器。 但是,来自 Pod 的请求可能会转到第二个 DNS 服务器。
原因:DNS 请求的多个目标
如果指定了两个自定义 DNS 服务器,并且第三个 DNS 服务器被指定为 Azure DNS(168.63.129.16),则节点将请求发送到第一个自定义 DNS 服务器(如果正在运行且可访问)。 在此设置中,节点可以解析自定义域。 但是,来自 Pod 的某些 DNS 请求可能定向到 Azure DNS。 这是因为 CoreDNS 可以随机选择上游服务器。 在此方案中,无法解析自定义域。 因此,DNS 请求失败。
解决方案:从虚拟网络设置中删除 Azure DNS
建议不要将 Azure DNS 与虚拟网络设置中的自定义 DNS 服务器组合在一起。 如果要使用自定义 DNS 服务器,请在虚拟网络设置中仅添加自定义 DNS 服务器。 然后,在自定义 DNS 服务器的转发器设置中配置 Azure DNS。
有关详细信息,请参阅使用自己的 DNS 服务器的名称解析。
第三方联系人免责声明
为了帮助您获取有关此主题的更多信息,Microsoft 提供了第三方的联系信息。 该联系信息可能会在不通知的情况下更改。 微软不保证第三方联系信息的准确性。