목표: 적절한 CPU/메모리 설정을 찾아 리소스 효율성을 높입니다 예상 시간: 45분

이 가이드의 범위

다루는 내용: 리소스 사용량 측정, requests/limits 적정값 산정, 스로틀링/OOM 해결

다루지 않는 내용: 자동 스케일링(스케일링 참조), Pod 시작 문제(Pod 트러블슈팅 참조)

시작하기 전에#

다음 조건을 확인하세요.

1. kubectl 설치 및 버전 확인#

kubectl version --client

성공 시 출력:

Client Version: v1.28.0

2. Metrics Server 설치 확인#

kubectl top nodes

성공 시 출력:

NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
node-1         250m         12%    1024Mi          50%

오류가 발생하면 Metrics Server를 설치하세요.

minikube addons enable metrics-server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

설치 후 1-2분 대기한 후 다시 확인하세요.

3. 대상 Pod 확인#

최적화할 Pod가 Running 상태인지 확인하세요.

kubectl get pods -l app=<your-app>

성공 시 출력:

NAME                     READY   STATUS    RESTARTS   AGE
my-app-xxx-yyy           1/1     Running   0          5m

1단계: 현재 사용량 측정#

측정 기간
정확한 분석을 위해 최소 1시간 이상 측정하세요. 피크 시간대를 포함하면 더 좋습니다.

Pod 리소스 사용량 확인#

kubectl top pods

예상 출력:

NAME                    CPU(cores)   MEMORY(bytes)
my-app-xxx-yyy          50m          256Mi
my-app-xxx-zzz          45m          248Mi

컨테이너별로 확인하려면 다음을 실행하세요.

kubectl top pods --containers

성공 확인: CPU(cores)와 MEMORY(bytes) 값이 표시되면 성공입니다.

시간별 사용량 추적#

2초마다 갱신되는 실시간 모니터링을 시작하세요.

watch -n 2 kubectl top pods

피크 시간대의 최대값과 평상시 값을 모두 기록하세요.

기록 예시:

시간대CPUMemory
평상시50m256Mi
피크200m400Mi

2단계: 현재 설정 확인#

현재 Deployment의 리소스 설정을 확인하세요.

kubectl get deployment <deployment-name> -o jsonpath='{.spec.template.spec.containers[0].resources}'

예상 출력:

{"limits":{"cpu":"1000m","memory":"2Gi"},"requests":{"cpu":"500m","memory":"1Gi"}}

문제 진단 기준#

현재 상태문제조치
requests가 실제 사용량의 5배 이상리소스 낭비requests 감소
requests가 실제 사용량보다 낮음스로틀링 위험requests 증가
limits가 피크 사용량보다 낮음OOM/스로틀링 발생limits 증가

성공 확인: 현재 설정값을 확인하고 실제 사용량과 비교할 수 있으면 성공입니다.


3단계: 적정 값 산정#

권장 계산 공식#

CPU requests = 평상시 사용량 × 1.2 (20% 여유)
CPU limits   = 피크 사용량 × 1.5 또는 미설정

Memory requests = 평상시 사용량 × 1.2
Memory limits   = requests × 1.5

계산 예시#

측정값:

  • 평상시 CPU: 50m, 피크 CPU: 200m
  • 평상시 Memory: 256Mi, 피크 Memory: 400Mi

계산:

CPU requests = 50m × 1.2 = 60m → 100m (반올림)
CPU limits   = 200m × 1.5 = 300m → 500m

Memory requests = 256Mi × 1.2 = 307Mi → 320Mi
Memory limits   = 320Mi × 1.5 = 480Mi → 512Mi

VPA Recommender 사용 (선택 사항)#

VPA를 설치하면 권장값을 자동으로 계산합니다.

# vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Off"  # 권장값만 확인, 자동 적용 안 함
kubectl apply -f vpa.yaml
kubectl describe vpa my-app-vpa

성공 확인: Recommendation 섹션에 권장값이 표시되면 성공입니다.


4단계: 설정 변경#

주의
프로덕션 환경에서는 한 번에 큰 변경을 하지 마세요. 점진적으로 조정하세요.

Deployment 수정#

kubectl edit deployment <deployment-name>

또는 patch 명령어를 사용하세요.

kubectl patch deployment <deployment-name> -p '
{
  "spec": {
    "template": {
      "spec": {
        "containers": [{
          "name": "<container-name>",
          "resources": {
            "requests": {
              "memory": "320Mi",
              "cpu": "100m"
            },
            "limits": {
              "memory": "512Mi",
              "cpu": "500m"
            }
          }
        }]
      }
    }
  }
}'

성공 확인: 새 Pod가 생성되고 Running 상태가 되면 성공입니다.

kubectl rollout status deployment <deployment-name>

5단계: 검증#

변경 후 다음을 확인하세요.

스로틀링 확인#

CPU 스로틀링이 발생하는지 확인하세요.

kubectl exec <pod-name> -- cat /sys/fs/cgroup/cpu/cpu.stat

출력에서 확인:

nr_throttled 0      # 0이면 스로틀링 없음
throttled_time 0    # 0이면 정상
cgroup v2 환경

cgroup v2 환경에서는 다음 명령어를 사용하세요.

kubectl exec <pod-name> -- cat /sys/fs/cgroup/cpu.stat

OOM 확인#

OOM 이벤트가 발생하는지 확인하세요.

kubectl get events --field-selector reason=OOMKilling

성공 확인: 이벤트가 없으면 성공입니다.

QoS 클래스 확인#

kubectl get pod <pod-name> -o jsonpath='{.status.qosClass}'
QoS 클래스의미권장 상황
Guaranteedrequests = limits중요 워크로드
Burstablerequests < limits일반 워크로드
BestEffort리소스 미설정테스트용만 권장

성공 확인: 의도한 QoS 클래스가 적용되면 성공입니다.


자주 발생하는 오류#

“OOMKilled” 반복 발생#

원인: Memory limits가 너무 낮습니다.

해결:

# 현재 limits 확인
kubectl describe pod <pod-name> | grep -A 2 "Limits"

# limits 증가 (예: 512Mi → 1Gi)
kubectl patch deployment <name> -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container>","resources":{"limits":{"memory":"1Gi"}}}]}}}}'

CPU 스로틀링으로 응답 지연#

원인: CPU limits가 너무 낮습니다.

해결:

  1. CPU limits를 증가시키거나
  2. CPU limits를 제거하세요 (requests만 설정)
resources:
  requests:
    cpu: "100m"
  # limits.cpu 생략 - 노드 CPU를 사용 가능
  limits:
    memory: "512Mi"

“0/N nodes are available: Insufficient cpu/memory”#

원인: requests가 노드 가용 리소스보다 큽니다.

해결:

# 노드 가용 리소스 확인
kubectl describe nodes | grep -A 5 "Allocatable"

# requests를 가용 리소스 이하로 조정

Metrics Server “error: Metrics API not available”#

원인: Metrics Server가 설치되지 않았거나 준비되지 않았습니다.

해결:

# Metrics Server 상태 확인
kubectl get pods -n kube-system | grep metrics-server

# 로그 확인
kubectl logs -n kube-system deployment/metrics-server

Java 애플리케이션 특화 설정#

Java 애플리케이션은 JVM 힙 메모리 설정이 중요합니다.

주의
JVM 힙을 컨테이너 메모리와 동일하게 설정하면 OOM이 발생합니다. JVM은 힙 외에 메타스페이스, 스레드 스택 등 추가 메모리를 사용합니다.

권장 설정#

resources:
  requests:
    memory: "512Mi"
  limits:
    memory: "1Gi"
env:
- name: JAVA_OPTS
  value: "-XX:MaxRAMPercentage=75.0 -XX:+UseG1GC"

컨테이너 메모리별 힙 비율#

컨테이너 메모리권장 힙 비율이유
< 512Mi50-60%비힙 메모리 비율이 상대적으로 높음
512Mi - 2Gi65-75%일반적인 설정
> 2Gi75-80%대규모 힙에서는 비힙 비율 감소

성공 확인: Pod가 OOM 없이 안정적으로 동작하면 성공입니다.


체크리스트#

측정#

  • Metrics Server가 설치되어 있는가?
  • 최소 1시간 이상 사용량을 측정했는가?
  • 피크 시간대 사용량을 확인했는가?

설정#

  • requests가 평상시 사용량의 100-120%인가?
  • limits가 피크 사용량을 수용할 수 있는가?
  • Java 앱의 경우 JVM 힙이 적절히 설정되었는가?

검증#

  • 변경 후 Pod가 정상 Running 상태인가?
  • CPU 스로틀링이 발생하지 않는가?
  • OOM이 발생하지 않는가?
  • 의도한 QoS 클래스가 적용되었는가?

다음 단계#

목표추천 문서
자동 스케일링 설정스케일링
Pod 문제 해결Pod 트러블슈팅
리소스 관리 개념리소스 관리