[주의] 개인 공부를 위해 쓴 글이기 때문에 주관적인 내용은 물론, 쓰여진 정보가 틀린 것일 수도 있습니다!
피드백 부탁드립니다. (- -)(_ _) 꾸벅
특정한 노드 집합에서만 동작하거나 선호하도록 파드를 제한할 수 있다. 보통은 쿠버 스케줄러가 자동으로 합리적인 배치를 수행하기에 이러한 제약 조건을 설정할 필요는 없지만, 예를 들어 SSD가 설치 된 노드 파드가 배포될 필요가 있다던지, 서로 간의 통신이 매우 많은 서로 다른 서비스들의 파드들은 동일한 가용영역(AZ) 배포해야 한다던지 등의 제어해야할 상황이 있을 때 사용한다.
파드를 특정 노드에 배포하기 위한 제약조건으로 여러가지 방법이 있는데
- Node Labels에 매칭되는 nodeSelector 필드
- Affinity와 Anti-affinity
- nodeName 필드
- Pod topology 분재 제약 조건
[ Node Labels와 nodeSelector 필드 ]
Node Labels
다른 k8s 오브젝트와 마찬가지로 노드도 레이블을 가질 수 있고 수동으로 추가할 수 있다.
이 뿐만 아니라 클러스터의 모든 노드들은 생성 후 표준화 된 레이블이 자동으로 달리게 되는데, 아래처럼 master 노드를 describe로 확인해보면 알 수 있듯이 노드 레이블들이 kubernetes.io와 k8s.io 네임스페이스 아래에 정의돼있다.
(어노테이션은 레이블과 비슷하게 리소스의 메타데이터를 표시하는 방법이지만 레이블은 리소스를 태깅하고 그룹하는데 쓰는데 비해, 어노테이션이 좀 더 부가적인 정보(설명, 버전 등)를 제공하는 느낌이다)
master@master:~$ kubectl describe node master
Name: master
Roles: control-plane,master
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=master
kubernetes.io/os=linux
node-role.kubernetes.io/control-plane=
node-role.kubernetes.io/master=
node.kubernetes.io/exclude-from-external-load-balancers=
Annotations: flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"12:4b:43:4e:d5:ef"}
flannel.alpha.coreos.com/backend-type: vxlan
flannel.alpha.coreos.com/kube-subnet-manager: true
flannel.alpha.coreos.com/public-ip: 192.168.127.129
kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
nodeSelector
위와 같은 레이블을 Selector를 통해 지정하고 특정할 수 있다. 특정 오브젝트가 실행될 노드를 선택하기 위해 사용하는 방법 중 하나이며 가장 간단하면서도 추천하는 형태이다.
nodeSelector 필드를 추가하고 타겟으로 삼고 싶은 노드가 갖고 있는 Node Label을 명시한다.
apiVersion: v1
kind: Pod
metadata:
name: eshop-store
spec:
containers:
- image: nginx
name: eshop-store
nodeSelector:
disktype: ssd
위와 같이 key-value 쌍으로 라벨을 지정하면, 디스크 타입이 ssd인 노드에만 파드가 배포되는 형태
[ Node Affinity - 노드 어피니티 ]
Affinity
개념적으로 nodeSelector와 비슷하지만 선택 로직에 대한 좀 더 많은 제어권을 제공한다.
- "소프트(soft)" 또는 "선호사항(preference)" 을 나타내어, 매치되는 노드를 찾지 못한 경우에도 파드를 스케줄링 할 수 있다.
- 파드 간 어피니티/안티-어피니티는 다른 파드의 레이블을 이용하여 해당 파드를 제한할 수 있게 해 준다.
- requiredDuringSchedulingIgnoredDuringExecution (필수로 반드시 지켜야하는)
규칙이 만족되지 않으면 스케줄러가 파드를 스케줄링 X
nodeSelector와 유사하지만, 좀 더 표현적인 문법을 제공한다. - preferredDuringSchedulingIgnoredDuringExecution (필수는 아니지만 가급적인)
스케줄러는 조건을 만족하는 노드를 가급적이면 찾으려고 노력.
해당되는 노드가 없더라도, 다른 노드에 파드를 스케줄링한다. - Operator로 key 값이 values에 어떻게 포함되는지에 대한 다양한 연산 표현방식을 제공한다.
In, NotIn, Exists, DoesNotExist, Gt, Lt
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0
예시에서는 다음의 규칙이 적용된다.
- 노드는 키가 topology.kubernetes.io/zone인 레이블을 갖고 있어야 하며, 레이블의 값이 antarctica-east1 혹은 antarctica-west1여야 한다.
- 키가 another-node-label-key이고 값이 another-node-label-value인 레이블을 갖고 있는 노드를 선호한다 .
Affinity weight (어피니티 가중치)
preferredDuringSchedulingIgnoredDuringExecution 어피니티 타입 인스턴스에 대해 1-100 범위의 weight를 명시할 수 있다. 선호하는 노드를 가중치로 표현하여 계산하며 스케줄러는 점수가 가장 높은 노드에 우선적으로 배포한다.
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: label-1
operator: In
values:
- key-1
- weight: 50
preference:
matchExpressions:
- key: label-2
operator: In
values:
- key-2
각각 label-1:key-1 레이블, label-2:key-2 레이블이 붙은 노드가 각각 있다면, 스케줄러는 각 노드의 weight를 확인한 뒤 해당 노드에 대한 다른 점수에 가중치를 더하고, 최종 점수가 가장 높은 노드에 해당 파드를 스케줄링한다.
Pod 간 Affinity와 Anti-Affinity
위에서는 노드에 달린 레이블을 기준으로 어피니티 되었다면, 파드 간 어피니트를 사용하여 각 노드에 이미 실행 중인 다른 파드의 레이블을 기반으로 파드가 스케줄링 될 노드를 제한할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: registry.k8s.io/pause:2.0
- 만약 security=S1 파드 레이블이 있는 하나 이상의 기존 파드를 실행하고 있는 노드가 zone=V에 하나 이상 존재한다면, 스케줄러는 파드를 topology.kubernetes.io/zone=V 레이블이 있는 노드에 배치해야 한다.
- 만약 security=S2 파드 레이블이 있는 파드가 실행되고 있는 zone=R에 다른 노드도 존재한다면, 스케줄러는 topology.kubernetes.io/zone=R 레이블이 있는 노드에는 가급적 해당 파드를 스케줄링하지 않야아 한다.
[ nodeName - 노드 네임]
nodeName은 어피니티랑 nodeSelector보다 더 직접적인 노트 선택 방법이다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-01
위 파드는 무조건 kube-01 이라는 노드에서만 실행될 것이다.
- 만약 명명된 노드가 없으면, 파드가 실행되지 않고 따라서 자동으로 삭제될 수 있다.
- 만약 명명된 노드에 파드를 수용할 수 있는 리소스가 없는 경우 파드가 실패하고, 그 이유는 다음과 같이 표시된다. 예: OutOfmemory 또는 OutOfcpu.
- 클라우드 환경의 노드 이름은 항상 예측 가능하거나 안정적인 것은 아니다.
'클라우드 > 쿠버네티스' 카테고리의 다른 글
[Kubernetes] 16. 쿠버네티스 Ingress 인그레스 (0) | 2023.04.23 |
---|---|
[Kubernetes] 15. 쿠버네티스 Configmap과 Secret (컨피그맵, 시크릿) (0) | 2023.04.04 |
[Kubernetes] 13. 쿠버네티스 사이드카 패턴(Sidecar pattern) 및 실습 (3) | 2023.03.05 |
CKA 정리 및 북마크 (0) | 2023.01.16 |
[Kubernetes] 12. 쿠버네티스 리소스 오브젝트들 및 생성 방법 (0) | 2023.01.05 |