你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
排查 AKS 群集中的网络问题
新安装的 Kubernetes 或增加 Kubernetes 负载时,可能会出现网络问题。 也可能出现与网络问题相关的其他问题。 请始终检查 AKS 故障排除指南,查看问题是否在其中描述。 本文从网络故障排除的角度介绍其他详细信息和注意事项,以及可能出现的特定问题。
客户端无法访问 API 服务器
这些错误涉及无法通过 Kubernetes 群集命令行工具 (kubectl) 或任何其他工具(如通过编程语言的 REST API)访问 Azure Kubernetes 服务 (AKS) 群集 API 服务器的连接问题。
错误
你可能会看到如下所示的错误:
Unable to connect to the server: dial tcp <API-server-IP>:443: i/o timeout
Unable to connect to the server: dial tcp <API-server-IP>:443: connectex: A connection attempt
failed because the connected party did not properly respond after a period, or established
connection failed because connected host has failed to respond.
原因 1
API 服务器授权的 IP 范围可能在群集的 API 服务器上启用,但客户端的 IP 地址不包含在这些 IP 范围中。 若要确定是否启用了 IP 范围,请使用 Azure CLI 中的以下 az aks show
命令。 如果 IP 范围已启用,该命令将生成一个 IP 范围列表。
az aks show --resource-group <cluster-resource-group> \
--name <cluster-name> \
--query apiServerAccessProfile.authorizedIpRanges
解决方案 1
确保客户端的 IP 地址在群集 API 服务器授权的范围内:
查找本地 IP 地址。 有关如何在 Windows 和 Linux 上查找它的信息,请参阅如何查找我的 IP。
使用 Azure CLI 中的
az aks update
命令更新 API 服务器授权的范围。 授权客户端的 IP 地址。 有关说明,请参阅更新群集的 API 服务器的授权 IP 范围。
原因 2
如果 AKS 群集是专用群集,则 API 服务器终结点没有公共 IP 地址。 需要使用对 AKS 群集的虚拟网络具有网络访问权限的 VM。
解决方案 2
有关如何解决此问题的信息,请参阅连接到专用群集的选项。
Pod 无法分配 IP 地址
错误
Pod 停留在 ContainerCreating
状态,其事件报告 Failed to allocate address
错误:
Normal SandboxChanged 5m (x74 over 8m) kubelet, k8s-agentpool-00011101-0 Pod sandbox
changed, it will be killed and re-created.
Warning FailedCreatePodSandBox 21s (x204 over 8m) kubelet, k8s-agentpool-00011101-0 Failed
create pod sandbox: rpc error: code = Unknown desc = NetworkPlugin cni failed to set up pod
"deployment-azuredisk6-874857994-487td_default" network: Failed to allocate address: Failed to
delegate: Failed to allocate address: No available addresses
或 not enough IPs available
错误:
Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox
'ac1b1354613465324654c1588ac64f1a756aa32f14732246ac4132133ba21364': plugin type='azure-vnet'
failed (add): IPAM Invoker Add failed with error: Failed to get IP address from CNS with error:
%w: AllocateIPConfig failed: not enough IPs available for 9c6a7f37-dd43-4f7c-a01f-1ff41653609c,
waiting on Azure CNS to allocate more with NC Status: , IP config request is [IPConfigRequest:
DesiredIPAddress , PodInterfaceID a1876957-eth0, InfraContainerID
a1231464635654a123646565456cc146841c1313546a515432161a45a5316541, OrchestratorContext
{'PodName':'a_podname','PodNamespace':'my_namespace'}]
检查插件 IPAM 存储中已分配的 IP 地址。 你可能会发现所有 IP 地址都已分配,但该数字远小于正在运行的 Pod 数:
如果使用的是 kubenet:
# Kubenet, for example. The actual path of the IPAM store file depends on network plugin implementation.
chroot /host/
ls -la "/var/lib/cni/networks/$(ls /var/lib/cni/networks/ | grep -e "k8s-pod-network" -e "kubenet")" | grep -v -e "lock\|last\|total" -e '\.$' | wc -l
244
注意
对于没有 Calico 的 kubenet,此路径为 /var/lib/cni/networks/kubenet
。 对于具有 Calico 的 kubenet,此路径为 /var/lib/cni/networks/k8s-pod-network
。 执行命令时,上述脚本会自动选择该路径。
# Check running Pod IPs
kubectl get pods --field-selector spec.nodeName=<your_node_name>,status.phase=Running -A -o json | jq -r '.items[] | select(.spec.hostNetwork != 'true').status.podIP' | wc -l
7
如果使用 Azure CNI 进行动态 IP 分配:
kubectl get nnc -n kube-system -o wide
NAME REQUESTED IPS ALLOCATED IPS SUBNET SUBNET CIDR NC ID NC MODE NC TYPE NC VERSION
aks-agentpool-12345678-vmss000000 32 32 subnet 10.18.0.0/15 559e239d-f744-4f84-bbe0-c7c6fd12ec17 dynamic vnet 1
# Check running Pod IPs
kubectl get pods --field-selector spec.nodeName=aks-agentpool-12345678-vmss000000,status.phase=Running -A -o json | jq -r '.items[] | select(.spec.hostNetwork != 'true').status.podIP' | wc -l
21
原因 1
此错误可能是是由网络插件中的 bug 引起的。 当 Pod 终止时,插件无法解除分配 IP 地址。
解决方案 1
请联系 Microsoft 获取解决方法。
原因 2
Pod 创建速度比终止的 Pod 的垃圾回收速度要快得多。
解决方案 2
为 kubelet 配置快速垃圾回收。 有关说明,请参阅 Kubernetes 垃圾回收文档。
服务无法在 Pod 内访问
解决此问题的第一步是检查是否已为服务自动创建终结点:
kubectl get endpoints <service-name>
如果结果为空,则服务的标签选择器可能不正确。 确认标签正确:
# Query Service LabelSelector.
kubectl get svc <service-name> -o jsonpath='{.spec.selector}'
# Get Pods matching the LabelSelector and check whether they're running.
kubectl get pods -l key1=value1,key2=value2
如果上述步骤返回预期值:
检查 Pod
containerPort
是否与服务containerPort
相同。检查
podIP:containerPort
是否正常工作:# Testing via cURL. curl -v telnet ://<Pod-IP>:<containerPort> # Testing via Telnet. telnet <Pod-IP>:<containerPort>
以下是导致服务问题的一些其他潜在原因:
- 容器不侦听指定的
containerPort
。 (查看 Pod 说明。) - 发生 CNI 插件错误或网络路由错误。
- kube-proxy 未运行或 iptables 规则未正确配置。
- 网络策略正在删除流量。 有关应用和测试网络策略的信息,请参阅 Azure Kubernetes 网络策略概述。
- 如果使用 Calico 作为网络插件,还可以捕获网络策略流量。 有关配置的信息,请参阅 Calico 站点。
节点无法访问 API 服务器
许多附加产品和容器都需要访问 Kubernetes API(例如,kube-dns 和运算符容器)。 如果在此过程中发生错误,以下步骤可帮助你确定问题的根源。
首先,确认 Kubernetes API 在 Pod 内是否可访问:
kubectl run curl --image=mcr.microsoft.com/azure-cli -i -t --restart=Never --overrides='[{"op":"add","path":"/spec/containers/0/resources","value":{"limits":{"cpu":"200m","memory":"128Mi"}}}]' --override-type json --command -- sh
然后在现在被封装到的容器中执行以下操作。
# If you don't see a command prompt, try selecting Enter.
KUBE_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -sSk -H "Authorization: Bearer $KUBE_TOKEN" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/default/pods
正常输出与以下内容类似。
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"selfLink": "/api/v1/namespaces/default/pods",
"resourceVersion": "2285"
},
"items": [
...
]
}
如果出现错误,请检查 kubernetes-internal
服务及其终结点是否正常:
kubectl get service kubernetes-internal
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes-internal ClusterIP 10.96.0.1 <none> 443/TCP 25m
kubectl get endpoints kubernetes-internal
NAME ENDPOINTS AGE
kubernetes-internal 172.17.0.62:6443 25m
如果两个测试都返回与前面相同的响应,并且返回的 IP 和端口与容器的响应匹配,则很可能是 kube-apiserver 没有运行或被网络阻止。
有四个主要原因可能导致访问被阻止:
- 你的网络策略。 它们可能会阻止访问 API 管理平面。 有关测试网络策略的信息,请参阅网络策略概述。
- API 允许的 IP 地址。 有关解决此问题的信息,请参阅更新群集的 API 服务器授权的 IP 范围。
- 专用防火墙。 如果通过专用防火墙路由 AKS 流量,请确保存在出站规则,如 AKS 群集需要的出站网络规则和 FQDN 中所述。
- 专用 DNS。 如果托管专用群集并且无法访问 API 服务器,则 DNS 转发器可能未正确配置。 若要确保正常通信,请完成具有自定义 DNS 的中心和分支中的步骤。
还可以使用容器见解检查 kube-apiserver 日志。 有关查询 kube-apiserver 日志以及许多其他查询的信息,请参阅如何从容器见解查询日志。
最后,可以在群集本身上检查 kube-apiserver 状态及其日志:
# Check kube-apiserver status.
kubectl -n kube-system get pod -l component=kube-apiserver
# Get kube-apiserver logs.
PODNAME=$(kubectl -n kube-system get pod -l component=kube-apiserver -o jsonpath='{.items[0].metadata.name}')
kubectl -n kube-system logs $PODNAME --tail 100
如果返回 403 - Forbidden
错误,则 kube-apiserver 可能配置了基于角色的访问控制 (RBAC),并且容器的 ServiceAccount
可能无权访问资源。 在这种情况下,应该创建适当的 RoleBinding
和 ClusterRoleBinding
对象。 有关角色和角色绑定的信息,请参阅访问和标识。 有关如何在群集上配置 RBAC 的示例,请参阅使用 RBAC 授权。
作者
本文由 Microsoft 维护, 它最初是由以下贡献者撰写的。
主要作者:
- Michael Walters | 高级顾问
其他参与者:
- Mick Alberts | 技术文档撰写人
- Ayobami Ayodeji | 高级项目经理
- Bahram Rushenas | 架构师