如何解决 Amazon EKS 中负载均衡器运行状况检查失败的问题?

5 分钟阅读
0

我的负载均衡器一直未能通过 Amazon Elastic Kubernetes Service (Amazon EKS) 运行状况检查。

简短描述

要排查 Amazon EKS 中负载均衡器运行状况检查问题,请完成以下部分中的步骤:

  • 检查 pod 的状态
  • 检查 pod 和服务标签选择器
  • 检查终端节点是否缺失
  • 检查 Application Load Balancer 的服务流量策略和集群安全组
  • 验证您的 EKS 是否已针对 targetPort 进行配置
  • 验证您的 AWS Load Balancer 控制器是否具有正确的权限
  • 检查入口注释中是否有 Application Load Balancer 的问题
  • 检查 Kubernetes 服务注释中是否有 Network Load Balancer 的问题
  • 手动测试运行状况检查
  • 检查联网情况
  • 重启 kube-proxy

解决方法

检查 pod 的状态

检查 pod 是否处于 Running(正在运行)状态,pod 中的容器是否已准备就绪:

$ kubectl get pod -n YOUR_NAMESPACE

**注意:**请将 YOUR_NAMESPACE 替换为您的 Kubernetes 命名空间。

示例输出:

NAME                           READY   STATUS    RESTARTS   AGE
podname                        1/1     Running   0          16s

**注意:**如果 Pod 中的应用程序容器未运行,则负载均衡器运行状况检查不会得到响应,因此将失败。

检查 pod 和服务标签选择器

对于 pod 标签,请运行以下命令:

$ kubectl get pod -n YOUR_NAMESPACE --show-labels

示例输出:

NAME                           READY   STATUS    RESTARTS   AGE     LABELS
alb-instance-6cc5cd9b9-prnxw   1/1     Running   0          2d19h   app=alb-instance,pod-template-hash=6cc5cd9b9

要验证您的 Kubernetes 服务是否正在使用 pod 标签,请运行以下命令来检查其输出是否与 pod 标签匹配:

$ kubectl get svc SERVICE_NAME -n YOUR_NAMESPACE -o=jsonpath='{.spec.selector}{"\n"}'

**注意:**请将 SERVICE_NAME 替换为您的 Kubernetes 服务,并将 YOUR_NAMESPACE 替换为您的 Kubernetes 命名空间。

示例输出:

{"app":"alb-instance"}

检查终端节点是否缺失

服务选择器的 Kubernetes 控制器会持续扫描与其选择器匹配的 pod,然后将更新发布到终端节点对象。如果选择了错误的标签,则不会显示任何终端节点。

运行以下命令:

$ kubectl describe svc SERVICE_NAME -n YOUR_NAMESPACE

示例输出:

Name:                     alb-instance
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=alb-instance-1      
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.44.151
IPs:                      10.100.44.151
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  32663/TCP
Endpoints:                <none>                 
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

检查终端节点是否缺失:

$ kubectl get endpoints SERVICE_NAME -n YOUR_NAMESPACE

示例输出:

NAME           ENDPOINTS                                AGE
alb-instance   <none>                                   2d20h

检查服务流量策略和集群安全组中是否有 Application Load Balancer 的问题

导致 Application Load Balancer 目标组中的目标运行状况不佳的原因有两个。服务流量策略 spec.externalTrafficPolicy设置为 Local(本地),而不是 Cluster(集群)。或者,集群中的节点组具有与之关联的不同集群安全组,并且流量无法在节点组之间自由流动。

验证流量策略配置是否正确:

$ kubectl get svc SERVICE_NAME -n YOUR_NAMESPACE -o=jsonpath='{.spec.externalTrafficPolicy}{"\n"}'

示例输出:

Local

将设置更改为 Cluster(集群):

$ kubectl edit svc SERVICE_NAME -n YOUR_NAMESPACE

检查集群安全组

1.    打开 Amazon EC2 控制台

2.    选择 healthy instance(运行正常的实例)。

3.    选择 Security(安全)选项卡,然后检查安全组入口规则。

4.    选择 unhealthy instance(运行状况不佳的实例)。

5.    选择 Security(安全)选项卡,然后检查安全组入口规则。

如果每个实例的安全组各不相同,则必须在安全组控制台修改安全入口规则:

1.    在 Security(安全)选项卡中,选择 security group ID(安全组 ID)。

2.    选择 Edit inbound rules(编辑入站规则)按钮以修改入口规则。

3.    添加入站规则以允许来自集群中其他节点组的流量。

验证您的服务是否已针对 TargetPort 进行配置

您的 targetPort 必须与服务正在向其发送流量的 pod 中的 containerPort 相匹配。

要验证 targetPort 配置的目标端口,请运行以下命令:

$ kubectl get svc  SERVICE_NAME -n YOUR_NAMESPACE -o=jsonpath="{.items[*]}{.metadata.name}{'\t'}{.spec.ports[].targetPort}{'\t'}{.spec.ports[].protocol}{'\n'}"

示例输出:

alb-instance 8080 TCP

在前面的示例输出中,targetPort 配置为 8080。但是,由于 ContainerPort 设置为 80,因此必须将 targetPort 配置为 80。

验证您的 AWS Load Balancer 控制器是否具有正确的权限

AWS Load Balancer 控制器必须具有更新安全组的正确权限,才能允许流量从负载均衡器传输到实例或 Pod。如果控制器没有正确的权限,则您会收到错误。

检查 AWS Load Balancer 控制器部署日志中是否有错误:

$ kubectl logs deploy/aws-load-balancer-controller -n kube-system

检查单个控制器 pod 日志中是否有错误:

$ kubectl logs CONTROLLER_POD_NAME -n YOUR_NAMESPACE

**注意:**请将 CONTROLLER_POD_NAME 替换为控制器 pod 名称,并将 YOUR_NAMESPACE 替换为您的 Kubernetes 命名空间。

检查入口注释中是否有 Application Load Balancer 的问题

有关 Application Load Balancer 的问题,请查看 Kubernetes 入口注释:

$ kubectl describe ing INGRESS_NAME -n YOUR_NAMESPACE

**注意:**请将 INGRESS_NAME 替换为 Kubernetes 入口的名称,并将 YOUR_NAMESPACE 替换为您的 Kubernetes 命名空间。

示例输出:

Name:             alb-instance-ingress
Namespace:        default
Address:          k8s-default-albinsta-fcb010af73-2014729787.ap-southeast-2.elb.amazonaws.com
Default backend:  alb-instance:80 (192.168.81.137:8080)
Rules:
  Host          Path  Backends
  ----          ----  --------
  awssite.cyou
                /   alb-instance:80 (192.168.81.137:8080)
Annotations:    alb.ingress.kubernetes.io/scheme: internet-facing        
                kubernetes.io/ingress.class: alb                         
Events:
  Type    Reason                  Age                  From     Message
  ----    ------                  ----                 ----     -------
  Normal  SuccessfullyReconciled  25m (x7 over 2d21h)  ingress  Successfully reconciled

要查找特定于您的使用案例的入口注释,请参阅入口注释(来自 Kubernetes 网站)。

检查 Kubernetes 服务注释中是否有 Network Load Balancer 的问题

有关 Network Load Balancer 的问题,请查看 Kubernetes 服务注释:

$ kubectl describe svc SERVICE_NAME -n YOUR_NAMESPACE

示例输出:

Name:                     nlb-ip
Namespace:                default
Labels:                   <none>
Annotations:              service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip              
                          service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing          
                          service.beta.kubernetes.io/aws-load-balancer-type: external                   
Selector:                 app=nlb-ip
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.100.161.91
IPs:                      10.100.161.91
LoadBalancer Ingress:     k8s-default-nlbip-fff2442e46-ae4f8cf4a182dc4d.elb.ap-southeast-2.amazonaws.com
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  31806/TCP
Endpoints:                192.168.93.144:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

**注意:**请记下 APPLICATION_POD_IP。您需要它来运行运行状况检查命令。

要查找特定于您的使用案例的 Kubernetes 服务注释,请参阅服务注释(来自 Kubernetes 网站)。

手动测试运行状况检查

检查您的应用程序 pod IP 地址:

$ kubectl get pod -n YOUR_NAMESPACE -o wide

运行测试 pod,手动测试集群内的运行状况检查以进行 HTTP 运行状况检查:

$ kubectl run -n YOUR_NAMESPACE troubleshoot -it --rm --image=amazonlinux -- /bin/bash

对于 HTTP 运行状况检查:

# curl -Iv APPLICATION_POD_IP/HEALTH_CHECK_PATH

**注意:**请将 APPLICATION_POD_IP 替换为应用程序 pod IP,将 HEALTH_CHECK_PATH 替换为 ALB 目标组运行状况检查路径。

示例命令:

# curl -Iv 192.168.81.137

示例输出:

* Trying 192.168.81.137:80...
* Connected to 192.168.81.137 (192.168.81.137) port 80 (#0)
> HEAD / HTTP/1.1
> Host: 192.168.81.137
> User-Agent: curl/7.78.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: nginx/1.21.3
Server: nginx/1.21.3
< Date: Tue, 26 Oct 2021 05:10:17 GMT
Date: Tue, 26 Oct 2021 05:10:17 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 615
Content-Length: 615
< Last-Modified: Tue, 07 Sep 2021 15:21:03 GMT
Last-Modified: Tue, 07 Sep 2021 15:21:03 GMT
< Connection: keep-alive
Connection: keep-alive
< ETag: "6137835f-267"
ETag: "6137835f-267"
< Accept-Ranges: bytes
Accept-Ranges: bytes

< 
* Connection #0 to host 192.168.81.137 left intact

检查 HTTP 响应状态代码。如果响应状态代码为 200 OK,则表示您的应用程序在运行状况检查路径上正确响应。

如果 HTTP 响应状态代码为 3xx 或 4xx,则可以更改运行状况检查路径。以下注释可以通过 200 OK 响应:

alb.ingress.kubernetes.io/healthcheck-path: /ping

– 或者 –

您可以在入口资源上使用以下注释来添加成功的运行状况检查响应状态代码范围:

alb.ingress.kubernetes.io/success-codes: 200-399

对于 TCP 运行状况检查,请使用以下命令安装 netcat 命令:

# yum update -y && yum install -y nc

测试 TCP 运行状况检查:

# nc -z -v APPLICATION_POD_IP CONTAINER_PORT_NUMBER

**注意:**请将 APPLICATION_POD_IP 替换为应用程序 pod IP,并将 CONTAINER_PORT_NUMBER 替换为容器端口。

示例命令:

# nc -z -v 192.168.81.137 80

示例输出:

Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.81.137:80.
Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.

检查联网情况

对于联网问题,请验证以下各项:

  • EKS 集群中的多个节点组可以自由通信
  • 与运行 pod 的子网关联的网络访问控制列表(网络 ACL)允许来自负载均衡器子网 CIDR 范围的流量
  • 与负载均衡器子网关联的网络 ACL 应允许从运行 pod 的子网返回临时端口范围内的流量
  • 路由表允许来自 VPC CIDR 范围内的本地流量

重启 kube-proxy

如果在每个节点上运行的 kube-proxy 行为不正确,则它可能无法更新服务和终端节点的 iptables 规则。重启 kube-proxy 以强制它重新检查和更新 iptables 规则:

kubectl rollout restart daemonset.apps/kube-proxy -n kube-system

示例输出:

daemonset.apps/kube-proxy restarted

相关信息

如何在 Amazon EKS 中的 Amazon EC2 节点组上使用 AWS Load Balancer 控制器设置 Application Load Balancer?

如何排查 Amazon EKS 的负载均衡器问题?

如何标记 Amazon EKS 集群中的 Amazon VPC 子网以便负载均衡器或入口控制器自动发现子网?


相关视频

AWS 官方
AWS 官方已更新 2 年前