EBS 파드가 Terminating에 남았을 때 확인할 것
노드가 죽었고 StatefulSet 파드는 Terminating에 남았습니다.
새 파드는 뜨지 않고 EBS 볼륨은 이전 노드에 붙어 있습니다.
데이터가 EBS에 살아 있으니 파드만 강제로 지우면 될 것 같지만, 여기서 가장 먼저 할 일은 삭제가 아닙니다.
기존 노드가 정말로 꺼졌는지 확인하는 일입니다.
네트워크만 끊긴 노드에서 프로세스가 여전히 쓰고 있는데 볼륨을 다른 노드에 붙이면 동시 쓰기와 데이터 손상으로 이어질 수 있습니다.
왜 StatefulSet 파드가 남아 있나
노드가 정상적으로 drain되면 kubelet이 파드를 종료하고 볼륨을 unmount합니다.
Attach/Detach controller는 기존 attachment가 정리된 뒤 같은 AZ의 새 노드에 볼륨을 붙입니다.
하드웨어 고장이나 OS hang에서는 kubelet이 이 절차를 끝내지 못합니다.
컨트롤 플레인은 노드와 통신할 수 없으므로 프로세스가 멈췄는지 확신할 수 없습니다.
StatefulSet은 같은 이름의 파드 두 개를 함부로 만들지 않습니다.
RWO 볼륨도 이전 attachment가 남은 동안 새 노드에 붙을 수 없습니다.
결과는 다음처럼 이어집니다.
Kubernetes의 Node Shutdown 문서 도 비정상 종료에서 StatefulSet 파드가 Terminating에 남고 VolumeAttachment가 삭제되지 않을 수 있다고 설명합니다.
이 동작은 느린 failover처럼 보이지만, 살아 있을지 모르는 writer로부터 데이터를 지키는 경계이기도 합니다.
계획된 교체와 급사는 다른 사건이다
두 사건을 같은 런북으로 다루면 위험합니다.
| 사건 | 노드 상태 | 일반적인 볼륨 경로 |
|---|---|---|
| 계획된 drain | kubelet 응답 가능 | unmount → detach → 새 노드 attach |
| 정상 재부팅 | 같은 노드가 돌아옴 | 기존 attachment와 볼륨 재사용 |
| OS hang·전원 상실 | kubelet 응답 불가 | 파드 종료와 detach 확인이 지연될 수 있음 |
| 네트워크 단절 | 프로세스가 계속 실행 중일 수 있음 | 강제 detach 시 동시 쓰기 위험 |
| AZ 장애 | 볼륨이 해당 AZ에 묶임 | 다른 AZ replica가 필요 |
EBS 볼륨은 같은 AZ의 새 노드에는 재부착할 수 있습니다.
다른 AZ로 직접 옮겨 붙일 수는 없습니다.
따라서 멀티 AZ 복제를 구성했다고 해도 장애 난 replica의 볼륨은 같은 AZ가 돌아오거나 그 AZ에 대체 노드가 생겨야 재사용할 수 있습니다.
먼저 상태를 모은다
파드 하나만 보지 말고 Node, Pod, PVC, PV, VolumeAttachment를 같은 시간에 봅니다.
kubectl get nodes -o wide
kubectl get pods -n clickhouse -o wide
kubectl get pvc -n clickhouse
kubectl get pv
kubectl get volumeattachment노드 이벤트와 조건을 확인합니다.
kubectl describe node <node-name>
kubectl describe pod <pod-name> -n clickhouse
kubectl get events -n clickhouse \
--sort-by=.metadata.creationTimestamp다음 신호를 구분합니다.
| 신호 | 의미 |
|---|---|
NotReady / Unknown | control plane이 kubelet 상태를 확인하지 못함 |
Terminating | 삭제 요청은 생겼지만 노드의 종료 처리가 끝나지 않았을 수 있음 |
Multi-Attach error | 이전 attachment가 남아 새 노드 attach가 막힘 |
VolumeAttachment가 이전 노드를 가리킴 | detach가 아직 완료되지 않음 |
| EC2 인스턴스가 running | 네트워크 단절·OS hang 가능성을 더 확인해야 함 |
| EC2 인스턴스가 stopped/terminated | 비정상 종료 복구 조건에 가까움 |
Kubernetes의 NotReady만으로 전원이 꺼졌다고 확정할 수 없습니다.
클라우드 인스턴스 상태, 시스템 관리 채널, 하이퍼바이저 신호 같은 외부 근거가 필요합니다.
파드 강제 삭제만으로 부족한 이유
kubectl delete pod --force는 API 객체를 빠르게 지울 수 있습니다.
하지만 이전 노드의 프로세스를 종료하거나 파일시스템을 unmount했다는 보장은 아닙니다.
VolumeAttachment 정리가 남으면 새 파드는 계속 attach에서 막힐 수 있습니다.
더 위험한 경우는 기존 프로세스가 살아 있는데 새 writer까지 시작하는 상황입니다.
그래서 파드 객체와 스토리지 attachment를 따로 봐야 합니다.
kubectl get volumeattachment \
-o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,PV:.spec.source.persistentVolumeName,ATTACHED:.status.attached해당 PV가 어느 노드에 연결됐다고 기록되는지 확인합니다.
AWS에서도 볼륨 상태와 attachment를 교차 확인할 수 있습니다.
aws ec2 describe-volumes \
--volume-ids <volume-id> \
--query 'Volumes[0].{State:State,AZ:AvailabilityZone,Attachments:Attachments}'out-of-service taint는 언제 쓰나
Kubernetes 1.28부터 non-graceful node shutdown 처리는 stable입니다.
종료된 노드에 node.kubernetes.io/out-of-service taint를 붙이면, 이를 tolerate하지 않는 파드를 강제 삭제하고 해당 파드의 볼륨 detach를 즉시 진행할 수 있습니다.
kubectl taint nodes <dead-node> \
node.kubernetes.io/out-of-service=nodeshutdown:NoExecute이 명령은 일반적인 “NotReady 노드 정리” 명령이 아닙니다.
공식 문서도 노드가 재부팅 중이 아니라 이미 shutdown 또는 power off 상태임을 먼저 확인하라고 명시합니다.
적용 조건을 체크리스트로 만들면 다음과 같습니다.
- 인스턴스가 실제로 중지 또는 종료됐다는 외부 근거가 있습니다.
- 단순 API server 연결 문제나 네트워크 partition이 아닙니다.
- 노드가 재부팅 중이며 곧 돌아올 상황이 아닙니다.
- 해당 볼륨을 사용하는 다른 프로세스가 기존 노드에서 실행 중이지 않습니다.
- 대체 파드가 배치될 같은 AZ에 노드 용량이 있습니다.
- 남은 ClickHouse replica가 서비스와 catch-up을 감당할 수 있습니다.
복구된 노드를 다시 쓸 때는 taint를 제거합니다.
kubectl taint nodes <dead-node> \
node.kubernetes.io/out-of-service=nodeshutdown:NoExecute-노드가 영구 폐기됐다면 리소스 정리 정책에 따라 Node 객체를 제거하는 경로를 검토합니다.
시간 숫자를 복구 상한으로 더하지 않는다
노드 monitor grace period, 기본 NoExecute toleration, force-detach timeout 같은 숫자가 보입니다.
이 값을 단순히 더해 “몇 분이면 반드시 복구된다”고 계산하면 안 됩니다.
클러스터 설정과 Kubernetes 버전, CSI 구현, 파드의 toleration, controller 상태에 따라 달라집니다.
공식 문서는 unhealthy node에서 파드 삭제가 6분 동안 성공하지 않으면 force detach할 수 있는 동작도 설명합니다.
동시에 기존 workload가 실제로 실행 중이면 CSI 계약 위반과 데이터 손상이 생길 수 있다고 경고합니다.
그래서 운영 목표는 타이머를 외우는 것이 아니라 각 구간을 측정하는 것입니다.
감지 → 노드 종료 판별 → 파드 정리 → 볼륨 detach
→ 같은 AZ 대체 노드 attach → ClickHouse 시작
→ part 로드 → replica delta catch-up → ReadyClickHouse는 재부착 뒤에도 바로 Ready가 아니다
EBS가 살아 있으면 로컬 NVMe처럼 모든 데이터를 다시 받을 필요는 없습니다.
그렇다고 attach 완료가 서비스 복구 완료는 아닙니다.
ClickHouse는 기존 part를 읽고 검증하며, 중단 중 생긴 변경분을 다른 replica에서 가져와야 합니다.
SELECT
database,
table,
is_readonly,
is_session_expired,
queue_size,
inserts_in_queue,
merges_in_queue,
absolute_delay,
total_replicas,
active_replicas
FROM system.replicas
ORDER BY absolute_delay DESC;replication queue의 반복 실패도 봅니다.
SELECT
database,
table,
type,
create_time,
num_tries,
last_exception
FROM system.replication_queue
WHERE num_tries > 0
ORDER BY create_time;active_replicas가 원래 RF로 돌아오고 queue와 delay가 안정화돼야 복구가 끝났다고 볼 수 있습니다.
PDB가 막아주는 범위
PDB는 Eviction API를 사용하는 계획된 중단에서 동시에 unavailable해질 파드 수를 제한합니다.
노드 급사, 전원 상실, AZ 장애를 막지 않습니다.
Kubernetes의 drain 문서 처럼 계획된 작업에서는 drain이 PDB와 graceful termination을 따릅니다.
급사 리허설은 별도로 해야 합니다.
| 리허설 | 확인할 것 |
|---|---|
| cordon + drain | PDB, graceful shutdown, 정상 detach |
| 인스턴스 stop | 노드 감지, 재부팅과 영구 소실 판별 |
| 강제 종료 | Terminating, VolumeAttachment, out-of-service 경로 |
| AZ 차단 가정 | 다른 AZ replica로 읽기·쓰기 지속 여부 |
런북의 시작은 판별이다
EBS 기반 ClickHouse의 장점은 볼륨이 살아 있으면 같은 AZ의 새 노드에 다시 붙일 수 있다는 것입니다.
그 장점을 얻으려다 기존 writer와 새 writer를 동시에 만드는 것이 가장 위험합니다.
따라서 런북의 첫 줄은 “파드를 지운다”가 아니라 다음 문장이어야 합니다.
노드가 정말로 꺼졌고 돌아오는 중이 아님을 두 개 이상의 독립 신호로 확인한다.
그다음에 out-of-service taint, detach, attach, ClickHouse catch-up 순서로 진행합니다.
복구 시간은 이 전체 경로를 staging에서 반복해서 재야 알 수 있습니다.
자료 확인 기준: 2026-09-15. 클러스터의 Kubernetes 버전, EBS CSI 드라이버, cloud-controller-manager 설정에 따라 세부 타이밍과 자동 처리 범위가 달라질 수 있습니다.