Como Resolver Recursos Presos em ‘Terminating’ no Kubernetes

Como Resolver Recursos Presos em ‘Terminating’ no Kubernetes

 

Gerenciar clusters Kubernetes é sempre um trabalho árduo, e dentre os processos de gestão é comum precisar excluir objetos ou recursos que não são mais necessários.

Quem faz esta gerência sabe o quão frustrante pode ser encontrar recursos que permanecem presos no estado Terminating indefinidamente, impedindo sua remoção. Isso pode acontecer com diversos tipos de recursos, como Namespaces, Pods, PersistentVolumeClaims (PVCs) e Custom Resource Definitions (CRDs).

O motivo deste problema é porque geralmente ocorre devido à presença de finalizadores (finalizers), que são mecanismos do Kubernetes que garantem que determinadas operações sejam concluídas antes que o recurso seja excluído.

Neste post, abordaremos como resolver esse problema para qualquer recurso do Kubernetes e utilizaremos Namespaces como exemplo prático.

🔍 Entendendo o Problema

Quando um recurso do Kubernetes é excluído, o cluster inicia um processo de limpeza e o recurso ganhará uma flag de Finalizer. Ele deve ser processado antes que o Kubernetes conclua a exclusão, no entanto, se o controlador responsável pelo Finalizer não puder executá-lo, o recurso permanecerá indefinidamente no estado Terminating.

Esse problema pode ocorrer em diferentes contextos, por exemplo:

  • Um Pod que depende de um PersistentVolumeClaim que ainda está em uso.
  • Um Namespace que contém recursos órfãos impedindo a remoção.
  • Um Custom Resource Definition (CRD) que não pode ser removido porque um controlador não processou sua finalização.

 ⚠️ ATENÇÃO!!

A remoção manual de Finalizers pode ser uma solução eficaz para desbloquear recursos presos em Terminating, porém não é considerada uma BOA PRÁTICA para o gerenciamento de clusters Kubernetes. Essa ação deve ser utilizada com cautela, pois pode gerar problemas secundários, dependendo do tipo de recurso e do seu controlador.

Quais Riscos ao Remover Finalizers Manualmente?

Há inúmeros riscos ao realizar esta ação sem analisar o contexto desta falha, podemos listar alguns:

  1. Perda de Processamento do Controlador: Finalizers existem para garantir que processos específicos sejam concluídos antes da remoção do recurso. Ao removê-los manualmente, você pode impedir a execução dessas etapas, o que pode causar:
    • Volumes não desmontados corretamente (PVCs).
    • Falha na liberação de IPs, cargas de trabalho e sessões de rede (Pods).
    • Remoção inconsistente de objetos filhos em CRDs.
  2. Referências Órfãs e Consistência do Cluster: Alguns controladores do Kubernetes dependem de Finalizers para limpar estados internos ou atualizar referências antes da remoção do recurso. A remoção manual pode resultar em:
    • Entradas inválidas em bancos de dados de estados (etcd).
    • Recursos órfãos que nunca serão completamente excluídos.
    • Problemas na reconciliação de objetos por controladores que esperavam processar o Finalizer.
  3. Impacto em Aplicações e Serviços: No caso de Finalizers aplicados a Namespaces, a remoção pode fazer com que serviços ainda em execução dentro do namespace sejam encerrados abruptamente, potencialmente corrompendo aplicações dependentes.

🛠️ Solução: Removendo Finalizers Manualmente

A solução para este problema é relativamente fácil, podemos editar o recurso diretamente e remover os Finalizers.

Vamos exemplificar com um Namespace, mas essa abordagem pode ser aplicada a outros recursos.

🔎 Identificando o Namespace Preso

Primeiro, liste todos os namespaces no cluster e veja quais estão no estado Terminating:

kubectl get namespaces

Exemplo de saída indicando um namespace com problema:

NAME             STATUS   AGE
app-frontend      Active   2d
app-backend       Active   2d
old-namespace  Terminating 10h

O namespace old-namespace está no estado Terminating há 10 horas, o que indica um possível problema.

Para verificar, use o comando:

kubectl get namespace old-namespace -o json

A saída pode conter algo semelhante a:

"spec": {
  "finalizers": [
    "kubernetes" 
  ]
}

📝 Verificar Objetos Existentes Dentro do Namespace

Antes de forçar a remoção do namespace, é importante verificar se existem recursos pendentes dentro dele. Use os comandos abaixo para listar os objetos dentro do namespace problemático:

kubectl get all -n old-namespace
Isso mostrará os pods, serviços, deployments e outros recursos dentro do namespace.

Caso ainda existam recursos ativos, tente deletá-los manualmente:

kubectl delete all --all -n old-namespace
Há recursos de Persistent Volume Claims (PVCs) que podem estar impedindo a exclusão, liste e remova-os:
kubectl get pvc -n old-namespace
kubectl delete pvc --all -n old-namespace
Verifique também se há NetworkPolicies que podem estar bloqueando a comunicação:
kubectl get networkpolicy -n old-namespace
kubectl delete networkpolicy --all -n old-namespace

Se todos os recursos forem removidos e o namespace ainda estiver em Terminating, vá para a próxima etapa.

🧹 Removendo o Finalizer

Para remover manualmente os Finalizers, edite o recurso e remova a seção finalizers:

kubectl edit namespace old-namespace

Apague a seção finalizers e salve o arquivo. Se preferir uma abordagem mais direta, utilize:

kubectl patch namespace old-namespace -p '{"metadata":{"finalizers":[]}}' --type=merge

Após isso, o Kubernetes concluirá a exclusão do Namespace.

 📝 Editar Diretamente o Namespace

Você pode editar diretamente o objeto do namespace e realizar a alteração do finalizers, para isso faça os passos abaixo:

kubectl edit namespace old-namespace

No editor, localize e remova a seção:

spec:
  finalizers:
    - kubernetes

Salve e saia do editor, o editor mais comum é o vim e para salvar e sair basta pressionar ‘Esc’ e depois digite: :wq! ou 😡 . Se o namespace ainda não for removido, use a abordagem forçada abaixo.

💀 Remover Finalizadores e Forçar a Exclusão do Namespace

Se a remoção manual não funcionar, há uma abordagem mais hardcore que você poderá executar:

kubectl get namespace old-namespace -o json > namespace.json

Abra o arquivo `namespace.json` e remova a linha que contém:

"finalizers": ["kubernetes"]

Agora, execute o comando abaixo para atualizar o namespace diretamente na API do Kubernetes:

kubectl replace --raw "/api/v1/namespaces/old-namespace/finalize" -f namespace.json

Isso removerá o finalizador e permitirá que o namespace seja excluído corretamente.

Para confirmar a remoção, execute:

kubectl get namespaces
O namespace old-namespace não deve mais aparecer na lista.

🔥 Prática DevOps: Automatizando a Remoção de Namespaces Presos

Se esse problema for recorrente em seu cluster, você pode criar um script Bash para automatizar a remoção de finalizadores de namespaces que estão presos no estado Terminating.

Crie um arquivo chamado force-delete-namespace.sh e adicione o seguinte código:

#!/bin/bash
NAMESPACE=$1
kubectl get namespace $NAMESPACE -o json | jq 'del(.spec.finalizers)' > temp.json
kubectl replace --raw "/api/v1/namespaces/$NAMESPACE/finalize" -f temp.json
rm -f temp.json

Dê permissão de execução ao script:

chmod +x force-delete-namespace.sh

Agora, para remover um namespace preso, basta rodar:

./force-delete-namespace.sh old-namespace

Isso automatiza o processo e pode ser útil em ambientes onde a remoção de namespaces presos ocorre com frequência.

🔄 Aplicação para Outros Recursos

Essa mesma abordagem pode ser aplicada para outros tipos de recursos presos em Terminating. Basta identificar o recurso e seguir os mesmos passos:

Para Pods

kubectl get pod <NOME_DO_POD> -o json
kubectl patch pod <NOME_DO_POD> -p '{"metadata":{"finalizers":[]}}' --type=merge

Para PersistentVolumeClaims (PVCs)

kubectl get pvc <NOME_DO_PVC> -o json
kubectl patch pvc <NOME_DO_PVC> -p '{"metadata":{"finalizers":[]}}' --type=merge

Para Custom Resource Definitions (CRDs)

kubectl get crd <NOME_DO_CRD> -o json
kubectl patch crd <NOME_DO_CRD> -p '{"metadata":{"finalizers":[]}}' --type=merge

🚀 Conclusão

Recursos presos em Terminating são um problema comum no Kubernetes e podem afetar diferentes tipos de objetos. Ao entender como remover manualmente os Finalizers, conseguimos desbloquear a exclusão de qualquer recurso problemático.

Mas lembrando, a remoção de Finalizers pode parecer uma solução rápida, mas pode trazer riscos ao cluster. A melhor abordagem é investigar o problema antes de remover um Finalizer manualmente.

Se for realmente necessário fazer, garanta que você compreenda o impacto e tenha um plano de mitigação. O mais importante: documente a intervenção pois a remoção manual pode ter consequências futuras.

A remoção manual de Finalizers deve ser tratada como último recurso e apenas quando:

  1. O controlador responsável não pode ser restaurado (exemplo: foi desinstalado acidentalmente).
  2. O recurso em questão está bloqueando operações críticas no cluster.
  3. Você já investigou dependências e não há impacto na remoção forçada.

Essa técnica é essencial para manter um ambiente Kubernetes saudável e sem resíduos de recursos desnecessários! 🚀

 

Anterior Kubernetes Gateway API - um "adeus e obrigado" ao Ingress Controller
Próxima Índices são sempre bons?

About author

Jeovany Batista
Jeovany Batista 9 posts

Formado em Segurança da Informação, trabalha com tecnologia há 11 anos, atualmente é Analista de Infraestrutura e Monitoramento na 4Linux, nas horas vagas se aventura na culinária e nos games. Entusiasta em opensource tools e no momento curtindo a distro OpenSuse!

View all posts by this author →

Você pode gostar também

DevOps

Guia definitivo: Como criar e implementar pipelines com Jenkins

O que é o Jenkins ? Jenkins é uma ferramenta de auxilio a construção de pipelines de construção de software. Com ele podemos automatizar toda as etapas de compilação e

DevOps

Terraform e Gitlab-CI: Como gerenciar sua infraestrutura em nuvem

Introdução O Terraform é uma ótima ferramenta para fazer o gerenciamento de sua infraestrutura em nuvem, normalmente iniciamos projetos de terraform rodando os principais comandos de construção e deleção de

Desenvolvimento

Introdução ao Robot Framework: Ferramenta para Testes Automatizados

Hoje, no blog da 4Linux, vamos falar sobre Robot Framework, uma ferramenta voltada para testes automatizados. O objetivo é fazer uma séries de posts até a criação de uma pipeline