Kubernetes Pod 배치전략, Taint와 Toleration에 대해 이해하고 실습해보기

Bakumando·2022년 5월 29일
1

Kubernetes

목록 보기
17/17

들어가기에 앞서...


0. 블로깅 목적

  • Pod 배치전략 중 Taint와 Toleration에 대해 이해하고 실습한다.

1. Pod 배치전략 중 Taint에 대해 이해하고 실습한다.

1) Taint & Toleration?

  • Taint 얼룩이라는 뜻으로 Node에 설정한다.
    • Node에 Taint를 설정하여 임의의 Pod가 할당되는 것을 방지한다.
  • Toleration은 용인이라는 뜻으로 Pod에 설정한다.
    • 특정 Taint를 용인할 수 있는 Toleration 설정을 가진 Pod는 해당 Node에 할당 가능하다.
      => 즉, 이 2가지 전략은 함께 이해하고 사용할 수밖에 없는 개념이다.

  • 위 그림을 토대로 해석을 해보자.
    • 앞에 2개의 Nodedp taint로 무언가 설정 값을 준 것을 알 수 있다.
    • 이러면 일반적인 Pod 생성시에는 해당 앞의 2개의 Node에는 얼룩이 있어서 배치될 수가 없다.
    • 허나 만약 Pod 생성 조건으로 Node에 준 얼룩(taint) 값(position=low)과 동일한 용인(toleration) 값을 주면, 앞의 2개의 Node에도 배치가 가능하게 된다.

2) Node Taint를 관리하는 방법

  • Node를 새로 구성할 때 kubelet 옵션을 통해서 기본 Taint 설정도 가능하다.
  • 이미 실행 중인 Node에 대해서 kubectl을 통해 노드의 Taint 관리가 가능하다.
    • Taint는 Label 및 Annotation과 비슷하게 Key=Value형식을 가지지만, 추가적으로 Effect라는 파라미터를 가질 수 있다.
    • ex) Key=Value:Effect
  • Effect
    • Taint가 노드에 설정될 때 어떤 효과를 가지게 될지 설정하는 것이다. (적용될 효과를 정의!)
    • 3가지 종류가 있다.
      • NoSchedule
        • 그 Tainit Node에 Pod의 스케줄링을 허용하지 않음
        • 기존 실행 중인 Pod는 어쩔수 없고, 앞으로 실행될 Pod에 대해서만 스케쥴링 제한
      • NoExecute
        • 그 Tainit Node에 Pod의 실행을 허용하지 않음
        • 앞으로 생성 될 Pod에 대한 스케쥴링을 제한함은 물론, 기존에 해당 Node에 배치된 Pod 모두 방출
      • PreferNoSchedule
        • 그 Tainit Node에 Pod 스케줄링을 선호하지 않음
        • Soft룰이라 할수 있다.
        • 기존 실행 중인 Pod는 허용하고, 앞으로 생성될 Pod도 스케쥴링되는 것을 선호하진 않지만, 해당 Node 밖에 스케쥴링 될 곳이 없다면 허용해줌!
  • 예시
1. $ kubectl taint node minikube-m02 role=system:NoSchedule
2. $ kubectl taint node minikube-m02 role:NoSchedule-
3. $ kubectl taint node minikube-m02 role-
    1. minikube-m02 노드에 role=system:NoSchedule Taint 추가
    1. minikube-m02 노드에 role:NoSchedule Taint 제거
    1. minikube-m02 노드에 role 키를 가진 모든 Taint 제거

3) 다양한 Toleration 설정 방법

  • tolerations 아래애 key, value, operator, effect를 줌으로써 설정한다. (operator 설정값은 Equal, Exists가 있다.)
  • 바로 예시로 보면서 이해하자

tolerations:
- operator: Exists
  • 모든 종류의 Taint를 용인한다.

tolerations:
- key: role
  operator: Exists
  • 키가 role인 모든 Taint를 용인한다.

tolerations:
- key: role
  operator: Exists
  effect: NoExecute
  • 키가 role이고 effect가 NoExecute인 모든 Taint를 용인한다.

tolerations:
- key: role
  operator: Equal
  value: system
  effect: NoSchedule
  • role=system:NoSchedule Taint를 용인한다.


4) Taint & Toleration 실습

  • toleration 디렉토리를 만들고 진입한다.
  • sh 및 yml 파일들을 준비한다. (몇몇 yml은 filebeat 폴더를 만들고 그 안에 만든다.)

set-node-taints.sh

kubectl taint node minikube-m03 --overwrite role=system:NoSchedule
  • minikube-m03 노드에 대해서만 role=system:NoSchedule이라는 Taint를 주겠다는 sh 파일이다.

normal.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: normal
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      name: hello
      labels:
        app: hello
    spec:
      containers:
      - name: nginx
        image: nginxdemos/hello:plain-text
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
  • 어떤 배치전략도 적용되지 않은 노멀한 Deployment를 준비했다.

tolerated.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tolerated
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      name: hello
      labels:
        app: hello
    spec:
      containers:
      - name: nginx
        image: nginxdemos/hello:plain-text
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
      tolerations:
      - key: role
        operator: Equal
        value: system
        effect: NoSchedule
  • tolerations을 잘 정의하면 된다.
  • key가 role이고 value는 system, effect는 NoSchedule인 Node에 대해서, 이 yml이 생성할 Pod의 배치를 용인해준다.

filebeat/daemonset.yml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat
  namespace: default
  labels:
    app.kubernetes.io/name: filebeat
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: filebeat
  template:
    metadata:
      labels:
        app.kubernetes.io/name: filebeat
    spec:
      serviceAccountName: filebeat
      terminationGracePeriodSeconds: 30
      # hostNetwork: true
      # dnsPolicy: ClusterFirstWithHostNet
      containers:
      - name: filebeat
        image: docker.elastic.co/beats/filebeat:7.15.0
        args:
        # Log to `stderr` instead of `syslog` or `file`
        - "-e"
        env:
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        securityContext:
          runAsUser: 0
        resources: {}
          # We usually recommend not to specify default resources and to leave this as a conscious
          # choice for the user. This also increases chances charts run on environments with little
          # resources, such as Minikube. If you do want to specify resources, uncomment the following
          # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
          # requests:
          #   cpu: 100m
          #   memory: 128Mi
          # limits:
          #   memory: 256Mi
        ports:
        - name: internal-http
          containerPort: 5066
        livenessProbe:
          httpGet:
            path: /
            port: internal-http
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /
            port: internal-http
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 5
          failureThreshold: 3
        volumeMounts:
        - mountPath: /usr/share/filebeat/filebeat.yml
          readOnly: true
          name: config
          subPath: filebeat.yml
        - mountPath: /usr/share/filebeat/data
          name: data
        - mountPath: /var/lib/docker/containers
          readOnly: true
          name: varlibdockercontainers
        - mountPath: /var/log
          readOnly: true
          name: varlog
      volumes:
      - name: config
        configMap:
          name: filebeat-config
          defaultMode: 0640
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers
      - name: varlog
        hostPath:
          path: /var/log
      # data folder stores a registry of read status for all files, so we don't send everything again on a Filebeat pod restart
      - name: data
        hostPath:
          # When filebeat runs as non-root user, this directory needs to be writable by group (g+w).
          path: /var/lib/filebeat-data
          type: DirectoryOrCreate
      tolerations:
      - key: role
        operator: Exists
  • 맨 아래 보면 daemonset도 당연히 Pod 영역이 있기 때문에, toleration 설정이 가능하다는 걸 알 수 있다.
  • daemonset은 보통 모든 노드에 띄워지는 daemon을 실행할 때 쓰이기 때문에, toleration이 daemonset 주로 설정되는 편이다.
  • 즉, taint 설정이 된 몇몇 노드에 daemon이 실행안되면 안되기 때문에, 모든 노드에 적용되게 하기 위해 Exists로 operator를 줘서 전부 용인되게 한다.

filebeat/configmap.yml

apiVersion: v1
kind: ConfigMap
metadata:
  name: filebeat-config
  namespace: default
data:
  filebeat.yml: |
    filebeat.inputs:
    - type: container
      paths:
      - /var/log/containers/*.log
      processors:
      - add_kubernetes_metadata:
          host: ${NODE_NAME}
          matchers:
          - logs_path:
              logs_path: "/var/log/containers/"
    http:
      enabled: true
      host: 0.0.0.0
      port: 5066
    output.console:
      enabled: true
  • filebeat.yml이라는 파일을 configmap의 key로하고 내용을 value로 한 걸 볼 수 있다.
  • filebeat는 input과 output을 하게 된다.

filebeat/rbac.yml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: filebeat
  namespace: default
  labels:
    app.kubernetes.io/name: filebeat
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: filebeat
  labels:
    app.kubernetes.io/name: filebeat
rules:
# "" indicates the core API group
- apiGroups: [""]
  resources:
  - namespaces
  - nodes
  - pods
  - services
  verbs:
  - get
  - watch
  - list
- apiGroups: ["apps"]
  resources:
  - replicasets
  verbs:
  - get
  - watch
  - list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: filebeat
  labels:
    app.kubernetes.io/name: filebeat
subjects:
- kind: ServiceAccount
  name: filebeat
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: filebeat
  • 이거는 filebeat에 필요한 권한들을 주는 설정이라고 할 수 있다.

실습을 진행해보자.

  • toleration 디렉토리에서 실습을 진행한다.
  • 참고로 권한 문제가 발생하면 다음 커맨드를 입력한다.
    • chmod +x set-node-taints.sh

  • 우선 watch 모드 실행을 위해 2개의 터미널을 새로 띄운다.
  • watch kubectl get pod
    • 실습 중에 1번 watch 터미널이라고 하겠다.
    • Pod의 상태를 실시간으로 볼 수 있다. 아직 아무것도 존재하지 않는다.
  • watch kubectl get nodes
    • 실습 중에 2번 watch 터미널이라고 하겠다.
    • Node의 상태를 실시간으로 볼 수 있다.
    • 현재 node가 3종류 임을 알 수 있다. (minikube, minikube-m02, minikube-m03)

  • ./set-node-taints.sh
    • modified 되었다는 메시지가 나온다.
    • 이미 살펴본 커맨드이지만 다시 설명하자면, minikube-m03 노드에 대해서만 role=system:NoSchedule이라는 Taint를 주게 된다.

  • kubectl apply -f normal.yml
    • normla.yml을 apply한다.
    • minikube-m03 노드에 Taint가 있기 때문에 그 외의 노드에만 Pod의 배치가 이루어졌다.

  • kubectl apply -f tolerated.yml
    • 이제 toleration으로 minikube-m03 노드에 대한 용인도 이루어져 모든 Node에 고루 배치되는 결과가 나왔다.

  • kubectl apply -f .
    • filebeat와 관련된 모든 yml을 apply한다.
    • 모든 노드에 filebeat가 띄워진 것을 확인할 수 있다.
profile
그렇게 바쿠만도는 개발에 퐁당 빠지고 말았답니다.

0개의 댓글