2 - Atribuindo Pods a Nós
Você pode restringir um Pod para que ele seja
limitado a executar em nó(s) específicos,
ou para preferir executar em nós específicos.
Existem várias maneiras de fazer isso e as abordagens recomendadas utilizam
seletores de rótulos para facilitar a seleção.
Frequentemente, você não precisa definir nenhuma dessas restrições; o
escalonador fará automaticamente uma alocação adequada
(por exemplo, distribuindo seus Pods entre os nós para não alocá-los em um nó com recursos livres insuficientes).
No entanto, existem algumas circunstâncias em que você pode querer controlar em qual nó
o Pod será implantado, por exemplo, para garantir que um Pod seja alocado em um nó com um SSD conectado,
ou para colocalizar Pods de dois serviços diferentes que se comunicam frequentemente na mesma zona de disponibilidade.
Você pode usar qualquer um dos seguintes métodos para escolher onde o Kubernetes aloca
Pods específicos:
Rótulos de nós
Assim como muitos outros objetos do Kubernetes, os nós possuem
rótulos. Você pode
anexar rótulos manualmente.
O Kubernetes também preenche um conjunto padrão de rótulos
em todos os nós de um cluster.
Nota:
O valor desses rótulos é específico do provedor de nuvem e não é garantido que seja confiável.
Por exemplo, o valor de kubernetes.io/hostname pode ser o mesmo que o nome do nó em alguns ambientes
e um valor diferente em outros ambientes.Isolamento/restrição de nós
Adicionar rótulos aos nós permite direcionar Pods para alocação em nós
ou grupos de nós específicos. Você pode usar essa funcionalidade para garantir que Pods
específicos executem apenas em nós com determinadas propriedades de isolamento,
segurança ou conformidade regulatória.
Se você usar rótulos para isolamento de nós, escolha chaves de rótulos que o kubelet
não possa modificar. Isso impede que um nó comprometido defina esses rótulos
em si mesmo para fazer com que o escalonador aloque cargas de trabalho no nó comprometido.
O plugin de admissão NodeRestriction
impede que o kubelet defina ou modifique rótulos com o
prefixo node-restriction.kubernetes.io/.
Para utilizar esse prefixo de rótulo para isolamento de nós:
- Certifique-se de estar usando o Node authorizer e ter habilitado o plugin de admissão
NodeRestriction. - Adicione rótulos com o prefixo
node-restriction.kubernetes.io/ aos seus nós e use esses rótulos em seus seletores de nós.
Por exemplo, example.com.node-restriction.kubernetes.io/fips=true ou example.com.node-restriction.kubernetes.io/pci-dss=true.
nodeSelector
nodeSelector é a forma recomendada mais simples de restrição de seleção de nós.
Você pode adicionar o campo nodeSelector à especificação do seu Pod e especificar os
rótulos de nós que você deseja que o nó de destino possua.
O Kubernetes aloca o Pod apenas em nós que possuem cada um dos rótulos que você
especificar.
Consulte Atribuir Pods a Nós para mais
informações.
Afinidade e antiafinidade
nodeSelector é a maneira mais simples de restringir Pods a nós com rótulos
específicos. Afinidade e antiafinidade expandem os tipos de restrições que você pode
definir. Alguns dos benefícios da afinidade e antiafinidade incluem:
- A linguagem de afinidade/antiafinidade é mais expressiva.
nodeSelector apenas
seleciona nós com todos os rótulos especificados. Afinidade/antiafinidade oferece
mais controle sobre a lógica de seleção. - Você pode indicar que uma regra é flexível ou preferencial, para que o escalonador
ainda aloque o Pod mesmo que não consiga encontrar um nó correspondente.
- Você pode restringir um Pod usando rótulos de outros Pods em execução no nó (ou outro domínio topológico),
em vez de apenas rótulos de nós, o que permite definir regras para quais Pods
podem ser colocalizados em um nó.
A funcionalidade de afinidade consiste em dois tipos de afinidade:
- Afinidade de nó funciona como o campo
nodeSelector, mas é mais expressiva e
permite especificar regras flexíveis. - Afinidade/antiafinidade entre Pods permite restringir Pods com base em rótulos
de outros Pods.
Afinidade de nó
Afinidade de nó é conceitualmente similar a nodeSelector, permitindo restringir em quais nós seu
Pod pode ser alocado com base em rótulos de nós. Existem dois tipos de afinidade
de nó:
requiredDuringSchedulingIgnoredDuringExecution: O escalonador não pode
alocar o Pod a menos que a regra seja atendida. Isso funciona como nodeSelector,
mas com uma sintaxe mais expressiva.preferredDuringSchedulingIgnoredDuringExecution: O escalonador tenta
encontrar um nó que atenda à regra. Se um nó correspondente não estiver disponível, o
escalonador ainda aloca o Pod.
Nota:
Nos tipos anteriores, IgnoredDuringExecution significa que se os rótulos do nó
mudarem após o Kubernetes alocar o Pod, o Pod continuará em execução.Você pode especificar afinidades de nó usando o campo .spec.affinity.nodeAffinity na
especificação do seu Pod.
Por exemplo, considere a seguinte especificação de Pod:
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:3.8
Neste exemplo, as seguintes regras se aplicam:
- O nó deve ter um rótulo com a chave
topology.kubernetes.io/zone e
o valor desse rótulo deve ser antarctica-east1 ou antarctica-west1. - O nó preferencialmente tem um rótulo com a chave
another-node-label-key e
o valor another-node-label-value.
Você pode usar o campo operator para especificar um operador lógico para o Kubernetes usar ao
interpretar as regras. Você pode usar In, NotIn, Exists, DoesNotExist,
Gt e Lt.
Leia Operadores
para saber mais sobre como eles funcionam.
NotIn e DoesNotExist permitem definir o comportamento de antiafinidade de nó.
Alternativamente, você pode usar taints de nó
para repelir Pods de nós específicos.
Nota:
Se você especificar tanto nodeSelector quanto nodeAffinity, ambos devem ser satisfeitos
para que o Pod seja alocado em um nó.
Se você especificar múltiplos termos em nodeSelectorTerms associados a tipos de nodeAffinity,
então o Pod pode ser alocado em um nó se um dos termos especificados
puder ser satisfeito (os termos são combinados com OR).
Se você especificar múltiplas expressões em um único campo matchExpressions associado a um
termo em nodeSelectorTerms, então o Pod pode ser alocado em um nó apenas
se todas as expressões forem satisfeitas (as expressões são combinadas com AND).
Consulte Atribuir Pods a Nós usando Afinidade de Nó
para mais informações.
Peso da afinidade de nó
Você pode especificar um weight (peso) entre 1 e 100 para cada instância do
tipo de afinidade preferredDuringSchedulingIgnoredDuringExecution. Quando o
escalonador encontra nós que atendem a todos os outros requisitos de alocação do Pod, o
escalonador itera por cada regra preferencial que o nó satisfaz e adiciona o
valor do weight dessa expressão a uma soma.
A soma final é adicionada à pontuação de outras funções de prioridade do nó.
Nós com a maior pontuação total são priorizados quando o escalonador toma uma
decisão de alocação para o Pod.
Por exemplo, considere a seguinte especificação de Pod:
apiVersion: v1
kind: Pod
metadata:
name: with-affinity-preferred-weight
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: label-1
operator: In
values:
- key-1
- weight: 50
preference:
matchExpressions:
- key: label-2
operator: In
values:
- key-2
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:3.8
Se houver dois nós possíveis que correspondem à regra
preferredDuringSchedulingIgnoredDuringExecution, um com o
rótulo label-1:key-1 e outro com o rótulo label-2:key-2, o escalonador
considera o weight de cada nó e adiciona o peso às outras pontuações daquele
nó, e aloca o Pod no nó com a maior pontuação final.
Nota:
Se você deseja que o Kubernetes aloque os Pods com sucesso neste exemplo, você
deve ter nós existentes com o rótulo kubernetes.io/os=linux.Afinidade de nó por perfil de alocação
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.20 [beta]
Ao configurar múltiplos perfis de alocação, você pode associar
um perfil a uma afinidade de nó, o que é útil se um perfil se aplica apenas a um conjunto específico de nós.
Para fazer isso, adicione um addedAffinity ao campo args do plugin NodeAffinity
na configuração do escalonador. Por exemplo:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
- schedulerName: foo-scheduler
pluginConfig:
- name: NodeAffinity
args:
addedAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: scheduler-profile
operator: In
values:
- foo
O addedAffinity é aplicado a todos os Pods que definem .spec.schedulerName como foo-scheduler, além da
NodeAffinity especificada no PodSpec.
Ou seja, para corresponder ao Pod, os nós precisam satisfazer o addedAffinity e
o .spec.NodeAffinity do Pod.
Como o addedAffinity não é visível para os usuários finais, seu comportamento pode ser
inesperado para eles. Use rótulos de nós que tenham uma correlação clara com o
nome do perfil do escalonador.
Nota:
O controlador DaemonSet, que
cria Pods para DaemonSets,
não suporta perfis de alocação. Quando o controlador DaemonSet cria
Pods, o escalonador padrão do Kubernetes aloca esses Pods e respeita quaisquer
regras de
nodeAffinity no controlador DaemonSet.
Afinidade e antiafinidade entre Pods
Afinidade e antiafinidade entre Pods permitem restringir em quais nós seus
Pods podem ser alocados com base nos rótulos de Pods já em execução naquele
nó, em vez dos rótulos do nó.
Tipos de afinidade e antiafinidade entre Pods
Afinidade e antiafinidade entre Pods assumem a forma "este
Pod deve (ou, no caso de antiafinidade, não deve) executar em um X se esse X
já estiver executando um ou mais Pods que atendem à regra Y", onde X é um domínio
topológico como nó, rack, zona ou região do provedor de nuvem, ou similar, e Y é a
regra que o Kubernetes tenta satisfazer.
Você expressa essas regras (Y) como seletores de rótulos
com uma lista opcional associada de namespaces. Pods são objetos com namespace no
Kubernetes, então rótulos de Pods também implicitamente possuem namespaces. Quaisquer seletores de rótulos
para rótulos de Pods devem especificar os namespaces nos quais o Kubernetes deve procurar esses
rótulos.
Você expressa o domínio topológico (X) usando uma topologyKey, que é a chave do
rótulo do nó que o sistema usa para indicar o domínio. Para exemplos, consulte
Rótulos, Anotações e Taints conhecidos.
Nota:
Afinidade e antiafinidade entre Pods requerem quantidades substanciais de
processamento, o que pode desacelerar significativamente a alocação em clusters grandes. Não
recomendamos usá-las em clusters maiores que algumas centenas de nós.Nota:
Antiafinidade de Pod requer que os nós sejam rotulados de forma consistente, em outras palavras,
cada nó no cluster deve ter um rótulo apropriado correspondendo à topologyKey.
Se alguns ou todos os nós não tiverem o rótulo topologyKey especificado, isso pode levar
a comportamentos não intencionais.Similar à afinidade de nó, existem dois tipos de afinidade e
antiafinidade de Pod, como segue:
requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution
Por exemplo, você poderia usar
afinidade requiredDuringSchedulingIgnoredDuringExecution para dizer ao escalonador para
colocalizar Pods de dois serviços na mesma zona do provedor de nuvem porque eles
se comunicam muito entre si. Da mesma forma, você poderia usar
antiafinidade preferredDuringSchedulingIgnoredDuringExecution para distribuir Pods
de um serviço em múltiplas zonas do provedor de nuvem.
Para usar afinidade entre Pods, use o campo affinity.podAffinity na especificação do Pod.
Para antiafinidade entre Pods, use o campo affinity.podAntiAffinity na especificação
do Pod.
Comportamento de alocação
Ao alocar um novo Pod, o escalonador do Kubernetes avalia as regras de afinidade/antiafinidade do Pod no contexto do estado atual do cluster:
Restrições rígidas (Filtragem de nós):
podAffinity.requiredDuringSchedulingIgnoredDuringExecution e podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution:- O escalonador garante que o novo Pod seja atribuído a nós que satisfaçam essas regras obrigatórias de afinidade e antiafinidade com base nos Pods existentes.
Restrições flexíveis (Pontuação):
podAffinity.preferredDuringSchedulingIgnoredDuringExecution e podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution:- O escalonador pontua os nós com base em quão bem eles atendem a essas regras preferenciais de afinidade e antiafinidade para otimizar a alocação do Pod.
Campos ignorados:
podAffinity.preferredDuringSchedulingIgnoredDuringExecution de Pods existentes:- Essas regras preferenciais de afinidade não são consideradas durante a decisão de alocação para novos Pods.
podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution de Pods existentes:- Da mesma forma, regras preferenciais de antiafinidade de Pods existentes são ignoradas durante a alocação.
Se o Pod atual sendo alocado é o primeiro de uma série que tem afinidade consigo mesmos,
ele pode ser alocado se passar em todas as outras verificações de afinidade. Isso é determinado
verificando que nenhum outro Pod no cluster corresponde ao namespace e seletor deste Pod,
que o Pod corresponde aos seus próprios termos, e que o nó escolhido corresponde a todas as topologias solicitadas.
Isso garante que não haverá um deadlock mesmo se todos os Pods tiverem afinidade entre Pods
especificada.
Exemplo de afinidade de Pod
Considere a seguinte especificação de Pod:
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: registry.k8s.io/pause:3.8
Este exemplo define uma regra de afinidade de Pod e uma regra de antiafinidade de Pod. A
regra de afinidade de Pod usa o "rígido"
requiredDuringSchedulingIgnoredDuringExecution, enquanto a regra de antiafinidade
usa o "flexível" preferredDuringSchedulingIgnoredDuringExecution.
A regra de afinidade especifica que o escalonador pode alocar o Pod de exemplo
em um nó apenas se esse nó pertencer a uma zona
específica onde outros Pods foram rotulados com security=S1.
Por exemplo, se tivermos um cluster com uma zona designada, vamos chamá-la de "Zona V",
consistindo de nós rotulados com topology.kubernetes.io/zone=V, o escalonador pode
atribuir o Pod a qualquer nó dentro da Zona V, desde que haja pelo menos um Pod dentro
da Zona V já rotulado com security=S1. Por outro lado, se não houver Pods com rótulos
security=S1 na Zona V, o escalonador não atribuirá o Pod de exemplo a nenhum nó nessa zona.
A regra de antiafinidade especifica que o escalonador deve tentar evitar alocar o Pod
em um nó se esse nó pertencer a uma zona
específica onde outros Pods foram rotulados com security=S2.
Por exemplo, se tivermos um cluster com uma zona designada, vamos chamá-la de "Zona R",
consistindo de nós rotulados com topology.kubernetes.io/zone=R, o escalonador deve evitar
atribuir o Pod a qualquer nó dentro da Zona R, desde que haja pelo menos um Pod dentro
da Zona R já rotulado com security=S2. Por outro lado, a regra de antiafinidade não impacta
a alocação na Zona R se não houver Pods com rótulos security=S2.
Para se familiarizar mais com os exemplos de afinidade e antiafinidade de Pod,
consulte a proposta de projeto.
Você pode usar os valores In, NotIn, Exists e DoesNotExist no
campo operator para afinidade e antiafinidade de Pod.
Leia Operadores
para saber mais sobre como eles funcionam.
Em princípio, a topologyKey pode ser qualquer chave de rótulo permitida, com as seguintes
exceções por razões de desempenho e segurança:
- Para afinidade e antiafinidade de Pod, um campo
topologyKey vazio não é permitido tanto em
requiredDuringSchedulingIgnoredDuringExecution
quanto em preferredDuringSchedulingIgnoredDuringExecution. - Para regras de antiafinidade de Pod
requiredDuringSchedulingIgnoredDuringExecution,
o controlador de admissão LimitPodHardAntiAffinityTopology limita
topologyKey a kubernetes.io/hostname. Você pode modificar ou desabilitar o
controlador de admissão se quiser permitir topologias personalizadas.
Além de labelSelector e topologyKey, você pode opcionalmente especificar uma lista
de namespaces com os quais o labelSelector deve corresponder usando o
campo namespaces no mesmo nível que labelSelector e topologyKey.
Se omitido ou vazio, namespaces assume como padrão o namespace do Pod onde a
definição de afinidade/antiafinidade aparece.
Seletor de Namespace
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.24 [stable]
Você também pode selecionar namespaces correspondentes usando namespaceSelector, que é uma consulta de rótulos sobre o conjunto de namespaces.
O termo de afinidade é aplicado aos namespaces selecionados tanto pelo namespaceSelector quanto pelo campo namespaces.
Note que um namespaceSelector vazio ({}) corresponde a todos os namespaces, enquanto uma lista namespaces nula ou vazia e
um namespaceSelector nulo correspondem ao namespace do Pod onde a regra é definida.
matchLabelKeys
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.33 [stable](habilitado por padrão)
Nota:
O campo matchLabelKeys é um campo de nível beta e está habilitado por padrão no
Kubernetes 1.35.
Quando você quiser desabilitá-lo, você deve desabilitá-lo explicitamente através do
feature gate MatchLabelKeysInPodAffinity.
O Kubernetes inclui um campo opcional matchLabelKeys para afinidade
ou antiafinidade de Pod. O campo especifica chaves para os rótulos que devem corresponder aos rótulos do Pod de entrada,
ao satisfazer a (anti)afinidade de Pod.
As chaves são usadas para buscar valores dos rótulos do Pod; esses rótulos de chave-valor são combinados
(usando AND) com as restrições de correspondência definidas usando o campo labelSelector. A filtragem
combinada seleciona o conjunto de Pods existentes que será considerado no cálculo de (anti)afinidade de Pod.
Cuidado:
Não é recomendado usar matchLabelKeys com rótulos que possam ser atualizados diretamente nos pods.
Mesmo se você editar o rótulo do pod que está especificado em matchLabelKeys diretamente (isto é, não através de um Deployment),
o kube-apiserver não reflete a atualização do rótulo no labelSelector mesclado.Um caso de uso comum é usar matchLabelKeys com pod-template-hash (definido em Pods
gerenciados como parte de um Deployment, onde o valor é único para cada revisão).
Usar pod-template-hash em matchLabelKeys permite selecionar os Pods que pertencem
à mesma revisão que o Pod de entrada, para que uma atualização gradual não quebre a afinidade.
apiVersion: apps/v1
kind: Deployment
metadata:
name: application-server
...
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- database
topologyKey: topology.kubernetes.io/zone
# Apenas Pods de um determinado rollout são considerados ao calcular a afinidade de pod.
# Se você atualizar o Deployment, os Pods substitutos seguem suas próprias regras de afinidade
# (se houver alguma definida no novo template de Pod)
matchLabelKeys:
- pod-template-hash
mismatchLabelKeys
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.33 [stable](habilitado por padrão)
Nota:
O campo mismatchLabelKeys é um campo de nível beta e está habilitado por padrão no
Kubernetes 1.35.
Quando você quiser desabilitá-lo, você deve desabilitá-lo explicitamente através do
feature gate MatchLabelKeysInPodAffinity.
O Kubernetes inclui um campo opcional mismatchLabelKeys para afinidade
ou antiafinidade de Pod. O campo especifica chaves para os rótulos que não devem corresponder aos rótulos do Pod de entrada,
ao satisfazer a (anti)afinidade de Pod.
Cuidado:
Não é recomendado usar mismatchLabelKeys com rótulos que possam ser atualizados diretamente nos pods.
Mesmo se você editar o rótulo do pod que está especificado em mismatchLabelKeys diretamente (isto é, não através de um Deployment),
o kube-apiserver não reflete a atualização do rótulo no labelSelector mesclado.Um exemplo de caso de uso é garantir que os Pods vão para o domínio topológico (nó, zona, etc.) onde apenas Pods do mesmo locatário ou equipe são alocados.
Em outras palavras, você quer evitar executar Pods de dois locatários diferentes no mesmo domínio topológico ao mesmo tempo.
apiVersion: v1
kind: Pod
metadata:
labels:
# Assume que todos os Pods relevantes têm um rótulo "tenant" definido
tenant: tenant-a
...
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# garante que os Pods associados a este locatário sejam alocados no pool de nós correto
- matchLabelKeys:
- tenant
labelSelector: {}
topologyKey: node-pool
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# garante que os Pods associados a este locatário não possam ser alocados em nós usados por outro locatário
- mismatchLabelKeys:
- tenant # qualquer que seja o valor do rótulo "tenant" para este Pod, impede
# a alocação em nós de qualquer pool onde qualquer Pod de um
# locatário diferente esteja em execução.
labelSelector:
# Precisamos ter o labelSelector que seleciona apenas Pods com o rótulo tenant,
# caso contrário, este Pod teria antiafinidade contra Pods de DaemonSets também, por exemplo,
# que não deveriam ter o rótulo tenant.
matchExpressions:
- key: tenant
operator: Exists
topologyKey: node-pool
Casos de uso mais práticos
Afinidade e antiafinidade entre Pods podem ser ainda mais úteis quando são usadas com coleções
de nível superior, como ReplicaSets, StatefulSets, Deployments, etc. Essas
regras permitem configurar que um conjunto de cargas de trabalho deve
ser colocalizado na mesma topologia definida; por exemplo, preferindo alocar dois Pods
relacionados no mesmo nó.
Por exemplo: imagine um cluster de três nós. Você usa o cluster para executar uma aplicação web
e também um cache em memória (como Redis). Para este exemplo, assuma também que a latência entre
a aplicação web e o cache em memória deve ser a mais baixa possível. Você poderia usar afinidade
e antiafinidade entre Pods para colocalizar os servidores web com o cache tanto quanto possível.
No seguinte exemplo de Deployment para o cache Redis, as réplicas recebem o rótulo app=store. A
regra podAntiAffinity diz ao escalonador para evitar alocar múltiplas réplicas
com o rótulo app=store em um único nó. Isso cria cada cache em um
nó separado.
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
spec:
selector:
matchLabels:
app: store
replicas: 3
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine
O seguinte exemplo de Deployment para os servidores web cria réplicas com o rótulo app=web-store.
A regra de afinidade de Pod diz ao escalonador para alocar cada réplica em um nó que tenha um Pod
com o rótulo app=store. A regra de antiafinidade de Pod diz ao escalonador para nunca alocar
múltiplos servidores app=web-store em um único nó.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
selector:
matchLabels:
app: web-store
replicas: 3
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.16-alpine
Criar os dois Deployments anteriores resulta no seguinte layout de cluster,
onde cada servidor web é colocalizado com um cache, em três nós separados.
| node-1 | node-2 | node-3 |
|---|
| webserver-1 | webserver-2 | webserver-3 |
| cache-1 | cache-2 | cache-3 |
O efeito geral é que cada instância de cache provavelmente será acessada por um único cliente que
está executando no mesmo nó. Esta abordagem visa minimizar tanto a assimetria (carga desbalanceada) quanto a latência.
Você pode ter outras razões para usar antiafinidade de Pod.
Consulte o tutorial do ZooKeeper
para um exemplo de um StatefulSet configurado com antiafinidade para alta
disponibilidade, usando a mesma técnica deste exemplo.
nodeName
nodeName é uma forma mais direta de seleção de nó do que afinidade ou
nodeSelector. nodeName é um campo na especificação do Pod. Se o campo nodeName
não estiver vazio, o escalonador ignora o Pod e o kubelet no nó nomeado
tenta alocar o Pod naquele nó. Usar nodeName sobrepõe o uso de
nodeSelector ou regras de afinidade e antiafinidade.
Algumas das limitações de usar nodeName para selecionar nós são:
- Se o nó nomeado não existir, o Pod não será executado e, em
alguns casos, pode ser automaticamente excluído.
- Se o nó nomeado não tiver os recursos para acomodar o
Pod, o Pod falhará e seu motivo indicará o porquê,
por exemplo OutOfmemory ou OutOfcpu.
- Nomes de nós em ambientes de nuvem nem sempre são previsíveis ou estáveis.
Aviso:
nodeName é destinado para uso por escalonadores personalizados ou casos de uso avançados onde
você precisa ignorar quaisquer escalonadores configurados. Ignorar os escalonadores pode levar a
Pods com falha se os nós atribuídos ficarem sobrecarregados. Você pode usar
afinidade de nó
ou o
campo nodeSelector para atribuir um Pod a um nó específico sem ignorar os escalonadores.
Aqui está um exemplo de uma especificação de Pod usando o campo nodeName:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-01
O Pod acima será executado apenas no nó kube-01.
nominatedNodeName
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.35 [beta](habilitado por padrão)
nominatedNodeName pode ser usado por componentes externos para nomear um nó para um pod pendente.
Esta nomeação é de melhor esforço: ela pode ser ignorada se o escalonador determinar que o pod não pode ir para o nó nomeado.
Além disso, este campo pode ser escrito (ou sobrescrito) pelo escalonador:
- Se o escalonador encontrar um nó para nomear através da preempção.
- Se o escalonador decidir para onde o pod vai e movê-lo para o ciclo de binding.
- Note que, neste caso,
nominatedNodeName é definido apenas quando o pod precisa passar pelos pontos de extensão WaitOnPermit ou PreBind.
Aqui está um exemplo de um status de Pod usando o campo nominatedNodeName:
apiVersion: v1
kind: Pod
metadata:
name: nginx
...
status:
nominatedNodeName: kube-01
Restrições de distribuição de topologia de Pod
Você pode usar restrições de distribuição de topologia para controlar como os Pods
são distribuídos pelo seu cluster entre domínios de falha como regiões, zonas, nós, ou entre quaisquer outros
domínios de topologia que você definir. Você pode fazer isso para melhorar o desempenho, a disponibilidade esperada ou
a utilização geral.
Leia Restrições de distribuição de topologia de Pod
para saber mais sobre como elas funcionam.
Rótulos de topologia de Pod
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.35 [beta](habilitado por padrão)
Os Pods herdam os rótulos de topologia (topology.kubernetes.io/zone e topology.kubernetes.io/region) do nó atribuído se esses rótulos estiverem presentes. Esses rótulos podem então ser utilizados através da Downward API para fornecer à carga de trabalho a informação da topologia do nó.
Aqui está um exemplo de um Pod usando a Downward API para sua zona e região:
apiVersion: v1
kind: Pod
metadata:
name: pod-with-topology-labels
spec:
containers:
- name: app
image: alpine
command: ["sh", "-c", "env"]
env:
- name: MY_ZONE
valueFrom:
fieldRef:
fieldPath: metadata.labels['topology.kubernetes.io/zone']
- name: MY_REGION
valueFrom:
fieldRef:
fieldPath: metadata.labels['topology.kubernetes.io/region']
Operadores
A seguir estão todos os operadores lógicos que você pode usar no campo operator para nodeAffinity e podAffinity mencionados acima.
| Operador | Comportamento |
|---|
In | O valor do rótulo está presente no conjunto de strings fornecido |
NotIn | O valor do rótulo não está contido no conjunto de strings fornecido |
Exists | Um rótulo com esta chave existe no objeto |
DoesNotExist | Nenhum rótulo com esta chave existe no objeto |
Os seguintes operadores só podem ser usados com nodeAffinity.
| Operador | Comportamento |
|---|
Gt | O valor do campo será interpretado como um inteiro, e o inteiro resultante da interpretação do valor de um rótulo nomeado por este seletor é maior que esse inteiro |
Lt | O valor do campo será interpretado como um inteiro, e o inteiro resultante da interpretação do valor de um rótulo nomeado por este seletor é menor que esse inteiro |
Nota:
Os operadores Gt e Lt não funcionarão com valores não inteiros. Se o valor fornecido
não puder ser interpretado como um inteiro, o Pod não conseguirá ser alocado. Além disso, Gt e Lt
não estão disponíveis para podAffinity.Próximos passos
3 - Taints e Tolerâncias
Afinidade de nó
é uma propriedade dos Pods que os associa a um conjunto de nós (seja como uma preferência ou uma exigência). Taints são o oposto -- eles permitem que um nó repudie um conjunto de pods.
Tolerâncias são aplicadas em pods e permitem, mas não exigem, que os pods sejam alocados em nós com taints correspondentes.
Taints e tolerâncias trabalham juntos para garantir que pods não sejam alocados em nós inapropriados. Um ou mais taints são aplicados em um nó; isso define que o nó não deve aceitar nenhum pod que não tolera essas taints.
Conceitos
Você adiciona um taint a um nó utilizando kubectl taint.
Por exemplo,
kubectl taint nodes node1 key1=value1:NoSchedule
define um taint no nó node1. O taint tem a chave key1, valor value1 e o efeito NoSchedule.
Isso significa que nenhum pod conseguirá ser executado no nó node1 a menos que possua uma tolerância correspondente.
Para remover o taint adicionado pelo comando acima, você pode executar:
kubectl taint nodes node1 key1=value1:NoSchedule-
Você especifica uma tolerância para um pod na especificação do Pod. Ambas as seguintes tolerâncias "correspondem" ao taint criado pelo kubectl taint acima, e assim um pod com qualquer uma delas poderia ser executado no node1:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerations:
- key: "key1"
operator: "Exists"
effect: "NoSchedule"
Aqui está um exemplo de um pod que utiliza tolerâncias:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"
O valor padrão de operator é Equal.
Uma tolerância "casa" um taint se as chaves e efeitos são os mesmos, e:
- o valor de
operator é Exists (no caso nenhum value deve ser especificado), ou - o valor de
operator é Equal e os valores de value são iguais.
Nota:
Existem dois casos especiais:
Uma key vazia com o operador Exists "casa" todas as chaves, valores e efeitos, o que significa que o pod irá tolerar tudo.
Um effect vazio "casa" todos os efeitos com a chave key1.
O exemplo acima usou effect de NoSchedule. De forma alternativa, você pode usar effect de PreferNoSchedule.
Nesse efeito, o sistema tentará evitar que o pod seja alocado ao nó caso ele não tolere os taints definidos, contudo a alocação não será evitada de forma obrigatória. Pode-se dizer que o PreferNoSchedule é uma versão permissiva do NoSchedule. O terceiro tipo de effect é o NoExecute que será descrito posteriormente.
Você pode colocar múltiplos taints no mesmo nó e múltiplas tolerâncias no mesmo pod.
O jeito que o Kubernetes processa múltiplos taints e tolerâncias é como um filtro: começa com todos os taints de um nó, em seguida ignora aqueles para os quais o pod tem uma tolerância relacionada; os taints restantes que não foram ignorados indicam o efeito no pod. Mais especificamente,
- se existe pelo menos um taint não tolerado com o efeito
NoSchedule, o Kubernetes não alocará o pod naquele nó - se existe um taint não tolerado com o efeito
NoSchedule, mas existe pelo menos um taint não tolerado com o efeito PreferNoSchedule, o Kubernetes tentará não alocar o pod no nó - se existe pelo menos um taint não tolerado com o efeito
NoExecute, o pod será expulso do nó (caso já esteja em execução) e não será alocado ao nó (caso ainda não esteja em execução).
Por exemplo, imagine que você tem um nó com os seguintes taints
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
E um pod com duas tolerâncias:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
Nesse caso, o pod não será alocado ao nó porque não possui uma tolerância para o terceiro taint. Porém, se ele já estiver rodando no nó quando o taint foi adicionado, não será afetado e continuará rodando, tendo em vista que o terceiro taint é o único não tolerado pelo pod.
Normalmente, se um taint com o efeito NoExecute é adicionado a um nó, qualquer pod que não o tolere será expulso imediatamente e pods que o toleram nunca serão expulsos. Contudo, uma tolerância com efeito NoExecute pode especificar de forma opcional o campo tolerationSeconds, que determina quanto tempo o pod continuará alocado ao nó depois que o taint é adicionado. Por exemplo,
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
significa que se esse pod está sendo executado e um taint correspondente é adicionado ao nó, o pod irá continuar rodando neste nó por 3600 segundos e depois será expulso. Se o taint for removido antes desse tempo acabar, o pod não será expulso.
Exemplos de Casos de Uso
Taints e tolerâncias são um modo flexível de conduzir pods para fora dos nós ou expulsar pods que não deveriam estar sendo executados. Alguns casos de uso são
Nós Dedicados: Se você quiser dedicar um conjunto de nós para uso exclusivo de um conjunto específico de usuários, poderá adicionar um taint nesses nós. (digamos, kubectl taint nodes nodename dedicated=groupName:NoSchedule) e em seguida adicionar uma tolerância correspondente para seus pods (isso seria feito mais facilmente com a escrita de um controlador de admissão customizado).
Os pods com tolerância terão sua execução permitida nos nós com taints (dedicados), assim como em qualquer outro nó no cluster. Se você quiser dedicar nós a esses pods e garantir que eles usem apenas os nós dedicados, precisará adicionar uma label similar ao taint para o mesmo conjunto de nós (por exemplo, dedicated=groupName), e o controle de admissão deverá adicionar uma afinidade de nó para exigir que os pods podem ser executados apenas nos nós definidos com a label dedicated=groupName.
Nós com hardware especial: Em um cluster no qual um pequeno grupo de nós possui hardware especializado (por exemplo, GPUs), é desejável manter pods que não necessitem desse tipo de hardware fora desses nós, dessa forma o recurso estará disponível para pods que precisem do hardware especializado. Isso pode ser feito aplicando taints nos nós com o hardware especializado (por exemplo, kubectl taint nodes nodename special=true:NoSchedule or kubectl taint nodes nodename special=true:PreferNoSchedule) e aplicando uma tolerância correspondente nos pods que usam o hardware especial. Assim como no caso de uso de nós dedicados, é provavelmente mais fácil aplicar as tolerâncias utilizando um controlador de admissão.
Por exemplo, é recomendado usar Extended Resources para representar hardware especial, adicione um taint ao seus nós de hardware especializado com o nome do recurso estendido e execute o controle de admissão ExtendedResourceToleration. Agora, tendo em vista que os nós estão marcados com um taint, nenhum pod sem a tolerância será executado neles. Porém, quando você submete um pod que requisita o recurso estendido, o controlador de admissão ExtendedResourceToleration irá adicionar automaticamente as tolerâncias necessárias ao pod que irá, por sua vez, ser alocado no nó com hardware especial. Isso garantirá que esses nós de hardware especial serão dedicados para os pods que requisitarem tal recurso e você não precisará adicionar manualmente as tolerâncias aos seus pods.
Expulsões baseadas em Taint: Um comportamento de expulsão configurada por pod quando problemas existem em um nó, o qual será descrito na próxima seção.
Expulsões baseadas em Taint
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.18 [stable]
O efeito de taint NoExecute, mencionado acima, afeta pods que já estão rodando no nó da seguinte forma
- pods que não toleram o taint são expulsos imediatamente
- pods que toleram o taint sem especificar
tolerationSeconds em sua especificação de tolerância, ficam alocados para sempre - pods que toleram o taint com um
tolerationSeconds especificado, permanecem alocados pela quantidade de tempo definida
O controlador de nó automaticamente adiciona um taint ao Nó quando certas condições se tornam verdadeiras. Os seguintes taints são embutidos:
node.kubernetes.io/not-ready: Nó não está pronto. Isso corresponde ao NodeCondition Ready com o valor "False".node.kubernetes.io/unreachable: Nó é inalcançável a partir do controlador de nó. Isso corresponde ao NodeCondition Ready com o valor "Unknown".node.kubernetes.io/memory-pressure: Nó possui pressão de memória.node.kubernetes.io/disk-pressure: Nó possui pressão de disco.node.kubernetes.io/pid-pressure: Nó possui pressão de PID.node.kubernetes.io/network-unavailable: A rede do nó está indisponível.node.kubernetes.io/unschedulable: Nó não é alocável.node.cloudprovider.kubernetes.io/uninitialized: Quando o kubelet é iniciado com um provedor de nuvem "externo", esse taint é adicionado ao nó para que ele seja marcado como não utilizável. Após o controlador do cloud-controller-manager inicializar o nó, o kubelet remove esse taint.
No caso de um nó estar prestes a ser expulso, o controlador de nó ou kubelet adicionam os taints relevantes com o efeito NoExecute. Se a condição de falha retorna ao normal, o kubelet ou controlador de nó podem remover esses taints.
Nota:
A camada de gerenciamento limita a taxa de adição de novos taints aos nós. Esse limite gerencia o número de expulsões que são disparadas quando muitos nós se tornam inalcançáveis ao mesmo tempo (por exemplo: se ocorre uma falha na rede).Você pode especificar tolerationSeconds em um Pod para definir quanto tempo ele ficará alocado em um nó que está falhando ou está sem resposta.
Por exemplo, você talvez queira manter uma aplicação com vários estados salvos localmente alocado em um nó por um longo período na ocorrência de uma divisão na rede, esperando que essa divisão se recuperará e assim a expulsão do pod pode ser evitada.
A tolerância que você define para esse Pod poderia ficar assim:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
Nota:
O Kubernetes automaticamente adiciona uma tolerância para node.kubernetes.io/not-ready e node.kubernetes.io/unreachable com tolerationSeconds=300, a menos que você, ou um controlador, defina essas tolerâncias explicitamente.
Essas tolerâncias adicionadas automaticamente significam que Pods podem continuar alocados aos Nós por 5 minutos após um desses problemas ser detectado.
Pods do tipo DaemonSet são criados com tolerâncias NoExecute sem a propriedade tolerationSeconds para os seguintes taints:
node.kubernetes.io/unreachablenode.kubernetes.io/not-ready
Isso garante que esses pods do DaemonSet nunca sejam expulsos por conta desses problemas.
Taints por condições de nó
A camada de gerenciamento, usando o controlador do nó, cria taints automaticamente com o efeito NoSchedule para condições de nó.
O agendador verifica taints, não condições de nó, quando realiza suas decisões de agendamento. Isso garante que as condições de nó não afetem diretamente o agendamento.
Por exemplo, se a condição de nó DiskPressure está ativa, a camada de gerenciamento adiciona o taint node.kubernetes.io/disk-pressure e não aloca novos pods no nó afetado. Se a condição MemoryPressure está ativa, a camada de gerenciamento adiciona o taint node.kubernetes.io/memory-pressure.
Você pode ignorar condições de nó para pods recém-criados adicionando tolerâncias correspondentes. A camada de controle também adiciona a tolerância node.kubernetes.io/memory-pressure em pods que possuem uma classe de QoS diferente de BestEffort. Isso ocorre porque o Kubernetes trata pods nas classes de QoS Guaranteed ou Burstable (até mesmo pods sem requisitos de memória definidos) como se fossem capazes de lidar com pressão de memória, enquanto novos pods com BestEffort não são alocados no nó afetado.
O controlador DaemonSet adiciona automaticamente as seguintes tolerâncias de NoSchedule para todos os daemons, prevenindo que DaemonSets quebrem.
node.kubernetes.io/memory-pressurenode.kubernetes.io/disk-pressurenode.kubernetes.io/pid-pressure (1.14 ou superior)node.kubernetes.io/unschedulable (1.10 ou superior)node.kubernetes.io/network-unavailable (somente rede do host)
Adicionando essas tolerâncias garante retro compatibilidade. Você também pode adicionar tolerâncias de forma arbitrária aos DaemonSets.
Próximos passos
4 - Sobrecarga de Pod
ESTADO DA FUNCIONALIDADE:
Kubernetes v1.18 [beta]
Quando você executa um Pod num nó, o próprio Pod usa uma quantidade de recursos do sistema. Estes
recursos são adicionais aos recursos necessários para executar o(s) contêiner(s) dentro do Pod.
Sobrecarga de Pod, do inglês Pod Overhead, é uma funcionalidade que serve para contabilizar os recursos consumidos pela
infraestrutura do Pod para além das solicitações e limites do contêiner.
No Kubernetes, a sobrecarga de Pods é definido no tempo de
admissão
de acordo com a sobrecarga associada à
RuntimeClass do Pod.
Quando é ativada a Sobrecarga de Pod, a sobrecarga é considerada adicionalmente à soma das
solicitações de recursos do contêiner ao agendar um Pod. Semelhantemente, o kubelet
incluirá a sobrecarga do Pod ao dimensionar o cgroup do Pod e ao
executar a classificação de prioridade de migração do Pod em caso de drain do Node.
Habilitando a Sobrecarga de Pod
Terá de garantir que o Feature Gate
PodOverhead esteja ativo (está ativo por padrão a partir da versão 1.18)
em todo o cluster, e uma RuntimeClass utilizada que defina o campo overhead.
Exemplo de uso
Para usar a funcionalidade PodOverhead, é necessário uma RuntimeClass que define o campo overhead.
Por exemplo, poderia usar a definição da RuntimeClass abaixo com um agente de execução de contêiner virtualizado
que use cerca de 120MiB por Pod para a máquina virtual e o sistema operacional convidado:
---
kind: RuntimeClass
apiVersion: node.k8s.io/v1beta1
metadata:
name: kata-fc
handler: kata-fc
overhead:
podFixed:
memory: "120Mi"
cpu: "250m"
As cargas de trabalho que são criadas e que especificam o manipulador RuntimeClass kata-fc irão
usar a sobrecarga de memória e cpu em conta para os cálculos da quota de recursos, agendamento de nós,
assim como dimensionamento do cgroup do Pod.
Considere executar a seguinte carga de trabalho de exemplo, test-pod:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
runtimeClassName: kata-fc
containers:
- name: busybox-ctr
image: busybox
stdin: true
tty: true
resources:
limits:
cpu: 500m
memory: 100Mi
- name: nginx-ctr
image: nginx
resources:
limits:
cpu: 1500m
memory: 100Mi
No tempo de admissão o controlador de admissão RuntimeClass
atualiza o PodSpec da carga de trabalho de forma a incluir o overhead como descrito na RuntimeClass. Se o PodSpec já tiver este campo definido
o Pod será rejeitado. No exemplo dado, como apenas o nome do RuntimeClass é especificado, o controlador de admissão muda o Pod de forma a
incluir um overhead.
Depois do controlador de admissão RuntimeClass, pode verificar o PodSpec atualizado:
kubectl get pod test-pod -o jsonpath='{.spec.overhead}'
A saída é:
map[cpu:250m memory:120Mi]
Se for definido um ResourceQuota, a soma das requisições dos contêineres assim como o campo overhead são contados.
Quando o kube-scheduler está decidindo que nó deve executar um novo Pod, o agendador considera o overhead do pod,
assim como a soma de pedidos aos contêineres para esse Pod. Para este exemplo, o agendador adiciona as requisições e a sobrecarga, depois procura um nó com 2.25 CPU e 320 MiB de memória disponível.
Assim que um Pod é agendado a um nó, o kubelet nesse nó cria um novo cgroup
para o Pod. É dentro deste Pod que o agente de execução de contêiners subjacente vai criar contêineres.
Se o recurso tiver um limite definido para cada contêiner (QoS garantida ou Burstrable QoS com limites definidos),
o kubelet definirá um limite superior para o cgroup do Pod associado a esse recurso (cpu.cfs_quota_us para CPU
e memory.limit_in_bytes de memória). Este limite superior é baseado na soma dos limites do contêiner mais o overhead
definido no PodSpec.
Para CPU, se o Pod for QoS garantida ou Burstrable QoS, o kubelet vai definir cpu.shares baseado na soma dos
pedidos ao contêiner mais o overhead definido no PodSpec.
Olhando para o nosso exemplo, verifique as requisições ao contêiner para a carga de trabalho:
kubectl get pod test-pod -o jsonpath='{.spec.containers[*].resources.limits}'
O total de requisições ao contêiner são 2000m CPU e 200MiB de memória:
map[cpu: 500m memory:100Mi] map[cpu:1500m memory:100Mi]
Verifique isto comparado ao que é observado pelo nó:
kubectl describe node | grep test-pod -B2
A saída mostra que 2250m CPU e 320MiB de memória são solicitados, que inclui PodOverhead:
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
default test-pod 2250m (56%) 2250m (56%) 320Mi (1%) 320Mi (1%) 36m
Verificar os limites cgroup do Pod
Verifique os cgroups de memória do Pod no nó onde a carga de trabalho está em execução. No seguinte exemplo, crictl
é usado no nó, que fornece uma CLI para agentes de execução compatíveis com CRI. Isto é um
exemplo avançado para mostrar o comportamento do PodOverhead, e não é esperado que os usuários precisem verificar
cgroups diretamente no nó.
Primeiro, no nó em particular, determine o identificador do Pod:
# Execute no nó onde o Pod está agendado
POD_ID="$(sudo crictl pods --name test-pod -q)"
A partir disto, pode determinar o caminho do cgroup para o Pod:
# Execute no nó onde o Pod está agendado
sudo crictl inspectp -o=json $POD_ID | grep cgroupsPath
O caminho do cgroup resultante inclui o contêiner pause do Pod. O cgroup no nível do Pod está um diretório acima.
"cgroupsPath": "/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/7ccf55aee35dd16aca4189c952d83487297f3cd760f1bbf09620e206e7d0c27a"
Neste caso especifico, o caminho do cgroup do Pod é kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2. Verifique a configuração cgroup de nível do Pod para a memória:
# Execute no nó onde o Pod está agendado
# Mude também o nome do cgroup para combinar com o cgroup alocado ao Pod.
cat /sys/fs/cgroup/memory/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/memory.limit_in_bytes
Isto é 320 MiB, como esperado:
335544320
Observabilidade
Uma métrica kube_pod_overhead está disponível em kube-state-metrics
para ajudar a identificar quando o PodOverhead está sendo utilizado e para ajudar a observar a estabilidade das cargas de trabalho
em execução com uma sobrecarga (Overhead) definida. Esta funcionalidade não está disponível na versão 1.9 do kube-state-metrics,
mas é esperado em uma próxima versão. Os usuários necessitarão entretanto construir o kube-state-metrics a partir do código fonte.
Próximos passos