본문으로 건너뛰기

Node Affinity와 Volume

Node Affinity와 Volume을 함께 사용하여 스토리지 제약이 있는 워크로드를 효율적으로 배치하는 방법을 학습합니다.

Node Affinity란?

Node Affinity는 Pod가 특정 노드에 스케줄링되도록 제어하는 메커니즘입니다.

Affinity 유형

  1. requiredDuringSchedulingIgnoredDuringExecution: 반드시 만족해야 함 (하드 제약)
  2. preferredDuringSchedulingIgnoredDuringExecution: 가능하면 만족 (소프트 제약)

Pod Affinity와 Volume의 관계

Azure Disk와 같은 ReadWriteOnce(RWO) 볼륨은 하나의 노드에만 연결될 수 있습니다. Pod Affinity를 사용하면 같은 볼륨을 사용하는 Pod들을 동일 노드에 배치할 수 있습니다.

실습 1: PVC와 Pod Affinity

1. PersistentVolumeClaim 생성

pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-azure-disk
spec:
storageClassName: default
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
kubectl apply -f pvc.yaml

2. Required Pod Affinity 적용

동일한 PVC를 사용하는 Pod들을 같은 노드에 배치합니다:

pvc-dep-required.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pvc-pod-dep
spec:
replicas: 6
selector:
matchLabels:
target: pvc-pod
template:
metadata:
labels:
target: pvc-pod
color: LightSalmon
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: 80m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
volumeMounts:
- mountPath: "/mnt/data"
name: mypvc
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: pvc-azure-disk
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: target
operator: In
values:
- pvc-pod
topologyKey: "kubernetes.io/hostname"
kubectl apply -f pvc-dep-required.yaml

3. 배포 확인

# Pod와 노드 확인
kubectl get pods -o wide

# 모든 Pod가 동일 노드에 있는지 확인
kubectl get pods -l target=pvc-pod -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName

4. 스케일 테스트

# 12개로 증가
kubectl scale --replicas=12 deployment/pvc-pod-dep

# 노드 확인 - 여전히 같은 노드
kubectl get pods -l target=pvc-pod -o wide

# 24개로 증가
kubectl scale --replicas=24 deployment/pvc-pod-dep

# 일부 Pod는 Pending 상태
kubectl get pods -l target=pvc-pod

노드에 더 이상 리소스가 없으면 다른 노드에 여유가 있어도 Pod가 Pending 상태로 남습니다.

실습 2: Preferred Affinity로 변경

1. Preferred Affinity 적용

pvc-dep-preferred.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: pvc-pod-dep
spec:
replicas: 24
selector:
matchLabels:
target: pvc-pod
template:
metadata:
labels:
target: pvc-pod
color: LightSalmon
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests:
cpu: 80m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
volumeMounts:
- mountPath: "/mnt/data"
name: mypvc
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: pvc-azure-disk
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: target
operator: In
values:
- pvc-pod
topologyKey: "kubernetes.io/hostname"
kubectl apply -f pvc-dep-preferred.yaml

2. 결과 확인

# Pending Pod들이 다른 노드에 스케줄링됨
kubectl get pods -l target=pvc-pod -o wide

# 하지만 볼륨 마운트 실패
kubectl describe pod <pod-name>

다른 노드의 Pod들은 볼륨을 마운트할 수 없어 에러 상태가 됩니다.

Zone-aware 스토리지

AKS에서 가용성 영역 활용

pvc-zonal.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-azure-disk-zonal
spec:
storageClassName: managed-csi
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi

Node Affinity와 Zone 결합

deployment-zone-affinity.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: zonal-workload
spec:
replicas: 3
selector:
matchLabels:
app: zonal-app
template:
metadata:
labels:
app: zonal-app
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- koreacentral-1
containers:
- name: app
image: nginx:1.27
volumeMounts:
- name: data
mountPath: /mnt/data
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-azure-disk-zonal
kubectl apply -f pvc-zonal.yaml
kubectl apply -f deployment-zone-affinity.yaml

# Zone 확인
kubectl get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,ZONE:.spec.nodeSelector

정리

kubectl delete deployment pvc-pod-dep
kubectl delete pvc pvc-azure-disk
kubectl delete pvc pvc-azure-disk-zonal
kubectl delete deployment zonal-workload

핵심 정리

  • Pod Affinity: 같은 볼륨을 사용하는 Pod를 동일 노드에 배치
  • Required Affinity: 필수 조건, 만족하지 못하면 Pending
  • Preferred Affinity: 선호 조건, 만족하지 못해도 다른 노드에 배치
  • RWO Volume: 하나의 노드에만 연결 가능
  • Zone-aware Storage: 가용성 영역을 고려한 스토리지 배치

실습 과제

  1. ReadWriteMany(RWX)를 지원하는 Azure Files PVC를 생성하고, 여러 노드에 Pod를 분산 배치해보세요.
  2. Node Affinity를 사용하여 특정 노드 풀(예: GPU 노드)에만 Pod를 배치해보세요.
  3. Preferred Affinity의 weight 값을 다르게 설정하여 스케줄링 우선순위를 조정해보세요.

다음 단계

Anti-Affinity와 StatefulSet에서 Pod를 분산 배치하는 방법을 학습합니다.