Répartissez les charges de travail entre les nœuds et les zones de disponibilité - AWS Directives prescriptives

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Répartissez les charges de travail entre les nœuds et les zones de disponibilité

La répartition d'une charge de travail entre des domaines de défaillance tels que les zones de disponibilité et les nœuds améliore la disponibilité des composants et réduit les risques de défaillance pour les applications évolutives horizontalement. Les sections suivantes présentent les moyens de répartir les charges de travail entre les nœuds et les zones de disponibilité.

Utiliser les contraintes de propagation de la topologie des pods

Les contraintes de propagation de la topologie des pods Kubernetes indiquent au planificateur Kubernetes de distribuer les pods gérés par ReplicaSet ou StatefulSet entre différents domaines de défaillance (zones de disponibilité, nœuds et types de matériel). Lorsque vous utilisez les contraintes de propagation de la topologie des pods, vous pouvez effectuer les opérations suivantes :

  • Répartissez ou concentrez les pods sur différents domaines de défaillance en fonction des exigences de l'application. Par exemple, vous pouvez distribuer des pods pour renforcer la résilience, et vous pouvez concentrer les pods pour améliorer les performances du réseau.

  • Combinez différentes conditions, telles que la distribution entre les zones de disponibilité et la distribution entre les nœuds.

  • Spécifiez l'action préférée si les conditions ne peuvent pas être remplies :

    • whenUnsatisfiable: DoNotScheduleÀ utiliser avec une combinaison de maxSkew et minDomains pour créer des exigences strictes pour le planificateur.

    • whenUnsatisfiable: ScheduleAnywayÀ utiliser pour réduiremaxSkew.

Si une zone de défaillance devient indisponible, les pods de cette zone deviennent inutilisables. Kubernetes replanifie les pods tout en respectant si possible la contrainte de propagation.

Contraintes de propagation de la topologie des pods

Le code suivant montre un exemple d'utilisation des contraintes de répartition de la topologie des pods entre les zones de disponibilité ou entre les nœuds :

... spec: selector: matchLabels: app: <your-app-label> replicas: 3 template: metadata: labels: <your-app-label> spec: serviceAccountName: <ServiceAccountName> ... topologySpreadConstraints: - labelSelector: matchLabels: app: <your-app-label> maxSkew: 1 topologyKey: topology.kubernetes.io/zone # <---spread those pods evenly over all availability zones whenUnsatisfiable: ScheduleAnyway - labelSelector: matchLabels: app: <your-app-label> maxSkew: 1 topologyKey: kubernetes.io/hostname # <---spread those pods evenly over all nodes whenUnsatisfiable: ScheduleAnyway

Contraintes de dispersion topologique par défaut à l'échelle du cluster

Kubernetes fournit un ensemble par défaut de contraintes de répartition topologique pour la distribution des pods entre les nœuds et les zones de disponibilité :

defaultConstraints: - maxSkew: 3 topologyKey: "kubernetes.io/hostname" whenUnsatisfiable: ScheduleAnyway - maxSkew: 5 topologyKey: "topology.kubernetes.io/zone" whenUnsatisfiable: ScheduleAnyway
Note

Les applications qui nécessitent différents types de contraintes topologiques peuvent contourner la politique au niveau du cluster.

Les contraintes par défaut définissent une valeur élevéemaxSkew, ce qui n'est pas utile pour les déploiements comportant un petit nombre de pods. Pour le moment, il ne KubeSchedulerConfiguration peut pas être modifié dans Amazon EKS. Si vous devez appliquer d'autres ensembles de contraintes de propagation topologique, pensez à utiliser un contrôleur d'admission mutant, comme indiqué dans la section ci-dessous. Vous pouvez également contrôler les contraintes de propagation topologique par défaut si vous exécutez un autre planificateur. Cependant, la gestion des planificateurs personnalisés ajoute de la complexité et peut avoir des répercussions sur la résilience des clusters et sur la haute disponibilité. Pour ces raisons, nous ne recommandons pas d'utiliser un autre planificateur uniquement pour les contraintes de dispersion topologique.

La politique de Gatekeeper pour les contraintes de dispersion topologique

Une autre option pour appliquer les contraintes de dispersion topologique consiste à utiliser une politique issue du projet Gatekeeper. Les politiques Gatekeeper sont définies au niveau de l'application.

Les exemples de code suivants montrent l'utilisation d'une Gatekeeper OPA politique de déploiement. Vous pouvez modifier la politique en fonction de vos besoins. Par exemple, appliquez la politique uniquement aux déploiements portant l'étiquetteHA=true, ou rédigez une stratégie similaire à l'aide d'un contrôleur de stratégie différent.

Ce premier exemple montre une ConstraintTemplate utilisation avec k8stopologyspreadrequired_template.yml :

apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate metadata: name: k8stopologyspreadrequired spec: crd: spec: names: kind: K8sTopologySpreadRequired validation: openAPIV3Schema: type: object properties: message: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8stopologyspreadrequired get_message(parameters, _default) =3D msg { not parameters.message msg :=_default } get_message(parameters, _default) =3D msg { msg := parameters.message } violation[{"msg": msg}] { input.review.kind.kind ="Deployment" not input.review.object.spec.template.spec.topologySpreadConstraint def_msg :"Pod Topology Spread Constraints are required for Deployments" msg :get_message(input.parameters, def_msg) }

Le code suivant montre le manifeste constraints k8stopologyspreadrequired_constraint.yml YAML :

apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sTopologySpreadRequired metadata: name: require-topologyspread-for-deployments spec: match: kinds: - apiGroups: ["apps"] kinds: ["Deployment"] namespaces: ## Without theses two lines will apply to the whole cluster - "example"

Quand utiliser les contraintes de dispersion topologique

Envisagez d'utiliser des contraintes de dispersion topologique pour les scénarios suivants :

  • Toute application évolutive horizontalement (par exemple, les services Web sans état)

  • Applications avec des répliques active-active ou active-passive (par exemple, bases de données ou caches NoSQL)

  • Applications dotées de répliques en veille (par exemple, contrôleurs)

Les composants du système qui peuvent être utilisés pour le scénario évolutif horizontalement, par exemple, sont les suivants :

Affinité et anti-affinité des capsules

Dans certains cas, il est avantageux de s'assurer que seul un pod d'un type spécifique est exécuté sur un nœud. Par exemple, pour éviter de planifier plusieurs pods gourmands en réseau sur le même nœud, vous pouvez utiliser la règle anti-affinité avec l'étiquette ou. Ingress Network-heavy Lorsque vous utilisezanti-affinity, vous pouvez également utiliser une combinaison des éléments suivants :

  • Taches sur les nœuds optimisés pour le réseau

  • Tolérances correspondantes sur les pods fortement sollicités par le réseau

  • Affinité de nœud ou sélecteur de nœuds pour garantir que les pods à forte densité réseau utilisent des instances optimisées pour le réseau

Les pods chargés en réseau sont utilisés à titre d'exemple. Vous pouvez avoir des exigences différentes, telles que le GPU, la mémoire ou le stockage local. Pour d'autres exemples d'utilisation et options de configuration, consultez la documentation de Kubernetes.

Capsules de rééquilibrage

Cette section décrit deux approches pour rééquilibrer les pods dans un cluster Kubernetes. Le premier utilise le Descheduler pour Kubernetes. Le Descheduler aide à maintenir la distribution des pods en appliquant des stratégies pour supprimer les pods qui enfreignent les contraintes de propagation topologique ou les règles anti-affinité. La deuxième approche utilise la fonction de consolidation et d'emballage des bacs de Karpenter. La consolidation évalue et optimise en permanence l'utilisation des ressources en consolidant les charges de travail sur un plus petit nombre de nœuds et de manière plus efficace.

Nous vous recommandons d'utiliser Descheduler si vous n'utilisez pas Karpenter. Si vous utilisez Karpenter et Cluster Autoscaler ensemble, vous pouvez utiliser Descheduler avec Cluster Autoscaler pour les groupes de nœuds.

Déplanificateur pour nœuds sans groupe

Rien ne garantit que les contraintes topologiques restent satisfaites lorsque les pods sont supprimés. Par exemple, la réduction d'un déploiement peut entraîner une distribution déséquilibrée des pods. Cependant, étant donné que Kubernetes utilise les contraintes de propagation de la topologie des pods uniquement au stade de la planification, les pods sont déséquilibrés dans le domaine de défaillance.

Pour maintenir une distribution équilibrée des pods dans de tels scénarios, vous pouvez utiliser Descheduler pour Kubernetes. Le dééchelonneur est un outil utile à de multiples fins, par exemple pour faire respecter l'âge ou la durée de vie maximum des capsules (TTL) ou pour améliorer l'utilisation de l'infrastructure. Dans le contexte de la résilience et de la haute disponibilité (HA), considérez les stratégies de Descheduler suivantes :

Fonctionnalité de consolidation et d'emballage en bacs de Karpenter

Pour les charges de travail qui utilisent Karpenter, vous pouvez utiliser les fonctionnalités de consolidation et de regroupement pour optimiser l'utilisation des ressources et réduire les coûts dans les clusters Kubernetes. Karpenter évalue en permanence l'emplacement des pods et l'utilisation des nœuds, et tente de consolider les charges de travail sur un nombre réduit de nœuds et de manière plus efficace lorsque cela est possible. Ce processus implique l'analyse des besoins en ressources, la prise en compte des contraintes telles que les règles d'affinité des pods et le déplacement éventuel des pods entre les nœuds afin d'améliorer l'efficacité globale du cluster. Le code suivant fournit un exemple :

apiVersion: karpenter.sh/v1beta1 kind: NodePool metadata: name: default spec: disruption: consolidationPolicy: WhenUnderutilized expireAfter: 720h

PourconsolidationPolicy, vous pouvez utiliser WhenUnderutilized ou WhenEmpty :

  • Lorsque consolidationPolicy ce paramètre est défini surWhenUnderutilized, Karpenter prend en compte tous les nœuds à consolider. Lorsque Karpenter découvre un nœud vide ou sous-utilisé, Karpenter tente de le supprimer ou de le remplacer afin de réduire les coûts.

  • Lorsqu'il consolidationPolicy est défini surWhenEmpty, Karpenter ne prend en compte pour la consolidation que les nœuds qui ne contiennent aucun module de charge de travail.

Les décisions de consolidation de Karpenter ne sont pas basées uniquement sur les pourcentages d'utilisation du processeur ou de la mémoire que vous pourriez observer dans les outils de surveillance. Karpenter utilise plutôt un algorithme plus complexe basé sur les demandes de ressources du pod et les optimisations potentielles des coûts. Pour en savoir plus, veuillez consulter la documentation Karpenter.