Agendar Pods do Kubernetes em Nós Específicos

KubernetesBeginner
Pratique Agora

Introdução

Normalmente, o scheduler escolhe qualquer nó que possa executar o Pod. Os rótulos e as regras de afinidade expressam as preferências da carga de trabalho, enquanto os taints permitem que os nós rejeitem Pods sem as tolerations correspondentes.

Você aplicará esses mecanismos progressivamente ao nó preparado e usará os eventos dos Pods para diferenciar uma regra de agendamento rígida de uma preferência flexível.

Use este modelo mental: os rótulos descrevem os nós, os seletores e as regras de afinidade expressam o que um Pod deseja, os taints indicam o que um nó rejeita e as tolerations permitem que um Pod passe por uma regra de rejeição correspondente. Nenhum desses mecanismos “move” diretamente um Pod que já esteja em execução.

Rotular o Nó para a Alocação

Nesta etapa, adicione rótulos descritivos e exiba-os como colunas.

Os rótulos foram escolhidos intencionalmente para representar a alocação da carga de trabalho, e não a identidade da aplicação. workload-zone=local representa a localização, enquanto disk-class=fast representa uma capacidade. O Kubernetes não valida o significado desses valores no contexto do negócio; são as suas regras de agendamento que lhes atribuem significado.

cd /home/labex/project/pod-scheduling
kubectl create namespace practice-scheduling
kubectl label node labex-v135 workload-zone=local disk-class=fast
kubectl get nodes -L workload-zone,disk-class

Os rótulos são informações usadas por seletores e regras de afinidade; eles não movem automaticamente os Pods existentes, a menos que um controlador crie substitutos.

A opção -L adiciona uma coluna para cada chave de rótulo. Ver local e fast na linha do nó confirma que o scheduler poderá avaliar as regras usadas nas etapas seguintes.

NAME         STATUS   ROLES           ...   VERSION   WORKLOAD-ZONE   DISK-CLASS
labex-v135   Ready    control-plane   ...   v1.35.5   local           fast

Isso também confirma que o ambiente atualizado está executando o Kubernetes v1.35.5. As duas colunas personalizadas vêm dos rótulos que você acabou de adicionar.

Exigir um Nó com nodeSelector

Nesta etapa, crie um Pod com a regra de alocação exata mais simples.

nodeSelector é um mapa de correspondências obrigatórias por igualdade. O Pod só poderá ser executado em um nó no qual cada chave tenha o valor solicitado. Essa opção é adequada para uma alocação simples e obrigatória.

cd /home/labex/project/pod-scheduling
cat <<'EOF' > selected-pod.yaml
apiVersion: v1
kind: Pod
metadata: {name: selected-pod, namespace: practice-scheduling}
spec:
  nodeSelector: {disk-class: fast}
  containers:
    - {name: worker, image: busybox:1.36, imagePullPolicy: IfNotPresent, command: ["sh", "-c", "while true; do sleep 30; done"]}
EOF

Aplique o Pod, aguarde até que esteja pronto e verifique o nó atribuído na coluna NODE:

kubectl apply -f selected-pod.yaml
kubectl wait --for=condition=Ready pod/selected-pod -n practice-scheduling --timeout=120s
kubectl get pod selected-pod -n practice-scheduling -o wide

nodeSelector é obrigatório: o Pod permanece no estado Pending quando nenhum nó possui todos os rótulos solicitados.

O nó selecionado deve ser labex-v135. O sucesso do agendamento comprova que disk-class=fast no Node correspondeu ao requisito do Pod.

pod/selected-pod condition met
NAME           READY   STATUS    ...   NODE
selected-pod   1/1     Running   ...   labex-v135

A coluna NODE mostra o resultado do agendamento; o nodeSelector no manifesto é o motivo pelo qual esse nó era elegível.

Comparar Afinidade Obrigatória e Preferencial

Nesta etapa, crie um Pod que exija a zona local e dê preferência a um disco rápido.

A afinidade de nós é mais expressiva do que nodeSelector. A seção obrigatória elimina os nós que não correspondem aos critérios; a seção preferencial atribui um peso aos nós correspondentes, mas não torna essa preferência obrigatória.

Os nomes longos dos campos descrevem quando a regra é aplicada: ela é avaliada durante o agendamento e ignorada durante a execução. Se um rótulo for alterado posteriormente, o Kubernetes não expulsará o Pod em execução apenas por causa dessa regra de afinidade.

cd /home/labex/project/pod-scheduling
cat <<'EOF' > affinity-pod.yaml
apiVersion: v1
kind: Pod
metadata: {name: affinity-pod, namespace: practice-scheduling}
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions: [{key: workload-zone, operator: In, values: [local]}]
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          preference:
            matchExpressions: [{key: disk-class, operator: In, values: [fast]}]
  containers:
    - {name: worker, image: busybox:1.36, imagePullPolicy: IfNotPresent, command: ["sh", "-c", "while true; do sleep 30; done"]}
EOF

Aplique o Pod e aguarde o agendamento:

kubectl apply -f affinity-pod.yaml
kubectl wait --for=condition=Ready pod/affinity-pod -n practice-scheduling --timeout=120s
kubectl get pod affinity-pod -n practice-scheduling -o wide

As regras obrigatórias filtram os nós viáveis; as regras preferenciais atribuem uma pontuação aos nós restantes. IgnoredDuringExecution significa que alterações posteriores nos rótulos não expulsam um Pod em execução.

A tabela resultante também deve indicar labex-v135. Neste cluster de um único nó, a regra obrigatória workload-zone=local determina a viabilidade; a regra preferencial para disco rápido demonstra a sintaxe de pontuação sem exigir a criação de um segundo nó apenas para comparação.

Usar um Taint e uma Toleration

Nesta etapa, aplique um taint ao nó, observe um Pod sem toleration permanecer no estado Pending e, em seguida, crie um Pod autorizado.

O taint possui a chave practice-reserved, o valor true e o efeito NoSchedule. Esse efeito impede a criação de novos Pods sem uma toleration correspondente, mas não expulsa os Pods que já estão em execução no nó.

kubectl taint node NODE key=value:effect associa essa regra a um nó. O comando kubectl run a seguir cria um Pod independente sem toleration, e a espera pela condição PodScheduled dá ao scheduler dez segundos, no máximo, para demonstrar a falha esperada.

cd /home/labex/project/pod-scheduling
kubectl taint node labex-v135 practice-reserved=true:NoSchedule
kubectl run blocked-pod -n practice-scheduling --image=busybox:1.36 --image-pull-policy=IfNotPresent --restart=Never -- sh -c 'sleep 3600'
kubectl wait --for=condition=PodScheduled pod/blocked-pod -n practice-scheduling --timeout=10s || true
kubectl events -n practice-scheduling --for pod/blocked-pod

O tempo limite da espera é esperado, e || true permite que a lição continue. O evento de agendamento deve mencionar um taint sem toleration, fornecendo evidências do motivo pelo qual o Pod permanece no estado Pending.

error: timed out waiting for the condition on pods/blocked-pod
LAST SEEN   TYPE      REASON             OBJECT            MESSAGE
...         Warning   FailedScheduling   Pod/blocked-pod   0/1 nodes are available: 1 node(s) had untolerated taint(s)...

Aqui, Pending é o resultado experimental correto. O scheduler avaliou o Pod, mas não encontrou nenhum nó que ele pudesse utilizar.

Crie uma toleration correspondente. Uma toleration permite que o Pod seja agendado apesar do taint; por si só, ela não seleciona o nó.

cat <<'EOF' > tolerated-pod.yaml
apiVersion: v1
kind: Pod
metadata: {name: tolerated-pod, namespace: practice-scheduling}
spec:
  nodeSelector: {workload-zone: local}
  tolerations:
    - {key: practice-reserved, operator: Equal, value: "true", effect: NoSchedule}
  containers:
    - {name: worker, image: busybox:1.36, imagePullPolicy: IfNotPresent, command: ["sh", "-c", "while true; do sleep 30; done"]}
EOF
kubectl apply -f tolerated-pod.yaml
kubectl wait --for=condition=Ready pod/tolerated-pod -n practice-scheduling --timeout=120s
kubectl delete pod blocked-pod -n practice-scheduling

O Pod com toleration também possui um nodeSelector; assim, uma regra escolhe o nó e a outra permite que o Pod seja executado nele. A exclusão do Pod bloqueado, criado intencionalmente, deixa o namespace em um estado limpo e saudável.

pod/tolerated-pod condition met confirma que adicionar a toleration correspondente alterou o resultado. Os Pods criados anteriormente continuam em execução porque NoSchedule afeta novas alocações; ele não expulsa Pods que já estão em execução.

Resumo

Você usou rótulos, nodeSelector, afinidade obrigatória e preferencial, eventos do scheduler, taints e tolerations para expressar separadamente a intenção de alocação e as regras de admissão dos nós.