728x90
■ 쿠버네티스(Kubernetes) 중단 (Disruption)
- Pod는 일반적 상황에서는 중단되지 않음. 하지만 관리자 또는 컨트롤러의 명령으로 인한 제거 (자발적 중단) 또는 Pod가 동작하는 하드웨어적인 오류로 인한 Pod 중단(비자발적 중단)이 발생 할 수 있음.
■ 쿠버네티스(Kubernetes) 중단 (Disruption) 종류
- 비자발적 중단
- 노드를 지원하는 물리 머신의 하드웨어 오류
- 클러스터 관리자의 실수로 VM(인스턴스) 삭제
- 클라우드 공급자 또는 하이퍼바이저의 오류로 인한 VM 장애
- 커널 패닉
- 클러스터 네트워크 파티션의 발생으로 클러스터에서 노드가 사라짐
- 노드의 리소스 부족으로 파드가 축출됨
- 비자발적 중단은 Pod Disruption Budget(PDB)로 막을 수는 없지만 Budget은 차감 됨
- 자발적 중단 (애플리케이션 소유자 작업)
- 디플로이먼트 제거 또는 다른 파드를 관리하는 컨트롤러의 제거
- 재시작을 유발하는 디플로이먼트의 파드 템플릿 업데이트
- 파드를 직접 삭제
- 자발적 중단 (클러스터 소유자 작업)
- 복구 또는 업그레이드를 위한 노드 드레이닝 (노드 제거)
- 클러스터의 스케일 축소를 위한 노드 드레이닝
- 노드에 다른 무언가를 추가하기 위해 파드를 제거
- 해당 작업은 관리자의 직접 수행, 자동화를 통한 수행 또는 클러스터 호스팅 공급자에 의해서도 수행 될 수 있음
■ 쿠버네티스(Kubernetes) Pod Disruption Budget
- Pod의 자발적 중단이 빈번하게 발생하는 경우 Pod Discruption Budget(PDB)를 설정하여, 애플리케이션이 고가용성을 보장할 수 있도록 하는 기능이다.
- Pod Discruption Budget(PDB) 는 자발적 중단으로 일시에 중지되는 복제된 애플리케이션 Pod의 수를 제한하는 방식으로 고가용성을 보장함. 단, 노드의 리소스가 부족하여 kubelet이 노드의 자원을 회수하는 경우 PDB를 고려하지 않는다.
- 쿠버네티스에서는 관리자가 직접적으로 Pod 또는 디플로이먼트를 삭제하는 대신 Pod Discruption Budget(PDB) 를 준수하는 "Eviction API"를 사용을 권장 한다.
- 사용자가 "kubectl drain <node-name>" 명령어를 사용하게 되면 컨트롤러는 해당 노드의 모든 Pod를 축출하게 되며, 작업 과정에서 Pod 축출이 실패하게 될 경우 모든 Pod가 축출되거나 설정한 Timeout 시간이 될 때 까지 모든 실패된 요청을 다시 시도 하게 된다.
- "kubectl drain <node-name> --disable-eviction" 옵션을 사용하게 되면 PDB를 무시하게 되어 애플리케이션 가용성에 문제가 생길 수 있어, 해당 옵션의 사용은 신중히 사용해야 한다.
- "kubectl drain <node-name> --pod-selector="key=value" 옵션을 사용하게 되면 Pod의 Label값을 이용하여 중단할 Pod를 필터링하여 중단 할 수 있다.
- Eviction API을 사용할 경우 API 서버가 " Eviction " 객체를 생성하여 Pod를 graceful shutdown 시킨다. API를 사용하게 되면 PodDiscruptionBudget과 terminationGracePeriodSeconds 를 준수하여 Pod를 종료 시킨다.
-
# nginxTest1-eviction.json 생성 { "apiVersion": "policy/v1", "kind": "Eviction", "metadata": { "name": "nginxTest1", "namespace": "evpicapi" } } # API 서버에 요청 curl -v -H 'Content-type: application/json' https://<API_SERVER>/api/v1/namespaces/evpicapi/pods/nginxTest1/eviction \ -d @nginxTest1-eviction.json --------------------------- # 파이썬을 사용하여 다수의 Pod 삭제 import requests import json # 쿠버네티스 API 서버 엔드포인트 api_server = "https://<API_SERVER>" # Eviction 요청을 위한 헤더 headers = { 'Content-type': 'application/json', 'Authorization': 'Bearer <YOUR_ACCESS_TOKEN>' # cat /var/run/secrets/kubernetes.io/serviceaccount/token 토큰 확인 } # 제거할 파드 목록 pods = ["nginxTest1", "nginxTest2", "nginxTest3", "nginxTest4"] namespace = "evpicapi" for pod in pods: eviction = { "apiVersion": "policy/v1", "kind": "Eviction", "metadata": { "name": pod, "namespace": namespace } } url = f"{api_server}/api/v1/namespaces/{namespace}/pods/{pod}/eviction" response = requests.post(url, headers=headers, data=json.dumps(eviction)) if response.status_code == 200: print(f"Successfully evicted {pod}") else: print(f"Failed to evict {pod}: {response.status_code} - {response.text}")
- HTTP 200 OK: 정상적으로 요청을 받아서 Pod가 삭제 됨
- HTTP 429 Too Many Requests: PDB 설정으로 인해 Pod 삭제 요청이 허용 되지 않음.
- HTTP 500 Internal Server Error: 잘못된 설정(misconfiguration)으로 인해 추축 명령이 허용되지 않음.
-
■ 쿠버네티스(Kubernetes) Pod Disruption Budget 예시
- 전제 조건
- 가용 노드: 3개
- 수용 가능 Pod: 노드 당 2개의 Pod만 수용 가능
- 가용 Pod: 3개 (레플리카 설정)+ 1 (별도)
- Pod Disruption Budget: 2개
node-1 | node-2 | node-3 |
pod-a ( available ) | pod-b ( available ) | pod-c ( available ) |
pod-x ( available ) |
- kubectl drain node-1 명령을 통해 해당 node의 pod 축출 수행. 명령 즉시 kubectl 은 node-1에 있는 pod-a, pod-x 중지 시켜 terminating 상태로 전환
node-1 (draining) | node-2 | node-3 |
pod-a (terminating) | pod-b ( available ) | pod-c ( available ) |
pod-x (terminating) |
- Pod replica를 관리하는 디플로이먼트가 Pod가 중지된것을 확인 하고, 다른 노드에 Pod 생성. pod-a 다른 노드에 생성 되고 pod-x 역시 관리 주체에 의해 다른 노드에 생성 됨.
node-1 (drained) | node-2 | node-3 |
pod-b ( available ) | pod-c ( available ) | |
pod-d (starting) | pod-y ( available ) |
- pod-d가 완전한 가용 상태가 아닌 순간에 다시 drain 명령을 수행 하게 되면, PDB에 의해 drain 작업이 취소 됨. 현재 설정 된 PDB는 2개 이고, 가용 pod는 b, c 2개이기 때문이다.
node-1 (drained) | node-2 | node-3 |
pod-b ( available ) | pod-c ( available ) | |
pod-d ( available ) | pod-y |
- 해당 상태에서 다시 node-2를 비우기 위해 drain 명령을 수행하게 되면 pod-b / pod-d 중 하나를 축출하게 된다. 만약, pod-b가 축출 된 이후 pod-d를 축출 하려고 하면 디플로이먼트 설정에 의해 해당 명령은 거부 된다.
- 디플로이먼트에 의해 새로운 pod-e가 생성되고, 해당 pod를 스케줄하기 위한 충분한 리소스가 없기 때문에 축출 명령은 차단 되고 클러스터는 아래 상태로 종료 되게 된다. 해당 시점에서 노드를 추가하여 정상적으로 pod가 배포 된다.
node-1 (drained) | node-2 | node-3 | no node |
pod-b ( available ) | pod-c ( available ) | pod-e (pending) | |
pod-d ( available ) | pod-y |
728x90
'K8S' 카테고리의 다른 글
쿠버네티스(Kubernetes) 디플로이먼트 (Deployment) 롤백 & 상태 (0) | 2024.09.13 |
---|---|
쿠버네티스(Kubernetes) 디플로이먼트 (Deployment) 생성 및 업데이트 (2) | 2024.09.11 |
쿠버네티스(Kubernetes) NameSpace CPU 자원 할당 (1) | 2024.08.25 |
쿠버네티스(Kubernetes) NameSpace 메모리 자원 할당 (0) | 2024.08.25 |
쿠버네티스(Kubernetes) Pod Quality of Service (QoS) (0) | 2024.08.23 |