쿠버네티스의 Affinity
쿠버네티스(Kubernetes)에서 애피니티(Affinity)는 파드를 어떤 노드, 혹은 어떤 다른 파드와 함께(또는 떨어져) 배치할지를 제어하는 스케줄링(Scheduling) 정책임.
즉, 단순히 CPU, 메모리와 같은 리소스 사용량만을 보는 것이 아니라, 클러스터에 존재하는 노드 라벨, 파드 라벨 등을 기준으로 세밀하게 파드를 배치하는 방식임.
애피니티에는 크게 아래와 같은 유형이 있음.
1. Node Affinity
2. Pod Affinity
3. Pod Anti-Affinity
Node Affinity
Node Affinity는 파드를 특정 노드 라벨(label)이 있는 노드에 스케줄링하도록 강제하거나, 혹은 스케줄러가 선호(prefer)하도록 유도하는 정책임.
예를 들어, “region=us-west” 라벨이 달려 있는 노드에만 파드를 배치하고 싶거나, GPU가 달린 노드(gpu=true)만 사용하도록 하고 싶을 때 사용함.
Node Affinity는 크게 두 가지 형식을 가짐.
1. requiredDuringSchedulingIgnoredDuringExecution
이 정책은 강제 규칙(hard requirement)을 의미함.
이 조건을 만족하는 노드가 없다면 파드는 스케줄링되지 못하고 Pending 상태에 머무르게 됨.
2. preferredDuringSchedulingIgnoredDuringExecution
이는 선호 규칙(soft requirement)을 의미함.
스케줄러는 가능하다면 해당 규칙에 부합하는 노드에 파드를 배치하려고 노력하지만, 모든 노드가 조건을 만족하지 않아도, 부합하지 않는 노드 중 하나에 파드를 스케줄링할 수도 있음.
Node Affinity 규칙 예시
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
1. nodeSelectorTerms: 노드 라벨 조건을 만족해야 하는 규칙들의 집합.
2. matchExpressions: key, operator, values로 구성되어 어떤 노드 라벨이 특정 값들과 일치하는지 여부를 정의.
3. operator: In, NotIn, Exists, DoesNotExist, Gt, Lt 등을 지원.
Node Affinity는 기존의 NodeSelector(파드 스펙에서 nodeSelector 필드를 사용하는 방법)를 대체할 수 있는 기능임.
훨씬 더 복잡하고 유연한 매칭 조건을 제공한다는 장점이 있음.
Pod Affinity
Pod Affinity는 특정 라벨(label)을 가진 파드와 같은 노드 또는 같은 토폴로지 영역(예: 같은 zone, 같은 region 등)에 파드를 함께 스케줄링하고자 할 때 사용됨.
마이크로서비스 간 통신 비용을 낮추기 위해 서로 가까운 노드(예: 동일한 Availability Zone)에 배치하고 싶은 경우가 대표적인 예임.
Pod Affinity도 Node Affinity와 유사하게 크게 두 가지 형식이 있음.
1. requiredDuringSchedulingIgnoredDuringExecution (강제)
2. preferredDuringSchedulingIgnoredDuringExecution (선호)
Pod Affinity 동작 방식
Pod Affinity를 설정할 때는 파드 라벨과 토폴로지(Topology) 키가 중요함.
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: "kubernetes.io/hostname"
1. labelSelector: 어떤 라벨을 가진 파드와의 Affinity를 적용할지 결정.
2. topologyKey: 해당 키를 기준으로 묶인 노드들에 대해서 Affinity를 적용.
예를 들어, "kubernetes.io/hostname", "failure-domain.beta.kubernetes.io/zone", "topology.kubernetes.io/region" 등.
app=frontend 라벨을 가진 파드가 있는 같은 호스트(kubernetes.io/hostname)에 파드를 배치하라고 스케줄러에 요청하는 것임.
만약 이렇게 하면, frontend 파드와 새로운 파드가 동일 노드에서 함께 실행되어, 네트워크 지연(Latency) 최소화 같은 이점을 얻을 수 있음.
Pod Anti-Affinity
Pod Anti-Affinity는 Pod Affinity의 반대 개념으로, 특정 라벨을 가진 파드와는 같은 노드나 같은 영역에 배치되지 않도록 하는 규칙임.
예를 들어, 서비스의 고가용성(HA)을 위해 replica 파드를 물리적으로 분산 배치하고 싶을 때 사용함.
Pod Anti-Affinity 또한, 아래와 같이 두 가지 형식으로 구성됨.
1. requiredDuringSchedulingIgnoredDuringExecution (강제)
이 조건을 만족하지 못하는 노드는 절대 사용하지 않음
2. preferredDuringSchedulingIgnoredDuringExecution (선호)
조건을 만족하는 노드를 우선적으로 선택
Pod Anti-Affinity 예시
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
topologyKey: "kubernetes.io/hostname"
app=redis 라벨을 가진 파드가 이미 존재하는 노드에는 절대(강제) 새 파드를 스케줄링하지 않음.
이를 통해 동일 노드 장애가 발생해도 모든 redis 파드가 동시에 죽지 않도록, 물리적으로 파드를 분산할 수 있음.
스케줄러 관점에서 Affinity 처리
쿠버네티스 스케줄러는 파드가 생성될 때 아래와 같은 순서로 파드를 노드에 할당함.
1. Filter 단계
Taint & Toleration, Node Affinity, Pod Anti-Affinity(강제 규칙), 리소스 제한 등으로 부적합한 노드를 제거.
2. Score 단계
남아있는 후보 노드들에 대해, Pod Affinity나 Node Affinity의 선호(Preferred) 규칙, 남은 리소스 잔여량 등을 고려해 점수를 매기고, 가장 높은 점수를 가진 노드를 선택.
Affinity, Anti-Affinity가 모두 requiredDuringSchedulingIgnoredDuringExecution로 지정되어 있다면 Filter 단계에서 해당 조건을 만족하지 못하는 노드를 모두 제외함.
이후 preferredDuringSchedulingIgnoredDuringExecution으로 지정된 규칙들을 Score 단계에서 가중치(Weight)에 따라 점수를 매김.
Affinity 사용 시 고려 사항
1. 오버스펙 Rule로 인한 스케줄링 지연(Pending) 문제
requiredDuringSchedulingIgnoredDuringExecution를 여러 개 설정해두면, 만족할 수 있는 노드가 없을 때 파드가 계속 Pending 상태로 남을 수 있음.
이런 상황을 방지하기 위해, 실제로 사용 가능한 노드가 있는지 모니터링하면서 Affinity 조건을 조정해야 함.
2. 복잡한 Label Selector 사용 시 주의
Label Selector가 복잡해질수록 스케줄러가 해당 규칙을 평가하는 데 시간이 오래 걸리므로, 큰 규모 클러스터에서는 스케줄링 성능 문제가 생길 수 있음.
필요 이상의 세밀한 규칙보다는, 실효성이 있는 라벨들에 집중하는 것이 좋음.
3. Topology Key 다양화
Availability Zone, Region, Rack 등 물리 인프라에 따라 다양한 수준에서 파드를 묶거나 분산할 수 있음.
멀티 리전에 걸친 배포는 topology.kubernetes.io/region 같은 라벨을 적극 활용해 Affinity/Anti-Affinity를 세팅해두면 장애 대응성이 좋아짐.
4. Pod의 리스타트(Execution) 시점 고려
…IgnoredDuringExecution이라는 이름에서 알 수 있듯이, Affinity는 런타임에 노드를 옮기거나 하지는 않음.
Affinity는 “파드를 새롭게 스케줄링할 때”만 적용되므로, 이미 동작 중인 파드는 강제로 이동되지 않음.
실행 중인 파드가 재시작(예: 노드가 다운되어 다른 노드로 파드가 재스케줄링)되는 시점에서 다시 Affinity 규칙이 적용됨.
Affinity vs Taint & Toleration
Affinity와 Taint/Toleration은 모두 스케줄링 정책이라는 공통점이 있지만, 개념적으로는 약간 다름.
1. Affinity
주로 라벨(노드 라벨, 파드 라벨) 기반으로 파드를 어디에, 혹은 어떤 파드와 함께(또는 떨어져) 둘지 정함.
2. Taint & Toleration
노드가 자신의 상태를 나타내기 위한 taint를 설정하면, 이 taint를 견딜(tolerate) 수 있는 파드만 해당 노드에 스케줄링될 수 있음.
예를 들어, “이 노드는 GPU 노드이니, GPU를 사용할 수 없는 파드는 배치하지 마라” 같은 정책에 활용 가능.
둘은 상호 보완적인 관계이므로, 고급 스케줄링 정책을 만들 때 함께 활용함.
Affinity 결론
쿠버네티스 Affinity는 클러스터 내 파드 배치를 세밀하게 제어함.
고가용성(HA)과 통신 지연 최소화 등 다양한 요구 사항을 충족하기 위해 필수적인 기능임.
1. Node Affinity
특정 노드 라벨을 만족하거나 선호하도록 파드를 배치
2. Pod Affinity
특정 파드 라벨을 가진 파드가 존재하는 노드 혹은 영역에 함께 배치
3. Pod Anti-Affinity
특정 파드 라벨을 가진 파드와는 떨어져 배치
requiredDuringSchedulingIgnoredDuringExecution(강제)와 preferredDuringSchedulingIgnoredDuringExecution(선호) 규칙을 적절히 섞어 사용해, 실제 운영 환경에서 원하는 배포 전략을 구현할 수 있음.
규모가 큰 클러스터나 멀티 리전, 고가용성 서비스의 경우 Affinity와 Anti-Affinity를 정교하게 설계해두면 장애 상황에 대한 회복탄력성과 리소스 활용도가 크게 향상됨.
'Operating System > Kubernetes' 카테고리의 다른 글
[Kubernetes] 쿠버네티스의 Secret 및 ConfigMap (0) | 2024.12.29 |
---|---|
[Kubernetes] EKS 생성시 자동으로 생성되는 노드의 라벨 (0) | 2024.12.29 |
[Kubernetes] Deployment 배포 전략 종류 (0) | 2024.12.28 |
[Kubernetes] Keycloak 개념 (1) | 2024.12.28 |
[Kubernetes] Airflow의 웹서버 개념 (1) | 2024.12.28 |