Mateus Müller

O carinha do Linux

17 mar. 2024

Como descobrir qual node não tem recursos para um pod de DaemonSet

Hey hey! Ressucitando o blog das cinzas, mas vambora.

Você já aplicou um DaemonSet em um cluster Kubernetes e viu um (ou alguns) pod no status de Pending?

fluentd-fsrxk                    1/1     Running            1 (4m58s ago)   65m
fluentd-jt6wc                    1/1     Running            1 (14m ago)     65m
fluentd-prrbj                    0/1     Pending            0               65m

Veja o pod fluentd-prrbj acima.

Geralmente a primeira ação é dar um describe para verificar a mensagem do evento que é mais verbosa em termos de detalhes.

$ kubectl describe pod <pod> -n <namespace>

Ao final do output, você verá uma mensagem similar à essa aqui:

message: '0/7 nodes are available: 1 Insufficient memory. preemption: 0/7 nodes
      are available: 7 No preemption victims found for incoming pod..'

O que podemos concluir é: O requests de memória do pod acima é maior do que o que está disponível no node.

E aí você fica tipo… Tá, mas qual o Node? rsrs.

Durante o scheduling dos pods do tipo DaemonSet, o DaemonSet controller injeta diretivas de NodeAffinity para cada Node do cluster. Ou seja, se você extrair o manifesto do pod aplicado no cluster, verá a qual Node ele foi assignado.

Sugiro fortemente a leitura dessa parte da documentação oficial para entender:

Eu fiz uma “reza” aqui para extrair essa informação like a boss. Você só vai precisar do jq instalado na sua máquina.

(⎈|homelab:logging)┌─[mateus@pop-os] - [~] - [Thu Mar 14, 09:39]
└─[$] <> kubectl get pod fluentd-9qhcq -ojson | jq -r '.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchFields[].values | join("")' 
k8s-worker-3

Agora eu sei que o Node é o k8s-worker-3. Com isso basta dar um describe no Node para entender porque o consumo de memória está alto, e reschedular alguns pods se necessário.

Unindo o útil ao agradável, eu deixei o comando acima mais “bonito” para usar no dia a dia, até porque certamente eu não vou lembrar da sintaxe rsrs.

Basta você editar o seu .zshrc ou .bashrc, seja qual for o Shell que esteja utilizando no dia a dia.

$ vim ~/.zshrc

Ao final do arquivo, você pode configurar o seguinte:

function find_node() {
        local pod="$1"
        local namespace="${2:-$(kubectl config view --minify --output 'jsonpath={..namespace}')}"

        kubectl get pod "$pod" \
                -n "$namespace" \
                -ojson |\
                jq -r '.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[].matchFields[].values | join("")'
}

E aí basta reabrir o terminal, ou iniciar uma nova sessão do Shell para ele fazer o load dessa função na sessão atual.

Uma função básica que aceita dois parâmetros: pod e namespace. Se a namespace não for informada (segundo parâmetro), ele vai pegar a namespace da sessão atual do kubectl.

Então basta rodar o seguinte:

(⎈|homelab:logging)┌─[mateus@pop-os] - [~] - [Sun Mar 17, 13:44]
└─[$] <> find_node fluentd-9qhcq
k8s-worker-3

ou

(⎈|homelab:logging)┌─[mateus@pop-os] - [~] - [Sun Mar 17, 13:44]
└─[$] <> find_node fluentd-9qhcq logging
k8s-worker-3

Quando é um cluster pequeno, é fácil saber o Node. Mas conforme o tamanho do cluster e quantidade de Nodes escala, fica inviável olhar um por um. Com essa “reza” aí fica barbada e podemos tomar uma ação reativa mais rápido.

Espero que ajude! Grande abraço.

Buy me a coffeeBuy me a coffee
Comentários Disqus