5 de janeiro de 20266 min de leitura

Kubernetes v1.35: Novos Operadores Numéricos em Tolerations Transformam o Escalonamento por SLA

Heba Elayoty

Kubernetes News

Muitos clusters Kubernetes em produção misturam nós sob demanda (SLA mais alto) e instâncias spot/preemptíveis (SLA mais baixo) para otimizar custos, mantendo a confiabilidade para workloads críticos. As equipes de plataforma precisam de um padrão seguro que mantenha a maioria das aplicações longe de capacidades de risco, permitindo que workloads específicos aceitem exceções com limites explícitos, como: "posso tolerar nós com probabilidade de falha de até 5%".

Até hoje, as taints e tolerations do Kubernetes podiam apenas coincidir valores exatos (Equal) ou verificar a existência (Exists), mas não conseguiam comparar limites numéricos. Para contornar isso, era necessário criar categorias discretas de taints, utilizar admission controllers externos ou aceitar decisões de posicionamento subotimizadas.

No Kubernetes v1.35, estamos introduzindo os Extended Toleration Operators como uma funcionalidade em estágio alpha. Essa melhoria adiciona os operadores Gt (Greater Than - Maior que) e Lt (Less Than - Menor que) ao spec.tolerations, permitindo decisões de scheduling baseadas em limiares (thresholds). Isso abre novas possibilidades para posicionamento baseado em SLA, otimização de custos (FinOps) e distribuição de carga sensível à performance.

A evolução das tolerations

Historicamente, o Kubernetes suportava dois operadores principais de toleration:

  • Equal: A toleration corresponde a uma taint se a chave e o valor forem exatamente iguais.
  • Exists: A toleration corresponde a uma taint se a chave existir, independentemente do valor.

Embora funcionem bem para cenários categóricos, eles falham em comparações numéricas. A partir da v1.35, essa lacuna está sendo fechada.

Considere estes cenários reais:

  • Requisitos de SLA: Escalonar workloads de alta disponibilidade apenas em nós com probabilidade de falha abaixo de um certo limite.
  • Otimização de Custos: Permitir que jobs em lote (batch) sensíveis ao custo sejam executados em nós mais baratos que excedam um valor específico de custo por hora.
  • Garantias de Performance: Garantir que aplicações sensíveis à latência rodem apenas em nós com IOPS de disco ou largura de banda de rede acima dos limites mínimos.

Sem operadores de comparação numérica, os operadores de cluster recorriam a workarounds como a criação de múltiplos valores de taint discretos ou o uso de admission controllers externos, soluções que não escalam bem nem oferecem a flexibilidade necessária para um agendamento dinâmico baseado em métricas.

Por que estender tolerations em vez de usar NodeAffinity?

Surge a dúvida: o NodeAffinity já suporta operadores de comparação numérica, então por que estender tolerations? Embora o NodeAffinity seja poderoso para expressar preferências de Pod, taints e tolerations oferecem benefícios operacionais críticos:

  1. Orientação a Políticas: O NodeAffinity é definido por Pod, exigindo que cada workload explicitamente evite nós de risco. As taints invertem o controle — os nós declaram seu nível de risco e apenas os Pods com tolerations correspondentes podem pousar ali. Isso fornece um padrão mais seguro (Secure by Default).
  2. Semântica de Evicção: O NodeAffinity não possui capacidade de evicção. As taints suportam o efeito NoExecute com tolerationSeconds, permitindo drenar e expulsar Pods quando o SLA de um nó degrada ou instâncias spot recebem avisos de terminação.
  3. Ergonomia Operacional: Uma política centralizada no lado do nó é consistente com outras taints de segurança, como disk-pressure e memory-pressure, tornando a gestão do cluster mais intuitiva.

Esta melhoria preserva o modelo de segurança das taints enquanto habilita o posicionamento inteligente para agendamento consciente de SLA.

Apresentando os operadores Gt e Lt

O Kubernetes v1.35 introduz dois novos operadores para tolerations:

  • Gt (Greater Than): A toleration coincide se o valor numérico da taint for maior que o valor da toleration.
  • Lt (Less Than): A toleration coincide se o valor numérico da taint for menor que o valor da toleration.

Quando um Pod tolera uma taint com Lt, ele está dizendo: "Eu tolero nós onde esta métrica é menor que o meu limite".

Nota Técnica:

  • Os valores numéricos para os operadores Gt e Lt devem ser inteiros positivos de 64 bits sem zeros à esquerda. Por exemplo, "100" é válido, mas "0100" ou "0" não são permitidos.
  • Os operadores funcionam com todos os efeitos de taint: NoSchedule, NoExecute e PreferNoSchedule.

Casos de Uso e Exemplos Práticos

Vamos explorar como esses operadores resolvem desafios reais de engenharia.

Exemplo 1: Proteção de Instâncias Spot com limites de SLA

Imagine que você deseja que a maioria dos workloads evite nós spot por padrão, mas permita que aplicações específicas optem por eles com limites claros de risco.

Primeiro, aplique uma taint nos nós spot com sua probabilidade de falha (ex: 15% de taxa de falha anual):

apiVersion: v1
kind: Node
metadata:
  name: spot-node-1
spec:
  taints:
  - key: "failure-probability"
    value: "15"
    effect: "NoExecute"

Workloads críticos podem especificar requisitos rígidos de SLA:

apiVersion: v1
kind: Pod
metadata:
  name: payment-processor
spec:
  tolerations:
  - key: "failure-probability"
    operator: "Lt"
    value: "5"
    effect: "NoExecute"
    tolerationSeconds: 30

Este Pod só será escalonado em nós com failure-probability menor que 5. Se o SLA do nó degradar (ex: o provedor de cloud alterar o valor da taint), o Pod terá 30 segundos para terminar graciosamente antes da evicção forçada.

Exemplo 2: Posicionamento de Workloads de IA com Tiers de GPU

Workloads de ML possuem requisitos de hardware específicos. Com os novos operadores, você pode criar camadas de nós de GPU.

Taint em um nó A100 (score de performance alto):

apiVersion: v1
kind: Node
metadata:
  name: gpu-node-a100
spec:
  taints:
  - key: "gpu-compute-score"
    value: "1000"
    effect: "NoSchedule"

Um workload de treinamento pesado pode exigir GPUs de alta performance:

spec:
  tolerations:
  - key: "gpu-compute-score"
    operator: "Gt"
    value: "800"
    effect: "NoSchedule"

Isso garante que o treinamento não ocorra em GPUs de baixo nível (como uma T4 com score 500), o que atrasaria o projeto.

Exemplo 3: Otimização de Custos (FinOps)

Nós podem ser marcados com seu custo por hora. Jobs de processamento em lote menos críticos podem expressar sua tolerância a nós caros:

tolerations:
- key: "cost-per-hour"
  operator: "Lt"
  value: "100"
  effect: "NoSchedule"

Exemplo 4: Posicionamento baseado em Performance de I/O

Aplicações intensivas de storage podem exigir IOPS mínimos garantidos diretamente no nível do scheduler:

tolerations:
- key: "disk-iops"
  operator: "Gt"
  value: "3000"
  effect: "NoSchedule"

Como habilitar o recurso

Como este é um recurso alpha no Kubernetes v1.35, ele deve ser habilitado via feature gate tanto no kube-apiserver quanto no kube-scheduler:

--feature-gates=TaintTolerationComparisonOperators=true

Atenção: Por ser uma funcionalidade alpha, o comportamento pode mudar em versões futuras. Recomendamos testes rigorosos em ambientes de staging antes de qualquer movimentação para instâncias críticas de produção.

O que vem a seguir?

Este lançamento é apenas o começo. O roadmap inclui:

  • Suporte para expressões CEL (Common Expression Language) para lógica de agendamento ainda mais flexível.
  • Melhor integração com o cluster-autoscaler para planejamento de capacidade consciente de limites.
  • Graduação para beta e GA conforme o feedback da comunidade amadurecer.

Fique atento a essas mudanças, pois elas representam um salto na maturidade de como operamos clusters heterogêneos e complexos em escala.


Artigo originalmente publicado por Heba Elayoty (Microsoft) em Kubernetes Blog.

Gostou? Compartilhe:
Precisa de ajuda?Fale com nossos especialistas 👋
Avatar Walcew - Headset