[LOG-001] FastAPI 메모리 부족 문제 해결

원형석·2025년 12월 4일

데일리 이슈 로그

목록 보기
1/1

날짜: 2025-12-04
프로젝트: ML Platform API
키워드: Kubernetes, Memory Management, OOM Kill, FastAPI, Resource Limits


문제 상황

FastAPI 서버가 메모리 부족으로 반복적으로 종료되는 현상 발생

현상: Pod가 주기적으로 재시작
원인 추정: OOM (Out of Memory) Kill

원인 분석

Kubernetes deployment 설정을 확인한 결과, 메모리 리소스 할당이 부족함을 발견. 초기에는 경량 데이터와 서비스를 제공하던 역할만 하고 있어서 메모리 할당량을 적게 부여한 상태였음.

기존 설정:

resources:
  requests:
    cpu: "100m"
    memory: "128Mi"    # 너무 낮음
  limits:
    cpu: "500m"
    memory: "512Mi"    # ML 작업에 부족

문제점:

  • FastAPI 애플리케이션이 ML 관련 작업 수행 (pandas, numpy, quantstats 등)
  • 차트 생성, 보고서 생성 등 메모리 intensive한 작업이 늘어남
  • 512Mi limit를 초과하면 OOM Kill 발생 → Pod 종료 → 재시작 반복

해결 방법

메모리 리소스 할당량 증가:

resources:
  requests:
    cpu: "100m"
    memory: "512Mi"    # 128Mi → 512Mi (4배)
  limits:
    cpu: "500m"
    memory: "2Gi"      # 512Mi → 2Gi (4배)

적용:

kubectl apply -f kubernetes/deployment.yaml

변경 사항 적용 후 rolling update를 통해 새로운 메모리 설정으로 pod 재시작.

학습 포인트

1. Kubernetes Memory Requests vs Limits

Memory Requests (요청량):

  • Pod 스케줄링 시 사용 (어느 노드에 배치할지 결정)
  • 실제 메모리 사용량을 제한하지 않음
  • requests가 낮아도 pod가 바로 종료되지는 않음

Memory Limits (제한량):

  • 실제 메모리 사용량의 상한선
  • 이 값을 초과하면 OOM Kill 발생 → Pod 강제 종료
  • 이게 메모리 부족으로 pod가 죽는 진짜 원인

2. Requests가 낮을 때의 영향

  1. 스케줄링: requests가 낮으면 어떤 노드에도 쉽게 배치 가능
  2. Eviction 우선순위: 노드 전체 메모리 부족 시 requests가 낮은 pod부터 축출될 수 있음
  3. 리소스 경쟁: 실제로 많은 메모리를 사용하는데 requests가 낮으면 다른 pod들과 메모리 경쟁

3. 리소스 할당 전략

권장 설정:

  • requests = 실제 평균 사용량
  • limits = 피크 사용량 + 여유분

모니터링:

# Pod 메모리 사용량 확인
kubectl top pods -n fastapi-app

# Pod 상세 정보
kubectl describe pod <pod-name> -n fastapi-app

추가 고려사항

고가용성 (High Availability)

현재 deployment 설정:

replicas: 2
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0

질문: 노드 1개 vs 노드 2개?

답변: 프로덕션 환경에서는 노드 2개 권장

이유:
1. 고가용성: 노드 1개 장애 시에도 서비스 계속 운영
2. 무중단 배포: maxUnavailable: 0 설정과 조합하여 진정한 무중단 배포
3. 장애 격리: 한 노드의 하드웨어/커널 문제가 전체 서비스에 영향 없음
4. Pod 분산: 2개 replica가 서로 다른 노드에 배치되어 리스크 분산

추가 최적화 - Pod Anti-affinity:

spec:
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - fastapi
          topologyKey: kubernetes.io/hostname

이 설정은 2개 pod를 서로 다른 노드에 배치하도록 유도함.

Replica 제대로 작동하는지 확인

# Pod 개수 확인
kubectl get pods -n fastapi-app -l app=fastapi

# Pod가 어느 노드에 있는지 확인 (분산되어 있는지)
kubectl get pods -n fastapi-app -l app=fastapi -o wide

# Deployment 상태 확인
kubectl get deployment -n fastapi-app fastapi-deployment

주의: 노드가 1개밖에 없으면 pod 2개가 같은 노드에 배치됨 → 고가용성 없음

다음 액션

  • 메모리 사용량 모니터링 (kubectl top pods)
  • 여전히 OOM 발생 시 limits를 4Gi까지 증가 고려
  • 노드 개수 및 분산 상태 확인
  • 필요시 Pod Anti-affinity 설정 추가
profile
Python을 좋아합니다.

0개의 댓글