Bonnes pratiques relatives aux fonctionnalités avancées du planificateur dans Azure Kubernetes Service (AKS)

Quand vous gérez des clusters dans Azure Kubernetes Service (AKS), il est souvent nécessaire d’isoler les équipes et les charges de travail. Les fonctionnalités avancées fournies par le planificateur Kubernetes vous permettent de contrôler :

  • Quels pods peuvent être planifiés sur certains nœuds.
  • La manière dont les applications multipods peuvent être distribuées de manière appropriée sur le cluster.

Cet article traite des bonnes pratiques relatives aux fonctionnalités de planification Kubernetes avancées pour les opérateurs de clusters. Dans cet article, vous apprendrez comment :

  • Utiliser des teintes (taints) et des tolérances (tolerations) pour limiter les pods pouvant être planifiés sur des nœuds.
  • Privilégier l’exécution de pods sur certains nœuds avec des sélecteurs de nœuds ou l’affinité de nœud.
  • Diviser ou regrouper des pods avec l’affinité ou l’anti-affinité entre pods.
  • Limitez la planification des charges de travail exigeant des GPU aux seuls nœuds dotés de GPU programmables.

Fournir des nœuds dédiés à l’aide de teintes et de tolérances

Guide des meilleures pratiques :

Limitez l’accès des applications gourmandes en ressources, comme les contrôleurs d’entrée, à des nœuds spécifiques. Conservez les ressources de nœud disponibles pour les charges de travail qui en ont besoin et n’autorisez pas la planification d’autres charges de travail sur les nœuds.

Quand vous créez votre cluster AKS, vous pouvez déployer des nœuds avec prise en charge des unités centrales graphiques (GPU) ou un grand nombre de processeurs puissants. Pour plus d’informations, consultez Utilisation des GPU sur AKS. Vous pouvez utiliser ces nœuds pour les charges de travail de traitement de données volumineuses, notamment celles liées au Machine Learning (ML) ou à l’intelligence artificielle (IA).

Le déploiement de ce matériel de ressources de nœuds étant généralement coûteux, limitez les charges de travail qui peuvent être planifiées sur ces nœuds. Vous devriez plutôt dédier certains nœuds du cluster à l’exécution des services d’entrée et empêcher d’autres charges de travail.

Cette prise en charge pour différents nœuds est fournie à l’aide de plusieurs pools de nœuds. Un cluster AKS prend en charge un ou plusieurs pools de nœuds.

Le planificateur Kubernetes utilise des teintes et des tolérances pour restreindre les charges de travail qui peuvent s’exécuter sur des nœuds.

  • Appliquez une teinte à un nœud pour indiquer que seuls des pods spécifiques peuvent être planifiés sur celui-ci.
  • Appliquez ensuite une tolérance à un pod, lui permettant de tolérer la teinte d’un nœud.

Quand vous déployez un pod sur un cluster AKS, Kubernetes planifie uniquement des pods sur les nœuds dont la teinte correspond à la tolérance. Les teintes et tolérances fonctionnent ensemble pour s’assurer que les pods ne sont pas planifiés sur des nœuds inappropriés. Une ou plusieurs teintes sont appliquées à un nœud, le marquant afin qu’il n’accepte pas les pods qui ne tolèrent pas les teintes.

Par exemple, supposons que vous avez ajouté un pool de nœuds dans votre cluster AKS pour les nœuds avec prise en charge des GPU. Vous définissez un nom, comme gpu, puis une valeur pour la planification. En définissant cette valeur sur NoSchedule, le planificateur Kubernetes ne peut pas planifier les pods sans tolérance définie sur le nœud.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name taintnp \
    --node-taints sku=gpu:NoSchedule \
    --no-wait

Après avoir appliqué une teinte aux nœuds dans le pool de nœuds, vous définissez une tolérance dans la spécification de pod qui autorise la planification sur les nœuds. L’exemple suivant définit sku: gpu et effect: NoSchedule pour tolérer la teinte appliquée au pool de nœuds à l’étape précédente :

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  tolerations:
  - key: "sku"
    operator: "Equal"
    value: "gpu"
    effect: "NoSchedule"

Quand ce pod est déployé en utilisant kubectl apply -f gpu-toleration.yaml, Kubernetes peut planifier le pod sur les nœuds avec la teinte appliquée. Cette isolation logique vous permet de contrôler l’accès aux ressources au sein d’un cluster.

Quand vous appliquez des teintes, collaborez avec les développeurs et propriétaires d’applications pour leur permettre de définir les tolérances requises dans leurs déploiements.

Pour plus d'informations sur l'utilisation de plusieurs pools de nœuds dans AKS, consultez Créer plusieurs pools de nœuds pour un cluster dans AKS.

Comportement des teintes et des tolérances dans AKS

Lorsque vous mettez à niveau un pool de nœuds dans AKS, les teintes et les tolérances suivent un modèle défini lorsqu’elles sont appliquées à de nouveaux nœuds :

Clusters par défaut qui utilisent Azure Virtual Machine Scale Sets

Vous pouvez appliquer une teinte à un pool de nœuds à partir de l’API AKS afin que les nœuds sur lesquels un scale-out vient d’être effectué reçoivent des teintes de nœud spécifiés par l’API.

Supposons que :

  1. Vous commencez avec un cluster à deux nœuds : node1 et node2.
  2. Vous mettez à niveau le pool de nœuds.
  3. Deux autres nœuds sont créés : node3 et node4.
  4. Les teintes sont transmises respectivement.
  5. Les node1 et node2 originaux sont supprimés.

Clusters sans prise en charge de Virtual Machine Scale Sets

Là encore, supposons que :

  1. Vous avez un cluster à deux nœuds : node1 et node2.
  2. Vous mettez à niveau le pool de nœuds.
  3. Un nœud supplémentaire est créé : node3.
  4. Les teintes de node1 sont appliquées à node3.
  5. node1 est supprimé.
  6. Un nouveau node1 est créé pour remplacer le node1 d’origine.
  7. Les teintes de node2 sont appliquées au nouveau node1.
  8. node2 est supprimé.

En substance, node1 devient node3 et node2 devient le nouveau node1.

Lorsque vous faites évoluer un pool de nœuds dans AKS, les teintes et les tolérances ne sont pas transmises par défaut.

Contrôler la planification des pods à l’aide de sélecteurs de nœud et de l’affinité de nœud

Conseils sur les bonnes pratiques

Contrôlez la planification des pods sur les nœuds à l’aide de sélecteurs de nœuds, de l’affinité entre nœuds ou de l’affinité entre pods. Ces paramètres permettent au planificateur Kubernetes d’isoler logiquement les charges de travail, notamment par matériel dans le nœud.

Les teintes et les tolérances isolent logiquement les ressources avec une coupure dure. Si le pod ne tolère pas la teinte d’un nœud, il n’est pas planifié sur ce nœud.

Vous pouvez également utiliser des sélecteurs de nœuds. Par exemple, vous étiquetez les nœuds pour indiquer un stockage SSD attaché localement ou une grande quantité de mémoire, puis vous définissez un sélecteur de nœuds dans la spécification du pod. Kubernetes planifie ces pods sur un nœud correspondant.

Contrairement aux tolérances, les pods sans sélecteur de nœuds correspondant peuvent toujours être planifiés sur des nœuds étiquetés. Ce comportement autorise la consommation des ressources inutilisées sur les nœuds, mais donne la priorité aux pods qui définissent le sélecteur de nœuds correspondant.

Examinons un exemple de nœuds avec une grande quantité de mémoire. Ces nœuds donnent la priorité aux pods qui demandent une grande quantité de mémoire. Pour s’assurer que les ressources ne restent pas inutilisées, d’autres pods sont également autorisés à s’exécuter. L’exemple de commande suivant ajoute un pool de nœuds avec l’étiquette hardware= highmem à myAKSCluster dans myResourceGroup. Tous les nœuds de ce pool de nœuds ont cette étiquette.

az aks nodepool add \
    --resource-group myResourceGroup \
    --cluster-name myAKSCluster \
    --name labelnp \
    --node-count 1 \
    --labels hardware=highmem \
    --no-wait

Une spécification de pod ajoute ensuite la propriété nodeSelector pour définir un sélecteur de nœud qui correspond à l’étiquette définie sur un nœud :

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  nodeSelector:
      hardware: highmem

Quand vous utilisez ces options du planificateur, collaborez avec les propriétaires et développeurs d’applications pour leur permettre de définir correctement leurs spécifications de pod.

Pour plus d’informations sur l’utilisation de sélecteurs de nœud, consultez Affectation de pods à des nœuds.

Affinité de nœud

Un sélecteur de nœuds est une solution de base permettant d’attribuer des pods à un nœud donné. L’affinité de nœud offre plus de flexibilité, vous permettant de définir ce qui se passe si le pod ne peut pas être mis en correspondance avec un nœud. Vous pouvez :

  • exiger que le planificateur Kubernetes mette en correspondance un pod avec un hôte étiqueté ; Ou,
  • préférer une correspondance, mais autoriser la planification du pod sur un autre hôte si aucune correspondance n’est disponible.

L’exemple suivant définit l’affinité de nœud avec la valeur requiredDuringSchedulingIgnoredDuringExecution. Selon cette affinité, la planification Kubernetes doit utiliser un nœud avec une étiquette correspondante. Si aucun nœud n’est disponible, le pod doit attendre pour que planification puisse se poursuivre. Pour autoriser la planification du pod sur un autre nœud, vous pouvez définir la valeur sur *preferredDuringSchedulingIgnoreDuringExecution :

kind: Pod
apiVersion: v1
metadata:
  name: app
spec:
  containers:
  - name: app
    image: <your-workload>:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: hardware
            operator: In
            values:
            - highmem

La partie IgnoredDuringExecution du paramètre indique que le pod ne doit pas être supprimé du nœud si ses étiquettes viennent à changer. Le planificateur Kubernetes n’utilise les étiquettes de nœud mises à jour que pour les nouveaux pods en cours de planification, pas pour ceux déjà planifiés sur les nœuds.

Pour plus d’informations, consultez Affinité et anti-affinité.

Affinité et anti-affinité entre pods

Une dernière approche, employée par le planificateur Kubernetes pour isoler logiquement des charges de travail, consiste à utiliser l’affinité ou l’anti-affinité entre pods. Ces paramètres définissent si oui ou non des pods peuvent être planifiés sur un nœud ayant un pod correspondant. Par défaut, le planificateur Kubernetes essaie de planifier plusieurs pods dans un jeu de réplicas sur les nœuds. Vous pouvez définir des règles plus spécifiques autour de ce comportement.

Par exemple, vous avez une application web qui utilise également Azure Cache pour Redis.

  • Vous utilisez des règles d’anti-affinité de pods pour demander au planificateur Kubernetes de distribuer les réplicas entre les nœuds.
  • Vous utilisez des règles d’affinité pour vous assurer que chaque composant de l’application web est planifié sur le même hôte que le cache correspondant.

La distribution des pods sur les nœuds est similaire à celle de l’exemple suivant :

Nœud 1 Nœud 2 Nœud 3
webapp-1 webapp-2 webapp-3
cache-1 cache-2 cache-3

L’affinité et l’anti-affinité entre pods permettent un déploiement plus complexe que les sélecteurs de nœuds ou l’affinité des nœuds. Grâce à ce déploiement, vous isolez logiquement les ressources et contrôlez la manière dont Kubernetes planifie les pods sur les nœuds.

Pour obtenir un exemple complet de cette application web avec un exemple Azure Cache pour Redis, consultez Colocaliser des pods sur le même nœud.

Étapes suivantes

Dans cet article, nous avons traité des fonctionnalités avancées du planificateur Kubernetes. Pour plus d’informations sur les opérations liées aux clusters dans AKS, consultez les bonnes pratiques suivantes :