nayoungs
항상 끈기있게
nayoungs
  • 분류 전체보기 (274)
    • Cloud (21)
      • AWS (15)
      • Azure (3)
      • NCP (2)
      • GCP (1)
    • DevOps (68)
      • Docker (16)
      • Kubernetes (50)
      • CICD (2)
    • IaC (25)
      • Ansible (17)
      • Terraform (8)
    • Certification (4)
    • 금융 IT (5)
    • AI (3)
    • Linux (47)
    • 미들웨어 (5)
    • Programming (7)
      • GoLang (3)
      • Spring (4)
    • CS (25)
      • 네트워크 (17)
      • 운영체제 (5)
      • Web (1)
      • 개발 상식 (2)
      • 데이터베이스 (0)
    • Algorithm (59)
      • 프로그래머스 (36)
      • 백준 (18)
      • 알고리즘 정리 (5)
    • ETC (5)

블로그 메뉴

  • 홈
  • 방명록

공지사항

인기 글

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
nayoungs

항상 끈기있게

DevOps/Kubernetes

[Kubernetes] k8s 어피니티(Affinity)와 안티-어피니티(Anti-Affinity)

2022. 5. 26. 19:43
728x90

어피니티(Affinity)란, 개념적으로 nodeSelector와 유사한 것으로,

노드의 레이블을 기반으로 파드를 스케줄할 수 있는 노드를 제한할 수 있다.

 

https://kimjingo.tistory.com/145

 

Affinity 종류와 대상

Node

  • nodeAffinity

Pod

  • podAffinity
  • podAntiAffinity

 

🔹 Node Affinity

pod.spec.affinity.nodeAffinity

 

Node Affinity는 Node 레이블을 기준으로 새로운 Pod가 특정 Worker Node로 배포되도록 Scheduling한다.

 

preferredDuringSchedulingIgnoredDuringExecution Pod를 조건에 따라 노드에 배포하려고 시도는 하지만 보증할 수 없다는 것을 의미한다. (Soft)
requiredDuringSchedulingIgnoredDuringExecution Pod가 노드에 스케줄 되도록 반드시 규칙을 만족해야 하는 것을 의미한다. (Hard)

 

preferredDuringSchedulingIgnoredDuringExecution

  • preference
  • weight : 1-100사이의 가중치를 부여한다.

 

requiredDuringSchedulingIgnoredDuringExecution

  • nodeSelectorTerms
    • matchExpressions
      • operater : In, NotIn, Exists, DoesNotExist
    • matchFeilds

 

nodeSelector 와 nodeAffinity 를 모두 지정한다면,

파드가 후보 노드에 스케줄되기 위해서는 둘 다 반드시 만족해야 한다.



🔹 Pod Affinity & Pod AntiAffinity

pod.spec.affinity.podAffinity

pod.spec.affinity.podAntiAffinity

 

기존에 실행 중인 Pod를 참고하여 새로운 Pod가 Worker Node로 배포되도록 Scheduling한다.

 

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

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

 

기본적으로 Pod Affinity와 Pod AntiAffinity의 구조는 동일하다.

 

preferredDuringSchedulingIgnoredDuringExecution Pod를 조건에 따라 노드에 배포하려고 시도는 하지만 보증할 수 없다는 것을 의미한다. (Soft)
requiredDuringSchedulingIgnoredDuringExecution Pod가 노드에 스케줄 되도록 반드시 규칙을 만족해야 하는 것을 의미한다. (Hard)

 

preferredDuringSchedulingIgnoredDuringExecution

  • podAffinityTerm
    • labelSelector : 레이블을 매칭한다.
    • namespaceSelector : 네임스페이스를 매칭한다.
    • namespaces : 네임스페이스를 매칭한다.
    • topologyKey : 노드의 레이블을 참조
      • 키를 기준으로 같은 노드에 구성(co-located) 또는 분리(not co-located)
      • 노드 어피니티에는 없는 필드로, 파드의 어피니티, 안티어피니에만 존재한다.
  • weight : 1~100 사이의 가중치를 부여한다.

requiredDuringSchedulingIgnoredDuringExecution

  • labelSelector
  • namespaceSelector
  • namespaces
  • topologyKey (required)

 

 

 

자주 사용되는 시나리오

같은 컨트롤러로 만들어진 파드는 서로 anti-affinity 설정하여 같은 노드에 배치되지 못하도록하고,

Web과 DB는 affinity로 설정하여, 같은 노드에 배치되도록한다.



💻 실습 : Affinity 실습

현재 node1, node2, node3에 gpu 레이블이 설정된 상태이다.

$ kubectl get nodes -L gpu        
NAME    STATUS                     ROLES                  AGE     VERSION   GPU
node1   Ready                      control-plane,master   9d      v1.22.8   highend
node2   Ready,SchedulingDisabled   <none>                 9d      v1.22.8   lowend
node3   Ready                      <none>                 7d10h   v1.22.8   lowend

다음과 같이 gpu key를 가진 node에 배치되도록 설정하는 nodeAffinity와

자기 자신을 배척하기 위한 podAntiAffinity가 설정된 ReplicaSet을 작성한다.

myweb-a.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myweb-a
spec:
  replicas: 2
  selector:
    matchLabels:
      app: a
  template:
    metadata:
      labels:
        app: a
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 10 #가중치는 여러개 있을 때 의미가 있어진다.
              preference:
                matchExpressions:
                  - key: gpu
                    operator: Exists
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                 matchLabels:
                   app: a #자기 자신을 배척
              topologyKey: "kubernetes.io/hostname" #호스트명을 기준으로 분리
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb

마찬가지로 자신을 배척하고, gpu 키를 가진 노드에 배치되도록하며,

app:a 레이블을 가진 파드와 같이 배치되도록하는 ReplicaSet을 다음과 같이 작성한다.

myweb-b.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myweb-b
spec:
  replicas: 2
  selector:
    matchLabels:
      app: b
  template:
    metadata:
      labels:
        app: b
    spec:
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 10
              preference:
                matchExpressions:
                  - key: gpu
                    operator: Exists
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                 matchLabels:
                   app: b #자기 자신을 배척
              topologyKey: "kubernetes.io/hostname"
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                 matchLabels:
                   app: a #a와 같이 배치되도록
              topologyKey: "kubernetes.io/hostname"
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb

myweb-a는 자기 자신을 배척하기 때문에

(node1,node2) 또는 (node2,node3) 또는 (node1,node3)에 배치되어야한다.

$ kubectl create -f myweb-a.yaml   
replicaset.apps/myweb-a created

(node2,node3)에 배치된 것을 확인할 수 있다.

$ kubectl get po -o wide        
NAME                                      READY   STATUS    RESTARTS        AGE   IP              NODE    NOMINATED NODE   READINESS GATES
myweb-a-m8s9p                             1/1     Running   0               11s   10.233.96.27    node2   <none>           <none>
myweb-a-pwxl2                             1/1     Running   0               11s   10.233.92.175   node3   <none>           <none>
$ kubectl create -f myweb-b.yaml
replicaset.apps/myweb-b created

myweb-b는 자기 자신을 배척하기 때문에

(node1,node2) 또는 (node2,node3) 또는 (node1,node3)에 배치되어야하고,

app:a 레이블의 podAffinity가 있기 때문에,

myweb-a가 있는 (node2, node3)에만 배치되는 것을 확인할 수 있다.

$ kubectl get po -o wide        
NAME                                      READY   STATUS    RESTARTS        AGE   IP              NODE    NOMINATED NODE   READINESS GATES
myweb-a-m8s9p                             1/1     Running   0               11s   10.233.96.27    node2   <none>           <none>
myweb-a-pwxl2                             1/1     Running   0               11s   10.233.92.175   node3   <none>           <none>
myweb-b-84ltx                             1/1     Running   0               5s    10.233.96.26    node2   <none>           <none>
myweb-b-qj89t                             1/1     Running   0               5s    10.233.92.174   node3   <none>           <none>





참고

더보기
  • https://ikcoo.tistory.com/89
  • https://velog.io/@hoonki/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EB%85%B8%EB%93%9C%EC%97%90-%ED%8C%8C%EB%93%9C%EB%A5%BC-%ED%95%A0%EB%8B%B9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-nodeSelector-affinity

 

 

 

728x90
저작자표시 비영리 (새창열림)
    'DevOps/Kubernetes' 카테고리의 다른 글
    • [Kubernetes] k8s Taint와 Toleration
    • [Kubernetes] k8s Cordon과 Drain
    • [Kubernetes] Pod Scheduling : nodeName, nodeSelector
    • [Kubernetes] HPA(Horizontal Pod Autoscaling)란?
    nayoungs
    nayoungs
    안되면 될 때까지

    티스토리툴바