Déployer des services de nœud avec des DaemonSets Kubernetes

KubernetesBeginner
Pratiquer maintenant

Introduction

Certains logiciels doivent s’exécuter une fois sur chaque nœud éligible plutôt qu’en fonction d’un nombre fixe de réplicas. Les collecteurs de journaux, les agents de supervision et les composants réseau utilisent couramment des DaemonSets pour ce type de déploiement centré sur les nœuds.

Vous allez étiqueter le nœud préparé, déployer un agent de signalement, retracer son propriétaire, modifier l’éligibilité du nœud, puis effectuer une mise à jour progressive. Cet environnement à nœud unique permet d’observer facilement la règle de placement, tout en conservant le même comportement de contrôleur que dans les clusters plus importants.

La question centrale de cet atelier n’est pas « combien de réplicas faut-il exécuter ? », mais « quels nœuds sont éligibles ? ». Un DaemonSet répond continuellement à cette question et crée un Pod sur chaque nœud correspondant. Dans cet environnement, il n’y a qu’un seul nœud : chaque changement d’éligibilité produit donc un résultat clair, passant de un à zéro Pod, ou de zéro à un.

Marquer un nœud éligible

Dans cette étape, vous allez ajouter au nœud un label correspondant à un usage précis. Les labels décrivent des attributs de nœud que les contrôleurs peuvent utiliser pour effectuer une sélection.

Commencez par afficher le nœud et les labels qui lui sont déjà associés. La sortie est large : inutile de la mémoriser. Vous devez seulement retenir que les labels sont des informations clé-valeur attachées à l’objet Node.

cd /home/labex/project/daemonset-workloads
kubectl get nodes --show-labels

Ajoutez le nouveau label. L’option --overwrite n’est pas nécessaire ici, car la préparation a supprimé toute ancienne valeur. Toutefois, kubectl label vous indiquera si une valeur en conflit existe déjà :

kubectl label node labex-v135 practice-tier=operations
kubectl get node labex-v135 -L practice-tier

-L practice-tier ajoute ce label sous forme de colonne dans le tableau. Le nœud se déclare désormais éligible pour l’agent d’exploitation utilisé dans cet exercice.

La deuxième commande fournit un résultat ciblé, plutôt que la très longue ligne produite avec --show-labels :

NAME         STATUS   ROLES           VERSION   PRACTICE-TIER
labex-v135   Ready    control-plane   v1.35.5   operations

PRACTICE-TIER=operations constitue la preuve recherchée. Le label n’exécute rien à lui seul ; il devient utile lorsqu’un workload le sélectionne à l’étape suivante.

Déployer un DaemonSet

Dans cette étape, vous allez créer un DaemonSet qui cible les nœuds portant le nouveau label.

Avant de le saisir, examinez le manifeste comme un ensemble de trois décisions liées. Le sélecteur et le label du Pod utilisent tous deux app: node-reporter, ce qui permet au contrôleur d’identifier ses Pods. nodeSelector limite ensuite l’éligibilité aux nœuds étiquetés practice-tier=operations. Enfin, l’API Downward copie la valeur spec.nodeName du Pod sélectionné dans le conteneur sous le nom NODE_NAME.

La boucle maintient l’agent de démonstration en fonctionnement. Dans un environnement réel, un DaemonSet pourrait exécuter un collecteur de journaux ou un agent de supervision.

cat <<'EOF' > node-reporter.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-reporter
  namespace: practice-daemon
spec:
  selector:
    matchLabels:
      app: node-reporter
  template:
    metadata:
      labels:
        app: node-reporter
    spec:
      nodeSelector:
        practice-tier: operations
      containers:
        - name: reporter
          image: busybox:1.36
          imagePullPolicy: IfNotPresent
          command: ["sh", "-c", "while true; do echo node=${NODE_NAME} version=v1; sleep 15; done"]
          env:
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
EOF

Créez l’espace de noms, appliquez le fichier, puis attendez la fin du déploiement progressif du DaemonSet :

kubectl create namespace practice-daemon
kubectl apply -f node-reporter.yaml
kubectl rollout status daemonset/node-reporter -n practice-daemon --timeout=60s
kubectl get daemonset,pods -n practice-daemon -o wide

L’API Downward, via fieldRef, expose le nom du nœud planifié sans avoir à le coder en dur. Dans ce cluster à un seul nœud, les compteurs désiré, actuel et prêt doivent tous être égaux à un.

Le nom du Pod contient un suffixe généré automatiquement, mais la colonne NODE doit afficher labex-v135. Cela prouve directement que la règle d’éligibilité et le résultat de la planification concordent.

Dans le cluster de test à un seul nœud, les colonnes importantes ressemblaient à ceci :

NAME            DESIRED   CURRENT   READY   NODE SELECTOR
node-reporter   1         1         1       practice-tier=operations

NAME                  READY   STATUS    NODE
node-reporter-...      1/1     Running   labex-v135

Lisez la première ligne de gauche à droite : un nœud correspond au sélecteur, un Pod existe et ce Pod est prêt. Dans un cluster plus vaste, ces compteurs augmenteraient avec le nombre de nœuds éligibles.

Observer l’éligibilité et la propriété

Dans cette étape, vous allez démontrer que le nombre de Pods du DaemonSet dépend de l’éligibilité des nœuds, et non d’un champ replicas.

Commencez par relever un état de référence sain. Les colonnes personnalisées relient le Pod généré au DaemonSet, tandis que les journaux prouvent que l’API Downward a fourni le nom du nœud :

kubectl get pods -n practice-daemon -l app=node-reporter -o custom-columns='POD:.metadata.name,NODE:.spec.nodeName,OWNER:.metadata.ownerReferences[0].kind,READY:.status.containerStatuses[0].ready'
kubectl logs -n practice-daemon -l app=node-reporter --tail=3

Le tableau de propriété et les journaux devraient ressembler à ceci :

POD                   NODE         OWNER       READY
node-reporter-...     labex-v135   DaemonSet   true
node=labex-v135 version=v1

Le champ OWNER prouve qu’il s’agit d’un Pod géré par un contrôleur. Le journal montre que NODE_NAME provient de la valeur réelle spec.nodeName du Pod, et non d’une valeur codée en dur.

Supprimez temporairement le label et observez la disparition du Pod :

kubectl label node labex-v135 practice-tier-
kubectl get daemonset node-reporter -n practice-daemon
kubectl wait --for=delete pod -n practice-daemon -l app=node-reporter --timeout=60s

Le signe - final supprime une clé de label. Restaurez l’éligibilité et attendez que le contrôleur crée un Pod de remplacement :

Après la suppression, le DaemonSet affiche brièvement la relation stable suivante :

NAME            DESIRED   CURRENT   READY
node-reporter   0         0         0

Il s’agit d’une réaction normale à la modification de l’éligibilité, et non d’un échec. Aucun nœud ne correspond actuellement au nodeSelector du DaemonSet ; le nombre désiré correct est donc zéro.

kubectl label node labex-v135 practice-tier=operations
kubectl rollout status daemonset/node-reporter -n practice-daemon --timeout=60s

Comparez le nom du Pod avant et après la modification du label. Le Pod de remplacement possède une nouvelle identité, tandis que le nom du DaemonSet et le comportement attendu restent inchangés. Vous observez ici la réconciliation en action.

Déployer une mise à jour du DaemonSet

Dans cette étape, vous allez mettre à jour le manifeste enregistré et observer le DaemonSet remplacer l’agent du nœud. Maintenir le fichier et l’objet actif en cohérence permet de reproduire l’état souhaité.

Commencez par créer une copie de travail avec cp. Utilisez ensuite la même méthode ciblée de modification de texte présentée dans Kubernetes pour débutants : sed -i 's/old/new/' file remplace directement le texte correspondant dans le fichier, tandis que grep -n affiche la ligne correspondante avec son numéro afin que vous puissiez vérifier le résultat avant de l’appliquer.

cp node-reporter.yaml node-reporter-v2.yaml
sed -i 's/version=v1/version=v2/' node-reporter-v2.yaml
grep -n 'version=' node-reporter-v2.yaml
kubectl apply -f node-reporter-v2.yaml
kubectl rollout status daemonset/node-reporter -n practice-daemon --timeout=60s
kubectl rollout history daemonset/node-reporter -n practice-daemon
kubectl logs -n practice-daemon -l app=node-reporter --tail=3

Le fichier copié conserve l’exemple original en v1 pour permettre la comparaison. La substitution ne modifie que le texte de version dans la commande du conteneur ; l’application du fichier mis à jour modifie le modèle de Pod, ce qui crée une nouvelle révision du contrôleur et un Pod de remplacement. Les journaux doivent désormais contenir version=v2.

rollout history confirme que Kubernetes a enregistré une nouvelle révision. Les DaemonSets prennent donc en charge les mises à jour contrôlées de modèles, à l’instar des Deployments, mais le remplacement est organisé autour des nœuds éligibles plutôt qu’autour d’un nombre de réplicas.

La sortie testée comportait deux révisions et le nouveau message dans les journaux :

REVISION  CHANGE-CAUSE
1         <none>
2         <none>

node=labex-v135 version=v2

CHANGE-CAUSE=<none> signifie simplement qu’aucune annotation lisible par un humain n’a été enregistrée pour décrire la modification. La révision 2, associée à version=v2 dans le journal du Pod de remplacement, constitue la preuve utile que la mise à jour a bien été effectuée.

Résumé

Vous avez utilisé des labels de nœuds pour contrôler l’éligibilité d’un DaemonSet, observé la réconciliation avec un Pod par nœud éligible, retracé la propriété exercée par le contrôleur et déployé une mise à jour de l’agent de nœud. Vous pouvez désormais comparer les DaemonSets aux Deployments orientés réplicas et aux Jobs orientés achèvement.