Plan de données Kubernetes - Amazon EKS

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.

Plan de données Kubernetes

La sélection des types d' EC2 instances est probablement l'une des décisions les plus difficiles auxquelles les clients sont confrontés, car il s'agit de clusters comportant de multiples charges de travail. Il n'y a pas one-size-fits de solution complète. Voici quelques conseils qui vous aideront à éviter les écueils courants liés à la mise à l'échelle du calcul.

Mise à l'échelle automatique des nœuds

Nous vous recommandons d'utiliser la mise à l'échelle automatique des nœuds qui réduit la charge de travail et s'intègre parfaitement à Kubernetes. Les groupes de nœuds gérés et Karpenter sont recommandés pour les clusters à grande échelle.

Les groupes de nœuds gérés vous offrent la flexibilité des groupes Amazon EC2 Auto Scaling, avec des avantages supplémentaires en termes de gestion des mises à niveau et de configuration. Il peut être mis à l'échelle à l'aide du Kubernetes Cluster Autoscaler et constitue une option courante pour les clusters ayant des besoins informatiques variés.

Karpenter est un autoscaler de nœuds open source, natif de la charge de travail, créé par AWS. Il fait évoluer les nœuds d'un cluster en fonction des exigences de charge de travail en matière de ressources (par exemple, GPU) et des contraintes et des tolérances (par exemple, la répartition des zones) sans gérer les groupes de nœuds. Les nœuds sont créés directement, EC2 ce qui permet d'éviter les quotas de groupes de nœuds par défaut (450 nœuds par groupe) et d'offrir une plus grande flexibilité de sélection d'instances tout en réduisant les frais opérationnels. Nous recommandons aux clients d'utiliser Karpenter dans la mesure du possible.

Utilisez de nombreux types d' EC2 instances différents

Chaque région AWS dispose d'un nombre limité d'instances disponibles par type d'instance. Si vous créez un cluster qui n'utilise qu'un seul type d'instance et que vous augmentez le nombre de nœuds au-delà de la capacité de la région, vous recevrez un message d'erreur indiquant qu'aucune instance n'est disponible. Pour éviter ce problème, vous ne devez pas limiter arbitrairement le type d'instances pouvant être utilisées dans votre cluster.

Karpenter utilisera par défaut un large éventail de types d'instances compatibles et choisira une instance au moment du provisionnement en fonction des exigences en matière de charge de travail, de disponibilité et de coût. Vous pouvez élargir la liste des types d'instances utilisés dans la karpenter.k8s.aws/instance-category clé de NodePools.

Le Kubernetes Cluster Autoscaler nécessite que les groupes de nœuds soient de taille similaire afin qu'ils puissent être mis à l'échelle de manière cohérente. Vous devez créer plusieurs groupes en fonction de la taille du processeur et de la mémoire et les dimensionner indépendamment. Utilisez le sélecteur d'instance ec2 pour identifier les instances dont la taille est similaire à celle de vos groupes de nœuds.

ec2-instance-selector --service eks --vcpus-min 8 --memory-min 16
a1.2xlarge
a1.4xlarge
a1.metal
c4.4xlarge
c4.8xlarge
c5.12xlarge
c5.18xlarge
c5.24xlarge
c5.2xlarge
c5.4xlarge
c5.9xlarge
c5.metal

Préférez des nœuds plus grands pour réduire la charge du serveur d'API

Lorsque vous décidez des types d'instances à utiliser, le nombre réduit de nœuds volumineux alourdira le plan de contrôle Kubernetes, car il y aura moins de kubelets et moins de nœuds en cours d'exécution. DaemonSets Cependant, les nœuds de grande taille peuvent ne pas être pleinement utilisés comme les nœuds plus petits. La taille des nœuds doit être évaluée en fonction de la disponibilité de votre charge de travail et de vos exigences d'échelle.

Un cluster avec trois instances u-24tb1.metal (24 To de mémoire et 448 cœurs) possède 3 kubelets et serait limité à 110 pods par nœud par défaut. Si vos pods utilisent 4 cœurs chacun, cela peut être attendu (4 cœurs x 110 = 440 cœurs/nœud). Avec un cluster à 3 nœuds, votre capacité à gérer un incident d'instance serait faible, car une panne d'instance pourrait avoir un impact sur un tiers du cluster. Vous devez spécifier les exigences relatives aux nœuds et la répartition des pods dans vos charges de travail afin que le planificateur Kubernetes puisse placer correctement les charges de travail.

Les charges de travail doivent définir les ressources dont elles ont besoin et la disponibilité requise en fonction des contraintes, des tolérances et. PodTopologySpread Ils doivent préférer les nœuds les plus grands qui peuvent être pleinement utilisés et atteindre les objectifs de disponibilité afin de réduire la charge du plan de contrôle, de réduire les opérations et de réduire les coûts.

Le planificateur Kubernetes essaiera automatiquement de répartir les charges de travail entre les zones de disponibilité et les hôtes si des ressources sont disponibles. Si aucune capacité n'est disponible, le Kubernetes Cluster Autoscaler tentera d'ajouter des nœuds de manière uniforme dans chaque zone de disponibilité. Karpenter essaiera d'ajouter des nœuds le plus rapidement et le moins cher possible, sauf si la charge de travail spécifie d'autres exigences.

Pour forcer les charges de travail à se répartir avec le planificateur et à créer de nouveaux nœuds entre les zones de disponibilité, vous devez utiliser : topologySpreadConstraints

spec:
  topologySpreadConstraints:
    - maxSkew: 3
      topologyKey: "topology.kubernetes.io/zone"
      whenUnsatisfiable: ScheduleAnyway
      labelSelector:
        matchLabels:
          dev: my-deployment
    - maxSkew: 2
      topologyKey: "kubernetes.io/hostname"
      whenUnsatisfiable: ScheduleAnyway
      labelSelector:
        matchLabels:
          dev: my-deployment

Utilisez des tailles de nœuds similaires pour des performances de charge de travail cohérentes

Les charges de travail doivent définir la taille des nœuds sur lesquels elles doivent être exécutées afin de garantir des performances constantes et une mise à l'échelle prévisible. Une charge de travail nécessitant 500 millions de processeurs fonctionnera différemment sur une instance à 4 cœurs par rapport à une instance à 16 cœurs. Évitez les types d'instance qui utilisent le burstable, CPUs comme les instances de la série T.

Pour garantir des performances constantes à vos charges de travail, une charge de travail peut utiliser les étiquettes Karpenter compatibles pour cibler des tailles d'instances spécifiques.

kind: deployment
...
spec:
  template:
    spec:
    containers:
    nodeSelector:
      karpenter.k8s.aws/instance-size: 8xlarge

Les charges de travail planifiées dans un cluster à l'aide du Kubernetes Cluster Autoscaler doivent associer un sélecteur de nœuds à des groupes de nœuds en fonction de la correspondance des étiquettes.

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: eks.amazonaws.com/nodegroup
            operator: In
            values:
            - 8-core-node-group    # match your node group name

Utiliser efficacement les ressources informatiques

Les ressources de calcul incluent EC2 les instances et les zones de disponibilité. L'utilisation efficace des ressources informatiques augmentera votre évolutivité, votre disponibilité, vos performances et réduira votre coût total. L'utilisation efficace des ressources est extrêmement difficile à prévoir dans un environnement de mise à l'échelle automatique comportant plusieurs applications. Karpenter a été créé pour fournir des instances à la demande en fonction des besoins de charge de travail afin de maximiser l'utilisation et la flexibilité.

Karpenter permet aux charges de travail de déclarer le type de ressources informatiques dont elles ont besoin sans créer au préalable des groupes de nœuds ou configurer des étiquettes altérées pour des nœuds spécifiques. Consultez les meilleures pratiques de Karpenter pour plus d'informations. Envisagez d'activer la consolidation dans votre fournisseur Karpenter pour remplacer les nœuds sous-utilisés.

Automatisez les mises à jour d'Amazon Machine Image (AMI)

La mise à jour des composants du nœud de travail vous permettra de disposer des derniers correctifs de sécurité et des fonctionnalités compatibles avec l'API Kubernetes. La mise à jour du kubelet est le composant le plus important pour les fonctionnalités de Kubernetes, mais l'automatisation du système d'exploitation, du noyau et des correctifs d'applications installés localement réduira la maintenance à mesure que vous évoluerez.

Il est recommandé d'utiliser la dernière AMI Bottlerocket optimisée pour Amazon EKS ou la dernière AMI Bottlerocket optimisée pour Amazon EKS pour l'image de votre nœud. Karpenter utilisera automatiquement la dernière AMI disponible pour approvisionner de nouveaux nœuds dans le cluster. Les groupes de nœuds gérés mettront à jour l'AMI lors d'une mise à jour de groupe de nœuds, mais ne mettront pas à jour l'ID de l'AMI au moment du provisionnement du nœud.

Pour les groupes de nœuds gérés, vous devez mettre à jour le modèle de lancement d'Auto Scaling Group (ASG) avec de nouvelles AMI IDs lorsqu'elles seront disponibles pour les versions de correctifs. Les versions mineures de l'AMI (par exemple 1.23.5 à 1.24.3) seront disponibles dans la console EKS et dans l'API sous forme de mises à niveau pour le groupe de nœuds. Les versions de patch (par exemple 1.23.5 à 1.23.6) ne seront pas présentées comme des mises à niveau pour les groupes de nœuds. Si vous souhaitez maintenir votre groupe de nœuds à jour avec les versions de correctifs de l'AMI, vous devez créer une nouvelle version du modèle de lancement et laisser le groupe de nœuds remplacer les instances par la nouvelle version de l'AMI.

Vous pouvez trouver la dernière AMI disponible sur cette page ou utiliser l'interface de ligne de commande AWS.

aws ssm get-parameter \
  --name /aws/service/eks/optimized-ami/1.24/amazon-linux-2/recommended/image_id \
  --query "Parameter.Value" \
  --output text

Utiliser plusieurs volumes EBS pour les conteneurs

Les volumes EBS ont un quota input/output (E/S) basé sur le type de volume (par exemple gp3) et la taille du disque. Si vos applications partagent un seul volume racine EBS avec l'hôte, cela peut épuiser le quota de disque pour l'ensemble de l'hôte et obliger les autres applications à attendre la capacité disponible. Les applications écrivent sur le disque si elles écrivent des fichiers sur leur partition superposée, montent un volume local depuis l'hôte, et également lorsqu'elles se déconnectent en sortie standard (STDOUT), selon l'agent de journalisation utilisé.

Pour éviter I/O l'épuisement du disque, vous devez monter un deuxième volume dans le dossier d'état du conteneur (par exemple /run/containerd), utiliser des volumes EBS distincts pour le stockage de la charge de travail et désactiver la journalisation locale inutile.

Pour monter un deuxième volume sur vos EC2 instances à l'aide d'eksctl, vous pouvez utiliser un groupe de nœuds avec cette configuration :

managedNodeGroups:
  - name: al2-workers
    amiFamily: AmazonLinux2
    desiredCapacity: 2
    volumeSize: 80
    additionalVolumes:
      - volumeName: '/dev/sdz'
        volumeSize: 100
    preBootstrapCommands:
    - |
      "systemctl stop containerd"
      "mkfs -t ext4 /dev/nvme1n1"
      "rm -rf /var/lib/containerd/*"
      "mount /dev/nvme1n1 /var/lib/containerd/"
      "systemctl start containerd"

Si vous utilisez Terraform pour provisionner vos groupes de nœuds, veuillez consulter des exemples dans EKS Blueprints for Terraform. Si vous utilisez Karpenter pour approvisionner des nœuds, vous pouvez utiliser les données utilisateur blockDeviceMappingsdes nœuds pour ajouter des volumes supplémentaires.

Pour monter un volume EBS directement sur votre pod, vous devez utiliser le pilote AWS EBS CSI et utiliser un volume avec une classe de stockage.

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ebs-sc
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-claim
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: ebs-sc
  resources:
    requests:
      storage: 4Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
    image: public.ecr.aws/docker/library/nginx
    volumeMounts:
    - name: persistent-storage
      mountPath: /data
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: ebs-claim

Évitez les instances avec de faibles limites d'attachement EBS si les charges de travail utilisent des volumes EBS

L'EBS est l'un des moyens les plus simples pour les charges de travail de disposer d'un stockage persistant, mais il comporte également des limites d'évolutivité. Chaque type d'instance possède un nombre maximum de volumes EBS pouvant être attachés. Les charges de travail doivent déclarer les types d'instances sur lesquels elles doivent s'exécuter et limiter le nombre de répliques sur une seule instance présentant des caractéristiques de Kubernetes.

Désactiver la journalisation inutile sur le disque

Évitez la journalisation locale inutile en n'exécutant pas vos applications grâce à la journalisation de débogage en production et en désactivant la journalisation qui lit et écrit fréquemment sur le disque. Journald est le service de journalisation local qui conserve une mémoire tampon de journal et la vide régulièrement sur le disque. Journald est préféré à Syslog qui enregistre chaque ligne immédiatement sur le disque. La désactivation de Syslog réduit également la quantité totale de stockage dont vous avez besoin et évite d'avoir à appliquer des règles complexes de rotation des journaux. Pour désactiver Syslog, vous pouvez ajouter l'extrait suivant à votre configuration cloud-init :

runcmd:
  - [ systemctl, disable, --now, syslog.service ]

Instances de correctifs en place lorsque la vitesse de mise à jour du système d'exploitation est une nécessité

Important

L'application de correctifs aux instances en place ne doit être effectuée que lorsque cela est nécessaire. Amazon recommande de traiter l'infrastructure comme immuable et de tester de manière approfondie les mises à jour proposées dans des environnements inférieurs, de la même manière que les applications. Cette section s'applique lorsque cela n'est pas possible.

L'installation d'un package sur un hôte Linux existant prend quelques secondes sans perturber les charges de travail conteneurisées. Le package peut être installé et validé sans boucler, vider ou remplacer l'instance.

Pour remplacer une instance, vous devez d'abord en créer, en valider et en distribuer une nouvelle AMIs. Une instance de remplacement doit être créée, et l'ancienne instance doit être bouclée et vidée. Les charges de travail doivent ensuite être créées sur la nouvelle instance, vérifiées et répétées pour toutes les instances qui doivent être corrigées. Il faut des heures, des jours ou des semaines pour remplacer les instances en toute sécurité sans perturber les charges de travail.

Amazon recommande d'utiliser une infrastructure immuable créée, testée et promue à partir d'un système déclaratif automatisé, mais si vous devez appliquer des correctifs à des systèmes rapidement, vous devrez appliquer des correctifs aux systèmes en place et les remplacer au fur et à mesure que de nouveaux systèmes seront AMIs disponibles. En raison du décalage horaire important entre l'application de correctifs et le remplacement des systèmes, nous recommandons d'utiliser AWS Systems Manager Patch Manager pour automatiser l'application de correctifs aux nœuds lorsque cela est nécessaire.

L'application de correctifs aux nœuds vous permettra de déployer rapidement les mises à jour de sécurité et de remplacer les instances selon un calendrier régulier après la mise à jour de votre AMI. Si vous utilisez un système d'exploitation doté d'un système de fichiers racine en lecture seule, tel que Flatcar Container Linux ou Bottlerocket OS, nous vous recommandons d'utiliser les opérateurs de mise à jour compatibles avec ces systèmes d'exploitation. L'opérateur de mise à jour Flatcar Linux et l'opérateur de mise à jour Bottlerocket redémarreront les instances pour maintenir les nœuds à jour automatiquement.