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 coffee