Overview
Kubernetes를 사용하면서 유지 관리, 업데이트 또는 확장 작업과 같은 운영 요구 사항에 따라 Pod를 종료하고 재시작하는 일이 빈번하다.
따라서 Pod를 안전하게 종료하고 시작하는 방법에 대해서 알아본다.
Kubernetes Pod를 안전하게 종료
Kubernetes에서 Pod 종료는 유지 관리, 업데이트 또는 확장 작업과 같은 운영 요구 사항에 따라 여러 가지 방법으로 처리할 수 있다. 다음은 `cordon, uncordon, drain, scale` 과 같은 Kubernetes 명령을 사용하여 Pod 종료를 안전하게 관리하는 방법에 대해서 알아본다.
1. kubectl cordon 사용
`cordon` 명령은 노드를 예약할 수 없음으로 표시하여 새 파드가 노드에 예약되는 것을 방지하지만 기존 파드에는 영향을 미치지 않는다. 이는 유지 관리 또는 업그레이드를 위해 노드를 준비할 때 유용하다.
kubectl cordon <node-name>
2. kubectl uncordon 사용
`uncordon` 명령은 유지 관리 또는 업데이트가 완료된 후 노드를 다시 예약 가능으로 표시하는 데 사용된다. `cordon` 명령어의 반대의 명령어다.
kubectl uncordon <node-name>
3. kubectl Drain 사용
노드를 Drain 하려면 Kubernetes의 예약 정책을 준수하면서 노드에서 모든 파드를 안전하게 제거해야 한다. 이는 시스템 업그레이드 또는 종료를 수행하기 전에 매우 중요하다. 특히 상태 저장 애플리케이션(Stateful) 의 경우 실시간 트래픽과 영구 데이터를 신중하게 처리해야 한다.
kubectl drain <node-name> --ignore-daemonsets --delete-local-data
- `--ignore-daemonsets`: 배수 명령이 DaemonSet 관리형 파드를 무시할 수 있도록 허용한다.
- `--delete-local-data`: 영구 볼륨 없이 StatefulSet에서 관리하지 않는 파드를 삭제할 경우 경고한다.
4. kubectl scale 사용
배포, StatefulSet 또는 기타 확장 가능한 리소스를 확장하려면 scale 명령어를 사용하면 된다. 이렇게 하면 복제본 수를 0으로 효과적으로 줄여 배포 또는 StatefulSet에서 관리하는 모든 Pod를 종료할 수 있다.
kubectl scale --replicas=0 deployment <deployment-name> -n <namespace>
kubectl scale --replicas=0 statefulset <statefulset-name> -n <namespace>
StatefulSet 및 Stateless 배포에서 Pod 종료
Pod를 안전하게 종료하고 다시 실행하면 되는 작업에서는 Scale 명령어를 사용해서 Replica를 0으로 만들어주는게 일반적이다.
StatefulSet
Scale down progressively(점진적으로 축소) : StatefulSet에서 복제본 수를 줄이면 가장 높은 순서대로 시작하여 파드의 제어된 종료가 트리거된다. 이는 순서대로 종료해야 하는 응용 프로그램(예: 데이터베이스)에서 중요하다.
MariaDB Galera Cluster 를 예를들자면, 2 → 1 → 0 순차적으로 Scale 후에 종료해줘야 한다.
kubectl scale --replicas=2 sts app-db -n <namespace>
kubectl scale --replicas=1 sts app-db -n <namespace>
# 첫번째로 올라오는 app-db가 가장 최신 데이터임을 말해주는 safe_to_bootstrap을 0에서 1로 변경한다.
kubectl exec -ti -n <namespace> app-db-0 -- sed -i 's/safe_to_bootstrap: 0/safe_to_bootstrap: 1
/' /var/lib/mysql/grastate.dat
kubectl scale --replicas=0 sts app-db -n <namespace>
Stateless
Direct scaling or deletion(직접 확장 또는 삭제) : Stateless 애플리케이션은 내부 상태를 유지하지 않으므로 데이터 일관성에 대한 큰 걱정 없이 축소하거나 Pod를 삭제할 수 있다.
일반적인 Stateless 애플리케이션을 사용중이라면, 아래와 같이 replicas=0으로 바로 scale 해줄 수 있다.
kubectl scale --replicas=0 deploy api -n <namespace>
추가 고려사항
- Pod 중단 예산(PDB): 제거 프로세스 중에 최소한의 Pod가 계속 실행되도록 PDB를 정의한다.
- 단계적 종료: Pod 제거 중에 Kubernetes가 이러한 신호를 보낼 때 SIGTERM 신호를 처리하여 정상적으로 종료되도록 애플리케이션을 구성한다.
- 모니터링: 특히 확장 작업 및 노드 유지 관리 중에 애플리케이션의 상태와 성능을 항상 모니터링한다.
PDB(Pod Disruption Budget) 란?
Pod Disruption Budget(PDB)은 voluntary disruptions(자발적 중단) 중에 지정된 최소 수의 Pod를 사용할 수 있도록 보장하는 데 도움이 되는 Kubernetes 리소스이다. 이는 노드 유지 관리, 클러스터 업그레이드 또는 클러스터 관리자가 관리하는 기타 중단과 같이 Pod 가용성에 영향을 줄 수 있는 작업 중에 애플리케이션의 가용성과 복원력을 유지하는 데 특히 중요하다.
여기서 voluntary disruptions 에는 `cordon, uncordon, drain, scale` 모든 명령어가 포함된다. voluntary disruptions(자발적 중단)은 일반적으로 애플리케이션에 대한 영향을 최소화하는 시간에 제어하고 예약할 수 있는 계획된 작업이다. 이는 PDB에서 예측할 수 없고 관리할 수 없는 하드웨어 오류 또는 예기치 않은 노드 손실과 같은 involuntary disruptions(비자발적 중단)과는 다르다.
PDB 작동 방식
- MinAvailable : 중단 중에도 항상 작동해야 하는 최소 가용 파드 수이다.
- MaxUnavailable : 중단 중에 사용할 수 없는 최대 파드 수이다.
PDB는 voluntary disruptions(자발적 중단) 중에도 Kubernetes 시스템이 PDB에서 설정한 제한을 준수하여 애플리케이션 성능과 가용성에 큰 영향을 미치지 않도록 보장한다.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: my-app
- 라벨이 붙은 두 개 이상의 파드가 `app: my-app` 항상 작동 상태를 유지하도록 보장한다.
- 즉 DB가 Scale 되더라도 항상 2개는 유지한다는 것을 의미한다.
Node 및 Pod 업그레이드 및 유지보수
Node 및 Pod를 업그레이드 및 유지 보수를 할때는 `cordon, uncordon, drain` 명령어가 사용된다.
Drain
노드 유지 관리 또는 업그레이드 : 노드에서 유지 관리를 수행해야 할 때(패치, 업데이트 또는 하드웨어 교체 등) drainPDB를 존중하면서 노드에서 모든 파드를 안전하게 제거하는 데 사용된다. 워크로드가 갑자기 중단되지 않고 가능한 경우 다른 노드로 안전하게 이동되도록 한다.
Cordon & Uncordon
유지 관리를 위한 노드 준비 : 파드를 즉시 Evicted 하지 않고 유지보수를 위해 노드를 준비할 때 `cordon` 을 사용하여 노드를 예약 불가능으로 표시한다. 이는 노드에서 새로운 파드가 예약되는 것을 방지하지만 기존 파드에는 영향을 미치지 않는다.
노드를 서비스에 반환 : 유지보수가 끝나면 `uncordon` 을 사용하여 노드 예약 가능을 다시 표시하여 노드에서 파드를 예약할 수 있도록 한다.
정리
`kubectl drain` 명령에는 암시적으로 `cordon` 작업이 포함된다. 노드에서 `drain` 을 사용하면 Kubernetes는 먼저 노드를 예약할 수 없는 것으로 표시하여(cordon이 수행하는 작업) 해당 노드에 새 Pod가 예약되지 않도록 한다. 그런 다음 PDB(Pod Disruption Budget) 및 종료 유예 기간 준수 등 지정된 정책에 따라 노드에서 모든 Pod를 안전하게 제거한다.
kubectl Drain을 사용할 때의 일반적인 작업 흐름은 다음과 같다.
- 노드 차단: 새 파드가 예약되지 않도록 노드를 예약 불가능으로 자동 설정한다.
- Evicted Pods: 노드에서 모든 Pod를 안전하게 제거한다. DaemonSet에 의해 제어되는 Pod가 있으면 이동되지 않는다. 대신, DaemonSet가 이를 허용하도록 구성된 경우 삭제된다.
- 파드 종료 대기: 달리 지정하지 않는 한 이 명령은 명령줄을 해제하기 전에 모든 파드가 안전하게 종료될 때까지 기다린다.
즉, `drain` 또는 `cordon` 사용 이후 모두 유지 관리가 완료되고 노드가 클러스터에 다시 참여할 준비가 되면 `uncordon` 명령을 실행하여 노드를 다시 예약 가능하게 만들어야 한다.
Reference
'Container Orchestration > Kubernetes' 카테고리의 다른 글
Kubernetes Garbage Collection (0) | 2024.08.30 |
---|---|
Kubernetes 생태계 표준화와 Container Interface(CRI, CSI, CNI) (0) | 2024.07.15 |
Ingress Nginx란? (0) | 2024.07.04 |
Kubernetes Volumes 및 StorageClass: CSI 드라이버 사용 가이드 (0) | 2024.04.28 |
Kubernetes Affinity 및 Scheduling 설정 가이드 (0) | 2024.04.19 |