你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
新安装的 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 范围,请使用 az aks show
Azure CLI 中的以下命令。 如果启用 IP 范围,该命令将生成 IP 范围列表。
az aks show --resource-group <cluster-resource-group> \
--name <cluster-name> \
--query apiServerAccessProfile.authorizedIpRanges
解决方案 1
确保客户端的 IP 地址在群集 API 服务器授权的范围内:
查找本地 IP 地址。 有关如何在 Windows 和 Linux 上查找它的信息,请参阅 如何查找我的 IP。
使用
az aks update
Azure CLI 中的命令更新 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维护。 它最初是由以下贡献者撰写的。
主要作者:
- 迈克尔·沃尔特斯 |高级顾问
其他参与者:
- 米克·阿尔伯特 |技术编写器
- Ayobami Ayodeji | 高级项目经理
- Bahram Rushenas |建筑师