Rechercher

7.4. Pratiques recommandées pour les hôtes de nœuds

download PDF

Le fichier de configuration des nœuds d'OpenShift Container Platform contient des options importantes. Par exemple, deux paramètres contrôlent le nombre maximum de pods qui peuvent être planifiés sur un nœud : podsPerCore et maxPods.

Lorsque les deux options sont utilisées, la plus faible des deux valeurs limite le nombre de pods sur un nœud. Le dépassement de ces valeurs peut avoir les conséquences suivantes

  • Augmentation de l'utilisation de l'unité centrale.
  • Lenteur de la programmation des pods.
  • Scénarios potentiels de dépassement de mémoire, en fonction de la quantité de mémoire dans le nœud.
  • Epuisement de la réserve d'adresses IP.
  • Surcharge des ressources, entraînant de mauvaises performances pour les applications utilisateur.
Important

Dans Kubernetes, un pod qui contient un seul conteneur utilise en réalité deux conteneurs. Le deuxième conteneur est utilisé pour mettre en place le réseau avant le démarrage du conteneur proprement dit. Par conséquent, un système exécutant 10 pods aura en réalité 20 conteneurs en cours d'exécution.

Note

La limitation des IOPS disque par le fournisseur de cloud peut avoir un impact sur CRI-O et kubelet. Ils peuvent être surchargés lorsqu'un grand nombre de pods à forte intensité d'E/S s'exécutent sur les nœuds. Il est recommandé de surveiller les E/S disque sur les nœuds et d'utiliser des volumes avec un débit suffisant pour la charge de travail.

podsPerCore définit le nombre de modules que le nœud peut exécuter en fonction du nombre de cœurs de processeur du nœud. Par exemple, si podsPerCore est défini sur 10 sur un nœud avec 4 cœurs de processeur, le nombre maximum de modules autorisés sur le nœud sera 40.

kubeletConfig:
  podsPerCore: 10

Le fait de régler podsPerCore sur 0 désactive cette limite. La valeur par défaut est 0. podsPerCore ne peut pas dépasser maxPods.

maxPods fixe le nombre de pods que le nœud peut exécuter à une valeur fixe, quelles que soient les propriétés du nœud.

 kubeletConfig:
    maxPods: 250

7.4.1. Création d'un CRD KubeletConfig pour éditer les paramètres des kubelets

La configuration du kubelet est actuellement sérialisée comme une configuration Ignition, elle peut donc être directement éditée. Cependant, une nouvelle adresse kubelet-config-controller a été ajoutée au contrôleur de configuration de la machine (MCC). Cela vous permet d'utiliser une ressource personnalisée (CR) KubeletConfig pour modifier les paramètres du kubelet.

Note

Comme les champs de l'objet kubeletConfig sont transmis directement au kubelet par Kubernetes en amont, le kubelet valide ces valeurs directement. Des valeurs non valides dans l'objet kubeletConfig peuvent entraîner l'indisponibilité des nœuds du cluster. Pour connaître les valeurs valides, consultez la documentation de Kubernetes.

Examinez les conseils suivants :

  • Créez un CR KubeletConfig pour chaque pool de configuration de machine avec toutes les modifications de configuration que vous souhaitez pour ce pool. Si vous appliquez le même contenu à tous les pools, vous n'avez besoin que d'un seul CR KubeletConfig pour tous les pools.
  • Modifiez un CR KubeletConfig existant pour modifier les paramètres existants ou en ajouter de nouveaux, au lieu de créer un CR pour chaque changement. Il est recommandé de ne créer un CR que pour modifier un pool de configuration de machine différent, ou pour des changements qui sont censés être temporaires, afin de pouvoir revenir sur les modifications.
  • Si nécessaire, créez plusieurs CR KubeletConfig dans la limite de 10 par cluster. Pour le premier CR KubeletConfig, l'opérateur de configuration de machine (MCO) crée une configuration de machine avec l'extension kubelet. Pour chaque CR suivant, le contrôleur crée une autre configuration machine kubelet avec un suffixe numérique. Par exemple, si vous avez une configuration machine kubelet avec un suffixe -2, la configuration machine kubelet suivante est complétée par -3.

Si vous souhaitez supprimer les configurations de machine, supprimez-les dans l'ordre inverse pour éviter de dépasser la limite. Par exemple, vous supprimez la configuration de la machine kubelet-3 avant de supprimer la configuration de la machine kubelet-2.

Note

Si vous avez une configuration de machine avec un suffixe kubelet-9 et que vous créez une autre CR KubeletConfig, une nouvelle configuration de machine n'est pas créée, même s'il y a moins de 10 configurations de machine kubelet.

Exemple KubeletConfig CR

$ oc get kubeletconfig

NAME                AGE
set-max-pods        15m

Exemple de configuration d'une machine KubeletConfig

$ oc get mc | grep kubelet

...
99-worker-generated-kubelet-1                  b5c5119de007945b6fe6fb215db3b8e2ceb12511   3.2.0             26m
...

La procédure suivante est un exemple qui montre comment configurer le nombre maximum de pods par nœud sur les nœuds de travail.

Conditions préalables

  1. Obtenez l'étiquette associée au CR statique MachineConfigPool pour le type de nœud que vous souhaitez configurer. Effectuez l'une des opérations suivantes :

    1. Voir le pool de configuration de la machine :

      oc describe machineconfigpool <name> $ oc describe machineconfigpool <name>

      Par exemple :

      $ oc describe machineconfigpool worker

      Exemple de sortie

      apiVersion: machineconfiguration.openshift.io/v1
      kind: MachineConfigPool
      metadata:
        creationTimestamp: 2019-02-08T14:52:39Z
        generation: 1
        labels:
          custom-kubelet: set-max-pods 1

      1
      Si un label a été ajouté, il apparaît sous labels.
    2. Si l'étiquette n'est pas présente, ajoutez une paire clé/valeur :

      $ oc label machineconfigpool worker custom-kubelet=set-max-pods

Procédure

  1. Affichez les objets de configuration de la machine disponibles que vous pouvez sélectionner :

    $ oc get machineconfig

    Par défaut, les deux configurations liées à kubelet sont 01-master-kubelet et 01-worker-kubelet.

  2. Vérifier la valeur actuelle du nombre maximum de pods par nœud :

    oc describe node <node_name>

    Par exemple :

    $ oc describe node ci-ln-5grqprb-f76d1-ncnqq-worker-a-mdv94

    Cherchez value: pods: <value> dans la strophe Allocatable:

    Exemple de sortie

    Allocatable:
     attachable-volumes-aws-ebs:  25
     cpu:                         3500m
     hugepages-1Gi:               0
     hugepages-2Mi:               0
     memory:                      15341844Ki
     pods:                        250

  3. Définissez le nombre maximum de pods par nœud sur les nœuds de travail en créant un fichier de ressources personnalisé qui contient la configuration du kubelet :

    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: set-max-pods
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: set-max-pods 1
      kubeletConfig:
        maxPods: 500 2
    1
    Saisissez l'étiquette du pool de configuration de la machine.
    2
    Ajoutez la configuration du kubelet. Dans cet exemple, utilisez maxPods pour définir le nombre maximum de pods par nœud.
    Note

    Le taux auquel le kubelet parle au serveur API dépend des requêtes par seconde (QPS) et des valeurs de rafale. Les valeurs par défaut, 50 pour kubeAPIQPS et 100 pour kubeAPIBurst, sont suffisantes si le nombre de pods fonctionnant sur chaque nœud est limité. Il est recommandé de mettre à jour les taux de QPS et de burst du kubelet s'il y a suffisamment de ressources de CPU et de mémoire sur le nœud.

    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: set-max-pods
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: set-max-pods
      kubeletConfig:
        maxPods: <pod_count>
        kubeAPIBurst: <burst_rate>
        kubeAPIQPS: <QPS>
    1. Mettre à jour le pool de configuration des machines pour les travailleurs avec le label :

      $ oc label machineconfigpool worker custom-kubelet=set-max-pods
    2. Créer l'objet KubeletConfig:

      $ oc create -f change-maxPods-cr.yaml
    3. Vérifiez que l'objet KubeletConfig est créé :

      $ oc get kubeletconfig

      Exemple de sortie

      NAME                AGE
      set-max-pods        15m

      En fonction du nombre de nœuds de travail dans la grappe, attendez que les nœuds de travail soient redémarrés un par un. Pour une grappe de 3 nœuds de travail, cela peut prendre de 10 à 15 minutes.

  4. Vérifiez que les modifications sont appliquées au nœud :

    1. Vérifier sur un nœud de travail que la valeur de maxPods a changé :

      oc describe node <node_name>
    2. Repérez la strophe Allocatable:

       ...
      Allocatable:
        attachable-volumes-gce-pd:  127
        cpu:                        3500m
        ephemeral-storage:          123201474766
        hugepages-1Gi:              0
        hugepages-2Mi:              0
        memory:                     14225400Ki
        pods:                       500 1
       ...
      1
      Dans cet exemple, le paramètre pods doit indiquer la valeur que vous avez définie dans l'objet KubeletConfig.
  5. Vérifiez la modification de l'objet KubeletConfig:

    $ oc get kubeletconfigs set-max-pods -o yaml

    L'état de True et type:Success devrait apparaître, comme le montre l'exemple suivant :

    spec:
      kubeletConfig:
        maxPods: 500
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: set-max-pods
    status:
      conditions:
      - lastTransitionTime: "2021-06-30T17:04:07Z"
        message: Success
        status: "True"
        type: Success

7.4.2. Modifier le nombre de nœuds de travail indisponibles

Par défaut, une seule machine est autorisée à être indisponible lors de l'application de la configuration liée à kubelet aux nœuds de travail disponibles. Dans le cas d'un grand cluster, la prise en compte de la modification de la configuration peut prendre beaucoup de temps. Vous pouvez à tout moment ajuster le nombre de machines mises à jour pour accélérer le processus.

Procédure

  1. Modifiez le pool de configuration de la machine worker:

    $ oc edit machineconfigpool worker
  2. Ajoutez le champ maxUnavailable et définissez sa valeur :

    spec:
      maxUnavailable: <node_count>
    Important

    Lors de la définition de cette valeur, il faut tenir compte du nombre de nœuds de travail qui peuvent être indisponibles sans affecter les applications fonctionnant sur le cluster.

7.4.3. Dimensionnement des nœuds du plan de contrôle

Les besoins en ressources des nœuds du plan de contrôle dépendent du nombre et du type de nœuds et d'objets dans le cluster. Les recommandations suivantes concernant la taille des nœuds du plan de contrôle sont basées sur les résultats d'un test focalisé sur la densité du plan de contrôle, ou Cluster-density. Ce test crée les objets suivants dans un nombre donné d'espaces de noms :

  • 1 flux d'images
  • 1 construire
  • 5 déploiements, avec 2 répliques de pods à l'état sleep, montant chacun 4 secrets, 4 cartes de configuration et 1 volume d'API descendant
  • 5 services, chacun pointant vers les ports TCP/8080 et TCP/8443 d'un des déploiements précédents
  • 1 itinéraire menant au premier des services précédents
  • 10 secrets contenant 2048 caractères aléatoires
  • 10 cartes de configuration contenant 2048 caractères aléatoires
Number of worker nodesDensité de la grappe (espaces nominatifs)Cœurs de l'unité centraleMémoire (GB)

24

500

4

16

120

1000

8

32

252

4000

16, mais 24 si l'on utilise le plug-in réseau OVN-Kubernetes

64, mais 128 si l'on utilise le plug-in réseau OVN-Kubernetes

501, mais non testé avec le plug-in réseau OVN-Kubernetes

4000

16

96

Les données du tableau ci-dessus sont basées sur une plateforme de conteneurs OpenShift fonctionnant au-dessus d'AWS, utilisant des instances r5.4xlarge comme nœuds de plan de contrôle et des instances m5.2xlarge comme nœuds de travail.

Dans un grand cluster dense comprenant trois nœuds de plan de contrôle, l'utilisation du processeur et de la mémoire augmente lorsque l'un des nœuds est arrêté, redémarré ou tombe en panne. Les pannes peuvent être dues à des problèmes inattendus d'alimentation, de réseau, d'infrastructure sous-jacente, ou à des cas intentionnels où le cluster est redémarré après avoir été arrêté pour réduire les coûts. Les deux nœuds restants du plan de contrôle doivent gérer la charge afin d'être hautement disponibles, ce qui entraîne une augmentation de l'utilisation des ressources. Ce phénomène se produit également lors des mises à niveau, car les nœuds du plan de contrôle sont isolés, vidés et redémarrés en série pour appliquer les mises à jour du système d'exploitation, ainsi que la mise à jour des opérateurs du plan de contrôle. Pour éviter les défaillances en cascade, maintenez l'utilisation globale des ressources CPU et mémoire sur les nœuds du plan de contrôle à un maximum de 60 % de la capacité disponible afin de gérer les pics d'utilisation des ressources. Augmentez l'UC et la mémoire des nœuds du plan de contrôle en conséquence pour éviter les temps d'arrêt potentiels dus au manque de ressources.

Important

Le dimensionnement des nœuds varie en fonction du nombre de nœuds et d'objets dans la grappe. Il dépend également de la création active d'objets sur la grappe. Pendant la création des objets, le plan de contrôle est plus actif en termes d'utilisation des ressources que lorsque les objets sont dans la phase running.

Operator Lifecycle Manager (OLM) s'exécute sur les nœuds du plan de contrôle et son empreinte mémoire dépend du nombre d'espaces de noms et d'opérateurs installés par l'utilisateur qu'OLM doit gérer sur la grappe. Les nœuds du plan de contrôle doivent être dimensionnés en conséquence afin d'éviter les pertes de mémoire (OOM kills). Les points de données suivants sont basés sur les résultats des tests de maximisation des grappes.

Nombre d'espaces de nomsMémoire OLM au repos (GB)Mémoire OLM avec 5 opérateurs utilisateurs installés (GB)

500

0.823

1.7

1000

1.2

2.5

1500

1.7

3.2

2000

2

4.4

3000

2.7

5.6

4000

3.8

7.6

5000

4.2

9.02

6000

5.8

11.3

7000

6.6

12.9

8000

6.9

14.8

9000

8

17.7

10,000

9.9

21.6

Important

Vous pouvez modifier la taille des nœuds du plan de contrôle dans un cluster OpenShift Container Platform 4.12 en cours d'exécution pour les configurations suivantes uniquement :

  • Clusters installés avec une méthode d'installation fournie par l'utilisateur.
  • Clusters AWS installés avec une méthode d'installation d'infrastructure fournie par l'installateur.
  • Les clusters qui utilisent un jeu de machines du plan de contrôle pour gérer les machines du plan de contrôle.

Pour toutes les autres configurations, vous devez estimer le nombre total de nœuds et utiliser la taille de nœud suggérée pour le plan de contrôle lors de l'installation.

Important

Les recommandations sont basées sur les points de données capturés sur les clusters OpenShift Container Platform avec OpenShift SDN comme plugin réseau.

Note

Dans OpenShift Container Platform 4.12, la moitié d'un cœur de CPU (500 millicores) est désormais réservée par le système par défaut par rapport à OpenShift Container Platform 3.11 et aux versions précédentes. Les tailles sont déterminées en tenant compte de cela.

7.4.4. Configuration du gestionnaire de CPU

Procédure

  1. Facultatif : Étiqueter un nœud :

    # oc label node perf-node.example.com cpumanager=true
  2. Modifiez le site MachineConfigPool des nœuds pour lesquels le gestionnaire de CPU doit être activé. Dans cet exemple, tous les travailleurs ont activé le gestionnaire de CPU :

    # oc edit machineconfigpool worker
  3. Ajouter une étiquette au pool de configuration de la machine de travail :

    metadata:
      creationTimestamp: 2020-xx-xxx
      generation: 3
      labels:
        custom-kubelet: cpumanager-enabled
  4. Créez une ressource personnalisée (CR) KubeletConfig, cpumanager-kubeletconfig.yaml. Référez-vous à l'étiquette créée à l'étape précédente pour que les nœuds corrects soient mis à jour avec la nouvelle configuration du kubelet. Voir la section machineConfigPoolSelector:

    apiVersion: machineconfiguration.openshift.io/v1
    kind: KubeletConfig
    metadata:
      name: cpumanager-enabled
    spec:
      machineConfigPoolSelector:
        matchLabels:
          custom-kubelet: cpumanager-enabled
      kubeletConfig:
         cpuManagerPolicy: static 1
         cpuManagerReconcilePeriod: 5s 2
    1
    Spécifier une politique :
    • none. Cette politique active explicitement le schéma d'affinité CPU par défaut existant, ne fournissant aucune affinité au-delà de ce que le planificateur fait automatiquement. Il s'agit de la stratégie par défaut.
    • static. Cette politique autorise les conteneurs dans les pods garantis avec des demandes de CPU entières. Elle limite également l'accès aux CPU exclusifs sur le nœud. Si static, vous devez utiliser une minuscule s.
    2
    Facultatif. Indiquez la fréquence de rapprochement du gestionnaire de CPU. La valeur par défaut est 5s.
  5. Créer la configuration dynamique du kubelet :

    # oc create -f cpumanager-kubeletconfig.yaml

    Cela ajoute la fonction CPU Manager à la configuration du kubelet et, si nécessaire, le Machine Config Operator (MCO) redémarre le nœud. Pour activer le gestionnaire de CPU, un redémarrage n'est pas nécessaire.

  6. Vérifier la configuration du kubelet fusionné :

    # oc get machineconfig 99-worker-XXXXXX-XXXXX-XXXX-XXXXX-kubelet -o json | grep ownerReference -A7

    Exemple de sortie

           "ownerReferences": [
                {
                    "apiVersion": "machineconfiguration.openshift.io/v1",
                    "kind": "KubeletConfig",
                    "name": "cpumanager-enabled",
                    "uid": "7ed5616d-6b72-11e9-aae1-021e1ce18878"
                }
            ]

  7. Consultez le travailleur pour obtenir la mise à jour de kubelet.conf:

    # oc debug node/perf-node.example.com
    sh-4.2# cat /host/etc/kubernetes/kubelet.conf | grep cpuManager

    Exemple de sortie

    cpuManagerPolicy: static        1
    cpuManagerReconcilePeriod: 5s   2

    1
    cpuManagerPolicy est défini lorsque vous créez le CR KubeletConfig.
    2
    cpuManagerReconcilePeriod est défini lorsque vous créez le CR KubeletConfig.
  8. Créer un pod qui demande un ou plusieurs cœurs. Les limites et les demandes doivent avoir une valeur CPU égale à un entier. Il s'agit du nombre de cœurs qui seront dédiés à ce module :

    # cat cpumanager-pod.yaml

    Exemple de sortie

    apiVersion: v1
    kind: Pod
    metadata:
      generateName: cpumanager-
    spec:
      containers:
      - name: cpumanager
        image: gcr.io/google_containers/pause-amd64:3.0
        resources:
          requests:
            cpu: 1
            memory: "1G"
          limits:
            cpu: 1
            memory: "1G"
      nodeSelector:
        cpumanager: "true"

  9. Créer la capsule :

    # oc create -f cpumanager-pod.yaml
  10. Vérifiez que le pod est planifié sur le nœud que vous avez étiqueté :

    # oc describe pod cpumanager

    Exemple de sortie

    Name:               cpumanager-6cqz7
    Namespace:          default
    Priority:           0
    PriorityClassName:  <none>
    Node:  perf-node.example.com/xxx.xx.xx.xxx
    ...
     Limits:
          cpu:     1
          memory:  1G
        Requests:
          cpu:        1
          memory:     1G
    ...
    QoS Class:       Guaranteed
    Node-Selectors:  cpumanager=true

  11. Vérifiez que l'adresse cgroups est correctement configurée. Obtenir l'ID du processus (PID) du processus pause:

    # ├─init.scope
    │ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
    └─kubepods.slice
      ├─kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice
      │ ├─crio-b5437308f1a574c542bdf08563b865c0345c8f8c0b0a655612c.scope
      │ └─32706 /pause

    Les pods du niveau de qualité de service (QoS) Guaranteed sont placés à l'intérieur du site kubepods.slice. Les pods des autres niveaux de QoS se retrouvent dans les enfants cgroups de kubepods:

    # cd /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-pod69c01f8e_6b74_11e9_ac0f_0a2b62178a22.slice/crio-b5437308f1ad1a7db0574c542bdf08563b865c0345c86e9585f8c0b0a655612c.scope
    # for i in `ls cpuset.cpus tasks` ; do echo -n "$i "; cat $i ; done

    Exemple de sortie

    cpuset.cpus 1
    tasks 32706

  12. Vérifiez la liste des unités centrales autorisées pour la tâche :

    # grep ^Cpus_allowed_list /proc/32706/status

    Exemple de sortie

     Cpus_allowed_list:    1

  13. Vérifiez qu'un autre pod (dans ce cas, le pod du niveau de qualité de service burstable ) sur le système ne peut pas fonctionner sur le cœur alloué au pod Guaranteed:

    # cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-podc494a073_6b77_11e9_98c0_06bba5c387ea.slice/crio-c56982f57b75a2420947f0afc6cafe7534c5734efc34157525fa9abbf99e3849.scope/cpuset.cpus
    0
    # oc describe node perf-node.example.com

    Exemple de sortie

    ...
    Capacity:
     attachable-volumes-aws-ebs:  39
     cpu:                         2
     ephemeral-storage:           124768236Ki
     hugepages-1Gi:               0
     hugepages-2Mi:               0
     memory:                      8162900Ki
     pods:                        250
    Allocatable:
     attachable-volumes-aws-ebs:  39
     cpu:                         1500m
     ephemeral-storage:           124768236Ki
     hugepages-1Gi:               0
     hugepages-2Mi:               0
     memory:                      7548500Ki
     pods:                        250
    -------                               ----                           ------------  ----------  ---------------  -------------  ---
      default                                 cpumanager-6cqz7               1 (66%)       1 (66%)     1G (12%)         1G (12%)       29m
    
    Allocated resources:
      (Total limits may be over 100 percent, i.e., overcommitted.)
      Resource                    Requests          Limits
      --------                    --------          ------
      cpu                         1440m (96%)       1 (66%)

    Cette VM dispose de deux cœurs de processeur. Le paramètre system-reserved réserve 500 millicores, ce qui signifie que la moitié d'un cœur est soustraite de la capacité totale du nœud pour obtenir la quantité Node Allocatable. Vous pouvez voir que Allocatable CPU est de 1500 millicores. Cela signifie que vous pouvez exécuter l'un des pods du gestionnaire de CPU, puisque chacun d'entre eux prendra un cœur entier. Un cœur entier est équivalent à 1000 millicores. Si vous essayez de planifier un deuxième module, le système acceptera le module, mais il ne sera jamais planifié :

    NAME                    READY   STATUS    RESTARTS   AGE
    cpumanager-6cqz7        1/1     Running   0          33m
    cpumanager-7qc2t        0/1     Pending   0          11s
Red Hat logoGithubRedditYoutubeTwitter

Apprendre

Essayez, achetez et vendez

Communautés

À propos de la documentation Red Hat

Nous aidons les utilisateurs de Red Hat à innover et à atteindre leurs objectifs grâce à nos produits et services avec un contenu auquel ils peuvent faire confiance.

Rendre l’open source plus inclusif

Red Hat s'engage à remplacer le langage problématique dans notre code, notre documentation et nos propriétés Web. Pour plus de détails, consultez leBlog Red Hat.

À propos de Red Hat

Nous proposons des solutions renforcées qui facilitent le travail des entreprises sur plusieurs plates-formes et environnements, du centre de données central à la périphérie du réseau.

© 2024 Red Hat, Inc.