kmg28801 / kubernetes-study

2 stars 0 forks source link

Chapter 16. 고급 스케줄링 #17

Open kmg28801 opened 1 year ago

kmg28801 commented 1 year ago

파드 스펙의 노드 셀렉터를 통해 특정 노드로 스케줄링되는 것을 수행할 수 있지만, 이것만으로는 특정 니즈를 처리할 수 없기 때문에 쿠버네티스에서는 이를 확장하는 매커니즘을 제공한다.

테인트와 톨러레이션을 사용해 특정 노드에서 파드 실행 제한

테인트와 노드 어피니티 규칙의 차이점 이해

테인트와 톨러레이션 소개

$ kubectl describe node master.k8s
Name:         master.k8s
Role:
Labels:       beta.kubernetes.io/arch=amd64
              beta.kubernetes.io/os=linux
              kubernetes.io/hostname=master.k8s
              node-role.kubernetes.io/master=
Annotations:  node.alpha.kubernetes.io/ttl=0
              volumes.kubernetes.io/controller-managed-attach-detach=true
Taints:       node-role.kubernetes.io/master:NoSchedule
...

image

파드의 톨러레이션에는 표시되지만 노드의 테인트에는 표시되지 않는 등호는 무시하라. kubectl은 테인트/톨러레이션 값이 null일 때 테인트와 톨러레이션을 다르게 표시한다. (현재는 null일 때 동일하게 표시한다.)

노드에 사용자 정의 테인트 추가하기

kmg88801@cloudshell:~ (awesome-caster-376906)$ kubectl taint node gke-cluster-1-default-pool-00c2d871-0ihe node-type=production:NoSchedule
node/gke-cluster-1-default-pool-00c2d871-0ihe tainted

파드에 톨러레이션 추가

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 3
  selector:
    matchLabels:
      app: kubia
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        name: nodejs
        resources:
          requests:
            cpu: 100m # 파드당 100밀리코어의 CPU 요청
      tolerations:
      - key : node-type
        operator: Equal
        value: production
        effect: NoSchedule
kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl get po -o wide
NAME                  READY   STATUS    RESTARTS   AGE   IP             NODE                                       NOMINATED NODE   READINESS GATES
kubia-bd7db89-g94d4   1/1     Running   0          24s   10.120.1.8     gke-cluster-1-default-pool-00c2d871-mrz4   <none>           <none>
kubia-bd7db89-n5jpl   1/1     Running   0          24s   10.120.2.6     gke-cluster-1-default-pool-00c2d871-tyej   <none>           <none>
kubia-bd7db89-sdsdm   1/1     Running   0          24s   10.120.1.138   gke-cluster-1-default-pool-00c2d871-0ihe   <none>           <none>

테인트와 톨러레이션의 활용 방안 이해

노드 어피니티를 사용해 파드를 특정 노드로 유인하기

파드 노드 어피니티 규칙 지정

apiVersion: v1
kind: Pod
metadata:
  name: kubia-gpu
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: gpu
            operator: In
            values:
            - "true"
  containers:
  - image: luksa/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP

파드의 스케줄링 시점에 노드 우선순위 지정

kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl get nodes
NAME                                       STATUS   ROLES    AGE   VERSION
gke-cluster-1-default-pool-00c2d871-0ihe   Ready    <none>   46h   v1.24.9-gke.2000
gke-cluster-1-default-pool-00c2d871-mrz4   Ready    <none>   46h   v1.24.9-gke.2000
gke-cluster-1-default-pool-00c2d871-tyej   Ready    <none>   46h   v1.24.9-gke.2000
kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl label node gke-cluster-1-default-pool-00c2d871-0ihe availability-zone=zone1
node/gke-cluster-1-default-pool-00c2d871-0ihe labeled
kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl label node gke-cluster-1-default-pool-00c2d871-0ihe share-type=dedicated
node/gke-cluster-1-default-pool-00c2d871-0ihe labeled
kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl label node gke-cluster-1-default-pool-00c2d871-mrz4 availability-zone=zone2
node/gke-cluster-1-default-pool-00c2d871-mrz4 labeled
kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl label node gke-cluster-1-default-pool-00c2d871-mrz4 share-type=shared
node/gke-cluster-1-default-pool-00c2d871-mrz4 labeled
kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl get nodes -L availability-zone -L share-type
NAME                                       STATUS   ROLES    AGE   VERSION            AVAILABILITY-ZONE   SHARE-TYPE
gke-cluster-1-default-pool-00c2d871-0ihe   Ready    <none>   46h   v1.24.9-gke.2000   zone1               dedicated
gke-cluster-1-default-pool-00c2d871-mrz4   Ready    <none>   46h   v1.24.9-gke.2000   zone2               shared
gke-cluster-1-default-pool-00c2d871-tyej   Ready    <none>   46h   v1.24.9-gke.2000
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubia
spec:
  replicas: 3
  selector:
    matchLabels:
      app: kubia
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        name: nodejs
        resources:
          requests:
            cpu: 100m # 파드당 100밀리코어의 CPU 요청
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80
            preference:
              matchExpressions:
              - key: availability-zone
                operator: In
                values:
                - zone1
          - weight: 20
            preference:
              matchExpressions:
              - key: share-type
                operator: In
                values:
                - dedicated

파드 어피니티와 안티-어피니티를 이용해 파드 함께 배치하기

kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl run backend -l app=backend --image=busybox -- sleep 999999
pod/backend created
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 5
  selector:
    matchLabels:
      app: kubia
  template:
    metadata:
      name: kubia
      labels:
        app: kubia
    spec:
      containers:
      - image: luksa/kubia:v1
        name: nodejs
        resources:
          requests:
            cpu: 100m # 파드당 100밀리코어의 CPU 요청
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - topologyKey: kubernetes.io/hostname
            labelSelector:
              matchLabels:
                app: backend
kmg88801@cloudshell:~/chapter16 (awesome-caster-376906)$ kubectl get po -o wide
NAME                        READY   STATUS    RESTARTS   AGE     IP            NODE                                       NOMINATED NODE   READINESS GATES
backend                     1/1     Running   0          2m4s    10.120.1.11   gke-cluster-1-default-pool-00c2d871-mrz4   <none>           <none>
frontend-5f944bb797-95g7x   1/1     Running   0          26s     10.120.1.13   gke-cluster-1-default-pool-00c2d871-mrz4   <none>           <none>
frontend-5f944bb797-h54wc   1/1     Running   0          26s     10.120.1.15   gke-cluster-1-default-pool-00c2d871-mrz4   <none>           <none>
frontend-5f944bb797-r76g7   1/1     Running   0          26s     10.120.1.16   gke-cluster-1-default-pool-00c2d871-mrz4   <none>           <none>
frontend-5f944bb797-tw57l   1/1     Running   0          26s     10.120.1.14   gke-cluster-1-default-pool-00c2d871-mrz4   <none>           <none>
frontend-5f944bb797-x4bpt   1/1     Running   0          26s     10.120.1.12   gke-cluster-1-default-pool-00c2d871-mrz4   <none>           <none>
kubia-5f475fb4bd-hbld2      1/1     Running   0          7m36s   10.120.2.8    gke-cluster-1-default-pool-00c2d871-tyej   <none>           <none>

topologyKey 작동 방법 이해

  1. 모든 노드에 rack 레이블을 추가
  2. 파드의 podAffinity 정의할때 topologyKey를 rack으로 설정
  3. 스케줄러가 파드를 배포할 위치를 결정할 때 파드의 podAffinity 구성 확인하고 레이블 셀렉터와 일치하는 파드를 찾은 다음 파드가 실행 중인 노드를 찾는다.
  4. 특히 podAffinity에 지정된 topologyKey 필드와 일치하는 키를 갖는 노드 레이블을 찾는다.
  5. 레이블이 이전에 찾은 파드의 값과 일치하는 모든 노드를 선택
  6. 레이블 셀렉터는 app:backend와 일치하고, 해당 노드의 랙 레이블값이 rack2이기 때문에 프론트엔드 파드를 스케줄링할 때 스케줄러는 rack=rack2 레이블이 있는 노드 중 하나를 선택한다.