티스토리 뷰

DevOps/kubernetes

kubernetes Taint & Toleration

김한성 2021. 4. 8. 17:53

먼저 해당 기능을 사용하게 된 이유는 master node에 pod가 스케줄링 되지 않게 NodeAffinity 옵션을 사용하였는데도 계속 master node에 pod가 스케줄링 되는 상황을 직면하였습니다. 사용한 NodeAffinity 속성은 다음과 같습니다.

 

아래의 속성에 관련된 Affinity 속성을 간단하게 정리해보았습니다.

 

□ Affinity

 

라벨링 기반의 스케줄링은 단순히 키 값이 같은지만을 비교해서 노드를 할당하기 때문에 활용 방법이 비교적 제한되어 있습니다. nodeSelector 대비 더 유연한 표현식으로 Node를 지정하고 싶을때 affinity나 inter pod affinity를 이용하면 됩니다. 위의 Taints가 Pod가 배포되지 못하도록 하는 정책이라면, affinity는 Pod를 특정 Node에 배포되도록 하는 정책입니다.

 

□ NodeAffinity

 

requiredDuringSchedulingIgnoredDuringExecution 

 

preferredDuringSchedulingIgnoredDuringExecution

 

requiredDuringSchedulingRequiredDuringExecution 

 

preferredDuringSchedulingRequiredDuringExecution

 

required(hard affinity) & preferred(soft affinity)는 반드시 포함해야 하는지 또는 우선시하되 필수는 아닌지를 결정하는 조건입니다. 파란색으로 표시된 부분 Ignored & Required는 운영 중(Runtime) Node의 Label이 변경되면 무시할 것인지(Ignore) 또는 즉시 Eviction 처리(Required)하여 재기동을 수행할 것인지를 결정합니다.

 

아래의 affinity속성에 대해 간단히 말하자면, nodeSelectorTerms 부분에 matchExpressions을 사용하여 label set-based selector 문법을 이용하여 아래같이 작성하면 되며, requiredDuringSchedulingIgnoredDuringExecution의 경우 아래 요구조건이 일치하는 node에 적용하겠다는 의미로 matchExpressions로 정의 된 key 값이 label의 [key], values 값이 label의 [value]와 일치해야 합니다. 여기서 operator라는 항목이 있는데 nodeAffinity에서 사용할 수 있는 operator에는 NotIn 외에도 In, Exists, DoesNotExist, Gt, Lt 등을 활용할 수 있습니다.

      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: node-role.kubernetes.io/master
                    operator: NotIn
                    values:
                      - 'true'

본론으로 다시 돌아와서 아래의 노드1(master1) 정보를 확인해보니 label에 node-role.kubernetes.io/master= 라는 라벨이 들어가있지만 value값이 없어서 적용이 안된거 같습니다. value가 있든 없든 위의 옵션에서 values에 true를 넣어주면 적용되게 하라고 작성한거 같은데, master node로 pod가 스케줄링 되는게 확인되었으므로 위의 내용은 잘못된 것이라고 판단되었습니다.

[admin@hskim-bastion ~]$ kc describe node node1
Name:               node1
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=node1
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    projectcalico.org/IPv4Address: 192.168.100.161/24
                    projectcalico.org/IPv4IPIPTunnelAddr: 172.18.154.0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Wed, 07 Apr 2021 10:46:10 +0900
Taints:             <none>

하지만, kubernetes 클러스터를 구성하면 위의처럼 Taints에 none이 아니라, 기본적으로 NoSchedule 옵션이 들어가있지만 왜 안들어가있나 확인해봤더니, 현재 kubernetes 클러스터를 구성할때 kubespary를 사용하여 구성했습니다. https://github.com/kubernetes-sigs/kubespray

해당 github 내용을 바탕으로 구성을 진행하면서 hosts.yaml에 아래와 같이 kube node에 master를 포함한 모든 node를 넣어서 Taints가 추가가 안되고 master node포함하지말고 worker node만 넣어서 구성을 하게 되면 master node에 Taints가 정상정으로 추가된다고 합니다 (회사 팀원분이 알려주심)

더보기

all:
  hosts:
    node1:
      ansible_host: 192.168.100.161
      ip: 192.168.100.161
      access_ip: 192.168.100.161
    node2:
      ansible_host: 192.168.100.162
      ip: 192.168.100.162
      access_ip: 192.168.100.162
    node3:
      ansible_host: 192.168.100.163
      ip: 192.168.100.163
      access_ip: 192.168.100.163
    node4:
      ansible_host: 192.168.100.164
      ip: 192.168.100.164
      access_ip: 192.168.100.164
    node5:
      ansible_host: 192.168.100.165
      ip: 192.168.100.165
      access_ip: 192.168.100.165
    node6:
      ansible_host: 192.168.100.166
      ip: 192.168.100.166
      access_ip: 192.168.100.166
  children:
    kube_control_plane:
      hosts:
        node1:
        node2:
        node3:
    kube-node:
      hosts:
        node1:
        node2:
        node3:
        node4:
        node5:
        node6:
    etcd:
      hosts:
        node1:
        node2:
        node3:
    k8s-cluster:
      children:
        kube_control_plane:
        kube-node:
    calico-rr:
      hosts: {}

따라서, master1 노드에 node-role.kubernetes.io/master= 해당 label에 적절한 values값을 추가하고 위의 nodeAffinity속성에서 values값을 변경해주면 정상적으로 master node에는 배포되지 않을꺼라고 생각합니다.

 

하지만, kubernetes에서 Taint & Toleration 옵션도 있어서 공부도 할겸 해당 옵션으로 master node에 pod가 스케줄링 되지 않도록 구성해봤습니다.

 

Taint & Toleration 옵션 설명

 

Taint & Toleration

  • taint: 노드마다 설정가능하며 설정한 노드에는 pod가 스케줄되지 않습니다.
  • toleration: taint를 무시하고 pod에 설정하면 해당 규칙대로 pod 스케줄링 가능

Taint Options

  • NoSchedule: toleration이 없으면 pod가 스케줄되지 않습니다. 단, 기존 실행되는 pod에는 적용 안됩니다.
  • PreferNoSchedule: toleration이 없으면 pod를 스케줄링안하려고 합니다.

따라서 현재 master 1,2,3를 사용하고 있으므로 아래처럼 master 노드에 적용시켰습니다.

[admin@hskim-bastion ~]$ kubectl taint node node1 node=no:NoSchedule
node/node1 tainted
[admin@hskim-bastion ~]$ kubectl taint node node2 node=no:NoSchedule
node/node2 tainted
[admin@hskim-bastion ~]$ kubectl taint node node3 node=no:NoSchedule
node/node3 tainted

아래처럼 Taints에 옵션 잘 들어가는 것을 확인하였습니다.

[admin@hskim-bastion ~]$ kc describe node node1
Name:               node1
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=node1
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    projectcalico.org/IPv4Address: 192.168.100.161/24
                    projectcalico.org/IPv4IPIPTunnelAddr: 172.18.154.0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Wed, 07 Apr 2021 10:46:10 +0900
Taints:             node=no:NoSchedule

이제 실제로 daemonset으로 테스트를 진행해보겠습니다, 원래 옵션이 적용안되었다면 모든 노드에 하나씩 떠야하지만 아래처럼 worker 노드에만 스케줄링 되는걸 확인할 수 있습니다.

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: cirrus-test
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: k8s.gcr.io/fluentd-elasticsearch:1.20
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
[admin@hskim-bastion test]$ kc get -n cirrus-test all
NAME                              READY   STATUS    RESTARTS   AGE
pod/fluentd-elasticsearch-9295h   1/1     Running   0          57s
pod/fluentd-elasticsearch-nvfzq   1/1     Running   0          57s
pod/fluentd-elasticsearch-w6kcz   1/1     Running   0          57s

 

 Taint해제 뒤에 "-" 추가

kubectl taint nodes {해제할 노드 이름} key=value:NoSchedule- 
댓글
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30