쿠버네티스를 학습하면서 control plane에서 Pod을 어디에 배포할지 정해주는 스케줄러를 배웠을 것이다.
쿠버네티스에서 스케줄링 은 Kubelet이 파드를 실행할 수 있도록 파드가 노드에 적합한지 확인하는 것을 말한다.
그말은 즉, Pod이 필요한 자원의 request와 limit에 실행되기 적합한 node를 내부 엔진을 통해 찾아준다는 것이다.
또한 원문을 읽다보면 다음과 같은 구절이 나온다.
"Kube-scheduler selects an optimal node to run newly created or not yet scheduled (unscheduled) pods. Since containers in pods - and pods themselves - can have different requirements, the scheduler filters out any nodes that don't meet a Pod's specific scheduling needs. Alternatively, the API lets you specify a node for a Pod when you create it, but this is unusual and is only done in special cases.( 원문 발췌 )""
Kube-scheduler는 새로 생성되거나 아직 예약되지 않은(예약되지 않은) 포드를 실행할 최적의 노드를 선택합니다. Pod의 컨테이너와 Pod 자체의 요구 사항이 다를 수 있으므로 스케줄러는 Pod의 특정 일정 요구 사항을 충족하지 않는 노드를 필터링합니다. 또는 API를 사용하면 포드를 생성할 때 포드에 대한 노드를 지정할 수 있지만 이는 일반적이지 않으며 특수한 경우에만 수행됩니다.
다시말해 특수한 경우인데, 예를 들어 이런경우가 있을 수도 있다.
- 여러 대의 Jetson device 혹은 엣지 시스템을 클러스터로 구축한 경우 각각 디바이스에 대한 성능 테스트
- 클러스터 구축에 노드 특성이 도드라질 경우 [노드에 GPU가 탑재, 노드에 대용량 SSD가 탑재된 경우]
Label 확인하기
kubectl get nodes --show-labels
aicomputing이라는 노드의 경우 Labe은 다음 과 같다
beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=aicomputing,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers= |
필자는 master node인 aicomputing 에서 taint 설정을 하여 Master와 Worker를 구축했다. 그래서 Label이 Master 등록을 확인할수 있다.
Label 추가하기
$ kubectl label node worker2 key=worker
//출력: node/worker2 labeled
이후, 노드를 확인해보자
$ kubectl get nodes --show-labels
worker2 Ready <none> 7d15h v1.21.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,key=worker,kubernetes.io/arch=amd64,...
으로 key=value로 지정한 값이 적용되었다
$ kubectl describe nodes worker2
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
key=worker
kubernetes.io/arch=amd64
kubernetes.io/hostname=worker2
kubernetes.io/os=linux
//로 확인할 수 있다
특정 노드에 배포하기 (Yaml 작성)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nodetest-app-deployment
labels:
app: nodetest-app
spec:
replicas: 1
selector:
matchLabels:
app: nodetest-app
template:
metadata:
labels:
app: nodetest-app
spec:
containers:
- name: my-nginx-pod
image: nginx:latest
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 80
protocol: TCP
nodeSelector:
key: worker
주요 특징이라면 containers 의 nodeSelector를 통하여 key의 value 가 worker 인 노드에 배포하게 작성하였다.
이제 터미널을 켜서 배포해보자
$ kubectl apply -f nodeSelectorDeploy.yaml
deployment.apps/nodetest-app-deployment created
이후 pod생성위치를 확인해보면 잘 알수 있다.
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nodetest-app-deployment-5647fb8657-r9cml 1/1 Running 0 28s 192.168.1.191 worker2 <none> <none>
//Node 부분에서 확인이 가능하다
다른 방법으로는 node affinity가 있다.
node affinity는 파드가 특정 노드와 결합되도록 지정하거나, 특정 노드와 분리되도록 지정할 수 있다.
즉, 이전의 nodeSelector는 지정 배포라고 하면 이 방법은 다양한 조건을 명시 할수 있다는 차이가 있다.
아래와 같이 4가지로 분류할 수 있다.
- requiredDuringSchedulingIgnoredDuringExecution
- preferredDuringSchedulingIgnoredDuringExecution
requiredDuringSchedulingIgnoredDuringExecution: 이 규칙을 사용하면 노드와 파드가 반드시 일치해야 한다. 즉, 특정 노드와 파드를 매칭하지 못하면 해당 파드는 스케줄링되지 않는다
preferredDuringSchedulingIgnoredDuringExecution: 이 규칙은 일치하는 노드가 여러 개인 경우에도 우선적으로 매칭되도록 지정하는 것이다. 하지만 필수적이지 않으며, 다른 제약사항들이 우선시한다.
- requiredDuringSchedulingRequiredDuringExecution
- preferredDuringSchedulingRequiredDuringExecution
Ignored & Required는 운영 중(Runtime) Node의 Label이 변경되면 무시할 것인지(Ignore) 또는 즉시 Eviction 처리(Required)하여 재기동을 수행할 것인지를 결정한다.
다음은 requiredDuringSchedulingIgnoredDuringExecution 일 경우를 위한 작성한 yaml 파일이다
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: nginx
image: nginx:latest
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: app
operator: In
values:
- backend
spec에서 affinity를 통하여 어떤 상태인지 정의해준다.
그리고 node에서 적용한것처럼 pod affinity 가 있다.
이와같이 affinity를 응용하여 활용한다면 다음과 같은 케이스에서 사용할 수 있을것 같다 (참조 자료)
- Active / Standby 구조로 동작하는 솔루션 이미지 등에 적용하여 Active 솔루션이 설치 된 노드에 중복되어 Standby가 배포되지 않도록 podAntiAffinity를 적용하여 사전에 방지하는 역할
- 이미 배포되어 있는 특정 Pod와 local 통신을 해야 하는 경우 해당 Pod가 배포되어 있는 개수 만큼 Replica를 지정하고 kubernetes.io/hostname을 topologyKey로 지정하여 배포하는 경우
- Kubernetes Cluster 내부에서 Pod를 기준으로 Cluster 단위를 다시한번 쪼개는 역할 등을 수행할 수 있습니다.
- 지역성(Locality) 보장: Affinity를 이용하여 파드를 특정 노드 또는 노드 그룹에 할당함으로써, 파드가 자원과 더 가까이 위치하게 할 수 있습니다. 이는 데이터와 파드 간의 지역성을 보장하고 네트워크 지연을 줄여 성능을 최적화할 수 있다.
- 서비스 품질(QoS) 관리: 특정 노드에 더 성능이 우수한 하드웨어가 있거나 특정 지역이 더 안정적인 네트워크 연결을 제공한다면, Affinity를 사용하여 파드를 해당 노드에 할당하여 서비스 품질을 향상시킬 수 있다.
- 동일 랙(Rack) 배치: 대규모 클러스터에서는 같은 랙에 있는 노드들 사이의 네트워크 속도가 더 빠를 수 있습니다. Affinity를 사용하여 파드를 동일 랙에 있는 노드에 배치함으로써 네트워크 병목 현상을 완화하고 성능을 개선할 수 있다.
- 노드 간 분리(Separation): Affinity의 반대 개념인 Anti-Affinity를 사용하여 파드가 특정 노드 또는 특정 노드 그룹과 함께 배치되지 않도록 할 수 있습니다. 이를 통해 파드의 가용성과 안정성을 향상시킬 수 있다.
- 하이브리드 클라우드 배포: Public Cloud와 Private Cloud를 혼합하여 하이브리드 클라우드 환경을 운영하는 경우, Affinity를 이용하여 특정 파드를 Private Cloud 노드에 할당하거나 Public Cloud 노드에 할당함으로써 자원 활용을 최적화할 수 있다.
'Kubernetes_쿠버네티스' 카테고리의 다른 글
[Kubetnetes/K8s] 쿠버네티스 Service(Cluster IP, NodePort, LoadBalancer) 개념 잡기 (0) | 2023.07.27 |
---|---|
[Kubernetes/K8s] 쿠버네티스란? (0) | 2023.07.25 |
[K8S] deployment 롤링 업데이트 하기 (0) | 2023.07.19 |
[k8s] Schedule GPU (GPU 스케줄링) 공식 원문 번역 (0) | 2023.07.19 |
[쿠버네티스] 클러스터와 분산 시스템 정리 (0) | 2023.01.20 |