학습 예시 안내: 본문의 상황과 출력은 개념 설명을 위한 예시로 정리했습니다. 당시 실행 여부는 확인되지 않았으며, 현재 환경에서의 클러스터 실습도 별도 검증이 필요합니다.
🎯 학습 목표
이 글을 통해 다음을 학습할 수 있습니다:
- Pod 리소스 관리의 필요성과 중요성
- CPU와 메모리 요청(Requests)과 제한(Limits) 설정 방법
- Quality of Service(QoS) 클래스 이해
- 리소스 부족 상황에서의 Pod 스케줄링과 Eviction
- CKA 준비 과정에서 연습할 리소스 관리 패턴
📝 지난 시간 복습과 새로운 문제 인식
지난 글에서는 ConfigMap과 Secret으로 설정을 분리하는 방법을 다뤘습니다. 이번에는 여러 Pod가 같은 노드의 CPU와 메모리를 사용하는 상황을 가정합니다.
예제에서 가정한 환경
# 기존에 만든 리소스들 상태 확인
kubectl get deployments
kubectl get pods -o wide
kubectl top nodes # 노드 리소스 사용량 확인
kubectl top pods # Pod 리소스 사용량 확인
문제 상황 시뮬레이션
리소스 제한 없이 여러 테스트용 Pod를 배포하는 상황을 가정해 봅니다:
# 메모리를 많이 사용하는 Pod 생성
kubectl run memory-hog --image=progrium/stress -- --vm 1 --vm-bytes 1G --vm-hang 0
# 상태 확인
kubectl get pods
kubectl describe pod memory-hog
가정한 상황의 문제점:
- 노드 리소스 고갈: 한 Pod가 노드의 모든 메모리를 사용해버림
- 다른 Pod 영향: 새로운 Pod가 스케줄링되지 않거나 기존 Pod가 종료됨
- 예측 불가능한 성능: 리소스 경합으로 인한 성능 저하
- 장애 전파: 한 애플리케이션의 문제가 전체 클러스터에 영향
# 문제 상황 확인
kubectl get events --sort-by=.metadata.creationTimestamp
# Warning Failed scheduler 0/1 nodes are available: 1 Insufficient memory.
리소스 경합을 관리하기 위한 리소스 요청과 제한 설정을 살펴보겠습니다.
💡 리소스 요청(Requests)과 제한(Limits) 이해하기
기본 개념 정리
Requests (요청)
- 컨테이너에 필요한 리소스를 선언하는 값
- 스케줄러가 Pod를 배치할 때 사용하는 기준
- 실제 사용량의 하한선이 아니므로 사용량이 requests보다 작을 수도 있음
Limits (제한)
- Pod가 사용할 수 있는 최대 리소스양
- 이 값을 초과하면 제한 조치 발생
- 리소스 사용량 상한선
Requests: 스케줄링과 자원 배분의 기준
실제 사용량: 부하에 따라 Requests보다 작거나 클 수 있음
Limits: CPU는 throttling, 메모리는 OOM 종료로 제한
메모리 제한은 초과 순간마다 즉시 종료시키는 방식이 아니며, 커널의 메모리 압박 감지에 따라 종료될 수 있습니다. 리소스 관리 공식 문서
첫 번째 리소스 제한 설정
기본적인 리소스 설정 예제입니다:
# resource-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: demo-container
image: nginx
resources:
requests:
memory: "64Mi" # 메모리 요청 64 MiB
cpu: "250m" # 최소 0.25 CPU 코어 필요
limits:
memory: "128Mi" # 메모리 제한 128 MiB
cpu: "500m" # 최대 0.5 CPU 코어 사용 가능
# Pod 생성
kubectl apply -f resource-pod.yaml
# 리소스 설정 확인
kubectl describe pod resource-demo
kubectl top pod resource-demo
CPU 단위 이해:
1000m=1= 1 CPU 코어500m= 0.5 CPU 코어100m= 0.1 CPU 코어
메모리 단위 이해:
Ki= 1024 bytes (Kibibyte)Mi= 1024 Ki (Mebibyte)Gi= 1024 Mi (Gibibyte)
🔍 리소스 제한 동작 실험
CPU 제한 테스트
CPU 부하를 주고 제한 동작을 확인하기 위한 실습 예제입니다:
# cpu-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: cpu-test
spec:
containers:
- name: cpu-stress
image: progrium/stress
args:
- --cpu
- "2" # 2개 CPU 코어를 사용하려고 시도
resources:
requests:
cpu: "100m"
limits:
cpu: "200m" # 하지만 최대 0.2 코어만 허용
# Pod 생성 및 모니터링
kubectl apply -f cpu-test-pod.yaml
# 실시간 리소스 사용량 확인
watch kubectl top pod cpu-test
실습에서 확인할 항목:
- 200m(0.2 코어) 제한을 적용한 뒤의 CPU 사용량
- CPU 부하가 제한을 넘으려 할 때의 throttling과 처리 시간 변화
메모리 제한 테스트
메모리 제한을 넘는 사용을 시도하고 컨테이너 상태를 확인하는 실습 예제입니다:
# memory-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: memory-test
spec:
containers:
- name: memory-stress
image: progrium/stress
args:
- --vm
- "1"
- --vm-bytes
- "200M" # 200MB 메모리 사용 시도
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi" # 메모리 제한 100 MiB
# Pod 생성 및 상태 확인
kubectl apply -f memory-test-pod.yaml
# Pod 상태 모니터링
watch kubectl get pod memory-test
출력 형식 예시:
NAME READY STATUS RESTARTS AGE
memory-test 0/1 OOMKilled 0 30s
주의할 점: 메모리 제한 초과로 컨테이너가 종료되면 종료 사유에 **OOMKilled(Out Of Memory Killed)**가 나타날 수 있습니다. 이는 Pod의 phase 이름이 아니며, 컨테이너 재시작 여부는 restartPolicy 등에 따라 결정됩니다.
# 상세 이벤트 확인
kubectl describe pod memory-test
# Reason: OOMKilled
# Message: Container was killed due to memory limit exceeded
📊 Quality of Service (QoS) 클래스 이해
Pod의 CPU·메모리 설정에 따라 QoS 클래스가 결정됩니다. 아래는 컨테이너별 리소스를 설정하는 예제이며, QoS 이름만으로 퇴거 순서나 서비스 성능이 보장되는 것은 아닙니다.
1. Guaranteed (보장)
조건: 모든 컨테이너에 CPU와 메모리 각각의 requests·limits가 설정되고, 리소스별로 두 값이 같음
# guaranteed-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "100Mi"
cpu: "100m"
limits:
memory: "100Mi" # requests와 동일
cpu: "100m" # requests와 동일
# QoS 클래스 확인
kubectl describe pod guaranteed-pod | grep "QoS Class"
# QoS Class: Guaranteed
2. Burstable (버스트 가능)
조건: 최소 하나의 컨테이너에 CPU 또는 메모리 requests·limits가 설정되어 있지만 Guaranteed 조건은 만족하지 않음
# burstable-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: burstable-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "100Mi" # requests보다 큰 값
cpu: "200m" # requests보다 큰 값
3. BestEffort (최선 노력)
조건: 어떤 컨테이너에도 CPU·메모리 requests와 limits가 설정되지 않음
# besteffort-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: besteffort-pod
spec:
containers:
- name: app
image: nginx
# resources 설정 없음
리소스 부족 시 퇴거 기준
메모리 압박 시에는 requests 초과 여부, Pod Priority, requests 대비 사용량을 함께 고려합니다. BestEffort → Burstable → Guaranteed라는 고정 순서는 아니며, 디스크 압박에는 CPU·메모리 QoS 분류를 그대로 적용할 수 없습니다. 노드 압박에 의한 퇴거
QoS 분류 확인 (퇴거 순서를 재현하는 실험은 아님):
# 세 가지 QoS Pod 모두 생성
kubectl apply -f guaranteed-pod.yaml
kubectl apply -f burstable-pod.yaml
kubectl apply -f besteffort-pod.yaml
# QoS 클래스 확인
kubectl get pods -o custom-columns=NAME:.metadata.name,QOS:.status.qosClass
🚀 Deployment에서 리소스 관리
실제 운영에서는 Deployment를 통해 리소스를 관리합니다.
리소스 제한이 적용된 Deployment
# web-app-with-resources.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web
image: nginx:1.21
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
# Deployment 생성
kubectl apply -f web-app-with-resources.yaml
# 모든 Pod의 리소스 사용량 확인
kubectl top pods -l app=web-app
리소스 부족 시 스케줄링 실험
# 현재 노드 리소스 확인
kubectl describe nodes
# 많은 리소스를 요구하는 Pod 생성
kubectl run big-pod --image=nginx --dry-run=client -o yaml > big-pod.yaml
kubectl set resources --local -f big-pod.yaml --requests=cpu=10,memory=10Gi -o yaml > big-pod-resources.yaml
kubectl apply -f big-pod-resources.yaml
# Pod 상태 확인
kubectl get pod big-pod
kubectl describe pod big-pod
예상 결과:
Status: Pending
Events:
Warning FailedScheduling scheduler 0/1 nodes are available: 1 Insufficient cpu, 1 Insufficient memory.
🔧 ResourceQuota와 LimitRange
네임스페이스 수준의 리소스 관리 예제도 살펴보겠습니다.
ResourceQuota 설정
# resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: development
spec:
hard:
requests.cpu: "4" # 총 CPU 요청량 제한
requests.memory: "8Gi" # 총 메모리 요청량 제한
limits.cpu: "8" # 총 CPU 제한량 제한
limits.memory: "16Gi" # 총 메모리 제한량 제한
pods: "10" # 최대 Pod 개수
# 네임스페이스 생성 및 ResourceQuota 적용
kubectl create namespace development
kubectl apply -f resource-quota.yaml
# ResourceQuota 확인
kubectl describe resourcequota dev-quota -n development
LimitRange 설정
# limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: dev-limit-range
namespace: development
spec:
limits:
- type: "Pod"
max:
cpu: "2"
memory: "2Gi"
min:
cpu: "100m"
memory: "50Mi"
- type: "Container"
default: # 기본 limits
cpu: "200m"
memory: "100Mi"
defaultRequest: # 기본 requests
cpu: "100m"
memory: "50Mi"
max:
cpu: "1"
memory: "1Gi"
min:
cpu: "50m"
memory: "20Mi"
# LimitRange 적용
kubectl apply -f limit-range.yaml
# 네임스페이스에서 리소스 설정 없이 Pod 생성 테스트
kubectl run test-pod --image=nginx -n development
# 자동으로 설정된 리소스 확인
kubectl describe pod test-pod -n development
💡 실전 시나리오: 리소스 최적화
여러 구성 요소에 리소스를 배분하는 학습용 시나리오입니다. 아래 수치는 운영 환경에서 측정한 최적값이 아닙니다.
현재 리소스 사용량 분석
# 전체 노드 리소스 현황
kubectl top nodes
# 모든 Pod 리소스 사용량
kubectl top pods --all-namespaces --sort-by=memory
# 특정 네임스페이스의 리소스 사용량
kubectl top pods -n kube-system
리소스 사용량 기반 최적화
# optimized-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: optimized-web-app
spec:
replicas: 3
selector:
matchLabels:
app: optimized-web
template:
metadata:
labels:
app: optimized-web
spec:
containers:
- name: web
image: nginx:1.21-alpine # 더 작은 이미지 사용
ports:
- containerPort: 80
resources:
requests:
memory: "32Mi" # 실제 사용량 기반으로 조정
cpu: "50m"
limits:
memory: "64Mi" # 적절한 여유분 확보
cpu: "100m"
# 리소스 효율성을 위한 추가 설정
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
수직 Pod 자동 스케일러 (VPA) 시뮬레이션
사용량을 관찰해 리소스 설정을 조정하는 절차의 예시입니다. 실제 측정값과 조정 전후 결과는 별도로 기록해야 합니다:
# 1주일간 모니터링한다고 가정
# 실제로는 monitoring 툴을 사용하지만, 여기서는 수동으로 확인
# 부하 테스트 Pod 생성
kubectl run load-test --image=busybox --rm -it -- sh
# 컨테이너 내에서: while true; do wget -q -O- http://optimized-web-app-service; done
# 리소스 사용량 모니터링
watch kubectl top pods -l app=optimized-web
🚨 문제 해결과 디버깅
리소스 관련 일반적인 문제들
1. Pod가 Pending 상태로 멈춤
# 원인 분석
kubectl describe pod <pod-name>
kubectl get events --sort-by=.metadata.creationTimestamp
# 노드 리소스 확인
kubectl describe nodes
kubectl top nodes
해결 방법:
- requests 값을 줄이기
- 노드 추가하기
- 다른 Pod의 리소스 사용량 최적화
2. Pod가 OOMKilled
# 메모리 사용량 확인
kubectl top pod <pod-name>
kubectl describe pod <pod-name>
해결 방법:
- memory limits 증가
- 애플리케이션 메모리 사용량 최적화
- 메모리 누수 확인
3. CPU Throttling
# CPU 사용률 확인
kubectl top pod <pod-name>
# 상세 메트릭 확인 (metrics-server 필요)
kubectl get --raw /api/v1/nodes/<node-name>/proxy/metrics/cadvisor
해결 방법:
- CPU limits 증가
- CPU 집약적 작업 최적화
디버깅 명령어 모음
# 리소스 현황 종합 확인
kubectl top nodes
kubectl top pods --all-namespaces
# 특정 Pod 리소스 세부사항
kubectl describe pod <pod-name>
kubectl get pod <pod-name> -o yaml
# 이벤트 확인
kubectl get events --sort-by=.metadata.creationTimestamp
kubectl get events --field-selector involvedObject.name=<pod-name>
# ResourceQuota 사용량 확인
kubectl describe resourcequota -n <namespace>
# LimitRange 설정 확인
kubectl describe limitrange -n <namespace>
🎯 CKA 대비 연습 패턴
연습할 문제 유형
1. Pod에 리소스 제한 설정
# 문제: nginx Pod에 CPU 0.1, 메모리 128Mi 제한 설정
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
# YAML 편집하여 resources 추가
2. Deployment에 리소스 설정 적용
# 기존 Deployment에 리소스 설정 추가
kubectl edit deployment <name>
# 또는
kubectl patch deployment <name> -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container>","resources":{"requests":{"cpu":"100m","memory":"64Mi"},"limits":{"cpu":"200m","memory":"128Mi"}}}]}}}}'
3. ResourceQuota나 LimitRange 생성
# 네임스페이스에 리소스 제한 설정
kubectl create quota dev-quota --hard=cpu=2,memory=4Gi,pods=10 -n development
4. 리소스 부족 문제 해결
- Pod가 Pending 상태인 이유 찾기
- OOMKilled된 Pod 문제 해결
- 노드 리소스 부족 상황 분석
시간 단축 팁
# 리소스 설정이 포함된 Pod 파일 생성 (kubectl run에는 --requests/--limits 옵션이 없음)
kubectl run <name> --image=<image> --dry-run=client -o yaml > pod.yaml
kubectl set resources --local -f pod.yaml --requests=cpu=100m,memory=128Mi --limits=cpu=200m,memory=256Mi -o yaml > pod-resources.yaml
kubectl apply -f pod-resources.yaml
# 기존 리소스의 YAML 추출 후 수정
kubectl get pod <name> -o yaml > pod.yaml
# 리소스 사용량 빠른 확인
kubectl top pods --sort-by=memory
kubectl top nodes
📊 리소스 관리 Best Practices 정리
권장 설정 가이드라인
아래 숫자는 비교를 위한 시작 예시입니다. 애플리케이션 유형만으로 적정값을 결정할 수 없으며 실제 부하와 사용량을 측정해 조정해야 합니다. 각 구분선 사이의 설정은 별도 예제입니다.
CPU 설정:
# Web 서버 (경량)
requests:
cpu: "100m"
limits:
cpu: "200m"
---
# API 서버 (중간)
requests:
cpu: "250m"
limits:
cpu: "500m"
---
# 배치 작업 (무거움)
requests:
cpu: "500m"
limits:
cpu: "1000m"
메모리 설정:
# 마이크로서비스
requests:
memory: "64Mi"
limits:
memory: "128Mi"
---
# 일반 웹 애플리케이션
requests:
memory: "256Mi"
limits:
memory: "512Mi"
---
# 데이터 처리 애플리케이션
requests:
memory: "1Gi"
limits:
memory: "2Gi"
QoS 클래스 선택 기준
| 애플리케이션 유형 | 권장 QoS | 이유 |
|---|---|---|
| 중요한 서비스 | Guaranteed 검토 | 요청량과 제한량을 같게 설정하되 성능·가용성은 별도로 검증 |
| 일반 웹 서비스 | Burstable | 유연성과 안정성 균형 |
| 중단을 허용하는 작업 | BestEffort 검토 | requests가 없어 자원 압박에 취약하며, 일반 배치 작업의 기본값은 아님 |
모니터링과 조정 프로세스
- 초기 설정: 보수적으로 시작 (약간 높게)
- 모니터링: 1-2주간 실제 사용량 관찰
- 조정: 사용량 패턴에 맞춰 최적화
- 재검토: 주기적으로 재평가
📚 필수 명령어 정리
리소스 관리 명령어
# 리소스 사용량 확인
kubectl top nodes
kubectl top pods
kubectl top pods --all-namespaces --sort-by=memory
# Pod 리소스 설정 확인
kubectl describe pod <name>
kubectl get pod <name> -o jsonpath='{.spec.containers[*].resources}'
# ResourceQuota 관리
kubectl create quota <name> --hard=cpu=2,memory=4Gi
kubectl describe quota <name>
# LimitRange 관리
kubectl describe limitrange <name>
# 리소스 관련 이벤트 확인
kubectl get events --field-selector reason=FailedScheduling
kubectl get events --field-selector reason=OOMKilling
리소스 설정 템플릿
# 기본 리소스 설정 템플릿
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
🚀 다음 학습 계획
리소스 설정 다음에는 애플리케이션의 응답 가능 여부를 확인하는 헬스체크를 살펴볼 계획입니다.
다음 주제들
- Liveness와 Readiness Probe 구성 - 헬스체크와 자동 복구
- 네임스페이스를 통한 리소스 격리와 다중 테넌시
- Ingress를 통한 외부 트래픽 관리와 라우팅
- 스토리지와 PersistentVolume 관리
- RBAC과 보안 설정
개인 학습 목표
- 실제 운영 환경에서의 리소스 최적화 경험 쌓기
- 다양한 워크로드별 적절한 리소스 설정 패턴 숙달
- 리소스 부족 상황에서의 빠른 문제 해결 능력 향상
- monitoring과 alerting을 통한 proactive한 리소스 관리
이 글은 requests와 limits의 역할, QoS 분류와 리소스 부족 상황의 확인 방법을 정리했습니다. 예제의 설정값은 출발점이며, 실제 사용량과 노드 조건을 측정해 조정해야 합니다.
다음 글에서는 애플리케이션의 준비·생존·시작 상태를 확인하는 Probe를 다룹니다.
🔗 참고 자료:
- Kubernetes 공식 문서 - Managing Resources for Containers
- Kubernetes 공식 문서 - Resource Quotas
- Kubernetes 공식 문서 - Limit Ranges
- kubectl set resources - 로컬 매니페스트 리소스 설정
yellow.log · 2025.08.10에 작성 · 2026.09.29에 수정
CKA 준비 전체 8편
- 1.Pod 생성과 관리 - 쿠버네티스의 기본 단위 이해하기
- 2.ReplicaSet과 Deployment로 Pod 관리하기 - 확장성과 가용성 확보
- 3.Service를 통한 Pod 네트워킹 - 안정적인 접근 경로 만들기
- 4.ConfigMap과 Secret으로 설정 관리하기 - 환경별 설정 분리
- 5.Pod 리소스 제한과 요청 설정 - 안정적인 클러스터 운영을 위한 리소스 관리읽는 중
- 6.Liveness와 Readiness Probe 구성 - 헬스체크와 자동 복구
- 7.네임스페이스를 통한 리소스 격리와 다중 테넌시 - 팀별, 환경별 격리
- 8.Ingress를 통한 외부 트래픽 관리와 라우팅 - 클러스터의 똑똑한 관문 구축