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.


