클러스터 문제 해결

클러스터 문제 해결 (Troubleshooting Clusters)

이 문서는 클러스터 문제 해결에 관한 내용이에요. 경험하는 문제의 근본 원인으로 애플리케이션을 이미 배제했다고 가정해요. 애플리케이션 디버깅 팁은 애플리케이션 문제 해결 가이드를 참고해요. 더 많은 정보는 문제 해결 개요 문서를 방문해도 돼요.

kubectl 문제 해결은 kubectl 문제 해결을 참고해요.

출처: 문서

본문

클러스터 나열하기

클러스터에서 가장 먼저 디버깅할 것은 노드가 모두 올바르게 등록되었는지예요.

다음 명령을 실행해요.

kubectl get nodes

보고 싶은 모든 노드가 존재하고 모두 Ready 상태인지 확인해요.

클러스터의 전반적인 건강 상태에 대한 상세 정보를 얻으려면 실행할 수 있어요.

kubectl cluster-info dump

예시: 다운/연결 불가 노드 디버깅

때로는 디버깅할 때 노드의 상태를 보는 것이 유용할 수 있어요. 예를 들어 노드에서 실행 중인 파드의 이상한 동작을 발견했거나, 파드가 왜 그 노드에 스케줄링되지 않는지 알아내기 위해서요. 파드와 마찬가지로 kubectl describe nodekubectl get node -o yaml로 노드에 대한 상세 정보를 검색할 수 있어요. 예를 들어, 노드가 다운(네트워크에서 끊기거나 kubelet이 죽어 재시작되지 않는 등)되면 볼 수 있는 것이 이렇습니다. 노드가 NotReady임을 보여주는 이벤트와, 파드가 더 이상 실행되지 않는 것(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
                    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:
    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
    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

로그 보기 (Looking at logs)

지금으로서는 클러스터를 더 깊이 파고들려면 관련 머신에 로그인해야 해요. 다음은 관련 로그 파일의 위치예요. systemd 기반 시스템에서는 로그 파일을 검사하는 대신 journalctl을 사용해야 할 수도 있어요.

컨트롤 플레인 노드

  • /var/log/kube-apiserver.log — API 서버. API 제공을 담당
  • /var/log/kube-scheduler.log — 스케줄러. 스케줄링 결정을 담당
  • /var/log/kube-controller-manager.log — 대부분의 Kubernetes 내장 컨트롤러를 실행하는 컴포넌트. 스케줄링(kube-scheduler가 담당)은 예외

워커 노드

  • /var/log/kubelet.log — kubelet 로그. 노드에서 컨테이너 실행을 담당
  • /var/log/kube-proxy.log — kube-proxy 로그. Service 엔드포인트로 트래픽을 안내하는 데 담당

클러스터 실패 모드 (Cluster failure modes)

다음은 잘못될 수 있는 것과 클러스터 설정을 조정해 문제를 완화하는 방법의 불완전한 목록이에요.

기여 원인 (Contributing causes)

  • VM 종료
  • 클러스터 내부 또는 클러스터와 사용자 사이의 네트워크 분할(network partition)
  • Kubernetes 소프트웨어의 크래시
  • 영구 스토리지의 데이터 손실 또는 사용 불가 (예: GCE PD 또는 AWS EBS 볼륨)
  • 운영자 오류 (예: 잘못 구성된 Kubernetes 소프트웨어나 애플리케이션 소프트웨어)

특정 시나리오 (Specific scenarios)

  • API 서버 VM 종료 또는 apiserver 크래시 — 결과: 파드·서비스·복제 컨트롤러를 중지·업데이트·시작할 수 없음. 기존 파드와 서비스는 Kubernetes API에 의존하지 않는 한 정상적으로 계속 동작해야 함
  • API 서버 백킹 스토리지 손실 — 결과: kube-apiserver 컴포넌트가 성공적으로 시작하여 건강해지지 못함. kubelet은 그것에 도달할 수 없게 되지만, 같은 파드를 계속 실행하고 같은 서비스 프록시를 제공함. apiserver가 재시작되기 전에 apiserver 상태의 수동 복구 또는 재생성이 필요함
  • 지원 서비스(노드 컨트롤러, 복제 컨트롤러 매니저, 스케줄러 등)의 VM 종료 또는 크래시 — 현재 그들은 apiserver와 공동 배치되며, 그들의 사용 불가는 apiserver와 비슷한 결과를 가짐. 미래에는 이것들도 복제되고 공동 배치되지 않을 수 있음. 그들은 자체 영구 상태가 없음
  • 개별 노드(VM 또는 물리 머신) 종료 — 결과: 그 노드의 파드가 실행을 멈춤
  • 네트워크 분할 — 결과: 분할 A는 분할 B의 노드가 다운되었다고 생각하고, 분할 B는 apiserver가 다운되었다고 생각함 (마스터 VM이 분할 A에 있다고 가정)
  • kubelet 소프트웨어 결함 — 결과: 크래시된 kubelet은 노드에서 새 파드를 시작할 수 없음. kubelet이 파드를 삭제할 수도 있고 안 할 수도 있음. 노드는 비정상으로 표시되고 복제 컨트롤러가 다른 곳에서 새 파드를 시작함
  • 클러스터 운영자 오류 — 결과: 파드·서비스 등의 손실. apiserver 백킹 스토어 손실. 사용자가 API를 읽을 수 없게 됨 등

완화책 (Mitigations)

  • 조치: IaaS VM에 IaaS 프로바이더의 자동 VM 재시작 기능 사용 — 완화: API 서버 VM 종료 또는 apiserver 크래시 / 지원 서비스 VM 종료 또는 크래시
  • 조치: apiserver+etcd가 있는 VM에 IaaS 프로바이더의 신뢰할 수 있는 스토리지(예: GCE PD 또는 AWS EBS 볼륨) 사용 — 완화: API 서버 백킹 스토리지 손실
  • 조치: 고가용성 구성 사용 — 완화: 컨트롤 플레인 노드 종료 또는 컨트롤 플레인 컴포넌트(스케줄러, API 서버, controller-manager) 크래시. 하나 이상의 동시 노드 또는 컴포넌트 실패를 허용함. 완화: API 서버 백킹 스토리지(즉 etcd의 데이터 디렉터리) 손실 — HA(고가용성) etcd 구성을 가정
  • 조치: apiserver PD/EBS 볼륨을 주기적으로 스냅샷 — 완화: API 서버 백킹 스토리지 손실 / 운영자 오류의 일부 경우 / Kubernetes 소프트웨어 결함의 일부 경우
  • 조치: 파드 앞에 복제 컨트롤러와 서비스 사용 — 완화: 노드 종료 / kubelet 소프트웨어 결함
  • 조치: 예기치 않은 재시작을 허용하도록 설계된 애플리케이션(컨테이너) — 완화: 노드 종료 / kubelet 소프트웨어 결함

다음 단계

더 알아보기 (Learn more)