이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

클라우드/Kubernetes

29. Kubernetes Scheduler (Affinity)

이쿠우우 2020. 10. 11. 10:36
반응형

 

 

 

 

 

Kubernetes Scheduler (Affinity)

 

 


[Kubernetes Scheduler 관련 글 목록]

Kubernetes Scheduler (Pod를 원하는 Worker Node에 배포하기)

Kubernetes Scheduler (nodeSelector)

Kubernetes Scheduler (Taint & Toleration)

Kubernetes Scheduler (Affinity)


 

 

 

 

Kube-Scheduler의 다양한 기능을 사용해서 관리자가 직접

특정 Worker Node에 Pod 가 생성되도록 설정할 수 도 있음

대표적으로

nodeSelector

Taint & Toleration

Affinity

3가지 방법이 있는데 

 

이 글에서는 Affinity에 대해서 알아보겠음.

 

 


 

[목차]

Affinity란?

Node Affinity 실습

Pod Affinity 실습

Affinity의 Operator 설명

Preferred Affinity 의 weight 설명

 


 

[환경]

 

Master Node server

 OS = CentOS 7

 리눅스 커널 버전 : Linux 3.10.0-1062.el7.x86_64

 docker version : 1.13.1

 api verison : 1.26

 

Worker Node server 1

 OS = CentOS 7

 리눅스 커널 버전 : Linux 3.10.0-1062.el7.x86_64

 docker version : 1.13.1

 api verison : 1.26

 

Worker Node server 2

 OS = CentOS 7

 리눅스 커널 버전 : Linux 3.10.0-1062.el7.x86_64

 docker version : 1.13.1

 api verison : 1.26

 

 

Kubernetes version

 1.18

 

 


 

Affinity란?

 

Pod가 특정 Worker Node에 배치되도록 하는 정책.

Node를 기준으로 Scheduling 하는 Node Affinity와

Pod를 기준으로 Scheduling 하는 Pod Affinity가 있음.

 

 

Node Affinity

새로운 Pod가 특정 Worker Node로 배포되도록 Scheduling 해주는 설정.

Node Affinity는 선호도를 설정할 수 있는 기능으로 

Required Node Affinity와 Preferred Node Affinity 2가지로 구분됨.

 

가장 처음 설명드렸던 nodeSelector는 Required Node Affinity와 동일한 원리.

만약 nodeSelector 도 설정되어있고

Node Affinity 도 설정되어있다면

두 조건을 모두 만족해야 Pod 가 배포됨.

 

nodeSelector와 차이점을 있다면

Affinity는 operator 설정이 가능함

 

[ operator 설정] 

in, Exists, Gt, Lt, NotIn, DoesNotExist, 설정이 올 수 있음

 

Required Node Affinity

반드시 규칙을 만족.

Pod를 모든 조건이 맞는 Worker Node에만 배포되도록 하는 설정.

설정 : requiredDuringSchedulingIgnoredDuringExecution (강제)

 

Preferred Node Affinity

우선순위 설정 가능.

가급적 규칙을 만족하는것이 좋음. 규칙을 꼭 만족하지 않아도 됨.

Pod를 모든 조건이 맞는 Worker Node에만 배포되도록 하는 설정.

설정 : preferredDuringSchedulingIgnoredDuringExecution (반강제)

 

 

 

Pod Affinity

새로운 Pod가 기존에 배포되어서 실행 중인 Pod를 참고해서 

Worker Node로 배포되도록 Scheduling 해주는 설정.

 

동일한 다수의 Pods가 

네트워크와 같은 리소스 효율을 위해 동일한 Worker Node 에서 동작하는것이 효율적일 수도 있고

HA구성을 해야하는 경우와 같이 반드시 서로 다른 Worker Node 배포되어야하는 경우가 있음.

그에 따라

Pod Affinity와 Pod AnitAffinity로 구분되어지는데

동일한 Pods가 같은 Worker Node에서 실행되어야한다면 Pod Affinity를 사용하고

동일한 Pods가 다른 Worker Node에서 실행되어야한다면 Pod AntiAffinity를 사용해야함.

 

Pod Affinity 또한 선호도를 설정할 수 있는 기능으로 

Required Pod Affinity와 Preferred Pod Affinity 2가지로 구분됨.

 

Required Pod Affinity

반드시 규칙을 만족.

Pod를 모든 조건이 맞는 Worker Node에만 배포되도록 하는 설정.

설정 : requiredDuringSchedulingIgnoredDuringExecution (강제)

 

Preferred Pod Affinity

우선순위 설정 가능.

가급적 규칙을 만족하는것이 좋음. 규칙을 꼭 만족하지 않아도 됨.

Pod를 모든 조건이 맞는 Worker Node에만 배포되도록 하는 설정.

설정 : preferredDuringSchedulingIgnoredDuringExecution (반강제)

 

일반적으로 실제 환경에서는 Pod의 replicaset을 

균등하게 분산하는 것보다 충분한 개수의 replicaset를 확보하는 것이 더 중요하므로 

Hard Pod Affinity보다 Soft Pod Affinity를 사용하는것을 추천한다고 함.

 

Pod AntiAffinity

주로 HA구성을 할 때 처럼 

동일한 Pods가 서로 다른 Worker Node에서 실행되야할 때 사용하는 설정.

 

 

 


 

 

Node Affinity 실습

 

0. 목표

 

[ Required Node Affinity Test를 위해 ]

Worker Node One과 Two 모두

requiredkey: iksoonvalue Label을 추가해서

Worker Node One, Two 이외의 

Worker Node 에는 Pod가 배포되지 않도록함

 

[ Preferred Node Affinity Test를 위해 ]

Worker Node One 에는

preferredkey1: iksoonvalue1 Label을 추가하고

weight : 10으로 부여,

 

Worker Node Two 에는

preferredkey2: iksoonvalue2 Label을 추가하고

weight : 20으로 부여해서

우선순위가 더 높은

Worker Node Two에 Pod가 배포되는지 확인.

 

 

1. Worker Node 의 Label 확인 

 

Kubernetes Cluster를 구성하고 있는 모든 Node에 미리 추가되어있는

Default Label 을 확인.

 

[명령어]

kubectl get nodes --show-labels

 

[확인 결과]

각 Node 의 CPU 종류, OS 종류, host name 이 Label로 설정되어있고

MasterNode는 추가로 

"node-role.kubernetes.io/master="

Labels이 있어서 Worker Node 와 구분되어 있음.

 

Node Selector의 경우에 이러한 기존의 Labels를 지정해서 사용할 수 있지만

리서치에서는 Labels 을 직접 추가해서

추가한 Label을 인식해서 Pod를 생성해보겠음.

 

 

2. Worker Node 의 Label 추가

 

Worker Node one, two 에 

requiredkey: iksoonvalue Label 추가.

 

Worker Node one에 

preferredkey1: iksoonvalue1 Label 추가

 

Worker Node Two에 

preferredkey2: iksoonvalue2 Label 추가

 

 

[명령어]

kubectl label nodes [Node name] [key]=[value]

예) 

kubectl label nodes kube.workerone.node requiredkey=iksoonvalue preferredkey1=iksoonvalue1

kubectl label nodes kube.workertwo.node requiredkey=iksoonvalue preferredkey2=iksoonvalue2

 

 

 

3. Node Affinity를 사용해서 특정 Worker Node에 Pod 배포

 

한가지 Pod에 다수의 Node Affinity를 적용할 수 있음.

아래의 예제 deployment.yaml은

Required Node Affinity 설정 1개와

Preferred Node Affinity 설정 1개로

총 2개의 Node Affinity가 설정되어있음.

 

[예제 deployment.yaml ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment-test

  labels:

    app: iksoon-test

spec:

  replicas: 1

  selector:

    matchLabels:

      app: iksoon-pod

  template:

    metadata:

      labels:

        app: iksoon-pod

    spec:

      containers:

      - name: iksoon-tomcat

        image: peksoon/iksoon_tomcat:1.0.6

        ports:

        - containerPort: 8080

      affinity:         # affinity 사용

        nodeAffinity:   # 종류는 Node Affinity로 설정

 

          # Label이 매칭 되는 Worker Node 에만 Pod 배포 가능.

          requiredDuringSchedulingIgnoredDuringExecution:  # Required Node Affinity로 설정

            nodeSelectorTerms: 

            - matchExpressions:   # 특정 Worker Node에 설정되어있는 Label과 

                                  # 해당 설정의 Label이 매칭되는 Worker Node에 Pod를 생성

                                  # Label set-based selector 문법 사용

              - key: requiredkey

                values: iksoonvalue

                operator: In # in, Exists, Gt, Lt, NotIn, DoesNotExist, 설정이 올 수 있음

 

          # 우선순위가 더 높은 Worker Node Two에 Pod가 배포되는지 확인.

          preferredDuringSchedulingIgnoredDuringExecution:  # Preferred Node Affinity로 설정

          - weight: 10

             preference:

               matchExpressions:   

               - key: preferredkey1

                 values: iksoonvalue1

                 operator: In

 

           preferredDuringSchedulingIgnoredDuringExecution: 

           - weight: 20

             preference:

               matchExpressions:   

               - key: preferredkey2

                 values: iksoonvalue2

                 operator: In

 

 

 

[결과]

deployment를 생성하면

Worker Node two에  Pod가 생성되어있는것을 확인할 수 있음

 

[ 이유 ]

Required Node Affinity 설정 : Worker Node One, Two 에 생성 가능 조건을 충족했음.

preferred Node Affinity 설정 : Worker Node One보다 two의 weight가 더 커서 two에 생성됨.

 

 

4. Worker Node 의 Label 삭제

 

[명령어]

kubectl label nodes [Node name] [key]-

예) 

kubectl label nodes kube.workerone.node requiredkey- preferredkey1-

kubectl label nodes kube.workertwo.node requiredkey- preferredkey2-

 

 

 


 

 

 

Pod Affinity 실습

 

0. 목표

 

[ Required Pod Anit Affinity Test를 위해 ]

2개의 Worker Node가 존재 할 경우

Deployment 에서 replicaset 을 3로 설정하여

3개의 Tomcat Pod를

Required Pod Anit Affinity로 서로 다른 Worker Node에 

배포되도록 했을 때 결과가 어떻게 나오는지 확인.

 

 

[ Preferred Pod Anti Affinity Test를 위해 ]

2개의 Worker Node가 존재 할 경우

Deployment 에서 replicaset 을 3로 설정하여

3개의 Mysql Pod를

Required Pod Anit Affinity로 서로 다른 Worker Node에 

배포되도록 했을 때 결과가 어떻게 나오는지 확인.

 

[ Preferred Pod Affinity Test를 위해 ]

Myql 은 생성했었던 Tomcat Pod 가 있는 위치에만 생성되도록 설정.

 

 

1. podAntiAffinity 설정된 Tomcat Pod생성 

 

[ 예제 deployment.yaml ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment-affinity

  labels:

    app: iksoon-tomcat

spec:

  replicas: 3   # 3개의 Pod가 생성.

  selector:

    matchLabels:

      app: iksoon-tomcat-pod 

  template:

    metadata:

      labels:

        app: iksoon-tomcat-pod # 생성되는 Pod 의 Label은 app=iksoon-tomcat-pod로 설정

    spec:

      containers:

      - name: iksoon-tomcat

        image: peksoon/iksoon_tomcat:1.0.6

        ports:

        - containerPort: 8080

      affinity:         # affinity 사용

 

        # Anit Affinity로 서로 다른 Worker Node에 배포되도록 설정

        podAntiAffinity:   # 종류는 Pod Anti Affinity로 설정

          requiredDuringSchedulingIgnoredDuringExecution:  # Required Pod Anti Affinity로 설정

          - labelSelector: 

              matchExpressions:  

              - key: app # podAntiAffinity를 적용할 Pod의 Key를 넣어줌.

                         # 해당 deployment로 생성될 Pod들이 서로 다른 Worker Node 에 생성되야하므로

                         # Deployment에서 생성되는 Pod의 Label을 넣어줌

                values:  # 마찬가지로 적용할 Pod의 value를 넣어줌

                - iksoon-tomcat-pod 

                operator: In # 아래에서 자세히 설명

            topologyKey: kubernetes.io/hostname Pod Anti Affinity를 적용할 Worker Node 찾음.

                                                # topologyKey는 Worker Node Label의 Key를 확인해서

                                                # 설정된 Key가 Worker Node에 존재하면 Pod Anti Affinity가 적용됨.

                                                # 해당 key의 value값은 확인하지 않음.

 

 

 

[ 생성 결과 ]

PodAntiAffinity 설정으로 인해

Pod 가 서로 다른 Worker Node 에 생성되는것을 확인할 수 있음

replicaset을 3으로 설정해서 총 3개의 Pod가 생성되었는데

Worker node가 2개이므로 

각각 Worker Node one, two 에서 하나씩 생성되었고

나머지 하나는 생성될 worker node 가 없어서 pending 상태가 됨.

 

 

2. podAntiAffinity 와 podAffinity설정된 Mysql Pod생성 

 

[ 예제 deployment.yaml ]

apiVersion: apps/v1

kind: Deployment

metadata:

  name: iksoon-deployment-mysql

  labels:

    app: iksoon-mysql

spec:

  replicas: 3   # 3개의 Pod가 생성.

  selector:

    matchLabels:

      app: iksoon-mysql-pod 

  template:

    metadata:

      labels:

        app: iksoon-mysql-pod # 생성되는 Pod 의 Label은 app=iksoon-mysql-pod로 설정

    spec:

      containers:

      - name: iksoon-mysql

        image: peksoon/iksoon_mysql:1.0.2

        ports:

        - containerPort: 3306

      affinity:        

 

        # Anit Affinity로 서로 다른 Worker Node에 배포되도록 설정

        podAntiAffinity:   

          requiredDuringSchedulingIgnoredDuringExecution:  

          - labelSelector: 

              matchExpressions:  

              - key: app 

                values: 

                - iksoon-mysql-pod 

                operator: In 

            topologyKey: kubernetes.io/hostname 

 

        # 상위에서 생성했던 tomcat pod가 있는 worker Node에만 mysql이 생성되도록 설정

        podAffinity:  # 이전에 생성했던   

          requiredDuringSchedulingIgnoredDuringExecution:  

          - labelSelector:

              matchExpressions:  

              - key: app # 상위에서 생성했던 tomcat pod 의 Label 값을 넣어줌

                values:

                - iksoon-tomcat-pod  # 상위에서 생성했던 tomcat pod 의 Label 값을 넣어줌

                operator: In

            topologyKey: kubernetes.io/hostname

 

 

[ 생성 결과 ]

PodAntiAffinity 설정으로 인해

Pod 가 서로 다른 Worker Node 에 생성되는것을 확인할 수 있음

replicaset을 3으로 설정해서 총 3개의 Pod가 생성되었는데

Worker node가 2개이므로 

각각 Worker Node one, two 에서 하나씩 생성되었고

나머지 하나는 생성될 worker node 가 없어서 pending 상태가 됨.

 

PodAffinity 설정으로 인해

tomcat pod 가 동작 중인 worker Node 에만 

mysql Pod가 배포됨.

 

 

 

3. tomcat Pod가 없는 상태에서 podAffinity설정된 Mysql Pod생성 

 

[결과]

PodAffinity 설정으로 인해

tomcat pod가 생성되어있는 Worker Node가 없음으로

어떠한 Worker Node 에도 

Mysql Pod 가 생성이 안됨.

 

 

 

 

 


 

 

 

Affinity의 Operator 설명

 

Operator는

Key / Value 를 어떠한 원리로 매칭 시킬것인가에 대한 설정으로

in, NotIn, Exists, DoesNotExist, Gt, Lt 설정이 올 수 있음

 

 

operator: In 

설정 중 1개라도 일치하면 매칭.

가장 많이 사용되는 operatoer 설정.

반드시 values 설정이 있어야함.

[ Operator 예제 ]

    affinity:         
        nodeAffinity: 
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions: 
              - key: requiredkey
                operator: In
                values: 
                - iksoonvalue1
                - iksoonvalue2
                - iksoonvalue3

상위 예제 yaml을 보면

values에 3개의 value가 있는데

In으로 설정하면

3개의 values 값 중 하나라도 매칭이 되면

Worker Node에 배포가 가능함.

[ 예시 ]

Worker Node 에 requiredkey=iksoonvalue1  Label만 있어도

정상 배포 됨.

 

 

operator: NotIn

설정 중 1개라도 일치하면 매칭 안됨.

Anti Affinity 설정으로 사용됨.

반드시 values 설정이 있어야함.

[ Operator 설명 예제 ]

    affinity:         

        nodeAffinity: 

          requiredDuringSchedulingIgnoredDuringExecution:

            nodeSelectorTerms:

            - matchExpressions: 

              - key: requiredkey

                operator: In

                values: 

                - iksoonvalue1

                - iksoonvalue2

                - iksoonvalue3

상위 예제 yaml을 보면

values에 3개의 value가 있는데

NotIn으로 설정하면

3개의 values 값 중 하나라도 매칭이 되면

Worker Node에 배포가 가능함.

[ 예시 ]

Worker Node 에 requiredkey=iksoonvalue1  Label만 있어도

배포가 안됨.

 

 

operator: Exists

명시한 모든 설정이 일치하면 매칭. (하나라도 없다면 매칭 안됨)

반드시 values 설정이 없어야함.

[ Operator 설명 예제 ]

    affinity:         

        nodeAffinity: 

          requiredDuringSchedulingIgnoredDuringExecution:

            nodeSelectorTerms:

            - matchExpressions: 

              - key: requiredkey

                key: preferredkey1

                key: preferredkey2

                operator: Exists          

key 값만 일치하면 매칭됨.

value 값 상관 없음. 

상위 예제를 보면 key만 있고 values는 없음

말그대로 동일한 Key만 존재하면 매칭됨.

 

상위 예제 yaml을 보면

3개의 key 값이 있는데

해당 3개의 key와 매칭되는 Label을 가진

worker node 에 배포가 됨.

1개라도 매칭이 안되면 배포 안됨.

 

(참고)

만약 " valuse: " 설정이 있는 상태에서 Exists Ehsms DoesNotExist를 사용하면

Forbidden: may not be specified when 'operator' is 'Exists' or 'DoesNotExists' 오류가 발생함.

 

 

operator: DoesNotExist

모든 설정이 일치하면 매칭 안됨. (하나라도 틀리면 매칭됨.)

반드시 values 설정이 없어야함.

[ Operator 설명 예제 ]

    affinity:         

        nodeAffinity: 

          requiredDuringSchedulingIgnoredDuringExecution:

            nodeSelectorTerms:

            - matchExpressions: 

              - key: requiredkey

                key: preferredkey1

                key: preferredkey2

                operator: DoesNotExists   

            

key 값만가지고 판단함.

value 값 상관 없음. 

상위 예제를 보면 key만 있고 values는 없음

말그대로 동일한 Key만 존재하면 매칭되지 않음.

 

상위 예제 yaml을 보면

3개의 key 값이 있는데

해당 3개의 key와 매칭되는 Label을 가진

worker node 에는 배포가 안됨

1개라도 매칭이 안되면 배포 됨.

 

 

operator: Gt

Greater than

반드시 value 가 하나 있어야하고

value는 정수값만 올 수 있음.

 

먼저 worker Node one 에

gtkey=200 Label 을 추가하고 진행.

[ Operator 설명 예제 ]

    affinity:         

        nodeAffinity: 

          requiredDuringSchedulingIgnoredDuringExecution:

            nodeSelectorTerms:

            - matchExpressions: 

              - key: gtkey

                values: ["100"] # Worker Node에 설정되어있는 gtKey value가 100보다 크면 생성

                operator: Gt

[Gt 특징]

해당 key Label이 있는 Worker Node에만 배포가 가능.

Worker Node에 설정되어있는 value가 affinity에 설정되어 있는 values보다 크면 배포.

Worker Node에 설정되어있는 value와 affinity에 설정되어 있는 values가 같으면 배포 안됨.

Key당 1개의 values 값만 비교 가능.

values 값이 많다면 가장 마지막 값으로 판단함. (이전 values값은 무시)

 

[ 예시 ]

Worker Node Label 설정이 gtkey=200 환경에서 

affinity values 설정이

100 이면 Running.

200 이면 Pending.

300 이면 Pending.

100, 300 이면 Pending.

300, 100 이면 Running.

 

 

operator: Lt

Less than

반드시 value 가 하나 있어야하고

value는 정수값만 올 수 있음.

 

먼저 worker Node one 에

gtkey=200 Label 을 추가하고 진행.

[ Operator 설명 예제 ]

    affinity:         

        nodeAffinity: 

          requiredDuringSchedulingIgnoredDuringExecution:

            nodeSelectorTerms:

            - matchExpressions: 

              - key: gtkey

                values: ["300"] # Worker Node에 설정되어있는 gtKey value가 300보다 작으면 생성

                operator: Lt

 

 

[Gt 특징]

해당 key Label이 있는 Worker Node에만 배포가 가능.

Worker Node에 설정되어있는 value가 affinity에 설정되어 있는 values보다 작으면 배포.

Worker Node에 설정되어있는 value와 affinity에 설정되어 있는 values가 같으면 배포 안됨.

Key당 1개의 values 값만 비교 가능.

values 값이 많다면 가장 마지막 값으로 판단함. (이전 values값은 무시)

 

[ 예시 ]

Worker Node Label 설정이 gtkey=200 환경에서 

affinity values 설정이

100 이면 Pending.

200 이면 Pending.

300 이면 Running.

100, 300 이면 Running.

300, 100 이면 Pending.

 

 

 

 


 

 

Preferred Affinity 의 weight 설명

 

1 ~ 100 사이의 값으로 설정 가능.

Worker Node 의 Preferred Affinity weight 값을 합해서

값이 높은 Worker Node를 가장 1순위로 선정해서

Pod를 배포함.

 

상황 예제

 

Worker Node One

Label 설정이

key1: value1

가 되어있고

 

Worker Node Two

Label 설정이

key2: value2

가 되어있고

 

Worker Node Three

Label 설정이

key1: value1

key2: value2

로 설정되어있음.

 

 

preferred Affinity 설정이 되어있는 Pod에서 

key1: value1 에 

weight를 10을 설정하고

 

Key2: value2에 

weight를 20을 설정했다면

 

해당 Pod 배포 시 우선 순위는

Worker Node Three weight 총합 = 30으로 1순위

Worker Node Two weight 총합 = 20으로 2순위

Worker Node one weight 총합 = 10으로 3순위

가 되어

Worker Node Three에 배포됨.

 

만약 

어떠한 Worker Node에도 

Label 설정이 안되어있다면

우선 순위가 동등하게 랜덤으로 배정됨.

 

 

 

 


제 글을 복사할 시 출처를 명시해주세요.
글에 오타, 오류가 있다면 댓글로 알려주세요! 바로 수정하겠습니다!


 

 

참고

 

[Affinity]

https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/

https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity

https://kublr.com/blog/implementing-advanced-scheduling-techniques-with-kubernetes/

https://bcho.tistory.com/1346?category=731548

 

 

반응형