플랫폼, 데브옵스와 클라우드

스케줄링과 리소스

meellon 2026. 6. 27. 05:40

학습 목표

requests·limits스케줄링런타임에서 각각 어떤 역할을 하는지 설명할 수 있다.

Guaranteed·Burstable·BestEffort QoS class 기준과 eviction 우선순위를 설명할 수 있다.

nodeSelector·affinity·taint/toleration으로 Pod 배치를 제어할 수 있다.

HPAmetrics를 보고 replicas를 조절하는 흐름을 설명할 수 있다.

문제 상황

  • Pod가 Pending인데 EventsInsufficient cpu만 반복된다
    • 노드 allocatable 대비 requests 합이 부족
  • 한 노드에 Pod가 몰려 한 VM 장애 시 서비스 전체가 내려간다
    • anti-affinity·노드 분산이 필요
  • CPU limit 없이 배포했더니 noisy neighbor가 다른 Pod를 굶긴다
    • limits·QoS 미설정
  • memory limit 없이 OOM이 나면 어떤 Pod가 죽을지 예측 불가
    • limits 없으면 BestEffort — eviction 최우선
  • 트래픽 급증에 수동으로 kubectl scale만 반복한다
    • HPA + metrics-server 자동 스케일
  • GPU·SSD 노드에 워크로드를 강제 배치하고 싶다
    • nodeSelector·node affinity·taint

앞서 StatefulSet·스토리지를 봤다. 이번 편은 어느 노드에·얼마나 Pod를 올릴지, 부하에 따라 몇 개 둘지다. Part 2 Kubernetes 마지막 편이다.

1. 스케줄러와 리소스 모델

kube-scheduler — Pending Pod를 적합한 노드 하나에 바인딩.

Pending Pod → Filter (필수 조건) → Score (선호) → Bind → kubelet 시작
단계 예시
Filter requests 합 ≤ 노드 여유, nodeSelector, taint/toleration
Score affinity 가중치, 리소스 균형, spread
Bind Pod → Node 할당 (API server 기록)
  • kubelet — 바인딩된 노드에서 컨테이너 실행·limits 집행
  • allocatable — 노드 전체 CPU/mem − 시스템·kube-reserved
  • kubectl describe nodeAllocated resources로 requests/limit 합 확인

2. requests와 limits

  requests limits
목적 스케줄링 — 노드에 “예약” 런타임 — 상한
CPU 스케줄 가능 여부 CFS quota — 초과 시 throttle
memory 스케줄 가능 여부 초과 시 OOMKilled
미설정 0 (BestEffort 쪽) 컨테이너 default (노드 한도까지)
resources:
  requests:
    cpu: "500m"      # 0.5 core
    memory: 512Mi
  limits:
    cpu: "1"
    memory: 1Gi
단위 CPU memory
표기 500m = 0.5 core, 1 = 1 core 512Mi, 1Gi
정수 1 = 1 core Ki, Mi, Gi (2진)
  • requests ≤ limits — 일반적 (limits만 크게 잡는 패턴도 있음)
  • Burstable — requests < limits (유휴 CPU 빌려 씀, limit까지 burst)
  • limit = request — CPU/mem Guaranteed에 가깝게
  • Java·Go 앱 — heap·GC 고려해 memory limit 여유 (OOM 방지)
kubectl top pods
kubectl describe node | grep -A5 "Allocated resources"

3. QoS Class

스케줄러가 아니라 kubelet이 Pod spec으로 QoS자동 분류eviction·OOM 우선순위에 영향.

QoS 조건 eviction
Guaranteed 모든 컨테이너: limits = requests (cpu·mem 둘 다) 마지막
Burstable requests 설정, Guaranteed 아님 중간
BestEffort requests·limits 없음 최우선
Guaranteed  — limits == requests (all containers, both cpu & mem)
Burstable   — some requests set
BestEffort  — no requests/limits
  • 노드 메모리 압박 — kubelet이 BestEffort → Burstable → Guaranteedevict
  • 프로덕션 — 최소 requests 설정, 핵심 워크로드는 Guaranteed 검토
  • LimitRange — namespace 기본 min/max/default requests·limits
  • ResourceQuota — namespace 총 requests/limits 상한

4. nodeSelector와 affinity

nodeSelector — 노드 label 필수 매칭 (단순, legacy).

nodeSelector:
  disktype: ssd
  node.kubernetes.io/instance-type: m5.large

affinityrequired vs preferred, Pod 간 co-location / anti-affinity.

종류 의미
nodeAffinity requiredDuringScheduling... 반드시 만족 (Filter)
nodeAffinity preferredDuringScheduling... 가능하면 (Score)
podAffinity 같은 topology에 함께 캐시·sidecar colocate
podAntiAffinity 같은 topology에 분산 AZ·노드 장애 격리
affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: api
          topologyKey: kubernetes.io/hostname
topologyKey 효과
kubernetes.io/hostname 노드당 Pod 분산
topology.kubernetes.io/zone AZ 분산
  • IgnoredDuringExecution스케줄 후 label 변경해도 추방하지 않음
  • RequiredDuringScheduling — 조건 깨지면 Pending (과도한 required는 주의)

5. taint와 toleration

taint — 노드에 “이 Pod는 받지 않음” 표시 (전용 노드·GPU·system).

toleration — Pod가 taint를 허용 — 스케줄 가능.

# Node (예시)
# kubectl taint nodes node1 dedicated=api:NoSchedule

tolerations:
  - key: dedicated
    operator: Equal
    value: api
    effect: NoSchedule
effect 동작
NoSchedule 새 Pod 스케줄 거부 (toleration 없으면)
PreferNoSchedule 가급적 거부
NoExecute 기존 Pod도 추방 (toleration + tolerationSeconds)
  • 전용 노드 풀 — taint dedicated=workload + 해당 toleration만 배치
  • system node — 기본 taint로 일반 워크로드 차단

6. HPA (Horizontal Pod Autoscaler)

HPADeployment·StatefulSet 등의 replicas메트릭에 맞춰 조절.

metrics-server (CPU/mem) → HPA controller → scale Deployment replicas
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
항목 설명
metrics-server kubelet summary API → 클러스터 메트릭 (HPA 필수)
averageUtilization Pod requests cpu 대비 사용률 (requests 없으면 동작 불안)
min/maxReplicas floor·ceiling — 비용·용량 한도
scale down cooldown·stabilization — flapping 방지
kubectl apply -f code/scheduling-resources.yaml
kubectl get hpa
kubectl describe hpa api
  • Custom metrics — Prometheus adapter, QPS·queue depth 기반 스케일 (Observability 연동)
  • VPA — Pod requests 자동 조정 (HPA와 동시 사용 시 주의)
  • Cluster Autoscaler — 노드 확장 (Pending + requests 합 기준)

7. 실무 체크리스트

증상 확인
Pending describe pod Events, node requests 여유, PVC·affinity
OOMKilled memory limits, JVM -Xmx, QoS
CPU throttle limits vs 실제 사용, kubectl top
한 노드 몰림 podAntiAffinity, topology spread
HPA Unknown metrics-server, requests.cpu 설정
워크로드 requests/limits 스케줄링 스케일
Stateless API cpu/mem 설정 anti-affinity HPA
Batch Job burst 허용 limits spot/taint 노드 Job parallelism
StatefulSet DB Guaranteed 검토 RWO + AZ spread 수동 또는 operator
DaemonSet node 전체 고려 모든 노드 replicas = node 수

8. 정리

  • requests스케줄 · limits런타임 상한 (CPU throttle, mem OOM)
  • QoS — Guaranteed / Burstable / BestEffort → eviction 순서
  • nodeSelector·affinity·taint어디에 배치할지
  • HPAmetricsreplicas (requests·metrics-server 전제)
  • Part 2 Kubernetes 핵심 오브젝트 흐름: Pod → Deployment → Service → Config → Storage → Scheduling

다음에 다룰 것

  • CI/CD 개요
  • build·test·deploy 파이프라인, CI vs CD

해당 내용은 Kubernetes Documentation (kubernetes.io) 의 내용을 기반으로 합니다.

'플랫폼, 데브옵스와 클라우드' 카테고리의 다른 글

GitHub Actions와 GitLab CI  (0) 2026.06.29
CI/CD 개요  (0) 2026.06.28
스토리지와 StatefulSet  (0) 2026.06.26
ConfigMap과 Secret  (0) 2026.06.25
Service와 Ingress  (0) 2026.06.24