기본 콘텐츠로 건너뛰기

Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결 로드맵

Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결 로드맵

AI 생성 이미지: Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결
AI 생성 이미지: Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결

문제 정의 — 노드 OOM이 파드 재스케줄링에 미치는 영향

노드 수준 OOM(Out Of Memory)은 한 번의 사건으로 여러 재스케줄링 문제와 연쇄적인 서비스 장애를 촉발할 수 있다. 주요 관찰 지표는 다음과 같다.

  • Evicted — kubelet의 eviction manager가 메모리 압박 시 우선순위가 낮은 파드를 강제 종료해 Evicted 상태로 만든다.
  • CrashLoopBackOff — OOM-killer가 컨테이너 프로세스를 종료하면 파드가 반복 재시작하며 지수적 백오프에 빠진다.
  • Pending — 스케줄러가 다른 노드에서 충분한 메모리를 찾지 못하거나 노드에 taint가 있어 파드를 배치하지 못한다.
  • NotReady — kubelet 장애로 노드가 NotReady 상태가 되면 컨트롤러에 의한 대체·복구 작업이 지연된다.

서비스 영향은 다양하게 나타난다. 요청 처리량이 감소하고 응답 지연이 길어질 수 있다. 세션 또는 캐시 손실이 발생하며, 상태 저장 워크로드는 복구에 시간이 더 걸린다. 파드 재시작으로 인한 트래픽 스파이크와 자동스케일링·헬스체크의 불안정은 부분적 또는 전체 서비스 장애로 이어질 수 있다. 실무 체크리스트 예: Evicted 로그와 노드 메모리 사용량을 우선 확인하고, 필요 시 QoS/Requests/Limits을 조정하거나 노드를 증설해 대응하라. 이러한 점검은 Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결에 직접적으로 도움이 된다.

근본 원인 분석 — 노드 메모리 고갈의 주요 원인

노드 OOM 원인을 빠르게 파악하려면 애플리케이션, 스케줄링·리소스 설정, 시스템(데몬·커널)의 세 가지 관점에서 접근하세요.

  • 애플리케이션 메모리 누수: 특정 파드의 메모리 사용량이 시간이 지날수록 점진적으로 증가합니다. 확인 방법 — kubectl top pod, 애플리케이션 메모리 프로파일링, cAdvisor 또는 Prometheus 시계열에서 누적 추세를 확인합니다.
  • 잘못된 requests·limits: requests가 과소하게 설정되거나 limits가 없으면 스케줄러가 노드를 과다할당하고, 메모리 압박 시 kubelet이 파드를 강제 종료(eviction)합니다. 확인 방법 — kubectl describe pod/node, 리소스 쿼터와 HPA 설정을 점검하세요.
  • 데몬·커널 OOM: kubelet의 eviction이 아닌 커널 레벨 OOM이면 시스템 프로세스 또는 컨테이너가 커널에 의해 OOMKILL 됩니다. 확인 방법 — dmesg, journalctl -k 또는 /var/log/kern.log와 kubelet 로그, 노드 이벤트(oom_kill 관련)를 확인합니다.

추가로 systemd-cgtop, crictl stats, kubelet의 evictionHard/evictionSoft 설정과 node allocatable(system-reserved, kube-reserved)을 함께 검토해 원인별 대응 우선순위를 정합니다. 실무 체크리스트 예: 메모리 사용 상위 파드 식별 → requests/limits·리소스 쿼터·HPA 점검 → eviction 설정 및 system-reserved/kube-reserved 값 확인 → 수정 후 모니터링. 이를 통해 Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결에 우선순위를 부여할 수 있습니다.

진단 체크리스트 — 로그·메트릭·이벤트에서 우선 확인할 항목

아래 체크리스트는 dmesg, kubelet/journal, eviction 이벤트, cgroup·cAdvisor·노드 메트릭을 빠르게 훑어 원인 추적할 때 우선 점검할 항목입니다.

  • dmesg/커널 로그: 'Out of memory', 'Killed process', 'oom_reaper' 같은 키워드를 찾고, PID·프로세스명·타임스탬프와 해당 프로세스의 cgroup 경로를 함께 확인하세요.
  • kubelet / journal: eviction manager 관련 로그와 메모리 임계치 경고(thresholds)를 점검하고, Pod 강제 종료 로그나 kubelet 재시작 여부도 확인합니다.
  • Kubernetes 이벤트: kubectl events에서 Evicted 또는 Failed 이벤트를 수집하고, Pod 상태(예: reason: OOMKilled)와 이벤트 타임라인을 통해 전후 관계를 파악하세요.
  • cgroup / cAdvisor 지표: container_memory_usage_bytes, working_set, rss, cache 등의 지표를 보고 /sys/fs/cgroup/.../memory.oom_control 및 memory.stat에서 oom 관련 이벤트 존재 여부를 확인합니다.
  • 노드 메트릭: node_memory_MemAvailable, memory pressure, swap 사용량, node_cpu 및 kubelet 메모리 사용량을 점검하고, Prometheus 타임라인에서 메트릭과 로그 타임스탬프를 정렬해 보세요.
  • 상관관계 분석: 커널 로그, kubelet 로그, 이벤트, 메트릭의 타임스탬프를 교차 검증해 최초 메모리 급감 원인(오버커밋, 메모리 누수, 대용량 배치 등)을 식별합니다.
  • 실무 팁: 최근 배포·크론잡·대용량 작업 여부를 우선 확인하고, Pod의 requests/limits 설정과 노드 리소스 여유를 점검하세요. 임시로는 문제 노드에서 파드 축출(cordon/evict)이나 노드 리부팅으로 셀프 힐링을 유도한 뒤, 재발 방지를 위해 리소스 쿼터·HPA나 예약 정책을 검토하는 것이 좋습니다. (참고: Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결 관점에서 유용합니다.)

즉시 대응 — 재스케줄링 장애 완화를 위한 긴급 조치

노드 OOM 발생 시 다음 조치를 동시에 실행해 재스케줄링 장애를 최소화합니다. 특히 Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결 관점에서 우선 대응해야 합니다.

  • 노드 cordon/drain — 영향을 받은 노드를 즉시 cordon하여 신규 스케줄링을 차단합니다 (kubectl cordon). 안전하게 마이그레이션 가능한 파드는 drain으로 축출하세요 (kubectl drain --ignore-daemonsets --delete-local-data). 중요 서비스는 강제 삭제 전 상태와 의존성을 반드시 확인합니다.
  • 우선순위/프로브 조정 — 긴급 PriorityClass를 만들어 핵심 파드의 우선순위를 올리고, 필요 시 preemption을 허용합니다. liveness 및 readiness 프로브의 민감도를 일시적으로 완화해 불필요한 재시작을 방지합니다.
  • 임시 리소스 재할당·파드 재배치 — 비핵심 디플로이먼트를 축소(scale down)하거나 리소스 요청(requests)을 임시로 낮춰 스케줄 여유를 확보합니다. 특정 노드로 강제 이동이 필요하면 nodeSelector/affinity를 사용해 재배치하고, taint/toleration으로 우선순위를 조정해 재스케줄링을 유도합니다. 실무 체크리스트: cordon → 우선순위 적용 → 비핵심 축소 순으로 빠르게 점검하세요.

재발 방지 설정 — kubelet·스케줄러·리소스 정책 조정

노드에서 OOM이 반복되지 않도록 하려면 kubelet, 스케줄러, 리소스 정책을 함께 조정해야 합니다. 운영 관점에서 특히 챙겨야 할 핵심 항목은 다음과 같습니다.

  • evictionThresholds — kubelet 플래그(--eviction-hard/--eviction-soft, memory.available 등)과 transition-period를 적절히 설정해 자동 퇴출 시점을 분명히 하세요. 임계값은 실사용 측정값을 기반으로 정하고, 모니터링 결과에 따라 주기적으로 조정합니다. 간단 체크: 측정 → 임계 설정 → 경보 및 재검토.
  • systemReserved / kubeReserved — 호스트 프로세스와 kube 컴포넌트의 실제 리소스 사용량을 파악해 예약합니다. 이렇게 하면 Node Allocatable을 보장할 수 있고, 예약 합계가 eviction 임계값보다 높지 않도록 맞추는 것이 중요합니다.
  • QoS 클래스 — 중요한 워크로드는 requests와 limits를 같게 설정해 Guaranteed로 배치하고, 중간 우선순위는 Burstable로, 핵심 서비스에 BestEffort는 피하세요. 리소스 요청과 제한을 일관되게 설정하면 OOM 발생 시 퇴출 우선순위를 제어할 수 있습니다.
  • PodDisruptionBudget 적용 포인트 — Stateful나 핵심 서비스에는 minAvailable 또는 maxUnavailable PDB를 적용해 자발적 중단을 제한하세요. 다만 PDB는 자발적 재스케줄링에는 유효하지만, 강제 퇴출(OOM)을 완전히 막지는 못하므로 eviction 정책과 함께 설계해야 합니다.
  • 스케줄러/우선순위 — PodPriority와 Preemption을 활성화하고, 낮은 우선순위와 BestEffort 파드를 먼저 퇴출 대상으로 지정하세요. 여기에 클러스터 오토스케일러를 연동하면 노드 압박을 완화하는 데 도움이 됩니다. 이런 조합은 Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결에 실무적으로 유용합니다.

운영 가이드와 자동화 — 모니터링·알림·복구 플레이북

모니터링 임계값과 알림을 명확하게 정의하고, 재스케줄링을 자동화해 신속하게 복구되도록 한다. 특히 Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결을 염두에 둔다.

  • 모니터링·알림: node_memory_available < 15% (또는 node_memory_bytes_available/node_memory_total < 0.15). 컨테이너 재시작률(kube_pod_container_status_restarts) > 3(5m) 또는 OOMKilled 이벤트 발생 시 즉시 경보 발송.
  • 자동스케일링·스케줄링: Cluster-Autoscaler와 HPA/VPA를 조합해 자동 확장 적용. 노드 용량이 부족하면 신규 노드 프로비저닝과 파드 우선순위 기반 재스케줄링을 수행한다.
  • 헬스체크·프로브: readiness와 liveness 프로브를 엄격히 설정하고, 노드 이상 감지 시 cordon → drain을 자동화(taint 및 eviction 활용).
  • 복구(runbook): 1) 문제 노드 cordon, 2) drain(Graceful), 3) OOM 파드는 필요 시 강제 삭제 후 재생성, 4) 노드 점검 → 재부팅 또는 교체 후 uncordon.
  • 정기 검증: 분기별 복구 연습과 Chaos 테스트로 실전 대응력을 점검하고, 알림 임계값 튜닝 회고를 통해 신뢰성을 유지한다. 예: 복구 연습 체크리스트 — cordon/drain 실행, 파드 재스케줄 확인, 알림 수신 및 관련 로그 검토.

경험에서 배운 점

노드 OOM 상황에서 파드가 재스케줄링되지 않는 주요 원인은 문제 진단 경로가 빠진 경우(예: kernel OOM 로그 확인 미흡, kubelet eviction 이벤트 미확인)나 파드·노드의 리소스 메타데이터가 부적절하게 설정된 경우가 많습니다. 실무에서 흔히 겪는 오류로는 리소스 요청(requests)/한도(limits)을 지정하지 않아 BestEffort 또는 Burstable로 분류된 파드가 먼저 종료되는 경우, PriorityClass를 고려하지 않아 중요한 파드가 재스케줄되지 않는 경우, 노드에 kube-reserved/system-reserved를 설정하지 않아 kubelet이 메모리 압박을 제대로 관리하지 못하는 경우가 있습니다. 또한 taint/toleration, nodeSelector/affinity, PDB(파드의 업데이트·삭제 제한) 같은 스케줄링 제약을 점검하지 않아 정상적인 재스케줄이 차단되는 사례도 자주 발생합니다. 실무 사례: 프로덕션 노드에서 kernel OOM으로 여러 파드가 죽었고, PriorityClass 미설정과 taint/toleration 불일치 때문에 재스케줄이 지연된 적이 있습니다. 이 글은 Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결에 실무적으로 접근하는 데 초점을 둡니다.

긴급 대응과 재발방지 체크리스트(간결 순서): 1) 증상 확인 — dmesg|grep -i oom, journalctl -u kubelet, kubectl describe node <NODENAME>, kubectl describe pod <POD>로 OOM 및 eviction 이벤트 확인; 2) 스케줄링 제약 확인 — taints/tolerations, nodeSelector/affinity, PodDisruptionBudget, PriorityClass 유무; 3) 파드 스펙 점검 — requests/limits, QoS 클래스, preemption 허용 여부; 4) kubelet/노드 설정 확인 — evictionHard/Soft, kube-reserved/system-reserved, cgroup driver, swap 비활성화; 5) 임시조치 — 노드 cordon/drain(또는 문제 프로세스 종료), kubelet 재시작 또는 노드 재부팅; 6) 영구조치 — 리소스 요청·한도 조정, 우선순위/프리엠션 정책, 클러스터 오토스케일러/노드 수 증설, 데몬셋 메모리 제한 설정; 7) 모니터링/알림 및 런북 업데이트 — OOM/eviction 이벤트와 노드 메모리 임계치에 대한 자동화 알림과 명확한 복구 절차 기재. 실무 팁: 문제 발생 시 우선 해당 노드를 cordon 후 drain으로 격리하고, 복구 절차를 진행하면서 kubelet 로그와 dmesg 출력을 함께 수집해 두면 원인 분석이 훨씬 수월합니다.

재발 방지 팁은 단순합니다: 핵심 워크로드에는 requests와 limits를 명시하고, Guaranteed/Burstable 등 QoS를 설계하며 PriorityClass로 복구 우선순위를 정하세요. kubelet의 eviction 설정과 nodeAllocatable을 현실적인 값으로 맞추고, system/kube-reserved를 설정해 노드 수준의 안정성을 확보하세요. 마지막으로 노드 메모리 사용량, eviction 이벤트, OOMKilled 카운트 같은 모니터링 지표와 실전용 런북(정확한 kubectl/ssh 명령, 복구 순서, 연락망)을 마련해 정기적으로 스테이징 환경에서 시뮬레이션하면 동일한 사건의 재발을 크게 줄일 수 있습니다.

AI 생성 이미지: Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결
AI 생성 이미지: Kubernetes 노드 OOM 발생 시 파드 재스케줄링 문제 해결

댓글

이 블로그의 인기 게시물

Java Servlet Request Parameter 완전 정복 — GET/POST 모든 파라미터 확인 & 디버깅 예제 (Request Parameter 전체보기)

Java Servlet Request Parameter 완전 정복 — GET/POST 모든 파라미터 확인 & 디버깅 예제 Java Servlet Request Parameter 완전 정복 웹 애플리케이션에서 클라이언트로부터 전달되는 Request Parameter 를 확인하는 것은 필수입니다. 이 글에서는 Java Servlet 과 JSP 에서 GET/POST 요청 파라미터를 전체 출력하고 디버깅하는 방법을 다양한 예제와 함께 소개합니다. 1. 기본 예제: getParameterNames() 사용 Enumeration<String> params = request.getParameterNames(); System.out.println("----------------------------"); while (params.hasMoreElements()){ String name = params.nextElement(); System.out.println(name + " : " + request.getParameter(name)); } System.out.println("----------------------------"); 위 코드는 요청에 포함된 모든 파라미터 이름과 값을 출력하는 기본 방법입니다. 2. HTML Form과 연동 예제 <form action="CheckParamsServlet" method="post"> 이름: <input type="text" name="username"><br> 이메일: <input type="email" name="email"><b...

PostgreSQL 달력(일별,월별)

SQL 팁: GENERATE_SERIES로 일별, 월별 날짜 목록 만들기 SQL 팁: GENERATE_SERIES 로 일별, 월별 날짜 목록 만들기 데이터베이스에서 통계 리포트를 작성하거나 비어있는 날짜 데이터를 채워야 할 때, 특정 기간의 날짜 목록이 필요할 수 있습니다. PostgreSQL과 같은 데이터베이스에서는 GENERATE_SERIES 함수를 사용하여 이 작업을 매우 간단하게 처리할 수 있습니다. 1. 🗓️ 일별 날짜 목록 생성하기 2020년 1월 1일부터 12월 31일까지의 모든 날짜를 '1 day' 간격으로 생성하는 쿼리입니다. WITH date_series AS ( SELECT DATE(GENERATE_SERIES( TO_DATE('2020-01-01', 'YYYY-MM-DD'), TO_DATE('2020-12-31', 'YYYY-MM-DD'), '1 day' )) AS DATE ) SELECT DATE FROM date_series 이 쿼리는 WITH 절(CTE)을 사용하여 date_series 라는 임시 테이블을 만들고, GENERATE_SERIES 함수로 날짜를 채웁니다. 결과 (일별 출력) 2. 📅 월별 날짜 목록 생성하기 동일한 원리로, 간격을 '1 MONTH' 로 변경하면 월별 목록을 생성할 수 있습니다. TO...

CSS로 레이어 팝업 화면 가운데 정렬하는 방법 (top·left·transform 완전 정리)

레이어 팝업 센터 정렬, 이 코드만 알면 끝 (CSS 예제 포함) 이벤트 배너나 공지사항을 띄울 때 레이어 팝업(center 정렬) 을 깔끔하게 잡는 게 생각보다 어렵습니다. 화면 크기가 변해도 가운데에 고정되고, 모바일에서도 자연스럽게 보이게 하려면 position , top , left , transform 을 정확하게 이해해야 합니다. 이 글에서는 아래 내용을 예제로 정리합니다. 레이어 팝업(center 정렬)의 기본 개념 자주 사용하는 position: absolute / fixed 정렬 방식 질문에서 주신 스타일 top: 3.25%; left: 50%; transform: translateX(-50%) 의 의미 실무에서 바로 쓰는 반응형 레이어 팝업 HTML/CSS 예제 1. 레이어 팝업(center 정렬)이란? 레이어 팝업(레이어 팝업창) 은 새 창을 띄우는 것이 아니라, 현재 페이지 위에 div 레이어를 띄워서 공지사항, 광고, 이벤트 등을 보여주는 방식을 말합니다. 검색엔진(SEO) 입장에서도 같은 페이지 안에 HTML이 존재 하기 때문에 팝업 안의 텍스트도 정상적으로 인덱싱될 수 있습니다. 즉, “레이어 팝업 센터 정렬”, “레이어 팝업 만드는 방법”과 같이 관련 키워드를 적절히 넣어주면 검색 노출에 도움이 됩니다. 2. 질문에서 주신 레이어 팝업 스타일 분석 질문에서 주신 스타일은 다음과 같습니다. <div class="layer-popup" style="width:1210px; z-index:9001; position:absolute; top:3.25%; left:50%; transform:translateX(-50%);"> 레이어 팝업 내용 <...