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:

1kubectl get namespaces

Exemplo de saída indicando um namespace com problema:

1NAME             STATUS   AGE
2app-frontend      Active   2d
3app-backend       Active   2d
4old-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:

1kubectl get namespace old-namespace -o json

A saída pode conter algo semelhante a:

1"spec": {
2  "finalizers": [
3    "kubernetes"
4  ]
5}

📝 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:

1kubectl 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:

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

1kubectl edit namespace old-namespace

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

1kubectl 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:

1kubectl edit namespace old-namespace

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

1spec:
2  finalizers:
3    - 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:

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

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

1"finalizers": ["kubernetes"]

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

1kubectl 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:

1kubectl 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:

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

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

1chmod +x force-delete-namespace.sh

Agora, para remover um namespace preso, basta rodar:

1./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

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

Para PersistentVolumeClaims (PVCs)

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

Para Custom Resource Definitions (CRDs)

1kubectl get crd <NOME_DO_CRD> -o json
2kubectl 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 10 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

Notícias

Novo curso DevOps: Práticas de Continuos Monitoring na 4Linux

Será o nono curso ofertado na carreira DEVOPS. A mais abrangente oferta do Brasil. A 4linux anuncia hoje o lançamento de mais um curso para enriquecer a sua oferta de

Containers

Guia passo a passo: Instalação e uso do Minishift para desenvolvimento

O Minishift compõe uma versão simplificada do Openshift Origin. Pode ser instalado no VirtualBox e utilizado como ambiente de desenvolvimento. O objetivo deste artigo, é mostrar a instalação e uso dessa plataforma, até

DevOps

Guia completo: Como automatizar a coleta de dados na web com Python e Selenium

Muita gente na internet tem dúvida de como fazer robôs que buscam coisas em sites, baixam conteúdo ou simplesmente executam ações para testar alguma funcionalidade do site, sistema ou algo