ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kubernetes] PodDisruptionBudget 알아보기 (PDB)
    Kubernetes 2024. 1. 6. 06:38
    728x90
    반응형

     

    - 목차

     

    Pod Disruption 이란 ?

    Pod Disruption 은 Pod 가 종료되는 상황을 의미합니다.

    또한 시스템 상에서 Pod 가 종료되는 케이스를 크게 두가지로 나누는데요.

    Voluntary Disruption, Involuntary Disruption 으로 나눕니다.

    Voluntary Disruption 는 "자발적인 종료", "의위적인 종료", "의도적인 종료" 와 같이 해석할 수 있을 것 같습니다.

    반면 Involuntary Disruption 은 Voluntary Disruption 에 반대되는 의미를 가지며,

    시스템, 하드웨어 이슈 등에 의한 Pod 의 종료를 의미합니다.

    Node 가 실행되는 서버에 문제가 발생하여 Node 가 종료되고,  Node 위에서 실행되던 Pod 들은 Involuntary Disruption 상황에 직면합니다.

     

    PodDisruptionBudget 이란 ?

    PodDisruptionBudget 은 PDB 라고도 불리는데요.

    Pod 의 Voluntary Disruption 을 방어할 수 있는 수단으로 사용됩니다.

    일반적으로 Quorum 을 기반으로 동작하는 ZooKeeper 같은 어플리케이션들에게 PodDisruptionBudget 을 적용합니다.

    왜냐하면 정족수 기반의 결정을 해야하기 때문에 최소 홀수 이상의 ZooKeeper 들이 Running 상태를 유지해야하며,

    이를 위해 Voluntary Disruption 의 위험으로부터 보호합니다.

     

    PodDisruptionBudget 이 적용되는 상황은 다음과 같습니다.

     

    Drain Node 를 수행하는 경우.

    PodDisruptionBudget 이 적용된 ReplicaSet 이 존재한다고 가정하겠습니다.

    PodDisruptionBudget 의 minAvailable 이 2 이고, ReplicaSet 의 Pod 들이 각각 다른 Node 에 2개 존재합니다.

     

    아래 이미지와 같은 상황일 때에 Drain Node 1 또는 Drain Node 2 와 같은 명령어는 동작하지 않게 됩니다.

    왜냐하면 PodDisruptionBudget 의 minAvailable 값에 의해서 최소값을 유지하기 위해 Drain Node 명령어가 Block 됩니다.

     

     

     

     

    PodDisruptionBudget 구현해보기.

    로컬 환경에서 Kubernetes 를 구현하고, 간단한 실습을 진행해보겠습니다.

    아래 링크는 KinD 로 Kubernetes 를 구성하는 방법을 설명하는 사이트의 링크입니다.

    https://westlife0615.tistory.com/407

     

    KinD 알아보기.

    - 목차 소개. KinD 는 "카인드" 라고 발음되며, 로컬 머신에서 쿠버네티스를 간편하게 실행할 수 있는 도구입니다. KinD 는 Kubernetes in Docker 의 약자이구요. Docker 를 활용하여 쿠버네티스 환경을 구성

    westlife0615.tistory.com

     

    먼저 Kubernetest Cluster 를 구성합니다.

    cat <<EOF> /tmp/multinode_config.yaml
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
    - role: worker
    - role: worker
    - role: worker
    - role: worker
    - role: worker
    EOF
    kind create cluster \
    --name test-cluster \
    --image kindest/node:v1.24.0 \
    --config /tmp/multinode_config.yaml

     

    위 명령어들을 실행함으로써 아래 사진과 같이 Node 들이 구성됩니다.

     

     

    아래 YAML 파일은 주키퍼 앙상블을 구성하는 Yaml 파일인데요.

    아래 웹 링크의 페이지에서 발췌하여 약간 수정하였습니다.

     

    https://kubernetes.io/docs/tutorials/stateful-application/zookeeper/

     

    Running ZooKeeper, A Distributed System Coordinator

    This tutorial demonstrates running Apache Zookeeper on Kubernetes using StatefulSets, PodDisruptionBudgets, and PodAntiAffinity. Before you begin Before starting this tutorial, you should be familiar with the following Kubernetes concepts: Pods Cluster DNS

    kubernetes.io

     

    cat <<EOF> /tmp/zookeeper.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: zk-hs
      labels:
        app: zk
    spec:
      ports:
      - port: 2888
        name: server
      - port: 3888
        name: leader-election
      clusterIP: None
      selector:
        app: zk
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: zk-cs
      labels:
        app: zk
    spec:
      ports:
      - port: 2181
        name: client
      selector:
        app: zk
    ---
    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: zk-pdb
    spec:
      selector:
        matchLabels:
          app: zk
      minAvailable: 3
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: zk
    spec:
      selector:
        matchLabels:
          app: zk
      replicas: 3
      serviceName: zk-hs
      updateStrategy:
        type: RollingUpdate
      podManagementPolicy: OrderedReady
      template:
        metadata:
          labels:
            app: zk
        spec:
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - key: "app"
                        operator: In
                        values:
                        - zk
                  topologyKey: "kubernetes.io/hostname"
          containers:
          - name: kubernetes-zookeeper
            imagePullPolicy: Always
            image: "registry.k8s.io/kubernetes-zookeeper:1.0-3.4.10"
            resources:
              requests:
                memory: "1Gi"
                cpu: "0.5"
            ports:
            - containerPort: 2181
              name: client
            - containerPort: 2888
              name: server
            - containerPort: 3888
              name: leader-election
            command:
            - sh
            - -c
            - "start-zookeeper \
              --servers=3 \
              --data_dir=/var/lib/zookeeper/data \
              --data_log_dir=/var/lib/zookeeper/data/log \
              --conf_dir=/opt/zookeeper/conf \
              --client_port=2181 \
              --election_port=3888 \
              --server_port=2888 \
              --tick_time=2000 \
              --init_limit=10 \
              --sync_limit=5 \
              --heap=512M \
              --max_client_cnxns=60 \
              --snap_retain_count=3 \
              --purge_interval=12 \
              --max_session_timeout=40000 \
              --min_session_timeout=4000 \
              --log_level=INFO"
            readinessProbe:
              exec:
                command:
                - sh
                - -c
                - "zookeeper-ready 2181"
              initialDelaySeconds: 10
              timeoutSeconds: 5
            livenessProbe:
              exec:
                command:
                - sh
                - -c
                - "zookeeper-ready 2181"
              initialDelaySeconds: 10
              timeoutSeconds: 5
            volumeMounts:
            - name: datadir
              mountPath: /var/lib/zookeeper
          securityContext:
            runAsUser: 1000
            fsGroup: 1000
      volumeClaimTemplates:
      - metadata:
          name: datadir
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 1Gi
    EOF
    kubectl apply -f /tmp/zookeeper.yaml

     

     

    위 명령어가 실행되면 3개의 replicas 를 가지는 StatefulSet 이 생성됩니다.

    그리고 각 Pod 들은 서로 다른 Node 에서 동작합니다.

     

    PodDisruptionBudget 의 설정은 아래와 같습니다.

    최소 3개의 Pod 가 유지되어야하므로 어떠한 Volunraty Disruption 도 허용되지 않습니다.

     

     

    이 상황에서 Drain Node 를 수행해보도록 하겠습니다.

    아래의 출력 결과처럼 PodDisruptionBudget 에 의해서 Drain Node 명령어는 수행되지 않습니다.

     

    kubectl drain test-cluster-worker4 --ignore-daemonsets

     

    < Drain Node 출력 결과 >

    node/test-cluster-worker4 already cordoned
    Warning: ignoring DaemonSet-managed Pods: default/listener-operator-node-daemonset-kwhtw, default/secret-operator-daemonset-jq9zz, kube-system/kindnet-r7m66, kube-system/kube-proxy-669fw
    evicting pod default/zk-2
    error when evicting pods/"zk-2" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
    evicting pod default/zk-2
    error when evicting pods/"zk-2" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
    evicting pod default/zk-2
    error when evicting pods/"zk-2" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
    evicting pod default/zk-2
    error when evicting pods/"zk-2" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
    evicting pod default/zk-2
    error when evicting pods/"zk-2" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
    evicting pod default/zk-2
    error when evicting pods/"zk-2" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
    evicting pod default/zk-2
    error when evicting pods/"zk-2" -n "default" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.

     

     

    반응형
Designed by Tistory.