EKS 노드 Ready/NotReady Flapping - 배치 작업 Disk I/O 병목과 EBS IOPS 증가로 해결

에러 스레드: Slack

1. 서론

새벽 2시에 EAP-EKS-TEST 클러스터에서 Node Ready Flapping Alert이 발생했다. 특정 노드가 Ready/NotReady를 반복하며 6회 상태가 바뀌었고, 메트릭 수집까지 끊겼다. 처음엔 노드 CPU 사용량 92%를 보고 CPU 과부하를 의심했지만, 실제 원인은 새벽 배치 CronJob이 유발한 Disk I/O 병목이었다.

2. 요약

항목내용
발생 시간2026-01-26 02:14 ~ 02:37 KST (약 23분)
영향 노드ip-10-20-46-107.ap-northeast-2.compute.internal
AlertEAP-EKS-TEST Node Ready Flapping
Root CauseDisk I/O 병목 - update-accumulated-rank 배치 작업의 과도한 I/O가 노드를 포화시킴

인과관계 요약

flowchart LR
    A[update-accumulated-rank] --> B[Disk I/O 급증]
    B --> C[iowait 58%]
    C --> D[PLEG 10초]
    D --> E[Node Flapping]
  • update-accumulated-rank 단독으로도 Node 장애 유발 가능
  • update-total-step 동시 실행은 악화 요인

핵심 수치

분석 대시보드 (01:30~03:00 KST)

지표정상문제 시변화
worker-app Disk Read160 KB/s7.4 MB/s46배
노드 iowait6%52%8.7배
PLEG relist duration0.04초10초250배
PLEG relist 횟수1회/초0.1회/초90% 감소
Node Ready changes06회-

3. 탐구 과정

3.1 처음 의심: CPU 병목

Alert 확인 직후 노드 CPU 사용량이 92%에 달했다. 자연스럽게 CPU 과부하를 의심했다. 그런데 실제 worker-app 컨테이너 CPU 사용량은 최대 0.38 cores — 노드 전체의 19%였다.

지표해석
worker-app CPU최대 0.38 cores노드(2 cores)의 19%
Node CPU Usage최대 92%높아 보이지만 대부분 I/O 대기
iowait 비중52%CPU 사용의 절반 이상이 I/O 대기

CPU 사용량이 높아 보인 이유는 CPU의 절반 이상이 I/O 대기(iowait)였기 때문이다. CPU가 바빠서 92%가 아니라, I/O를 기다리느라 block된 것이다.

3.2 전환점: iowait 52%

iowait 52%를 확인한 순간 병목이 Disk I/O임을 파악했다. 다음 질문은 “어떤 Pod가 이 I/O를 만들고 있는가”였다.

근거데이터
iowait 52%CPU의 절반 이상이 I/O 대기 상태
Disk Read 46배 증가160KB/s → 7.4MB/s
메트릭 수집 실패kubelet/cadvisor/node-exporter 모두 응답 불가

Pod별 네트워크 수신량을 분리해보니 worker-app-hwl69 Pod로 트래픽이 집중되어 있었고, 해당 Pod가 위치한 노드가 문제 노드와 일치했다.

3.3 CronJob 2개인가, 1개인가

02:00에 두 CronJob이 동시 실행됐다는 사실이 확인됐다. 처음엔 두 작업의 동시 실행이 원인이라고 생각했다. 해결책이 스케줄 분산이라면 상대적으로 간단하다.

그런데 update-total-step이 02:11에 완료된 후에도 문제가 02:26까지 지속됐다. update-accumulated-rank 단독으로도 Node 장애를 유발할 수 있다는 뜻이다. 스케줄 분산만으로는 충분하지 않고, 근본 원인은 단일 작업의 I/O 자체임이 드러났다.

4. 타임라인 분석

시간순 지표 변화

분석 대시보드 (01:55~02:45 KST)

시간 (KST)worker-app Disk ReadiowaitPLEGNode ReadyScrape
02:00160 KB/s6%0.04초ReadyUp
02:082.3 MB/s16%0.09초ReadyUp
02:103.6 MB/s28%6.85초ReadyDown
02:115.2 MB/s51%10초ReadyDown
02:147.0 MB/s51%10초NotReadyDown
02:217.6 MB/s (최대)58%10초NotReady (6회)Down
02:271.9 MB/s18%0.36초불안정불안정
02:371.5 KB/s4%0.02초복구Up

지표 선후관계

sequenceDiagram
    participant APP as worker-app
    participant IO as iowait
    participant PLEG as PLEG
    participant NODE as Node

    Note over APP: 02:08
    APP->>IO: Disk Read 14배 증가
    Note over IO: 02:09
    IO->>PLEG: iowait 28%
    Note over PLEG: 02:10
    PLEG->>PLEG: PLEG 6.85초
    Note over NODE: 02:14
    PLEG->>NODE: NotReady

5. 원인 분석

5.1 CronJob 실행 현황 (02:00~02:30 KST)

CronJob스케줄시작완료소요 시간
update-accumulated-rank0 17 * * *02:0002:2626분
update-membership-weekly-rank0 17 * * *02:0002:008초
update-membership-total-step5 17 * * *02:0502:116분

5.2 update-accumulated-rank 단독으로도 문제가 발생하는가?

분석 대시보드 (02:00~03:00 KST)

시간 (KST)실행 중인 작업iowaitPLEG상태
02:05~02:11accumulated-rank + total-step52%10초장애
02:11~02:26accumulated-rank 단독3~58%0.3~10초불안정
02:26~없음3%0.02초정상

상세 데이터 (02:11 이후, accumulated-rank만 실행 중):

분석 대시보드 (02:11~02:40 KST)

시간 (KST)iowaitPLEG분석
02:212.9%10초PLEG 지연 지속
02:2446%9.3초iowait 다시 급등
02:2558%9.3초최대치 도달
02:373.8%0.04초복구 (작업 완료)

update-accumulated-rank 단독 실행만으로도 Node 장애 유발 가능. 02:11에 total-step 완료 후에도 02:26까지 15분간 문제 지속. total-step 동시 실행은 문제를 악화시켰지만 근본 원인이 아니다.

5.3 왜 특정 노드만 문제가 발생했는가?

Pod노드역할
worker-app-hwl69ip-10-20-46-107 (문제 노드)실제 작업 처리
worker-app-j99p6ip-10-20-32-96 (정상 노드)실제 작업 처리

Pod별 네트워크 수신량 Explorer (01:30~03:00 KST)

시간 (KST)hwl69 (문제 노드)j99p6 (정상 노드)비율
02:0714 KB13 KB1:1
02:0825 MB4 MB6:1
02:1180 MB20 KB4000:1

update-accumulated-rank가 hwl69 Pod로 라우팅되어 해당 노드에서만 문제 발생.

6. PLEG → Node Ready 인과관계

Kubernetes 메커니즘

flowchart LR
    subgraph 정상
        K1[kubelet] -->|1초마다| P1[PLEG]
        P1 --> H1[heartbeat]
    end
    subgraph 문제
        K2[kubelet] -->|10초마다| P2[PLEG]
        P2 -.->|지연| H2[heartbeat 실패]
    end

왜 50초 grace period를 초과했는가?

분석 대시보드 (01:30~03:30 KST)

시간relist 횟수/초50초 동안 기회상태
정상1.050회heartbeat 충분
02:12~02:210.15회heartbeat 부족

PLEG가 10초씩 걸리면서 relist 횟수 자체가 90% 감소했다.

7. 메트릭 수집 실패

시간 (KST)kubeletcadvisornode-exporter
02:08DownUpUp
02:13~02:29불안정불안정불안정
02:37 이후UpUpUp

그래프가 끊긴 것 자체가 문제의 심각성을 증명한다. 노드가 메트릭 수집 요청에도 응답 불가 상태였다.

8. Root Cause 인과관계 체인

flowchart TD
    A[update-accumulated-rank<br/>26분 소요] --> B[Disk I/O 46배]
    B --> C[iowait 58%]
    C --> D[kubelet 응답 지연]
    D --> E[PLEG 10초]
    D --> F[메트릭 수집 실패]
    E --> G[Node Flapping 6회]

update-total-step 완료(02:11) 후에도 update-accumulated-rank 완료(02:26)까지 문제 지속 → 단일 작업만으로도 Node 장애 유발.

9. 배제된 원인

분석 대시보드 (01:30~03:00 KST)

가설검증 결과배제 이유
CPU 병목배제worker-app CPU 최대 0.38 cores (노드의 19%)
Memory Pressure배제가용 메모리 충분
Disk Pressure배제디스크 용량 문제 없음
네트워크 문제배제다른 노드 정상
2개 작업 동시 실행이 필수 조건배제단독 실행 시에도 문제 지속 확인

10. 해결 방안

즉시 조치

단기 조치: EBS IOPS/Throughput 증가

병목이 Disk I/O이므로 디스크 성능 향상이 근본 해결책이다.

IaC 변경 (2026-01-27)

/services/eap/test/variables.tf에서 worker 노드 그룹에 block_device_mappings 추가:

worker = {
  instance_types  = ["t4g.medium"]
  # ... 기존 설정 ...
  block_device_mappings = {
    xvda = {
      device_name = "/dev/xvda"
      ebs = {
        volume_size = 20
        volume_type = "gp3"
        iops        = 6000
        throughput  = 250
      }
    }
  }
}

/services/eap/test/main.tfeks_managed_node_groups에 전달:

block_device_mappings = config.block_device_mappings

terraform plan 결과:

# module.eks.module.eks_managed_node_group["worker"].aws_launch_template.this[0]
+ block_device_mappings {
    + device_name = "/dev/xvda"
    + ebs {
        + iops       = 6000
        + throughput = 250
        + volume_size = 20
        + volume_type = "gp3"
    }
  }

Plan: 0 to add, 2 to change, 0 to destroy.
설정현재변경 후추가 비용
IOPS3,0006,000+$15/월
Throughput125 MB/s250 MB/s+$5/월

적용 방법:

cd /Users/nudge_947/gitRepo/SRE/Nudge-IaC/services/eap/test
terraform apply

11. 대시보드 해석 가이드

지표 확인 순서

flowchart TD
    A[Node Ready?] -->|NotReady| B[PLEG Duration?]
    B -->|3초 이상| C[iowait?]
    C -->|30% 이상| D[어떤 컨테이너?]

임계값 기준

지표정상주의위험
Node Ready1-0
PLEG Duration<0.1초1~3초>3초
iowait<5%10~30%>30%
Scrape Target1-0

12. 교훈

  • Node NotReady가 발생하면 PLEG Duration부터 확인해라. PLEG 지연이 있으면 kubelet 자체가 느린 것이고, CPU가 아닌 I/O 병목일 가능성이 높다.
  • 노드 CPU 90% 이상을 보고 CPU 병목이라고 단정하지 마라. iowait 비중을 함께 확인해라. iowait이 높으면 CPU가 바쁜 게 아니라 I/O를 기다리고 있는 것이다.
  • 컨테이너 CPU/메모리 limit이 정상이어도 Disk I/O는 노드 전체를 포화시킬 수 있다. 배치 작업처럼 대량 I/O를 유발하는 작업이 있다면 EBS IOPS를 넉넉히 잡아야 한다.
  • 두 작업의 동시 실행을 의심했다면, 한 작업이 끝난 후에도 문제가 지속되는지 확인해라. 단독 실행 시에도 문제가 있다면 스케줄 분산이 아닌 작업 자체의 최적화가 필요하다.

13. 결론

항목내용
Root Causeupdate-accumulated-rank 작업의 과도한 Disk I/O (26분간 지속)
악화 요인update-total-step 동시 실행 (02:05~02:11)
병목Disk I/O 포화 (iowait 최대 58%)
결과PLEG 지연 → Node Ready Flapping 6회
해결EBS IOPS 3000 → 6000 증가

재발 방지

우선순위조치효과
1EBS IOPS 6000 증가I/O 병목 근본 해결
2update-accumulated-rank 작업 최적화근본 원인 제거
3CronJob 스케줄 분산동시 부하 방지
4worker-app 전용 노드 분리다른 Pod 영향 차단

참고 자료