리소스 관리
Kubernetes의 리소스 Requests/Limits, LimitRange, ResourceQuota를 이해하고 실습합니다.
리소스 관리 개요
Kubernetes는 다음 메커니즘으로 리소스를 관리합니다:
- Resource Requests/Limits: Pod/Container 레벨 리소스 설정
- LimitRange: Namespace의 기본값 및 최소/최대 제한
- ResourceQuota: Namespace의 총 리소스 할당량
실습 1: Resource Requests/Limits
1. 리소스 설정 없는 워크로드 생성
workload1-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: workload1-dep
labels:
app: demo
spec:
replicas: 3
selector:
matchLabels:
app: workload1
template:
metadata:
labels:
app: workload1
color: lime
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
workload2-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: workload2-dep
labels:
app: demo
spec:
replicas: 3
selector:
matchLabels:
app: workload2
template:
metadata:
labels:
app: workload2
color: orange
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
workload3-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: workload3-dep
labels:
app: demo
spec:
replicas: 3
selector:
matchLabels:
app: workload3
template:
metadata:
labels:
app: workload3
color: aqua
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
workload4-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: workload4-dep
labels:
app: demo
spec:
replicas: 3
selector:
matchLabels:
app: workload4
template:
metadata:
labels:
app: workload4
color: pink
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
kubectl apply -f workload1-dep.yaml \
-f workload2-dep.yaml \
-f workload3-dep.yaml \
-f workload4-dep.yaml
# Pod 리소스 확인
kubectl describe pods -l app=workload1
Requests/Limits가 설정되지 않은 것을 확인할 수 있습니다 (BestEffort QoS).
실습 2: LimitRange 적용
1. LimitRange 생성
namespace-limit-range.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: namespace-limit-range
labels:
app: demo
spec:
limits:
- default: # 기본 Limit (설정 안 했을 때)
cpu: 200m
memory: 256Mi
defaultRequest: # 기본 Request (설정 안 했을 때)
cpu: 100m
memory: 128Mi
max: # 최대 Limit
cpu: 1
memory: 1Gi
min: # 최소 Request
cpu: 50m
memory: 64Mi
type: Container
kubectl apply -f namespace-limit-range.yaml
# LimitRange 확인
kubectl describe limitrange namespace-limit-range
2. 기존 Pod 업데이트
LimitRange는 새로운 Pod에만 적용됩니다. 기존 Pod를 재생성해야 합니다:
# 이미지를 변경하여 새 ReplicaSet 생성
kubectl set image deployment/workload1-dep nginx=nginx:1.27
kubectl set image deployment/workload2-dep nginx=nginx:1.27
kubectl set image deployment/workload3-dep nginx=nginx:1.27
kubectl set image deployment/workload4-dep nginx=nginx:1.27
# Pod 확인
kubectl get pods
# 리소스 확인
kubectl describe pod -l app=workload1 | grep -A 5 "Requests:"
이제 모든 Pod에 기본 Requests/Limits가 적용됩니다.
3. 실제 리소스 사용량 확인
# Metrics Server 확인
kubectl top pods
# 특정 워크로드
kubectl top pods -l app=workload1
실습 3: ResourceQuota 적용
1. ResourceQuota 생성
namespace-resource-quotas.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-resource-quota-1
labels:
app: demo
spec:
hard:
requests.cpu: "1200m" # 총 CPU Request 제한
limits.cpu: "2000m" # 총 CPU Limit 제한
requests.memory: 1.25Gi # 총 Memory Request 제한
limits.memory: 2.5Gi # 총 Memory Limit 제한
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-resource-quota-2
labels:
app: demo
spec:
hard:
pods: "10" # 최대 Pod 개수
configmaps: "10" # 최대 ConfigMap 개수
secrets: "40" # 최대 Secret 개수
persistentvolumeclaims: "4" # 최대 PVC 개수
services: "10" # 최대 Service 개수
services.loadbalancers: "2" # 최대 LoadBalancer 개수
kubectl apply -f namespace-resource-quotas.yaml
# ResourceQuota 확인
kubectl describe resourcequota
2. Quota 초과 테스트
# 이미지 변경으로 재배포 시도
kubectl set image deployment/workload1-dep nginx=nginx:1.27
kubectl set image deployment/workload2-dep nginx=nginx:1.27
kubectl set image deployment/workload3-dep nginx=nginx:1.27
kubectl set image deployment/workload4-dep nginx=nginx:1.27
# ReplicaSet 이벤트 확인
kubectl describe replicaset -l app=workload1
# "exceeded quota" 메시지 확인
Memory Limit이 Quota를 초과하여 업데이트가 실패합니다.
3. Quota 증가
namespace-resource-quotas-slight.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-resource-quota-1
labels:
app: demo
spec:
hard:
requests.cpu: "1400m"
limits.cpu: "2400m"
requests.memory: 1.5Gi
limits.memory: 3Gi
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-resource-quota-2
labels:
app: demo
spec:
hard:
pods: "15"
configmaps: "10"
secrets: "40"
persistentvolumeclaims: "4"
services: "10"
services.loadbalancers: "2"
kubectl apply -f namespace-resource-quotas-slight.yaml
# 상태 관찰
kubectl get pods -w
ReplicaSet이 조금씩 Pod를 교체하기 시작합니다 (여유 공간이 생기면).
4. Quota 대폭 증가
namespace-resource-quotas-double.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-resource-quota-1
labels:
app: demo
spec:
hard:
requests.cpu: "2400m"
limits.cpu: "4000m"
requests.memory: 2.5Gi
limits.memory: 5Gi
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-resource-quota-2
labels:
app: demo
spec:
hard:
pods: "30"
configmaps: "20"
secrets: "50"
persistentvolumeclaims: "10"
services: "20"
services.loadbalancers: "5"
kubectl apply -f namespace-resource-quotas-double.yaml
# 이미지 변경
kubectl set image deployment/workload1-dep nginx=nginx:1.27
kubectl set image deployment/workload2-dep nginx=nginx:1.27
kubectl set image deployment/workload3-dep nginx=nginx:1.27
kubectl set image deployment/workload4-dep nginx=nginx:1.27
# 빠르게 업데이트됨
kubectl get pods -w
이제 충분한 Quota가 있어 모든 Pod가 동시에 업데이트됩니다.
실습 4: QoS 클래스
Guaranteed QoS
guaranteed-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: nginx
image: nginx:1.27
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 200m # Request = Limit
memory: 256Mi # Request = Limit
kubectl apply -f guaranteed-pod.yaml
# QoS 확인
kubectl get pod guaranteed-pod -o jsonpath='{.status.qosClass}'
# Guaranteed
Burstable QoS
burstable-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: burstable-pod
spec:
containers:
- name: nginx
image: nginx:1.27
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m # Request < Limit
memory: 512Mi # Request < Limit
kubectl apply -f burstable-pod.yaml
# QoS 확인
kubectl get pod burstable-pod -o jsonpath='{.status.qosClass}'
# Burstable
BestEffort QoS
besteffort-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: besteffort-pod
spec:
containers:
- name: nginx
image: nginx:1.27
# 리소스 설정 없음
kubectl apply -f besteffort-pod.yaml
# QoS 확인
kubectl get pod besteffort-pod -o jsonpath='{.status.qosClass}'
# BestEffort
정리
kubectl delete deployment -l app=demo
kubectl delete limitrange namespace-limit-range
kubectl delete resourcequota -l app=demo
kubectl delete pod guaranteed-pod burstable-pod besteffort-pod
핵심 정리
- Requests: 보장된 리소스, 스케줄링에 사용
- Limits: 최대 사용 가능 리소스, 초과 시 제한
- LimitRange: Namespace의 기본값 및 최소/최대 제한
- ResourceQuota: Namespace의 총 할당량
- QoS 클래스: Guaranteed > Burstable > BestEffort
- 리소스 부족: QoS 낮은 순서로 Pod 제거
실습 과제
- CPU Limit을 초과하는 워크로드를 생성하고 Throttling을 관찰해보세요.
- Memory Limit을 초과하는 워크로드를 생성하고 OOMKilled를 확인해보세요.
- 여러 Namespace를 생성하고 각각 다른 ResourceQuota를 적용해보세요.
- LimitRange의 max/min 값을 위반하는 Pod를 생성하고 에러 메시지를 확인해보세요.
다음 단계
Horizontal Pod Autoscaler에서 CPU/Memory 기반 자동 스케일링을 학습합니다.