B2B Solution/트러블슈팅

Kubernetes OOMKilled 문제 해결 가이드: 원인 분석부터 예방까지

SangPedia 2026. 4. 5. 09:01
반응형

Kubernetes OOMKilled 문제 해결: 실무 가이드

애플리케이션을 Kubernetes 환경에서 운영하다 보면 예기치 않게 OOMKilled 오류를 마주할 수 있습니다. 이 글에서는 OOMKilled 오류의 원인을 분석하고, 단계별 해결 방법을 제시하며, 재발 방지를 위한 예방 조치를 안내합니다. IT 관리자와 엔지니어가 실제 환경에서 겪는 어려움을 해결하는 데 도움이 될 것입니다.

Kubernetes OOMKilled 문제 해결 가이드: 원인 분석부터 예방까지

에러 현상

OOMKilled는 컨테이너가 할당된 메모리 제한을 초과하여 Linux 커널에 의해 강제로 종료될 때 발생하는 오류입니다. 다음은 일반적인 OOMKilled 오류 메시지 예시입니다.

OOMKilled: true
reason: OOMKilled
message: 'Container example-container terminated because it used more memory than allowed.'
lastState:
  terminated:
    exitCode: 137
    reason: OOMKilled
    signal: 9
    startedAt: '2024-01-01T00:00:00Z'
    finishedAt: '2024-01-01T00:01:00Z'

위 오류 메시지는 example-container라는 컨테이너가 허용된 메모리보다 더 많은 메모리를 사용하여 종료되었음을 나타냅니다. exitCode: 137은 컨테이너가 SIGKILL 신호(signal 9)에 의해 종료되었음을 의미하며, 이는 OOM Killer가 컨테이너를 강제 종료했음을 시사합니다. 이 오류는 Kubernetes 클러스터의 특정 Pod에서 발생하며, 해당 Pod의 상태가 비정상으로 변경됩니다. 스크린샷을 통해 오류 발생 시점의 Pod 상태 변화를 시각적으로 확인할 수 있습니다.

kubernetes pod oomkilled

원인 분석

OOMKilled 오류는 다양한 원인으로 인해 발생할 수 있습니다. 주요 원인과 확인 방법은 다음과 같습니다.

1. 메모리 누수 (Memory Leak)

애플리케이션 코드의 결함으로 인해 메모리 누수가 발생하면, 시간이 지남에 따라 메모리 사용량이 계속 증가하여 결국 메모리 제한을 초과하게 됩니다. 이는 OOMKilled의 가장 흔한 원인 중 하나입니다.

확인 방법:

애플리케이션의 메모리 프로파일링 도구를 사용하여 메모리 누수 여부를 확인합니다. Java 애플리케이션의 경우, VisualVM 또는 JProfiler와 같은 도구를 사용할 수 있습니다. 또한, Kubernetes 환경에서는 kubectl top pod 명령어를 사용하여 Pod의 메모리 사용량을 실시간으로 모니터링할 수 있습니다.

kubectl top pod <pod-name> --namespace <namespace>

2. 과도한 메모리 사용

애플리케이션이 예상보다 많은 메모리를 사용하는 경우, 설정된 메모리 제한을 초과하여 OOMKilled가 발생할 수 있습니다. 이는 애플리케이션의 설정 오류, 데이터 처리량 증가, 또는 비효율적인 알고리즘 사용으로 인해 발생할 수 있습니다.

확인 방법:

애플리케이션의 로그를 분석하여 메모리 사용량이 급증하는 시점을 파악합니다. 또한, 애플리케이션의 성능 모니터링 도구를 사용하여 메모리 사용량 추이를 확인합니다. Kubernetes 환경에서는 Prometheus와 Grafana를 연동하여 Pod의 메모리 사용량을 시각적으로 모니터링할 수 있습니다. [출처: velog.io]

3. 불충분한 메모리 제한

Pod에 설정된 메모리 제한이 애플리케이션의 실제 메모리 요구량보다 낮은 경우, 애플리케이션이 정상적으로 작동하더라도 일시적인 트래픽 증가나 특정 작업으로 인해 OOMKilled가 발생할 수 있습니다.

확인 방법:

Pod의 YAML 파일을 확인하여 메모리 제한 설정을 확인합니다. 또한, 애플리케이션의 평균 및 최대 메모리 사용량을 파악하여 설정된 제한이 적절한지 평가합니다. Kubernetes 환경에서는 Vertical Pod Autoscaler (VPA)를 사용하여 적절한 리소스 요청 및 제한을 자동으로 설정할 수 있습니다.

Mermaid diagram: graph TD

해결 방법

각 원인에 따른 해결 방법은 다음과 같습니다.

1. 메모리 누수 해결

  • 실행 전 확인: 애플리케이션의 메모리 프로파일링 도구를 사용하여 메모리 누수가 발생하는 코드 영역을 식별합니다.

  • 조치: 메모리 누수를 유발하는 코드를 수정합니다. 불필요한 객체 생성을 줄이고, 사용이 끝난 객체를 명시적으로 해제합니다. Java의 경우, try-with-resources 구문을 사용하여 리소스를 자동으로 해제할 수 있습니다.

    java try (FileInputStream fis = new FileInputStream("example.txt")) { // 파일 처리 로직 } catch (IOException e) { // 예외 처리 } // fis는 자동으로 close() 됩니다.

  • 실행 후 검증: 수정된 코드를 배포한 후, 메모리 프로파일링 도구를 사용하여 메모리 누수가 해결되었는지 확인합니다. kubectl top pod 명령어를 사용하여 Pod의 메모리 사용량이 안정적으로 유지되는지 모니터링합니다.

    bash kubectl top pod <pod-name> --namespace <namespace>

2. 과도한 메모리 사용 최적화

  • 실행 전 확인: 애플리케이션의 성능 모니터링 도구를 사용하여 메모리 사용량이 높은 작업 또는 기능을 식별합니다. 애플리케이션 로그를 분석하여 메모리 사용량이 급증하는 시점을 파악합니다.

  • 조치:

    • 데이터 처리 알고리즘을 최적화하여 메모리 사용량을 줄입니다. 예를 들어, 대량의 데이터를 한 번에 처리하는 대신, 페이지네이션 또는 스트리밍 방식을 사용하여 데이터를 분할 처리합니다.
    • 불필요한 기능을 제거하거나, 필요에 따라 기능을 비활성화할 수 있도록 설정 옵션을 추가합니다.
    • 캐싱 전략을 사용하여 자주 사용되는 데이터를 메모리에 저장하고, 데이터베이스 또는 외부 API 호출을 줄입니다.
  • 실행 후 검증: 최적화된 코드를 배포한 후, 성능 모니터링 도구를 사용하여 메모리 사용량이 감소했는지 확인합니다. kubectl top pod 명령어를 사용하여 Pod의 메모리 사용량이 허용 범위 내에 있는지 모니터링합니다.

3. 메모리 제한 증가

  • 실행 전 확인: 애플리케이션의 평균 및 최대 메모리 사용량을 파악합니다. Kubernetes 환경에서는 Vertical Pod Autoscaler (VPA)를 사용하여 적절한 리소스 요청 및 제한을 자동으로 설정할 수 있습니다.

  • 조치: Pod의 YAML 파일을 수정하여 메모리 제한을 증가시킵니다. 리소스 요청도 함께 조정하여 스케줄러가 Pod를 적절한 노드에 배치할 수 있도록 합니다.

    yaml apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: example-container image: example-image resources: requests: memory: "256Mi" limits: memory: "512Mi"

  • 실행 후 검증: Pod를 재배포한 후, kubectl describe pod <pod-name> --namespace <namespace> 명령어를 사용하여 메모리 제한이 정상적으로 변경되었는지 확인합니다. 애플리케이션이 정상적으로 작동하는지 확인하고, 메모리 사용량을 지속적으로 모니터링합니다.

Mermaid diagram: sequenceDiagram

예방 조치

OOMKilled 오류를 예방하기 위해서는 다음과 같은 조치를 취할 수 있습니다.

  • 메모리 모니터링: Prometheus와 Grafana를 사용하여 Pod의 메모리 사용량을 지속적으로 모니터링합니다. 메모리 사용량이 임계값을 초과할 경우 알림을 설정하여 사전에 대응할 수 있도록 합니다.

    ```yaml

    Prometheus 설정 예시

    • alert:
      OOMKilledDetected
      expr: |
      kube_pod_container_status_last_terminated_reason{reason="OOMKilled"} > 0
      for: 5m
      labels:
      severity: critical
      annotations:
      summary: "OOMKilled detected on {{ $labels.pod }} ({{ $labels.namespace }})"
      description: "Container {{ $labels.container }} in pod {{ $labels.pod }} (namespace {{ $labels.namespace }}) has been OOMKilled."
      ```
  • 자동 스케일링: Horizontal Pod Autoscaler (HPA)를 사용하여 Pod의 수를 자동으로 조절합니다. CPU 사용량 또는 메모리 사용량에 따라 Pod의 수를 늘리거나 줄여, 리소스 부족으로 인한 OOMKilled를 예방할 수 있습니다.

  • 정기 점검: 애플리케이션의 메모리 사용 패턴을 정기적으로 분석하고, 메모리 누수 또는 비효율적인 메모리 사용이 있는지 확인합니다. 코드 리뷰를 통해 메모리 관련 문제를 사전에 발견하고 수정합니다.

  • 라이브니스 프로브 설정: 라이브니스 프로브를 통해 애플리케이션의 상태를 주기적으로 확인하고, 비정상적인 상태일 경우 자동으로 재시작하도록 설정합니다. 이를 통해 OOMKilled 발생 시 애플리케이션의 가용성을 유지할 수 있습니다.

kubernetes monitoring dashboard

관련 에러/참고 자료

  • CrashLoopBackOff: Pod가 계속해서 시작에 실패하는 경우 발생합니다. 리소스 요청 부족 또는 잘못된 설정으로 인해 발생할 수 있습니다.
  • ImagePullBackOff: 컨테이너 이미지를 가져오는 데 실패하는 경우 발생합니다. 이미지 이름 오류 또는 레지스트리 접근 권한 문제로 인해 발생할 수 있습니다.
  • Kubernetes 공식 문서: Kubernetes와 관련된 다양한 문제 해결 방법과 예방 조치를 제공합니다. [Microsoft Learn 공식 문서 참고]

FAQ

위의 FAQ는 상단 JSON에 포함되어 있습니다.


반응형