如何疑難排解 Amazon EKS 叢集中的活躍度和準備度探查問題?

4 分的閱讀內容
0

我想要疑難排解與 Amazon Elastic Kubernetes Service (Amazon EKS) 叢集中的活躍度和準備度探查相關的問題。

簡短描述

在工作節點上執行的 Kubelet 會使用探查來定期檢查 Pod 狀態。Kubernetes 目前在探查中支援三種狀態:成功、失敗和未知。在下列情況下,kubelet 會將 Pod 視為成功或運作狀態良好:

  • 容器內執行的應用程式已準備就緒。
  • 應用程式接受流量並回應 Pod 清單檔案上定義的探查。

如果探查沒有回應,kubelet 會將應用程式 Pod 視為失敗或運作狀態不佳。kubelet 接著會將此 Pod 標記為運作狀態不佳,並將 SIGTERM 傳送至 Pod。下列任一情況會根據部署上定義的生命週期政策和 restartPolicy 發生:

  • Pod 會立即終止。
  • Pod 會在停止接受流量後正常關閉。

範例:

spec:
 containers:
 - name: "example-container"
  image: "example-image"
  lifecycle:
   preStop:
    exec:
     command: ["sh", "-c", "sleep 10"]

在此範例中,如果在 example-pod 內執行的 example-container 因未回應探查而運作狀態不佳,則 Pod 會在 10 秒內停止接受流量。然後,kubelet 適度地關閉 Pod。如果在 30 秒後 Pod 仍未終止,kubelet 會強制移除 Pod。如果無法使用部署清單檔案上定義的探查來判斷 Pod 的狀態,kubelet 會將應用程式 Pod 視為未知。在此情況下,kubelet 會執行其他檢查以判斷 Pod 狀態。

Kubernetes 提供有關活躍度探查、準備度探查和啟動探查的探查檢查。

  • kubelet 使用活躍度探查來了解 Pod 內部執行的應用程式狀態。
  • kubelet 使用準備度探查來了解您的應用程式何時準備好開始處理傳入流量。
  • kubelet 會針對 Pod 內部緩慢啟動的應用程式使用啟動探查。設定啟動探查時,活躍度和準備度探查在啟動視為成功之前不會檢查 Pod。

如果 Pod 清單檔案上未定義這些探查,kubelet 會無限期地將 Pod 標記為成功或運作狀態良好。您可以設定下列其中一個探查來檢查 Pod 的運作狀態:

  • HTTP 探查
  • 命令探查
  • TCP 通訊端探查
  • gRPC 探查

解決方案

應用程式運作狀態檢查因用戶端逾時而失敗錯誤

當您的活躍度或準備度探查失敗時,您會收到下列錯誤訊息:

Liveness probe failed: Get "http://podIP:8080/health ": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

Readiness probe failed: Get "http://podIP:8080/health ": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

若要對這些錯誤進行疑難排解,請執行以下操作:

檢查您是否正確設定應用程式 Pod 的活躍度和準備度探查。

如果您使用的是 Amazon Virtual Private Cloud (Amazon VPC) CNI 或更新版本,請確保在 aws-node DaemonSet 中將 POD_SECURITY_GROUP_ENFORCING_MODE 設定為標準。如果此設定不正確,請執行下列命令:

kubectl set env daemonset aws-node -n kube-system POD_SECURITY_GROUP_ENFORCING_MODE=standard

當以下條件成立時,請務必針對 initcontainers 下的容器 amazon-k8s-cni-init,將 DISABLE_TCP_EARLY_DEMUX 設定為 true

  • 您使用的是 1.11.0 版本之前的 Amazon VPC CNI。
  • 您的 Pod 已設定安全群組。
  • ENABLE_POD_ENI 已設定為 true。
kubectl patch daemonset aws-node -n kube-system \
-p '{"spec": {"template": {"spec": {"initContainers": [{"env":[{"name":"DISABLE_TCP_EARLY_DEMUX","value":"true"}],"name":"aws-vpc-cni-init"}]}}}}'

Amazon VPC CNI 故障錯誤

您的 aws-node DaemonSet 可能會失敗並顯示下列錯誤:

Liveness probe failed: OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: read init-p: connection reset by peer: unknown
Warning  Unhealthy  11m (x3 over 12m)    kubelet            Liveness probe failed:
Normal   Killing    11m                  kubelet            Container aws-node failed liveness probe, will be restarted

Readiness probe failed: OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: process_linux.go:99: starting setns process caused: fork/exec /proc/self/exe: resource temporarily unavailable: unknown
Warning  Unhealthy  11m (x9 over 13m)    kubelet            Readiness probe failed:

您可以在 aws-node DaemonSet 上將 timeoutSeconds 值增加到 60 秒,以解決這些錯誤。

若要檢視 VPC CNI 中欄位的目前值,請執行下列命令:

$kubectl get daemonset aws-node -n kube-system -o yaml

輸出類似於以下內容:

"livenessProbe":
          exec:
            command:
            - /app/grpc-health-probe
            -addr=:50051
            -connect-timeout=5s
            -rpc-timeout=5s
          failureThreshold: 3
          initialDelaySeconds: 60
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 60

應用程式連線錯誤

當您在自訂應用程式 Pod 上執行 describe 命令時,如果 Pod 未通過活躍度和準備度探查檢查,您會收到下列錯誤:

2m 25s Warning  Unhealthy  Liveness probe failed: Get "http://podIP:8081/health ": dial tcp 192.168.187.28: 8081: connect: connection refused

2m 25s Warning  Unhealthy   Readiness probe failed: Get "http:// podIP:8081/health": dial tcp 192.168.187.28:8081: connect: connection refused

Warning  Unhealthy  39s (x4 over 2m19s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 500

Warning  Unhealthy  29s (x5 over 2m19s)  kubelet            Readiness probe failed: HTTP probe failed with statuscode: 500

若要對此錯誤進行疑難排解,請執行以下動作:

1.    從工作節點對 Pod 清單檔案上定義的運作狀態檢查路徑手動執行 curl 命令。

[ec2-user@ip-10-0-0-11 ~]$ curl -ikv podIP:8081/health

2.    在活躍度或整備度探查失敗的應用程式 Pod 中執行 Exec 命令。然後,對 Pod 清單檔案上定義的運作狀態檢查路徑執行 curl 命令:

local@bastion-host ~ % kubectl exec <pod-name> -- curl  -ikv "http://localhost:8081/_cluster/health?"

3.    檢查執行 Pod 所在工作節點的 Kubelet 記錄中是否有任何錯誤:

[ec2-user@ip-10-0-0-11 ~]$ journalctl -u kubelet //optionally 'grep' with pod name

4.    在 Pod 上執行 describe pod 命令,並檢查 Pod 中執行之容器的目前狀態。此外,請檢查 Pod 日誌:

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

$ kubectl logs <pod name>

5.    如果您仍然沒有關於錯誤的資訊,請考慮增加在工作節點上執行之基礎 kubelet 的詳細程度:

$ sudo systemctl status kubelet
$ vi /etc/systemd/system/kubelet.service.d/10-kubelet-args.conf 
   [Service]
   Environment='KUBELET_ARGS=--node-ip=192.168.31.211 --pod-infra-container-image=602401143452.dkr.ecr.us-east-2.amazonaws.com/eks/pause:3.5 --v=2'

在組態檔案中,將 --v=2 變更為 --v=9,然後儲存該檔案。

重新啟動 kubelet,以使變更生效:

$ sudo systemctl daemon-reload && sudo systemctl restart kubelet && sudo systemctl enable kubelet

執行下列命令以檢查 kubelet 的詳細程度:

$ systemctl status kubelet -l

輸出必須如下所示:

CGroup: /system.slice/kubelet.service 
       └─5909 /usr/bin/kubelet --cloud-provider aws --config /etc/kubernetes/kubelet/kubelet-config.json --kubeconfig /var/lib/kubelet/kubeconfig --container-runtime docker --network-plugin cni --node-ip=10.0.0.11 --pod-infra-container-image=602401143452.dkr.ecr.us-east-1.amazonaws.com/eks/pause:3.1-eksbuild.1 --v=9

重新啟動未能通過活躍度或準確度探查的 Pod。然後,請確定此 Pod 正在進行前述變更的 Amazon EKS 工作節點上部署。您可以透過執行下列命令來檢查 kubelet 日誌:

$ journalctl -u kubelet //optionally 'grep' with pod name

6.    在堡壘主機上執行相同的容器映像,並檢查您是否可以對清單檔案中為探查定義的運作狀態檢查路徑執行 curl 命令。另外,請檢查容器日誌。

7.    對於 HTTP 探查,請檢查自訂 http 標頭是否正確設定。kubelet 使用相當於 curl 的 golang 程式碼來對您的 Pod 執行 HTTP 測試。

範例:

"livenessProbe":
   httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

8.    如果您使用的是 exec 探查,請檢查您的 Pod 是否設定正確。在下列範例中,Pod 會通過檢查 30 秒,然後失敗:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: registry.k8s.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

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