Kubernetes namespace의 phase가 Terminating에서 멈춰있을 때
원인, 해결책 분석
custom finalizer가 정리되지 않는 케이스
Namespace
.spec.finalizers
내용을 확인했을 때 배열에kubernetes
를 제외한 다른 element가 남아있다면 어떤 extension controller가 namespace를 초기화는 하고 정리는 못한 케이스.이 케이스는 우선 현재 클러스터에 namespace finalizer를 붙이는 controller가 무엇인가를 먼저 파악하고 수정해야한다.
kubernetes
finalizer가 정리되지 않는 케이스kubernetes
는 기본 finalizer로 namespace 내부의 모든 리소스가 정리되면 삭제된다. 그런데 이 finalizer가 삭제되지 않는다는 이야기는 리소스 정리 과정에서 에러가 발생했다는 이야기가 된다.따라서 우선 namespace에 진짜 모든 리소스가 삭제된건지 확인해봐야한다.
kubectl get all
의 경우 category all인 리소스들만 보여주므로 진짜로 모든 리소스를 보여주는게 아니다.kubectl api-resources --namespaced=true -o name
명령어로 체크해야될 모든 리소스의 이름을 확인할 수 있다. 확인 과정에서 삭제되지않고 있는 리소스가 있다면 그 리소스가 삭제되지 못하고 있는 이유를 확인해야한다. 보통은.metadata.finalizers
에 원인이 있을 가능성이 높다.위에서 확인해본 결과 모든 리소스가 삭제된게 맞다면 이번에는 admission webhook이나 extension api server 에서 에러가 발생했다는 이야기다. namespace가 삭제될 때 각 리소스를 삭제하기 위해서 보내는 요청은 delete가 아니라 delete-collection이므로 delete-collection에 대해서 제대로 처리했는지 다시 한번 확인해야한다.
참고로 namespace의 .spec.finalizers
는 sub resource이기 때문에 kubectl edit
또는 kubectl update
으로 수정되지 않는다. 따라서 curl 등을 통해서 직접 finalizers sub resources api를 호출해야 한다.
사용한 스크립트
모든 리소스 체크용 스크립트
#!/usr/bin/env bash
die() {
echo "$*" 1>&2
exit 1
}
need() {
command -v "$1" &>/dev/null || die "Binary '$1' is missing but required"
}
need "kubectl"
echo "------------------------------------------------"
echo "get all resources in namespace..."
echo "------------------------------------------------"
FOUND=""
NOT_FOUND=""
ERROR=""
RESOURCES=$(kubectl api-resources --namespaced=true -o name)
for resource in $RESOURCES; do
if [[ $resource =~ "metrics" ]]; then
continue
fi
found=$(kubectl get "$resource" 2>&1)
if [[ "$found" == "No resources found." ]]; then
echo "$resource: $found"
NOT_FOUND="$NOT_FOUND\n$resource"
elif [[ $found =~ "Error" ]]; then
echo "$resource: $found"
ERROR="$ERROR\n$resource"
else
printf ">> %s:\n%s" "$resource" "$found"
FOUND="$FOUND\n$resource"
fi
done
echo "------------------------------------------------"
echo "summary"
echo "------------------------------------------------"
printf ">> found: %b\n" "$FOUND"
echo "------------------------------------------------"
printf ">> not found: %b\n" "$NOT_FOUND"
echo "------------------------------------------------"
printf ">> error: %b\n" "$ERROR"
namespace finalizers 강제로 비우는 스크립트
#!/usr/bin/env bash
set -eo pipefail
die() {
echo "$*" 1>&2
exit 1
}
need() {
command -v "$1" &>/dev/null || die "Binary '$1' is missing but required"
}
need "jq"
need "curl"
need "kubectl"
TARGET_NAMEPSACE="$1"
TOKEN="$2"
API_SERVER=$(kubectl cluster-info | grep "Kubernetes master" | awk -F ' ' '{print $6}' | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g")
test -n "$TARGET_NAMEPSACE" || die "Missing arguments: $0 <namespace> <token>"
test -n "$TOKEN" || die die "Missing arguments: $0 <namespace> <token>"
test -n "$API_SERVER" || die "failed to get kubernets api address"
echo "trying to remove finalizers of namespace '$TARGET_NAMEPSACE'..."
kubectl get namespace "$TARGET_NAMEPSACE" -o json | \
jq 'del(.spec.finalizers[] | select("kubernetes"))' | \
curl -k -X PUT --insecure "$API_SERVER/api/v1/namespaces/$TARGET_NAMEPSACE/finalize" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
--data-binary @-
Last updated