며칠 전 Kubernetes 클러스터를 정리하면서 필요 없는 네임스페이스 몇 개를 지우려고 했어요.kubectl delete ns
명령어로 삭제하자마자 응답이 오길래 잘 됐나보다 했죠. 근데 왠걸… kubectl get ns
해보니까 삭제하려던 네임스페이스가 계속 Terminating 상태로 남아있는 거예요.
처음엔 잠깐 기다리면 되겠지 했는데, 몇 분이 지나도, 심지어 몇 시간이 지나도 여전히 Terminating
… 뭔가 이상하단 느낌이 확 왔어요.
검색을 해보니 이 문제가 생각보다 흔하더라고요. 특히 네임스페이스 안에 있는
리소스 중 일부가 정상적으로 정리되지 않거나, 특정 Finalizer가 남아있는 경우 이런 현상이 발생한다고 해요.
그래서 직접 해결해봤어요. 꽤 삽질도 했지만… 결국 성공했죠! 이번 글에서는 Kubernetes에서 삭제되지 않고 Terminating 상태로 멈춰버린 네임스페이스를 강제로 삭제하는 실전 방법을 정리해볼게요.
네임스페이스 삭제 명령을 실행했는데도 Terminating 상태일 때
처음엔 평소처럼 아래 명령어로 삭제를 시도했어요:
kubectl delete namespace {네임스페이스명}

응답은 바로 왔고, 아무런 에러 메시지도 없었어요. 그런데 kubectl get ns
로 확인해보니까 상태가 Terminating에서 멈춰있더라구요.
이건 내부적으로 뭔가가 완전히 정리되지 않았다는 뜻이에요. 일반적으로 Finalizer가 문제를 일으키는 경우가 많아요. 리소스 정리 완료 전까지 네임스페이스 삭제를 막는 일종의 보호 장치라고 보시면 돼요.
네임스페이스 정보를 JSON으로 저장해서 확인해보기
먼저 아래 명령어로 현재 네임스페이스의 메타 정보를 JSON 파일로 저장했어요:
kubectl get namespace {네임스페이스명} -o json > ns.json
그다음 vi 에디터로 파일을 열어봤죠. 예상대로 spec.finalizers
안에 kubernetes
항목이 남아있었어요. 이 항목이 제거되지 않으면 네임스페이스 삭제가 끝나지 않아요.
Finalizer 항목을 제거하고 JSON을 수정
이제 핵심은 여기서부터예요. 아래처럼 spec
하위의 finalizers
값을 빈 배열로 바꿔줬어요:
"spec": {
"finalizers": []
}
수정한 파일을 저장하고 나면, Kubernetes API를 통해 강제로 이 JSON을 다시 서버에 반영해야 해요. 이 작업이 안 되면 삭제는 절대 끝나지 않아요.
kubectl proxy 실행하고 curl로 API 호출
수정한 JSON을 Kubernetes에 적용하기 위해선 먼저 kubectl proxy
를 백그라운드에서 띄워야 해요:
kubectl proxy &

그다음 아래 curl 명령어로 수정된 JSON 파일을 네임스페이스 리소스에 직접 PATCH하는 거예요:
curl -k -H "Content-Type: application/json" -X PUT --data-binary @ns.json \
http://127.0.0.1:8001/api/v1/namespaces/{네임스페이스명}/finalize
이 과정을 거치면 마침내 그 지긋지긋한 Terminating 상태가 사라지고 네임스페이스가 완전히 삭제돼요. 저도 마지막에 kubectl get ns
로 확인했을 때 목록에서 깔끔하게 사라진 걸 보고 속이 다 시원하더라구요.
Terminating 상태가 사라졌는지 확인하는 마지막 점검
curl 요청을 마친 후 다시 아래 명령어로 네임스페이스 상태를 확인해봤어요:
kubectl get ns

드디어! 삭제 요청했던 네임스페이스가 목록에서 사라졌고, 다른 네임스페이스들은 정상적인 Active
상태로 남아 있더라구요.
추가로 /api/v1/namespaces/{네임스페이스명}/finalize
에 대한 응답을 보면 status: Success
메시지와 함께, 모든 컨텐츠가 제거되고 finalizer까지 처리 완료되었다는 로그가 남아요. 예시 출력에서는 다음과 같은 JSON 응답을 확인할 수 있어요:
"type": "NamespaceFinalizersRemoved",
"status": "True",
"reason": "ContentDeleted",
"message": "All content successfully removed"
이 메시지를 보면 시스템 입장에서도 네임스페이스 제거가 최종 완료되었다는 뜻이에요. 이 단계까지 확인하면 안심하고 다른 작업으로 넘어갈 수 있죠.
왜 이런 일이 생길까?
Kubernetes는 리소스 삭제 시 데이터 정합성과 종속성 문제를 방지하기 위해 finalizer라는 보호 메커니즘을 사용해요. 문제는 일부 컨트롤러나 애드온이 이를 제대로 처리하지 못하고 중간에 끊겨버릴 때, 네임스페이스 전체가 Terminating 상태로 묶여버릴 수 있다는 점이죠.
특히 kubernetes
라는 기본 finalizer가 빠져나가지 못하면, 아무리 기다려도 네임스페이스는 삭제되지 않아요. 시스템 입장에서는 “아직 해야 할 일이 남아 있다”고 판단하는 거예요.
다음엔 어떻게 대비할까?
저는 이후부터는 네임스페이스를 삭제하기 전, 먼저 그 안의 리소스들을 kubectl delete all --all -n {네임스페이스}
명령어로 전부 지워주는 습관을 들였어요.
그리고 kubectl get namespace {이름} -o json
으로 finalizer 항목이 남아있는지도 체크하구요. 이 과정만 미리 해두면, 불필요한 Terminating 지옥은 대부분 피할 수 있어요.
자주 묻는 질문 (FAQ)
Q1. Kubernetes에서 네임스페이스가 계속 Terminating 상태로 남는 이유는 뭔가요?
A1. 보통 spec.finalizers
필드에 남은 항목들이 삭제 완료되지 않아 발생합니다. 특히 kubernetes
finalizer가 제거되지 않으면 네임스페이스는 완전히 삭제되지 않아요.
Q2. 단순히 기다리면 Terminating 상태가 풀리기도 하나요?
A2. 아주 드물게 리소스 정리가 오래 걸릴 경우 자동으로 완료되기도 하지만, 대부분의 경우 수동 개입 없이는 상태가 유지돼요. 수 시간이 지나도 그대로면 수동 정리가 필요합니다.
Q3. curl
명령으로 JSON을 다시 반영하는 방법이 위험하진 않나요?
A3. API를 직접 호출하는 방식이라 위험할 수 있지만, 네임스페이스에 최후의 수단으로 적용하는 것이므로 다른 리소스엔 영향이 없습니다. 단, 정확한 경로와 포맷을 사용하는 게 중요해요.
Q4. finalizers 필드가 비어있어도 Terminating 상태가 유지되는데 왜 그럴까요?
A4. 쿠버네티스 내부 컨트롤러의 sync 지연이나 API 서버 오류, 관련 리소스의 잔존 등 복합적인 이유가 있을 수 있어요. describe ns
명령어로 상태 메시지를 확인해보세요.
Q5. 네임스페이스 삭제 전 사전 점검해야 할 항목이 있을까요?
A5. 있습니다. 반드시 해당 네임스페이스 내 리소스 삭제, finalizers 존재 여부, 디스크나 API 통신 상태 등을 확인한 후 삭제를 시도해야 오류를 줄일 수 있어요.
Kubernetes 네임스페이스가 Terminating 상태일 때, 당황하지 말고 이렇게 해보세요
처음엔 단순한 네임스페이스 삭제 명령이었는데, 예상치 못한 Terminating
상태로 고생하면서 Kubernetes 내부 구조에 대해 다시 공부하게 되었어요. 특히 Finalizer라는 개념이 이렇게까지 중요한 줄은 몰랐죠.
요약해보자면,
- 삭제 중 멈춘 네임스페이스는 Finalizer가 원인일 확률이 높고,
- JSON을 수정한 뒤 Kubernetes API에 직접 반영해줘야 완전히 삭제돼요.
kubectl proxy
와curl
조합으로 안전하게 마무리하면 끝.
이 방법은 특히 운영 환경에서는 신중하게 써야 하긴 하지만, 정말 급할 땐 꼭 필요한 솔루션이에요.
제 팁을 하나 드리자면, 네임스페이스를 지우기 전에 그 안의 리소스를 전부 수동 삭제하거나 Helm으로 생성된 리소스는 helm uninstall
로 먼저 정리하는 습관을 들이면 이런 문제를 사전에 막을 수 있어요.
혹시 여러분도 비슷한 상황 겪으셨다면 댓글로 공유해주세요. 다음엔 “Finalizer 커스텀 리소스 처리법”이나 “Kubernetes 리소스 정리 루틴”도 다뤄볼게요.