쿠버네티스 노드 구성 및 관리 실습 가이드
📚 실습 개요
쿠버네티스 클러스터에서 워커 노드들을 효과적으로 관리하는 방법을 실습을 통해 학습합니다. 노드 격리, 드레인, 레이블링, 스케줄링 제어 등 실제 운영에서 필요한 핵심 기능들을 다룹니다.
🎯 학습 목표
- 노드 상태 관리 및 점검 방법 습득
- 노드 격리(cordon) 및 드레인(drain) 실습
- 노드 레이블링 및 셀렉터 활용법 이해
- 어피니티/안티 어피니티를 통한 고급 스케줄링 제어
🛠️ 실습 환경 준비
필수 도구
# 쿠버네티스 클러스터 (minikube 또는 Docker Desktop)
minikube start --nodes 3 --cpus=2 --memory=4096
# kubectl 설정 확인
kubectl cluster-info
kubectl get nodes멀티 노드 환경 구성 (minikube)
# 3개 노드로 클러스터 시작
minikube start --nodes 3 --driver=docker
# 노드 상태 확인
kubectl get nodes -o wide📋 1. 노드 구성 및 기본 관리
1.1 노드 상태 확인
# 전체 노드 목록 조회
kubectl get nodes
# 노드 상세 정보 확인
kubectl describe node <node-name>
# 노드별 리소스 사용량 확인
kubectl top nodes실습 결과 예시:
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 5m v1.28.3
minikube-m02 Ready <none> 3m v1.28.3
minikube-m03 Ready <none> 2m v1.28.3
1.2 노드 정보 분석
# JSON 형태로 노드 정보 조회
kubectl get node minikube-m02 -o json | jq '.status.conditions'
# 노드의 할당 가능한 리소스 확인
kubectl get node minikube-m02 -o jsonpath='{.status.allocatable}'🚫 2. 노드 격리(Cordon) 및 드레인(Drain)
2.1 노드 격리 (Cordon) 실습
개념 정리
- Cordon: 노드에 새로운 파드 스케줄링을 차단
- 기존 파드는 그대로 유지, 새로운 파드만 차단
# 노드 격리 (새로운 파드 스케줄링 차단)
kubectl cordon minikube-m02
# 노드 상태 확인 (SchedulingDisabled 상태)
kubectl get nodes격리 상태 확인
# 격리된 노드에 파드 배포 시도
kubectl create deployment test-cordon --image=nginx --replicas=3
# 파드 배포 위치 확인 (minikube-m02 제외)
kubectl get pods -o wide2.2 노드 격리 해제 (Uncordon)
# 노드 격리 해제
kubectl uncordon minikube-m02
# 상태 확인
kubectl get nodes2.3 노드 드레인 (Drain) 실습
드레인 준비 작업
# 테스트용 파드 배포
kubectl create deployment drain-test --image=nginx --replicas=6
# 파드 배포 상태 확인
kubectl get pods -o wide노드 드레인 실행
# 노드 드레인 (모든 파드 다른 노드로 이동)
kubectl drain minikube-m02 --ignore-daemonsets --delete-emptydir-data
# 드레인 후 파드 위치 확인
kubectl get pods -o wide드레인 중 발생 가능한 문제 해결
# DaemonSet 파드가 있는 경우
kubectl drain minikube-m02 --ignore-daemonsets
# 로컬 스토리지를 사용하는 파드가 있는 경우
kubectl drain minikube-m02 --ignore-daemonsets --delete-emptydir-data
# 강제 드레인 (주의: 데이터 손실 가능)
kubectl drain minikube-m02 --ignore-daemonsets --delete-emptydir-data --force🏷️ 3. 노드 레이블 관리
3.1 기본 노드 레이블 확인
# 모든 노드의 레이블 확인
kubectl get nodes --show-labels
# 특정 노드 레이블 상세 조회
kubectl describe node minikube-m02 | grep Labels -A 103.2 사용자 정의 레이블 추가
# 노드에 환경 레이블 추가
kubectl label node minikube-m02 environment=production
kubectl label node minikube-m03 environment=development
# 하드웨어 타입 레이블 추가
kubectl label node minikube-m02 hardware=ssd
kubectl label node minikube-m03 hardware=hdd
# 위치 레이블 추가
kubectl label node minikube-m02 zone=asia-northeast1-a
kubectl label node minikube-m03 zone=asia-northeast1-b3.3 레이블 기반 노드 검색
# 특정 레이블로 노드 필터링
kubectl get nodes -l environment=production
kubectl get nodes -l hardware=ssd
kubectl get nodes -l zone=asia-northeast1-a
# 복합 조건으로 노드 검색
kubectl get nodes -l environment=production,hardware=ssd3.4 레이블 수정 및 삭제
# 레이블 값 변경
kubectl label node minikube-m02 environment=staging --overwrite
# 레이블 삭제
kubectl label node minikube-m02 hardware-
# 변경 결과 확인
kubectl get nodes --show-labels🎯 4. 노드 셀렉터 실습
4.1 기본 노드 셀렉터 사용
노드 셀렉터를 사용한 파드 배포
# nodeSelector-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: production-app
spec:
replicas: 3
selector:
matchLabels:
app: production-app
template:
metadata:
labels:
app: production-app
spec:
nodeSelector:
environment: production # production 레이블이 있는 노드에만 배포
containers:
- name: app
image: nginx
ports:
- containerPort: 80# 배포 실행
kubectl apply -f nodeSelector-demo.yaml
# 파드 배포 위치 확인
kubectl get pods -l app=production-app -o wide4.2 다양한 노드 셀렉터 조건
하드웨어 타입별 배포
# ssd-app.yaml
apiVersion: v1
kind: Pod
metadata:
name: ssd-app
spec:
nodeSelector:
hardware: ssd
containers:
- name: app
image: redis
ports:
- containerPort: 6379# SSD 노드에만 배포
kubectl apply -f ssd-app.yaml
# 배포 결과 확인
kubectl get pod ssd-app -o wide⚡ 5. 어피니티 (Affinity) 실습
5.1 노드 어피니티 (Node Affinity)
필수 조건 (requiredDuringSchedulingIgnoredDuringExecution)
# node-affinity-required.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: affinity-required-demo
spec:
replicas: 2
selector:
matchLabels:
app: affinity-demo
template:
metadata:
labels:
app: affinity-demo
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: environment
operator: In
values: ["production", "staging"]
- key: zone
operator: Exists
containers:
- name: app
image: nginx선호 조건 (preferredDuringSchedulingIgnoredDuringExecution)
# node-affinity-preferred.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: affinity-preferred-demo
spec:
replicas: 3
selector:
matchLabels:
app: preferred-demo
template:
metadata:
labels:
app: preferred-demo
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: hardware
operator: In
values: ["ssd"]
- weight: 50
preference:
matchExpressions:
- key: environment
operator: In
values: ["production"]
containers:
- name: app
image: nginx# 어피니티 규칙 적용
kubectl apply -f node-affinity-required.yaml
kubectl apply -f node-affinity-preferred.yaml
# 배포 결과 확인
kubectl get pods -l app=affinity-demo -o wide
kubectl get pods -l app=preferred-demo -o wide5.2 파드 간 어피니티 (Pod Affinity)
파드 어피니티 - 함께 배치
# pod-affinity-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
tier: frontend
spec:
containers:
- name: web
image: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache-app
spec:
replicas: 2
selector:
matchLabels:
app: cache
template:
metadata:
labels:
app: cache
tier: cache
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["web"]
topologyKey: kubernetes.io/hostname
containers:
- name: cache
image: redis5.3 안티 어피니티 (Anti-Affinity) 실습
파드 안티 어피니티 - 분산 배치
# pod-anti-affinity-demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: distributed-app
spec:
replicas: 3
selector:
matchLabels:
app: distributed-app
template:
metadata:
labels:
app: distributed-app
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["distributed-app"]
topologyKey: kubernetes.io/hostname
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: environment
operator: In
values: ["production"]
containers:
- name: app
image: nginx# 안티 어피니티 배포
kubectl apply -f pod-anti-affinity-demo.yaml
# 분산 배치 결과 확인 (각 노드에 하나씩 배치됨)
kubectl get pods -l app=distributed-app -o wide🔍 6. 고급 스케줄링 시나리오
6.1 복합 조건 스케줄링
# complex-scheduling.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: complex-app
spec:
replicas: 2
selector:
matchLabels:
app: complex-app
template:
metadata:
labels:
app: complex-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: environment
operator: NotIn
values: ["development"]
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: hardware
operator: In
values: ["ssd"]
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values: ["complex-app"]
topologyKey: kubernetes.io/hostname
containers:
- name: app
image: nginx6.2 테인트와 톨러레이션 (Taints & Tolerations)
# 노드에 테인트 추가
kubectl taint node minikube-m03 special=true:NoSchedule
# 테인트가 있는 노드 확인
kubectl describe node minikube-m03 | grep Taints톨러레이션을 가진 파드 배포
# toleration-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: toleration-pod
spec:
tolerations:
- key: "special"
operator: "Equal"
value: "true"
effect: "NoSchedule"
containers:
- name: app
image: nginx
nodeSelector:
kubernetes.io/hostname: minikube-m03# 톨러레이션 파드 배포
kubectl apply -f toleration-demo.yaml
# 배포 결과 확인
kubectl get pod toleration-pod -o wide🧪 7. 실습 검증 및 문제 해결
7.1 스케줄링 문제 진단
# 파드가 스케줄되지 않는 경우
kubectl describe pod <pending-pod-name>
# 이벤트 로그 확인
kubectl get events --sort-by=.metadata.creationTimestamp
# 스케줄러 로그 확인 (kube-system 네임스페이스)
kubectl logs -n kube-system -l component=kube-scheduler7.2 노드 리소스 분석
# 노드별 리소스 사용률 확인
kubectl top nodes
# 각 노드의 파드 목록
kubectl get pods --all-namespaces -o wide --field-selector spec.nodeName=minikube-m02
# 노드의 할당 가능한 리소스 vs 요청된 리소스
kubectl describe node minikube-m02 | grep -A 5 "Allocated resources"🧹 8. 실습 환경 정리
8.1 생성한 리소스 정리
# 배포된 애플리케이션 삭제
kubectl delete deployment test-cordon drain-test production-app
kubectl delete deployment affinity-required-demo affinity-preferred-demo
kubectl delete deployment web-app cache-app distributed-app complex-app
# 테스트 파드 삭제
kubectl delete pod ssd-app toleration-pod
# 노드 레이블 정리
kubectl label node minikube-m02 environment- hardware- zone-
kubectl label node minikube-m03 environment- hardware- zone-
# 노드 테인트 제거
kubectl taint node minikube-m03 special=true:NoSchedule-
# 모든 노드 언코든
kubectl uncordon minikube-m02
kubectl uncordon minikube-m038.2 최종 상태 확인
# 노드 상태 확인
kubectl get nodes
# 남은 파드 확인
kubectl get pods --all-namespaces📝 실습 요약
✅ 주요 학습 내용
- 노드 관리 기초: 상태 확인, 리소스 모니터링
- 노드 격리/드레인: 유지보수 시 필수 작업
- 레이블 관리: 노드 분류 및 관리
- 노드 셀렉터: 간단한 스케줄링 제어
- 어피니티/안티어피니티: 고급 스케줄링 전략
- 테인트/톨러레이션: 특수 노드 관리
🎯 실무 적용 포인트
- Blue-Green 배포 시 노드 드레인 활용
- 하드웨어 특성에 따른 워크로드 분산
- 가용성 향상을 위한 안티어피니티 적용
- 특수 워크로드 격리를 위한 테인트 활용
🔗 연관 학습 자료
- 02_쿠버네티스_StatefulSet_실습_가이드 - 상태 관리
- 05_02_Storage_PV_PVC_VolumeClaimTemplate_완전정리 - 스토리지와 노드
- 04_워커노드_분석_근육은_어떻게_움직이는가 - 이론 배경
📅 작성일: 2025.11.19
🏷️ 태그: kubernetes node-management scheduling affinity 실습
🔗 상위: 00_k8s_실습_시리즈_목차