如何解決 Amazon EKS 中負載平衡器運作狀態檢查失敗的問題?

上次更新日期:2021 年 12 月 13 日

我的負載平衡器在 Amazon Elastic Kubernetes Service (Amazon EKS) 中的運作狀態檢查一直失敗。

簡短描述

若要解決 Amazon EKS 中負載平衡器的運作狀態檢查問題,請完成以下部分所述的步驟:

  • 檢查 Pod 的狀態
  • 檢查 Pod 和服務標籤選取器
  • 檢查是否缺少端點
  • 檢查 Application Load Balancer 的服務流量政策和叢集安全群組
  • 確認 targetPort 是否設為 EKS
  • 確認 AWS 負載平衡器控制器是否有正確的許可
  • 檢查 Application Load Balancer 是否有傳入註解的問題
  • 檢查 Network Load Balancer 是否有 Kubernetes Service 註解的問題
  • 手動測試運作狀態檢查
  • 檢查聯網
  • 重新啟動 kube-proxy

解決方案

檢查 Pod 的狀態

檢查 Pod 是否處於執行中狀態,且 Pod 中的容器已準備就緒:

$ kubectl get pod -n YOUR_NAMESPACE

注意:請以您的 Kubernetes 命名空間取代 YOUR_NAMESPACE

範例輸出:

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 Service 是否使用 Pod 標籤,請執行以下命令檢查其輸出是否與 Pod 標籤相符:

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

注意:請以您的 Kubernetes Service 取代 SERVICE_NAME,並以您的 Kubernetes 命名空間取代 YOUR_NAMESPACE

範例輸出:

{"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.    選取運作狀態良好的執行個體

3.    選擇安全性索引標籤並檢查安全群組傳入規則。

4.    選取運作狀態不佳的執行個體

5.    選擇安全性索引標籤並檢查安全群組傳入規則。

如果每個執行個體的安全群組不同,則必須使用安全群組主控台來修改安全傳入規則:

1.    在安全性索引標籤中,選取安全群組 ID

2.    選擇編輯連入規則按鈕以修改傳入規則。

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 負載平衡器控制器是否有正確的許可

AWS 負載平衡器控制器必須具有更新安全群組的正確許可,才能讓負載平衡器的流量傳送到執行個體或 Pod。如果控制器沒有正確的許可,則您會收到錯誤訊息。

檢查 AWS 負載平衡器控制器部署記錄中是否有錯誤:

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

檢查個別控制器 Pod 記錄中是否有錯誤:

$ kubectl logs CONTROLLER_POD_NAME -n YOUR_NAMESPACE

注意:請以您的控制器 Pod 名稱取代 CONTROLLER_POD_NAME,並以您的 Kubernetes 命名空間取代 YOUR_NAMESPACE

檢查 Application Load Balancer 是否有傳入註解的問題

有關 Application Load Balancer 的問題,請查看 Kubernetes 傳入註解:

$ kubectl describe ing INGRESS_NAME -n YOUR_NAMESPACE

注意:請以您的 Kubernetes 傳入名稱取代 INGRESS_NAME,並以您的 Kubernetes 命名空間取代 YOUR_NAMESPACE

範例輸出:

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 網站中的傳入註解

檢查 Network Load Balancer 是否有 Kubernetes Service 註解的問題

有關 Network Load Balancer 的問題,請查看 Kubernetes Service 註解:

$ 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 Service 註解,請參閲 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

注意:請以您的應用程式 Pod IP 取代APPLICATION_POD_IP,並以 ALB 目標群組運作狀態檢查路徑取代 HEALTH_CHECK_PATH

命令範例:

# 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

注意:請以您的應用程式 Pod IP 取代 APPLICATION_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

此文章是否有幫助?


您是否需要帳單或技術支援?