En esta página, se muestra cómo resolver problemas con el programador de Kubernetes (kube-scheduler
) para Google Distributed Cloud.
Kubernetes siempre programa los Pods en el mismo conjunto de nodos
Este error puede observarse de diferentes maneras:
Uso desequilibrado. Puedes inspeccionar el uso del clúster para cada nodo con el comando
kubectl top nodes
. En el siguiente resultado de ejemplo exagerado, se muestra el uso pronunciado en ciertos nodos: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%
Demasiadas solicitudes. Si programas muchos Pods a la vez en el mismo nodo y estos realizan solicitudes HTTP, es posible que se le aplique un límite de frecuencia al nodo. El error común que muestra el servidor en esta situación es
429 Too Many Requests
.Servicio no disponible. Por ejemplo, un servidor web alojado en un nodo con una carga alta podría responder a todas las solicitudes con errores
503 Service Unavailable
hasta que se encuentre con una carga menor.
Para verificar si tienes Pods que siempre están programados en los mismos nodos, sigue estos pasos:
Ejecuta el siguiente comando de
kubectl
para ver el estado de los Pods:kubectl get pods -o wide -n default
Para ver la distribución de los Pods entre nodos, consulta la columna
NODE
en el resultado. En el siguiente resultado de ejemplo, todos los Pods se programan en el mismo nodo: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
Los Pods tienen una serie de características que te permiten ajustar su comportamiento de programación. Estas características incluyen restricciones de distribución de topología y reglas de antiafinidad. Puedes usar una de estas funciones o una combinación de ellas. Los requisitos que defines se combinan mediante el operador Y mediante kube-scheduler
.
Los registros del programador no se capturan en el nivel de verbosidad de registro predeterminado. Si necesitas los registros del programador para solucionar problemas, sigue estos pasos a fin de capturar los registros del programador:
Aumenta el nivel de verbosidad del registro:
Edita el Deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Agrega la marca
--v=5
en la secciónspec.containers.command
:containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true - --v=5
Cuando termines de solucionar el problema, restablece el nivel de verbosidad al predeterminado:
Edita el Deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Vuelve a establecer el nivel de verbosidad en el valor predeterminado:
containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true
Restricciones de propagación de la topología
Las restricciones de propagación de topología se pueden usar para distribuir Pods de manera uniforme entre los nodos según su zones
, regions
, node
o alguna otra topología definida de forma personalizada.
En el siguiente manifiesto de ejemplo, se muestra un Deployment que distribuye las réplicas de manera uniforme entre todos los nodos programables mediante las restricciones de propagación de topología:
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
Las siguientes consideraciones se aplican cuando se usan restricciones de distribución de topología:
- El
labels.app: myapp
de un Pod coincide con ellabelSelector
de la restricción. topologyKey
especificakubernetes.io/hostname
. Esta etiqueta se adjunta automáticamente a todos los nodos y se propaga con el nombre de host del nodo.- El
matchLabelKeys
evita que los lanzamientos de implementaciones nuevas tengan en cuenta los pods de revisiones anteriores cuando se calcula dónde programar un pod. Un Deployment propaga automáticamente la etiquetapod-template-hash
.
Antiafinidad de pods
La antiafinidad de Pods te permite definir restricciones para los Pods que se pueden ubicar en el mismo nodo.
En el siguiente manifiesto de ejemplo, se muestra un Deployment que usa antiafinidad para limitar las réplicas a un Pod por nodo:
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
Este Deployment de ejemplo especifica réplicas de 30
, pero solo se expande a la cantidad de nodos disponibles en tu clúster.
Las siguientes consideraciones se aplican cuando se usa la antiafinidad de Pods:
- El
labels.app: myapp
de un Pod coincide con ellabelSelector
de la restricción. topologyKey
especificakubernetes.io/hostname
. Esta etiqueta se adjunta automáticamente a todos los nodos y se propaga con el nombre de host del nodo. Puedes elegir usar otras etiquetas si el clúster las admite, comoregion
ozone
.
Extraer imágenes de contenedor previamente
Ante la ausencia de otras restricciones, de forma predeterminada, kube-scheduler
prefiere programar los Pods en los nodos que ya tienen descargada la imagen de contenedor. Este comportamiento puede ser de interés en clústeres más pequeños sin otras opciones de configuración de programación en las que sería posible descargar las imágenes de cada nodo. Sin embargo, este concepto debería considerarse como último recurso. Una mejor solución es usar nodeSelector
, restricciones de propagación de topología o afinidad o antiafinidad. Para obtener más información, consulta Asigna Pods a nodos.
Si deseas asegurarte de que las imágenes de contenedor se extraigan previamente de todos los nodos, puedes usar un DaemonSet
como en el siguiente ejemplo:
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
Después de que el Pod esté Running
en todos los nodos, vuelve a implementar tus Pods para ver si los contenedores ahora están distribuidos de manera uniforme entre los nodos.