Estas páginas mostram como resolver problemas com o programador do Kubernetes (kube-scheduler
) para o Google Distributed Cloud.
O Kubernetes agenda sempre os pods para o mesmo conjunto de nós
Este erro pode ser observado de várias formas:
Utilização desequilibrada do cluster. Pode inspecionar a utilização do cluster para cada nó com o comando
kubectl top nodes
. O exemplo de saída exagerado seguinte mostra uma utilização pronunciada em determinados nós:NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% XXX.gke.internal 222m 101% 3237Mi 61% YYY.gke.internal 91m 0% 2217Mi 0% ZZZ.gke.internal 512m 0% 8214Mi 0%
Demasiados pedidos. Se agendar muitos pods em simultâneo no mesmo nó e esses pods fizerem pedidos HTTP, é possível que o nó seja limitado pela taxa. O erro comum devolvido pelo servidor neste cenário é
429 Too Many Requests
.Serviço indisponível. Por exemplo, um servidor Web alojado num nó sob carga elevada pode responder a todos os pedidos com erros
503 Service Unavailable
até estar sob carga mais baixa.
Para verificar se tem pods sempre agendados para os mesmos nós, use os seguintes passos:
Execute o seguinte comando
kubectl
para ver o estado dos pods:kubectl get pods -o wide -n default
Para ver a distribuição de pods nos nós, verifique a coluna
NODE
na saída. No exemplo de saída seguinte, todos os pods estão agendados no mesmo nó:NAME READY STATUS RESTARTS AGE IP NODE nginx-deployment-84c6674589-cxp55 1/1 Running 0 55s 10.20.152.138 10.128.224.44 nginx-deployment-84c6674589-hzmnn 1/1 Running 0 55s 10.20.155.70 10.128.226.44 nginx-deployment-84c6674589-vq4l2 1/1 Running 0 55s 10.20.225.7 10.128.226.44
Os grupos de anúncios têm várias funcionalidades que lhe permitem otimizar o respetivo comportamento de agendamento. Estas funcionalidades incluem restrições de dispersão de topologia e regras de antiafinidade. Pode usar uma ou uma combinação destas funcionalidades. Os requisitos
que definir são cumulativos através do operador kube-scheduler
.
Os registos do programador não são capturados no nível de detalhe de registo predefinido. Se precisar dos registos do agendador para a resolução de problemas, siga os passos abaixo para capturar os registos do agendador:
Aumente o nível de detalhe do registo:
Edite a implementação de
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Adicione a flag
--v=5
na secçãospec.containers.command
:containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true - --v=5
Quando terminar a resolução de problemas, reponha o nível de detalhe para o nível predefinido:
Edite a implementação de
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Defina o nível de detalhe novamente para o valor predefinido:
containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true
Restrições de dispersão da topologia
As restrições de propagação da topologia podem ser usadas para distribuir uniformemente os pods entre os nós de acordo com o respetivo zones
, regions
, node
ou outra topologia definida pelo utilizador.
O manifesto de exemplo seguinte mostra uma implementação que distribui as réplicas uniformemente entre todos os nós agendáveis através de restrições de distribuição de topologia:
apiVersion: apps/v1
kind: Deployment
metadata:
name: topology-spread-deployment
labels:
app: myapp
spec:
replicas: 30
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
topologySpreadConstraints:
- maxSkew: 1 # Default. Spreads evenly. Maximum difference in scheduled Pods per Node.
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule # Default. Alternatively can be ScheduleAnyway
labelSelector:
matchLabels:
app: myapp
matchLabelKeys: # beta in 1.27
- pod-template-hash
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
As seguintes considerações aplicam-se quando usa restrições de dispersão de topologia:
- O
labels.app: myapp
de um pod corresponde aolabelSelector
da restrição. - O elemento
topologyKey
especificakubernetes.io/hostname
. Esta etiqueta é anexada automaticamente a todos os nós e é preenchida com o nome de anfitrião do nó. - O
matchLabelKeys
impede que as implementações de novas implementações considerem os pods de revisões antigas ao calcular onde agendar um pod. A etiquetapod-template-hash
é preenchida automaticamente por uma implementação.
Antiafinidade de agrupamentos
A antiafinidade de agrupamentos permite-lhe definir restrições para os agrupamentos que podem ser colocados em conjunto no mesmo nó.
O manifesto de exemplo seguinte mostra uma implementação que usa a antiafinidade para limitar as réplicas a um pod por nó:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-affinity-deployment
labels:
app: myapp
spec:
replicas: 30
selector:
matchLabels:
app: myapp
template:
metadata:
name: with-pod-affinity
labels:
app: myapp
spec:
affinity:
podAntiAffinity:
# requiredDuringSchedulingIgnoredDuringExecution
# prevents Pod from being scheduled on a Node if it
# does not meet criteria.
# Alternatively can use 'preferred' with a weight
# rather than 'required'.
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
# Your nodes might be configured with other keys
# to use as `topologyKey`. `kubernetes.io/region`
# and `kubernetes.io/zone` are common.
topologyKey: kubernetes.io/hostname
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
Esta implementação de exemplo especifica 30
réplicas, mas só se expande até ao número de nós disponíveis no seu cluster.
As seguintes considerações aplicam-se quando usa a antiafinidade de pods:
- O
labels.app: myapp
de um pod corresponde aolabelSelector
da restrição. - O elemento
topologyKey
especificakubernetes.io/hostname
. Esta etiqueta é anexada automaticamente a todos os nós e é preenchida com o nome de anfitrião do nó. Pode optar por usar outras etiquetas se o seu cluster as suportar, comoregion
ouzone
.
Extraia previamente imagens de contentores
Na ausência de outras restrições, por predefinição, o kube-scheduler
prefere agendar pods em nós que já tenham a imagem do contentor transferida para os mesmos. Este comportamento pode ser interessante em clusters mais pequenos sem outras configurações de agendamento, onde seria possível transferir as imagens em todos os nós. No entanto, a utilização deste conceito deve ser vista como último recurso. Uma solução
melhor é usar nodeSelector
, restrições de dispersão da topologia ou
afinidade / antiafinidade. Para mais informações, consulte o artigo
Atribuir pods a nós.
Se quiser certificar-se de que as imagens de contentores são pré-extraídas para todos os nós, pode usar um DaemonSet
como no exemplo seguinte:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: prepulled-images
spec:
selector:
matchLabels:
name: prepulled-images
template:
metadata:
labels:
name: prepulled-images
spec:
initContainers:
- name: prepulled-image
image: IMAGE
# Use a command the terminates immediately
command: ["sh", "-c", "'true'"]
containers:
# pause is a lightweight container that simply sleeps
- name: pause
image: registry.k8s.io/pause:3.2
Depois de o pod estar Running
em todos os nós, volte a implementar os pods para ver se os contentores estão agora distribuídos uniformemente pelos nós.
O que se segue?
Se precisar de assistência adicional, contacte o apoio ao cliente do Google Cloud.
Também pode consultar o artigo Receber apoio técnico para mais informações sobre recursos de apoio técnico, incluindo o seguinte:
- Requisitos para abrir um registo de apoio técnico.
- Ferramentas para ajudar a resolver problemas, como registos e métricas.
- Componentes suportados, versões e funcionalidades do Google Distributed Cloud para VMware (apenas software).