排查与 AKS 群集中托管的应用的连接问题

在当前的动态云环境中,确保与 Azure Kubernetes 服务 (AKS) 群集中托管的应用程序无缝连接对于保持最佳性能和用户体验至关重要。 本文介绍如何排查和解决各种因素导致的连接问题,包括应用程序端问题、网络策略、网络安全组(NSG)规则或其他因素。

注意

若要排查尝试连接到 AKS API 服务器时的常见问题,请参阅 API 服务器的群集连接问题的基本故障排除。

先决条件

需要考虑的因素

本部分介绍在尝试连接到 AKS 群集中托管的应用程序时出现问题时要采取的故障排除步骤。

在任何网络方案中,管理员应在故障排除时考虑以下重要因素:

  • 请求的源和目标是什么?

  • 源和目标之间的跃点是什么?

  • 请求-响应流是什么?

  • 哪些跃点在顶部具有额外的安全层,例如以下项:

    • 防火墙
    • 网络安全组 (NSG)
    • 网络策略

检查每个组件时, 获取和分析 HTTP 响应代码。 这些代码可用于识别问题的性质,在应用程序响应 HTTP 请求的情况下尤其有用。

如果其他故障排除步骤不提供任何最终结果,请从客户端和服务器获取数据包捕获。 当客户端和服务器之间涉及非 HTTP 流量时,数据包捕获也很有用。 有关如何收集 AKS 环境的数据包捕获的详细信息,请参阅数据收集指南中的以下文章:

了解如何获取 HTTP 响应代码并获取数据包捕获,以便更轻松地排查网络连接问题。

AKS 上应用程序的基本网络流

通常,使用Azure 负载均衡器服务类型公开应用程序时,访问它们的请求流如下所示:

客户端 >> DNS 名称 >> AKS 负载均衡器 IP 地址 >> AKS 节点 >> Pod

还有其他可能的情况,其中可能会涉及额外的组件。 例如:

  • 启用了应用程序 路由加载项 功能的托管 NGINX 入口。
  • 应用程序网关通过应用程序网关入口控制器(AGIC)而不是Azure 负载均衡器使用。
  • Azure Front Door 和 API 管理可能用于负载均衡器之上。
  • 进程使用内部负载均衡器。
  • 连接可能不会在 Pod 和请求的 URL 处结束。 这可能取决于 Pod 是否可以连接到另一个实体,例如数据库或同一群集中的其他任何服务。

了解应用程序的请求流非常重要。

AKS 群集中应用程序的基本请求流类似于下图所示的流。

Azure Kubernetes 服务 (A K S) 群集上应用程序的基本请求流示意图。

内部故障排除

排查连接问题可能涉及许多检查,但 内部 方法可以帮助查找问题的来源并识别瓶颈。 在此方法中,从 Pod 本身开始,检查应用程序是否在 Pod 的 IP 地址上做出响应。 然后,检查每个组件是否都已转到最终客户端。

步骤 1:检查 Pod 是否正在运行,Pod 中的应用或容器是否正确响应

若要确定 Pod 是否正在运行,请运行以下 kubectl get 命令之一:

# List pods in the specified namespace.
kubectl get pods -n <namespace-name>

# List pods in all namespaces.
kubectl get pods -A

如果 Pod 未运行,该怎么办? 在这种情况下,请使用 kubectl 描述 命令检查 Pod 事件:

kubectl describe pod <pod-name> -n <namespace-name>

如果 Pod 未处于 ReadyRunning 状态,或者它多次重新启动,请检查 kubectl describe 输出。 这些事件将显示阻止启动 Pod 的任何问题。 或者,如果 Pod 已启动,则 Pod 中的应用程序可能已失败,导致 Pod 重启。 相应地 对 Pod 进行故障排除,以确保它处于合适的状态。

如果 Pod 正在运行,则检查 Pod 中容器的日志也很有用。 运行以下系列 kubectl 日志 命令:

kubectl logs <pod-name> -n <namespace-name>

# Check logs for an individual container in a multicontainer pod.
kubectl logs <pod-name> -n <namespace-name> -c <container-name>

# Dump pod logs (stdout) for a previous container instance.
kubectl logs <pod-name> --previous                      

# Dump pod container logs (stdout, multicontainer case) for a previous container instance.
kubectl logs <pod-name> -c <container-name> --previous      

Pod 是否正在运行? 在这种情况下,通过在群集中启动测试 Pod 来测试连接。 在测试 Pod 中,可以直接访问应用程序的 Pod IP 地址,并检查应用程序是否正确响应。 运行 kubectl runapt-getcURL命令,如下所示:

# Start a test pod in the cluster:
kubectl run -it --rm aks-ssh --image=debian:stable

# After the test pod is running, you will gain access to the pod.
# Then you can run the following commands:
apt-get update -y && apt-get install dnsutils -y && apt-get install curl -y && apt-get install netcat-traditional -y

# After the packages are installed, test the connectivity to the application pod:
curl -Iv http://<pod-ip-address>:<port>

对于侦听其他协议的应用程序,可以在测试 Pod(如 netcat 工具)中安装相关工具,然后运行以下命令来检查与应用程序 Pod 的连接:

# After the packages are installed, test the connectivity to the application pod using netcat/nc command:
nc -z -v <pod-ip-address> <port>

有关对 Pod 进行故障排除的更多命令,请参阅 调试正在运行的 Pod。

步骤 2:检查应用程序是否可从服务访问

对于 Pod 内部的应用程序正在运行的方案,主要可以专注于如何公开 Pod。

Pod 是否公开为服务? 在这种情况下,请检查服务事件。 此外,检查 Pod IP 地址和应用程序端口是否可用作服务说明中的终结点:

# Check the service details.
kubectl get svc -n <namespace-name>

# Describe the service.
kubectl describe svc <service-name> -n <namespace-name>

检查 Pod 的 IP 地址是否以服务中的终结点的形式存在,如以下示例所示:

$ kubectl get pods -o wide  # Check the pod's IP address.
NAME            READY   STATUS        RESTARTS   AGE   IP            NODE                                
my-pod          1/1     Running       0          12m   10.244.0.15   aks-agentpool-000000-vmss000000  

$ kubectl describe service my-cluster-ip-service  # Check the endpoints in the service.
Name:              my-cluster-ip-service
Namespace:         default
Selector:          app=my-pod
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.0.174.133
IPs:               10.0.174.133
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.15:80     # <--- Here

$ kubectl get endpoints  # Check the endpoints directly for verification.
NAME                      ENDPOINTS           AGE
my-cluster-ip-service     10.244.0.15:80      14m

如果终结点未指向正确的 Pod IP 地址,请验证 Labels Selectors Pod 和服务。

服务中的终结点是否正确? 如果是,请访问该服务,并检查应用程序是否可访问。

访问 ClusterIP 服务

ClusterIP对于服务,可以在群集中启动测试 Pod 并访问服务 IP 地址:

在 Azure Kubernetes 服务 (A K S) 群集中使用测试 Pod 访问群集 I P 地址的关系图。

# Start a test pod in the cluster:
kubectl run -it --rm aks-ssh --image=debian:stable
  
# After the test pod is running, you will gain access to the pod.
# Then, you can run the following commands:
apt-get update -y && apt-get install dnsutils -y && apt-get install curl -y && apt-get install netcat-traditional -y
  
# After the packages are installed, test the connectivity to the service:
curl -Iv http://<service-ip-address>:<port>

对于侦听其他协议的应用程序,可以在测试 Pod(如 netcat 工具)中安装相关工具,然后运行以下命令来检查与应用程序 Pod 的连接:

# After the packages are installed, test the connectivity to the application pod using netcat/nc command:
nc -z -v <pod-ip-address> <port>

如果上一个命令未返回适当的响应,请检查服务事件是否存在任何错误。

访问 LoadBalancer 服务

LoadBalancer对于服务,可以从群集外部访问负载均衡器 IP 地址。

从 Azure Kubernetes 服务 (A K S) 群集外部访问负载均衡器 I P 地址的测试用户示意图。

curl -Iv http://<service-ip-address>:<port>

对于侦听其他协议的应用程序,可以在测试 Pod(如 netcat 工具)中安装相关工具,然后运行以下命令来检查与应用程序 Pod 的连接:

nc -z -v <pod-ip-address> <port>

LoadBalancer服务 IP 地址是否返回正确的响应? 如果没有,请执行以下步骤:

  1. 验证服务的事件。

  2. 验证与 AKS 节点和 AKS 子网关联的网络安全组(NSG)是否允许服务端口上的传入流量。

有关对服务进行故障排除的更多命令,请参阅 调试服务

使用入口而不是服务的方案

对于使用 Ingress 资源公开应用程序的情况,流量流类似于以下进度:

群集>>服务或 Pod 内的客户端 >> DNS 名称>>负载均衡器或应用程序网关 IP 地址>>入口控制器 Pod

使用入口资源公开Azure Kubernetes 服务(A K S)群集内的应用时网络流量流图。

也可以在此处应用内部故障排除方法。 还可以查看入口 kubernetes 资源和入口控制器详细信息,了解详细信息:

$ kubectl get ing -n <namespace-of-ingress>  # Checking the ingress details and events.
NAME                         CLASS    HOSTS                ADDRESS       PORTS     AGE
hello-world-ingress          <none>   myapp.com            20.84.x.x     80, 443   7d22h

$ kubectl describe ing -n <namespace-of-ingress> hello-world-ingress
Name:             hello-world-ingress
Namespace:        <namespace-of-ingress>
Address:          20.84.x.x
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
  tls-secret terminates myapp.com
Rules:
  Host                Path  Backends
  ----                ----  --------
  myapp.com
                      /blog   blog-service:80 (10.244.0.35:80)
                      /store  store-service:80 (10.244.0.33:80)

Annotations:          cert-manager.io/cluster-issuer: letsencrypt
                      kubernetes.io/ingress.class: nginx
                      nginx.ingress.kubernetes.io/rewrite-target: /$1
                      nginx.ingress.kubernetes.io/use-regex: true
Events:
  Type    Reason  Age    From                      Message
  ----    ------  ----   ----                      -------
  Normal  Sync    5m41s  nginx-ingress-controller  Scheduled for sync
  Normal  Sync    5m41s  nginx-ingress-controller  Scheduled for sync

此示例包含一个 Ingress 资源:

  • myapp.com 听主机上。
  • 配置了两个 Path 字符串。
  • 路由到后端中的两 Services 个。

验证后端服务是否正在运行,并响应入口说明中提到的端口:

$ kubectl get svc -n <namespace-of-ingress>
NAMESPACE       NAME                                     TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                      
ingress-basic   blog-service                             ClusterIP      10.0.155.154   <none>        80/TCP                       
ingress-basic   store-service                            ClusterIP      10.0.61.185    <none>        80/TCP             
ingress-basic   nginx-ingress-ingress-nginx-controller   LoadBalancer   10.0.122.148   20.84.x.x     80:30217/TCP,443:32464/TCP   

如果出现错误,请验证入口控制器 Pod 的日志:

$ kubectl get pods -n <namespace-of-ingress>  # Get the ingress controller pods.
NAME                                                     READY   STATUS    RESTARTS   AGE
aks-helloworld-one-56c7b8d79d-6zktl                      1/1     Running   0          31h
aks-helloworld-two-58bbb47f58-rrcv7                      1/1     Running   0          31h
nginx-ingress-ingress-nginx-controller-9d8d5c57d-9vn8q   1/1     Running   0          31h
nginx-ingress-ingress-nginx-controller-9d8d5c57d-grzdr   1/1     Running   0          31h

$ # Check logs from the pods.
$ kubectl logs -n ingress-basic nginx-ingress-ingress-nginx-controller-9d8d5c57d-9vn8q

如果客户端向入口主机名或 IP 地址发出请求,但在入口控制器 Pod 的日志中未看到任何条目,该怎么办? 在这种情况下,请求可能无法到达群集,并且用户可能会收到 Connection Timed Out 错误消息。

另一种可能性是,入口 Pod(如负载均衡器或应用程序网关)上的组件未正确将请求路由到群集。 如果这是真的,可以检查这些资源的后端配置。

如果收到 Connection Timed Out 错误消息,请检查与 AKS 节点关联的网络安全组。 此外,请检查 AKS 子网。 它可能会阻止从负载均衡器或应用程序网关到 AKS 节点的流量。

有关如何对入口进行故障排除的详细信息(例如 Nginx 入口),请参阅 ingress-nginx 故障排除

联系我们寻求帮助

如果你有任何疑问或需要帮助,请创建支持请求联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区

第三方联系人免责声明

Microsoft 会提供第三方联系信息来帮助你查找有关本主题的其他信息。 此联系信息可能会更改,恕不另行通知。 Microsoft 不保证第三方联系信息的准确性。