보람찬 코기의 개발자 블로그
article thumbnail
반응형

쿠버네티스를 학습하면서 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 노드에 할당함으로써 자원 활용을 최적화할 수 있다.
반응형
profile

보람찬 코기의 개발자 블로그

@BoChan

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!