AOC55

Cloud, Devops, Backend, Kubernetes, Openstack, ...

Cloud/kubernetes (k8s)

k8s :: PodDisruptionBudget (PDB)과 Disruption (#2)

aoc55.soft@gmail.com 2025. 10. 18. 23:23
개인적으로 공부하는 관점에서 작성한 내용이라, 잘못된 부분이 있을 수 있습니다. 발견 시 말씀주시면 감사하겠습니다.

 

이전편: https://aoc55.tistory.com/77

PodDisruptionBudget (PDB)

PDB가 어떠한 상황에 필요한지 먼저 알아보았으니, 이제 PDB에 대해 좀더 알아보자.

PodDisruptionBudget 선언 예시

아래는 PDB를 선언하는 예시 YAML 파일이다.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: rabbitmq-disruption-budget
  namespace: openstack
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: openstack

다시 한번 PDB를 한줄로 정의하면 "Cluster 위에서 실행되는 워크로드가, 빈번하게 발생하는 자발적인 중단에 대해서 HA(highly availablity)를 보장하기 위한 도구"라고 정의할 수 있을 것 같다.

Eviction API 와 PDB

만약 특정 워크로드에 대해 PDB를 선언한 경우, Node Drain 등에 의해 발생하는 Evicition API 요청에 대해, 위와 같이 선언한 PDB와 현재 상태에 따라서 Pod Evcition이 허용되거나 거부되는 구조이다. 즉, PDB는 Evcition API와 연관성이 있다.

좀 더 예시를 들어보면, 서비스 특성 상 최소한 개수(혹은 퍼센테이지)를 보장해줘야 하는 Pod들이 있는데, 이때 PDB 선언을 통해 클러스터 관리자가 Node Drain을 통해 Eviction 을 하더라도, 워크로드 서비스 관점에서 이를 방어(?)하여 서비스가 살아 있을 수 있도록 하는 것이다.

그리고 PDB는 Node drain 등이 사용하는 "Eviction API"와 상관이 있는 것이기 때문에, Eviction API 기반이 아닌 Pod Delete 등이 PDB 에 의해 거절되거나 하지는 않는다.

즉, 어떻게 보면 PDB는 Eviction을 제어하는 정책이라고도 볼 수 있다.

Restart(Rolling Update) 와 PodDisruptionBudget 간의 관계

앞에서 Pod Delete(ex. kubectl delete pod ...) 등의 경우에는 PDB의 영향을 받지 않는다고 말하였다. 그러면 Statefulset/Deployment와 같은 컨트롤러 기반의 리소스들의 Restart는 PDB와 어떠한 관계가 있을까?

결론적으로 Depoyments/Statuefulset 의 Restart 역시도 PDB가 Restart를 막는 구조는 아니다. 즉, PDB로 설정한다 하더라도 컨트롤러의 롤링 업데이트를 막거나 할 수는 없다. 해당 Rolling Update에 대한 전략은 PDB가 아닌 Deployements, Statefulset에 선언된 대로 철저히 수행이 된다. (ex. spec.strategy.rollingUpdate.maxUnavailable, spec.strategy.rollingUpdate.maxSurge, ...)

왜인지 생각해보면 Controller가 있는 Resource 들의 Rolling Update 방식은, 새로 Controller를 생성해서 관련 리소스를 Create 한 뒤 => 이전 컨트롤러에 매핑된 리소스를 Delete 하는 구조이다. 즉, Evcition API 방식이 아니다. (이전 Node Drain과 는 다른 방식이다.)

다만, 그래도 Contoller에 의해 Restart 과정에서 발생하는 Pod 종료 등에 대해서는 PDB 설정 내역에 "Counting(반영)"은 된다. 따라서 만약 Restart 과정에서 동시에 node drain 이 요청 온다던가 하는 경우에 "Counting 등이 반영된 PDB"에 의해 Eviction API에 대한 '거절 및 방지' 역할은 할 수 있다.

간단한 PodDisruptionBudget 동작 시나리오

상세한 시나리오는 공식문서 내 https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#pdb-example 에서 참고하자.

아주 간단한 시나리오를 살펴보자.

사전 전제사항으로 Node 별로 Pod가 1개씩 배치되어 있고, PDB 설정에 maxUnavailable:1 로 설정되어 있는 상태이다.

node1
- pod-a-1

node2
- pod-a-2

node3
- pod-a-3

---
now Unavailable:0

이후 node1 에 대해서 node drain 을 수행하게 되면, node1에 있던 pod-a-1이 다른 Node에 배치될 것이다. 그리고 이 과정중에서는 Unavailable: 1 로 증가하게 된다.

이때 (node1에서 Eviction 된) Pod가 다른 Node에서 기동이 완료되기 이전에, 또 다른 node에 대해 바로 Eviction 을 수행하게 되면?

node1 (drain)

node2 <----- Drain(Eviction) 시도
- pod-a-2

node3
- pod-a-3 
- pod-a-4 (아직 기동중)

---
now Unavailable:1

이때 node3로 대피한 Pod가 기동이 완료지 않음으로 아직 Unavailable: 1 인 상태이고, 이는 곧 사전 설정된 PDB (maxUnavailable:1) 에 의해, node2에 대한 Evcition은 거절된다!

물론 node3 에서 Pod 생성이 완료 되고 이에 따라 maxUnavailable: 0으로 내려간 뒤, 다시 node2에 대해 drain 을 요청하면 성공할 수 있다.

node1 (drain)

node2 (drain)

node3
- pod-a-3
- pod-a-4 
- pod-a-5
---
now Unavailable:0

"Role" 과 PodDisruptionBudget ?

PDB와 관련해서 kubernetes 공식 문서에서는 PDB가 실제 Role 간의 '인터페이스'로 동작한다고 적어놨다.

이게 무슨 의미인가 하니, 대부분 클러스터에서 워크로드가 실행되는 경우 "워크로드 관리자"와 "클러스터가 관리자"가 각각의 Role로 나누어져 있는 경우가 보통이다.

그리고 이 상태에서 클러스터 관리자가 클러스터 관리를 위한 작업(ex. Node의 버전 업그레이드 등을 위한 Node drain 수행)을 진행하다고 할때, 워크로드 관리자는 서비스에 PDB를 적절하게 선언하는 방식을 통해 앞서 말한 클러스터 관리자의 작업(ex. Node Drain)이 임의적으로 수행되는 것을 방지할 수도 있다.

즉, "클러스터 관리의 영역"과 "워크로드 서비스 관리의 영역"에 대해서 PDB 선언을 통해서 인터페이스화(?) 하였다는 의미이다.

끝.