Amazon EKS 클러스터의 활성 및 준비 프로브 문제를 해결하려면 어떻게 해야 하나요?

6분 분량
0

Amazon Elastic Kubernetes Service(Amazon EKS) 클러스터의 활성 및 준비 프로브와 관련된 문제를 해결하고 싶습니다.

간략한 설명

워커 노드에서 실행 중인 Kubelet은 프로브를 사용하여 주기적으로 포드 상태를 확인합니다. Kubernetes는 현재 성공, 실패, 알 수 없음의 세 가지 프로브 상태를 지원합니다. Kubelet은 다음 조건에서 포드를 성공 또는 정상 상태로 간주합니다.

  • 컨테이너 내에서 실행되는 애플리케이션이 준비되었습니다.
  • 애플리케이션이 트래픽을 수신하고 포드 매니페스트에 정의된 프로브에 응답합니다.

Kubelet은 프로브가 응답하지 않을 때 애플리케이션 포드를 실패 또는 비정상으로 간주합니다. 그런 다음 Kubelet은 이 포드를 비정상으로 표시하고 SIGTERM을 포드로 전송합니다. 배포에 정의된 수명 주기 정책 및 restartPolicy에 따라 다음 중 하나가 발생합니다.

  • 포드가 즉시 종료됩니다.
  • 포드가 트래픽 수신을 중지한 후 정상적으로 종료됩니다.

예:

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

이 예에서 example-Pod 내에서 실행되는 example-container가 프로브에 응답하지 않아 비정상 상태가 되면 포드는 10초 후에 트래픽 수신을 중단합니다. 그런 다음 kubelet은 포드를 정상적으로 종료합니다. 30초 후에도 포드가 종료되지 않으면 kubelet은 포드를 강제로 제거합니다. kubelet이 배포 매니페스트에 정의된 프로브를 사용하여 포드의 상태를 확인할 수 없을 때 kubelet은 포드를 알 수 없는 상태로 간주합니다. 이 경우 kubelet은 추가 확인을 수행하여 포드 상태를 결정합니다.

Kubernetes는 활성 프로브, 준비 프로브 및 시작 프로브에 대한 프로브 확인을 제공합니다.

  • Kubelet은 활성 프로브를 사용하여 포드 내에서 실행 중인 애플리케이션의 상태를 파악합니다.
  • Kubelet은 준비 프로브를 사용하여 애플리케이션이 트래픽 수신 서비스를 시작할 준비가 된 시점을 파악합니다.
  • Kubelet은 포드 내의 느리게 시작하는 애플리케이션에 대해 시작 프로브를 사용합니다. 시작 프로브가 구성되면 시작이 성공한 것으로 간주될 때까지 활성 및 준비 프로브가 포드를 확인하지 않습니다.

이러한 프로브가 포드 매니페스트에 정의되어 있지 않은 경우 kubelet은 포드를 성공 또는 정상으로 무기한 표시합니다. 다음 프로브 중 하나를 구성하여 포드 상태를 확인할 수 있습니다.

  • 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)

이러한 오류를 해결하려면 다음을 수행합니다.

애플리케이션 포드의 활성 및 준비 프로브를 올바르게 구성했는지 확인합니다.

Amazon Virtual Private Cloud(VPC) CNI 버전 1.11.0 이상을 사용하는 경우 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_DEMUXtrue로 설정해야 합니다.

  • 버전 1.11.0 이전의 Amazon VPC CNI 버전을 사용하고 있습니다.
  • 포드가 보안 그룹으로 구성되어 있습니다.
  • 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

애플리케이션 연결 오류

사용자 지정 애플리케이션 포드에서 describe 명령을 실행할 때 포드가 활성 및 준비 프로브 확인에 실패하면 다음 오류가 발생합니다.

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.    포드 매니페스트에 정의된 상태 확인 경로를 워커 노드에서 수동으로 컬링합니다.

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

2.    활성 또는 준비 프로브에 실패한 애플리케이션 포드로 실행합니다. 그런 다음 포드 매니페스트에 정의된 상태 확인 경로를 컬링합니다.

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

3.    포드가 실행 중인 워커 노드의 kubelet 로그에 오류가 있는지 확인합니다.

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

4.    포드에서 describe 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

활성 또는 준비 상태 확인을 통해 실패한 포드를 다시 시작합니다. 그런 다음 이전 변경 사항이 적용된 Amazon EKS 워커 노드에 이 포드가 배포되고 있는지 확인합니다. 다음 명령을 실행하여 kubelet 로그를 확인할 수 있습니다.

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

6.    Bastion 호스트에서 동일한 컨테이너 이미지를 실행하고 매니페스트의 프로브에 정의된 상태 확인 경로를 컬링할 수 있는지 확인합니다. 그리고 컨테이너 로그도 확인합니다.

7.    HTTP 프로브의 경우 사용자 지정 http 헤더가 올바르게 구성되었는지 확인합니다. Kubelet은 curl과 동등한 golang 코드를 사용하여 포드를 HTTP 테스트합니다.

예:

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

8.    exec 프로브를 사용하는 경우 포드가 올바르게 구성되었는지 확인합니다. 다음 예시에서는 포드가 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 공식업데이트됨 일 년 전