Node Pressure(OOM, DiskPressure)
K8s에서 Node Pressure(OOM, DiskPressure)이 발생하게 된다면
OOM (Memory Pressure) 발생 시 동작 #
커널레벨 (Linux OOM Killer)
- 노드의 물리 메모리가 고갈되면 Linux 커널의 OOM Killer가 동작함
- OOM Score가 높은 프로세스부터 강제 종료함
- K8s 컨테이너도 일반 리눅스 프로세스이므로 그대로 대상이 된다.
우선순위는 대략 다음과 같다.
- requests는 없고 limits만 크거나 없는 컨테이너
- 메모리를 많이쓰는 BestEffort Pod
- QoS가 낮은 Pod 순서
K8s QoS 기반 동작 #
Pod는 QoS 클래스로 나뉜다.
- Guaranteed: requests == limits 가장 마지막에 죽는다
- Burstable: request < limits 중간 우선순위다
- BestEffort: requests, limit 없음으로 가장 먼저 죽는다
OOM 발생시 BestEffort -> Burstable -> Guaranteed 순으로 죽는다.
Kubelet 동작 #
컨테이너가 OOM으로 종료되면 컨테이너 상태는 OOMKilled가 된다.
Pod는 CrashLoopBackOff가 가능하다. 중요한점은 OOM은 eviction이 아니다.
노드가 파드를 정책적으로 제거한느 것이 아니라 커널이 찍어서 죽이는것이다. 그래서 좀 다름
DiskPressure 발생 시 동작 #
다음 리소스가 임계치 이하로 떨어지면 DiskPressure가 발생한다.
- node filesystem /
- image filesystem (컨테이너 이미지 저장 공간)
- emptyDir or localstorage
kubelet 내부 eviction threshold가 있다.
nodefs.available < 10%imagefs.available < 15%
Node Condition도 변화하는데 DiskPressure 발생시에
NodeCondition:
- DiskPressure = True
이 상태가 되면 다음 규칙이 적용된다.
Pod Eviction 동작 (정책적 제거) #
DiskPressure는 Eviction 기반으로 동작한다.
- 새 파드 스케쥴을 차단해 해당 노드에 새 파드 스케줄이 불가능하도록 한다
- 우선순위 낮은 파드부터 evction한다. BestEffort, QoS낮은 파드, emptyDir를 많이 사용하는 파드
- 파드는 정상 종료 (SIGTERM) -> grace period -> SIGKILL
즉, oom과 다르게 질서 있게 정리한다.
정리 대상 리소스는 kubelet이 먼저 시도하는 순서고
- 죽은 컨테이너 로그 삭제
- 사용되지 않은 이미지 gc
- 그래도 안되면 pod eviction
순으로 동작한다.
OOM vs DiskPressure #
| 항목 | OOM | DiskPressure |
|---|---|---|
| 발생 주체 | Linux Kernel | Kubelet |
| 처리 방식 | 즉시 Kill | Eviction |
| 순서 | QoS 기반으로 무작위에 가까움 | 정책적 |
| SIGTERM | 없음 | 있음 |
| Pod 상태 | OOMKilled | Evicted |
| 노드 스케줄링 | 유지 | 차단 |
OOM은 메모리 설계 실패 신호로 reqeust/limit 값을 잘 봐야하거나 메모리 릭이 없는지 보거나 gc 튜닝을 확인해보자. 이건 막아야할 상태
DiskPressure는 청소 전략 실패인데 이미지 gc 주기나 로그 관ㄹ ㅣ실패로 무한 증가 emptyDir 과다 사용으로 주기적 정리로 예방할 수 있다.