클러스터 트러블슈팅

일반적인 클러스터 이슈를 디버깅한다.

이 문서는 클러스터 트러블슈팅에 대해 설명한다. 사용자가 겪고 있는 문제의 근본 원인으로서 사용자의 애플리케이션을 이미 배제했다고 가정한다. 애플리케이션 디버깅에 대한 팁은 애플리케이션 트러블슈팅 가이드를 참조한다. 자세한 내용은 트러블슈팅 문서를 참조한다.

클러스터 나열하기

클러스터에서 가장 먼저 디버그해야 할 것은 노드가 모두 올바르게 등록되었는지 여부이다.

다음을 실행한다.

kubectl get nodes

그리고 보일 것으로 예상되는 모든 노드가 존재하고 모두 Ready 상태인지 확인한다.

클러스터의 전반적인 상태에 대한 자세한 정보를 얻으려면 다음을 실행할 수 있다.

kubectl cluster-info dump

예제: 다운(down) 상태이거나 통신이 닿지 않는(unreachable) 노드 디버깅하기

때때로 디버깅할 때 노드의 상태를 확인하는 것이 유용할 수 있다(예를 들어, 어떤 노드에서 실행되는 파드가 이상하게 행동하는 것을 발견했거나, 특정 노드에 파드가 스케줄링되지 않는 이유를 알아보기 위해). 파드의 경우와 마찬가지로, kubectl describe nodekubectl get node -o yaml 명령을 사용하여 노드에 대한 상세 정보를 볼 수 있다. 예를 들어, 노드가 다운 상태(네트워크 연결이 끊어졌거나, kubelet이 종료된 후 재시작되지 못했거나 등)라면 아래와 같은 출력이 나올 것이다. 노드가 NotReady 상태라는 것을 나타내는 이벤트(event)와, 더 이상 실행 중이 아닌 파드(NotReady 상태 이후 5분 뒤에 축출되었음)에 주목한다.

kubectl get nodes
NAME                     STATUS       ROLES     AGE     VERSION
kube-worker-1            NotReady     <none>    1h      v1.23.3
kubernetes-node-bols     Ready        <none>    1h      v1.23.3
kubernetes-node-st6x     Ready        <none>    1h      v1.23.3
kubernetes-node-unaj     Ready        <none>    1h      v1.23.3
kubectl describe node kube-worker-1
Name:               kube-worker-1
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=kube-worker-1
                    kubernetes.io/os=linux
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Thu, 17 Feb 2022 16:46:30 -0500
Taints:             node.kubernetes.io/unreachable:NoExecute
                    node.kubernetes.io/unreachable:NoSchedule
Unschedulable:      false
Lease:
  HolderIdentity:  kube-worker-1
  AcquireTime:     <unset>
  RenewTime:       Thu, 17 Feb 2022 17:13:09 -0500
Conditions:
  Type                 Status    LastHeartbeatTime                 LastTransitionTime                Reason              Message
  ----                 ------    -----------------                 ------------------                ------              -------
  NetworkUnavailable   False     Thu, 17 Feb 2022 17:09:13 -0500   Thu, 17 Feb 2022 17:09:13 -0500   WeaveIsUp           Weave pod has set this
  MemoryPressure       Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  DiskPressure         Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  PIDPressure          Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  Ready                Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
Addresses:
  InternalIP:  192.168.0.113
  Hostname:    kube-worker-1
Capacity:
  cpu:                2
  ephemeral-storage:  15372232Ki
  hugepages-2Mi:      0
  memory:             2025188Ki
  pods:               110
Allocatable:
  cpu:                2
  ephemeral-storage:  14167048988
  hugepages-2Mi:      0
  memory:             1922788Ki
  pods:               110
System Info:
  Machine ID:                 9384e2927f544209b5d7b67474bbf92b
  System UUID:                aa829ca9-73d7-064d-9019-df07404ad448
  Boot ID:                    5a295a03-aaca-4340-af20-1327fa5dab5c
  Kernel Version:             5.13.0-28-generic
  OS Image:                   Ubuntu 21.10
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.5.9
  Kubelet Version:            v1.23.3
  Kube-Proxy Version:         v1.23.3
Non-terminated Pods:          (4 in total)
  Namespace                   Name                                 CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                                 ------------  ----------  ---------------  -------------  ---
  default                     nginx-deployment-67d4bdd6f5-cx2nz    500m (25%)    500m (25%)  128Mi (6%)       128Mi (6%)     23m
  default                     nginx-deployment-67d4bdd6f5-w6kd7    500m (25%)    500m (25%)  128Mi (6%)       128Mi (6%)     23m
  kube-system                 kube-proxy-dnxbz                     0 (0%)        0 (0%)      0 (0%)           0 (0%)         28m
  kube-system                 weave-net-gjxxp                      100m (5%)     0 (0%)      200Mi (10%)      0 (0%)         28m
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                1100m (55%)  1 (50%)
  memory             456Mi (24%)  256Mi (13%)
  ephemeral-storage  0 (0%)       0 (0%)
  hugepages-2Mi      0 (0%)       0 (0%)
Events:
...
kubectl get node kube-worker-1 -o yaml
apiVersion: v1
kind: Node
metadata:
  annotations:
    kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
    node.alpha.kubernetes.io/ttl: "0"
    volumes.kubernetes.io/controller-managed-attach-detach: "true"
  creationTimestamp: "2022-02-17T21:46:30Z"
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: kube-worker-1
    kubernetes.io/os: linux
  name: kube-worker-1
  resourceVersion: "4026"
  uid: 98efe7cb-2978-4a0b-842a-1a7bf12c05f8
spec: {}
status:
  addresses:
  - address: 192.168.0.113
    type: InternalIP
  - address: kube-worker-1
    type: Hostname
  allocatable:
    cpu: "2"
    ephemeral-storage: "14167048988"
    hugepages-2Mi: "0"
    memory: 1922788Ki
    pods: "110"
  capacity:
    cpu: "2"
    ephemeral-storage: 15372232Ki
    hugepages-2Mi: "0"
    memory: 2025188Ki
    pods: "110"
  conditions:
  - lastHeartbeatTime: "2022-02-17T22:20:32Z"
    lastTransitionTime: "2022-02-17T22:20:32Z"
    message: Weave pod has set this
    reason: WeaveIsUp
    status: "False"
    type: NetworkUnavailable
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has sufficient memory available
    reason: KubeletHasSufficientMemory
    status: "False"
    type: MemoryPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has no disk pressure
    reason: KubeletHasNoDiskPressure
    status: "False"
    type: DiskPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has sufficient PID available
    reason: KubeletHasSufficientPID
    status: "False"
    type: PIDPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:15:15Z"
    message: kubelet is posting ready status. AppArmor enabled
    reason: KubeletReady
    status: "True"
    type: Ready
  daemonEndpoints:
    kubeletEndpoint:
      Port: 10250
  nodeInfo:
    architecture: amd64
    bootID: 22333234-7a6b-44d4-9ce1-67e31dc7e369
    containerRuntimeVersion: containerd://1.5.9
    kernelVersion: 5.13.0-28-generic
    kubeProxyVersion: v1.23.3
    kubeletVersion: v1.23.3
    machineID: 9384e2927f544209b5d7b67474bbf92b
    operatingSystem: linux
    osImage: Ubuntu 21.10
    systemUUID: aa829ca9-73d7-064d-9019-df07404ad448

로그 보기

현재로서는 클러스터를 더 깊이 파고들려면 관련 머신에서 로그 확인이 필요하다. 관련 로그 파일 위치는 다음과 같다. (systemd 기반 시스템에서는 journalctl을 대신 사용해야 할 수도 있다.)

컨트롤 플레인 노드

  • /var/log/kube-apiserver.log - API 서버, API 제공을 담당
  • /var/log/kube-scheduler.log - 스케줄러, 스케줄 결정을 담당
  • /var/log/kube-controller-manager.log - 레플리케이션 컨트롤러를 담당하는 컨트롤러

워커 노드

  • /var/log/kubelet.log - Kubelet, 노드에서 컨테이너 실행을 담당
  • /var/log/kube-proxy.log - Kube Proxy, 서비스 로드밸런싱을 담당

클러스터 장애 모드

아래에 일부 오류 상황 예시 및 문제를 완화하기 위해 클러스터 설정을 조정하는 방법을 나열한다.

근본 원인

  • VM(들) 종료
  • 클러스터 내 또는 클러스터와 사용자 간의 네트워크 분할
  • 쿠버네티스 소프트웨어의 충돌
  • 데이터 손실 또는 퍼시스턴트 스토리지 사용 불가 (e.g. GCE PD 또는 AWS EBS 볼륨)
  • 운영자 오류, 예를 들면 잘못 구성된 쿠버네티스 소프트웨어 또는 애플리케이션 소프트웨어

특정 시나리오

  • API 서버 VM 종료 또는 API 서버 충돌
    • 다음의 현상을 유발함
      • 새로운 파드, 서비스, 레플리케이션 컨트롤러를 중지, 업데이트 또는 시작할 수 없다.
      • 쿠버네티스 API에 의존하지 않는 기존 파드 및 서비스는 계속 정상적으로 작동할 것이다.
  • API 서버 백업 스토리지 손실
    • 다음의 현상을 유발함
      • API 서버가 구동되지 않을 것이다.
      • kubelet에 도달할 수 없게 되지만, kubelet이 여전히 동일한 파드를 계속 실행하고 동일한 서비스 프록시를 제공할 것이다.
      • API 서버를 재시작하기 전에, 수동으로 복구하거나 API서버 상태를 재생성해야 한다.
  • 지원 서비스 (노드 컨트롤러, 레플리케이션 컨트롤러 매니저, 스케쥴러 등) VM 종료 또는 충돌
    • 현재 그것들은 API 서버와 같은 위치에 있기 때문에 API 서버와 비슷한 상황을 겪을 것이다.
    • 미래에는 이들도 복제본을 가질 것이며 API서버와 별도로 배치될 수도 있다.
    • 지원 서비스들은 상태(persistent state)를 자체적으로 유지하지는 않는다.
  • 개별 노드 (VM 또는 물리적 머신) 종료
    • 다음의 현상을 유발함
      • 해당 노드의 파드가 실행을 중지
  • 네트워크 분할
    • 다음의 현상을 유발함
      • 파티션 A는 파티션 B의 노드가 다운되었다고 생각한다. 파티션 B는 API 서버가 다운되었다고 생각한다. (마스터 VM이 파티션 A에 있다고 가정)
  • Kubelet 소프트웨어 오류
    • 다음의 현상을 유발함
      • 충돌한 kubelet은 노드에서 새 파드를 시작할 수 없다.
      • kubelet이 파드를 삭제할 수도 있고 삭제하지 않을 수도 있다.
      • 노드는 비정상으로 표시된다.
      • 레플리케이션 컨트롤러는 다른 곳에서 새 파드를 시작한다.
  • 클러스터 운영자 오류
    • 다음의 현상을 유발함
      • 파드, 서비스 등의 손실
      • API 서버 백업 저장소 분실
      • API를 읽을 수 없는 사용자
      • 기타

완화

  • 조치: IaaS VM을 위한 IaaS 공급자의 자동 VM 다시 시작 기능을 사용한다.

    • 다음을 완화할 수 있음: API 서버 VM 종료 또는 API 서버 충돌
    • 다음을 완화할 수 있음: 지원 서비스 VM 종료 또는 충돌
  • 조치: API 서버+etcd가 있는 VM에 IaaS 제공자의 안정적인 스토리지(예: GCE PD 또는 AWS EBS 볼륨)를 사용한다.

    • 다음을 완화할 수 있음: API 서버 백업 스토리지 손실
  • 조치: 고가용성 구성을 사용한다.

    • 다음을 완화할 수 있음: 컨트롤 플레인 노드 종료 또는 컨트롤 플레인 구성 요소(스케줄러, API 서버, 컨트롤러 매니저) 충돌
      • 동시에 발생하는 하나 이상의 노드 또는 구성 요소 오류를 허용한다.
    • 다음을 완화할 수 있음: API 서버 백업 스토리지(i.e., etcd의 데이터 디렉터리) 손실
      • 고가용성 etcd 구성을 사용하고 있다고 가정
  • 조치: API 서버 PD/EBS 볼륨의 주기적인 스냅샷

    • 다음을 완화할 수 있음: API 서버 백업 스토리지 손실
    • 다음을 완화할 수 있음: 일부 운영자 오류 사례
    • 다음을 완화할 수 있음: 일부 쿠버네티스 소프트웨어 오류 사례
  • 조치: 파드 앞에 레플리케이션 컨트롤러와 서비스 사용

    • 다음을 완화할 수 있음: 노드 종료
    • 다음을 완화할 수 있음: Kubelet 소프트웨어 오류
  • 조치: 예기치 않은 재시작을 허용하도록 설계된 애플리케이션(컨테이너)

    • 다음을 완화할 수 있음: 노드 종료
    • 다음을 완화할 수 있음: Kubelet 소프트웨어 오류

다음 내용

최종 수정 February 22, 2023 at 9:09 AM PST: 更新编辑 (f4a7975)