Cette page explique comment résoudre les problèmes liés au programmeur Kubernetes (kube-scheduler
) pour Google Distributed Cloud.
Kubernetes planifie toujours les pods sur le même ensemble de nœuds
Cette erreur peut être observée de différentes manières:
Utilisation déséquilibrée des clusters. Vous pouvez inspecter l'utilisation des clusters pour chaque nœud à l'aide de la commande
kubectl top nodes
. L'exemple de résultat exagéré suivant montre une utilisation prononcée sur certains nœuds: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%
Trop de requêtes. Si vous planifiez plusieurs pods à la fois sur le même nœud et que ces pods effectuent des requêtes HTTP, le nœud peut être limité en débit. Dans ce scénario, l'erreur courante renvoyée par le serveur est
429 Too Many Requests
.Service indisponible. Un serveur Web, par exemple, hébergé sur un nœud avec une charge élevée peut répondre à toutes les requêtes avec des erreurs
503 Service Unavailable
jusqu'à ce qu'il soit moins chargé.
Pour vérifier si certains de vos pods sont toujours planifiés sur les mêmes nœuds, procédez comme suit:
Exécutez la commande
kubectl
suivante pour afficher l'état des pods:kubectl get pods -o wide -n default
Pour afficher la distribution des pods sur les nœuds, consultez la colonne
NODE
dans le résultat. Dans l'exemple de résultat suivant, tous les pods sont planifiés sur le même nœud: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
Les pods disposent d'un certain nombre de fonctionnalités qui vous permettent d'ajuster leur comportement de planification. Ces fonctionnalités incluent les contraintes de répartition de la topologie et les règles d'anti-affinité. Vous pouvez utiliser une ou plusieurs de ces fonctionnalités. Les exigences que vous définissez sont reliées par l'opérateur AND par kube-scheduler
.
Les journaux du programmeur ne sont pas capturés au niveau de verbosité de la journalisation par défaut. Si vous avez besoin des journaux du programmeur à des fins de dépannage, procédez comme suit pour les capturer:
Augmentez le niveau de verbosité de la journalisation:
Modifiez l'objet Deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Ajoutez l'indicateur
--v=5
dans la sectionspec.containers.command
:containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true - --v=5
Lorsque vous avez terminé le dépannage, rétablissez le niveau de verbosité par défaut:
Modifiez l'objet Deployment
kube-scheduler
:kubectl --kubeconfig ADMIN_CLUSTER_KUBECONFIG edit deployment kube-scheduler \ -n USER_CLUSTER_NAMESPACE
Redéfinissez le niveau de verbosité sur la valeur par défaut:
containers: - command: - kube-scheduler - --profiling=false - --kubeconfig=/etc/kubernetes/scheduler.conf - --leader-elect=true
Contraintes de répartition de la topologie
Les contraintes de répartition de topologie permettent de répartir uniformément les pods entre les nœuds en fonction de leur topologie zones
, regions
, node
ou d'une autre topologie personnalisée.
L'exemple de fichier manifeste suivant montre un déploiement qui répartit équitablement les instances répliquées entre tous les nœuds programmables à l'aide de contraintes de répartition de la topologie:
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
Les considérations suivantes s'appliquent lorsque vous utilisez des contraintes de répartition de la topologie:
- Le paramètre
labels.app: myapp
d'un pod est associé au paramètrelabelSelector
de la contrainte. - Le
topologyKey
spécifiekubernetes.io/hostname
. Cette étiquette est automatiquement associée à tous les nœuds et renseignée avec le nom d'hôte du nœud. - Le
matchLabelKeys
empêche les déploiements de nouveaux déploiements de tenir compte des pods d'anciennes révisions lors du calcul de l'emplacement de planification d'un pod. L'étiquettepod-template-hash
est automatiquement renseignée par un déploiement.
Anti-affinité de pod
L'anti-affinité de pod vous permet de définir des contraintes pour lesquelles les pods peuvent être colocalisés sur le même nœud.
L'exemple de fichier manifeste suivant montre un déploiement qui utilise l'anti-affinité pour limiter les instances répliquées à un pod par nœud:
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
Cet exemple de déploiement spécifie 30
instances répliquées, mais ne s'étend qu'au nombre de nœuds disponibles dans votre cluster.
Les considérations suivantes s'appliquent lorsque vous utilisez l'anti-affinité de pod:
- Le paramètre
labels.app: myapp
d'un pod est associé au paramètrelabelSelector
de la contrainte. - Le
topologyKey
spécifiekubernetes.io/hostname
. Cette étiquette est automatiquement associée à tous les nœuds et renseignée avec le nom d'hôte du nœud. Vous pouvez choisir d'utiliser d'autres étiquettes si votre cluster les accepte, telles queregion
ouzone
.
Extraire des images de conteneurs à l'avance
En l'absence de toute autre contrainte, kube-scheduler
préfère programmer par défaut les pods sur les nœuds sur lesquels l'image de conteneur a déjà été téléchargée. Ce comportement peut être intéressant dans les clusters plus petits sans autre configuration de planification, où il serait possible de télécharger les images sur chaque nœud. Cependant, s'appuyer sur ce concept ne doit être considéré qu'en dernier recours. Une meilleure solution consiste à utiliser nodeSelector
, des contraintes de propagation de la topologie ou des contraintes d'affinité / anti-affinité. Pour en savoir plus, consultez la page Affecter des pods à des nœuds.
Pour vous assurer que les images de conteneurs sont pré-pullées sur tous les nœuds, vous pouvez utiliser un DaemonSet
comme dans l'exemple suivant:
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
Une fois que le pod est à l'état Running
sur tous les nœuds, redéployez vos pods pour voir si les conteneurs sont maintenant répartis uniformément entre les nœuds.