Introduction
Dans la première section du cours, vous avez exploré un cluster Kubernetes sans le modifier. Vous avez appris que kubectl envoie des requêtes au serveur d’API et que les contrôleurs Kubernetes comparent en permanence l’état souhaité à l’état réel.
Vous allez maintenant effectuer vos premières requêtes concernant une application. Plutôt que d’indiquer à Kubernetes chaque opération élémentaire à exécuter, vous allez décrire le résultat souhaité dans des fichiers YAML appelés manifestes. Kubernetes enregistre ces définitions d’objets et s’efforce de les mettre en œuvre.
Vous commencerez par un seul Pod afin d’observer clairement la structure de base d’un manifeste. Vous définirez ensuite un Deployment qui gère deux Pods. La comparaison entre le Pod autonome et les Pods gérés par le Deployment vous montrera pourquoi les contrôleurs de niveau supérieur sont généralement privilégiés pour les applications.
Cet atelier se concentre volontairement sur la création de charges de travail. Vous apprendrez à exposer les applications via des Services plus tard, lorsque les notions de Pods, de labels et de Deployments vous seront familières.
Comprendre les objets déclaratifs Kubernetes
Démarrage de l’environnement : Ce lab démarre pour vous un cluster Kubernetes complet. La configuration du plan de contrôle, du nœud et des composants réseau prend généralement 2 à 3 minutes. Veuillez patienter jusqu’à la fin du chargement de l’environnement avant de commencer.
Dans cette étape, vous allez relier la notion d’état souhaité abordée dans l’atelier précédent aux manifestes Kubernetes et préparer un espace de travail pour vos premières définitions d’applications.
Des commandes à l’état souhaité
Kubernetes prend en charge deux grandes approches de gestion :
- Avec une commande impérative, vous demandez directement une action, par exemple « créer un Pod nommé
first-nginx». - Avec un manifeste déclaratif, vous enregistrez la configuration souhaitée de l’objet dans un fichier et demandez à Kubernetes d’aligner le cluster sur cette configuration.
Les fichiers déclaratifs sont précieux, car vous pouvez les lire avant d’appliquer une modification, les réutiliser, examiner les différences et les conserver dans un système de gestion de versions. Ce cours privilégiera cette approche déclarative.
Chaque objet Kubernetes renvoyé par l’API possède plusieurs champs de premier niveau importants :
apiVersionsélectionne le groupe et la version de l’API Kubernetes.kindidentifie le type d’objet, commePodouDeployment.metadatadécrit l’identité de l’objet, notamment son nom et ses labels.specdécrit l’état souhaité de l’objet.statusindique l’état observé. Il est normalement renseigné par Kubernetes après la création, et non écrit dans votre manifeste.
Cela forme une boucle essentielle :
manifest spec -> API server stores desired state -> controllers act -> object status reports actual state
Préparer le répertoire des manifestes
Accédez au répertoire préparé pour cet atelier :
cd /home/labex/project/k8s-manifests
Vérifiez votre emplacement avec pwd, qui signifie print working directory :
pwd
/home/labex/project/k8s-manifests
Créez un court fichier de notes contenant les quatre champs de manifeste que vous utiliserez. La commande printf écrit chaque chaîne entre guillemets sur une ligne distincte, et > redirige cette sortie vers un fichier en le remplaçant s’il existe déjà.
printf '%s\n' apiVersion kind metadata spec > manifest-fields.txt
Affichez le fichier pour le vérifier :
cat manifest-fields.txt
apiVersion
kind
metadata
spec
Ce fichier de notes constitue un petit point de contrôle pédagogique : ces quatre champs apparaîtront dans les deux manifestes que vous allez créer.
Rédiger et valider un manifeste de Pod
Dans cette étape, vous allez rédiger un manifeste YAML pour un Pod et en valider la structure avant de l’envoyer au cluster.
Découvrir le Pod
Un Pod est l’objet Kubernetes déployable le plus petit. Il fournit à un ou plusieurs conteneurs étroitement liés une identité réseau et un contexte de stockage partagés. Dans la plupart des exemples destinés aux débutants, chaque Pod contient un seul conteneur.
Le Pod de cet atelier exécutera NGINX, un petit serveur web. L’image est figée sur nginx:1.27-alpine. Fixer une version rend le résultat plus reproductible que l’utilisation du tag évolutif latest. L’image a déjà été mise en cache dans le cluster afin que votre travail ne dépende pas d’un téléchargement depuis Internet.
Créer le fichier YAML
Assurez-vous d’être dans le répertoire des manifestes :
cd /home/labex/project/k8s-manifests
Vous allez utiliser un here-document pour créer le fichier. Le shell redirige chaque ligne située entre <<'EOF' et le EOF final vers first-pod.yaml. Les guillemets autour du premier EOF empêchent le shell d’interpréter les caractères spéciaux présents dans le YAML.
cat <<'EOF' > first-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: first-nginx
namespace: default
labels:
app: first-nginx
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
EOF
Le YAML représente la hiérarchie à l’aide de l’indentation. Utilisez systématiquement des espaces ; les tabulations peuvent rendre le YAML invalide. Un tiret, comme dans - name: nginx, commence un élément de liste.
Lisez l’objet de haut en bas :
apiVersion: v1sélectionne l’API principale utilisée par les Pods.kind: Poddéclare le type de ressource.metadata.nameattribue au Pod le nom stablefirst-nginx.metadata.namespace: defaultle place dans l’espace de noms applicatif standard du cours plutôt que dans un espace de noms système.metadata.labelsajouteapp=first-nginx, ce qui permettra ultérieurement de sélectionner ce Pod.spec.containersest la liste des conteneurs que le Pod doit exécuter.imagePullPolicy: IfNotPresentutilise l’image mise en cache lorsqu’elle est disponible.- Le port nommé
httputilisecontainerPort: 80etprotocol: TCP. Il indique où NGINX écoute à l’intérieur du conteneur ; il n’expose pas le Pod à l’extérieur du cluster.
Valider avant de créer
Utilisez une simulation côté client pour analyser le fichier sans créer le Pod. L’option -f signifie file, et --dry-run=client conserve la requête localement :
kubectl apply --dry-run=client -f first-pod.yaml
pod/first-nginx created (dry run)
Les mots dry run sont essentiels : la syntaxe est valide, mais le cluster n’a pas été modifié.
Demandez à kubectl d’afficher l’objet normalisé au format YAML :
L’option de sortie -o signifie output format. En fournissant yaml, vous demandez à kubectl de restituer l’objet analysé au format YAML au lieu d’afficher uniquement un résultat sur une ligne :
kubectl apply --dry-run=client -f first-pod.yaml -o yaml
Vous verrez vos champs ainsi que des valeurs par défaut ajoutées par le client. Cette méthode est utile pour détecter les erreurs d’indentation, de nom de champ ou de type avant une véritable application.
Créer et examiner votre premier Pod
Dans cette étape, vous allez appliquer le manifeste validé, observer Kubernetes faire évoluer le Pod vers son état souhaité et examiner l’objet obtenu.
Appliquer le manifeste
Accédez au répertoire des manifestes si nécessaire :
cd /home/labex/project/k8s-manifests
Appliquez le fichier sans l’option de simulation :
kubectl apply -f first-pod.yaml
pod/first-nginx created
kubectl apply envoie l’objet au serveur d’API. Le serveur d’API enregistre la spécification souhaitée du Pod, tandis que le planificateur et le kubelet coopèrent pour l’exécuter sur le nœud.
Attendre que le Pod soit prêt
La création d’un Pod est asynchrone : kubectl apply peut renvoyer un résultat avant que le conteneur soit prêt. Utilisez kubectl wait pour attendre la condition Ready du Pod. La commande se termine avec succès lorsque la condition devient vraie, ou échoue après 60 secondes :
kubectl wait --for=condition=Ready pod/first-nginx --timeout=60s
pod/first-nginx condition met
Répertoriez maintenant le Pod. Cet atelier répète -o wide afin que chaque atelier puisse être utilisé indépendamment : -o sélectionne un format de sortie et wide ajoute des informations telles que l’adresse IP du Pod et le nom du nœud :
kubectl get pod first-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE
first-nginx 1/1 Running ... ... ... labex-v135
READY=1/1 signifie que l’unique conteneur est prêt, tandis que STATUS=Running correspond à la phase du Pod. L’affichage détaillé indique également l’adresse IP du Pod et le nœud qui lui a été attribué. Les adresses IP et les âges des Pods sont générés automatiquement ; ils peuvent donc différer.
Examiner les labels et la propriété
Affichez les labels du Pod :
kubectl get pod first-nginx --show-labels
Recherchez app=first-nginx. Les labels sont enregistrés avec l’objet et deviendront importants lorsque les Deployments et les Services sélectionneront des Pods.
Demandez à Kubernetes si un autre objet contrôle ce Pod. -o jsonpath='...' extrait certains champs au lieu d’afficher l’objet complet. L’expression parcourt metadata.ownerReferences ; {"\n"} ajoute un retour à la ligne final afin que l’invite du shell apparaisse sur la ligne suivante :
kubectl get pod first-nginx -o jsonpath='Owner: {.metadata.ownerReferences[0].kind}{"\n"}'
Owner:
Le propriétaire est vide, car vous avez créé directement ce Pod autonome. S’il est supprimé, aucun contrôleur de niveau supérieur ne saura qu’il doit être recréé. Vous comparerez ce comportement avec celui des Pods gérés dans les étapes suivantes.
Point de contrôle
Vous avez transformé un fichier local décrivant l’état souhaité en un objet Kubernetes en cours d’exécution. L’API a accepté le Pod, le planificateur lui a attribué un nœud et le kubelet a rendu son conteneur opérationnel. Le Pod existe, mais aucun contrôleur ne gère son cycle de vie.
Définir un Deployment
Dans cette étape, vous allez définir un Deployment demandant à Kubernetes de maintenir deux copies d’un Pod NGINX.
Pourquoi utiliser un Deployment ?
Un Pod autonome est utile pour l’apprentissage, mais les applications ont généralement besoin d’un contrôleur. Un Deployment définit un nombre souhaité de répliques et un modèle de Pod. Il crée un ReplicaSet, qui maintient ensuite le nombre de Pods demandé.
La chaîne de propriété est la suivante :
Deployment -> ReplicaSet -> Pods -> containers
Si un Pod géré disparaît, le ReplicaSet constate que le nombre réel de répliques est inférieur au nombre souhaité et crée un remplacement. Les prochains ateliers utiliseront les Deployments pour mettre à l’échelle les applications et effectuer des mises à jour progressives.
Créer le manifeste du Deployment
Revenez au répertoire des manifestes :
cd /home/labex/project/k8s-manifests
Créez course-web-deployment.yaml à l’aide d’un here-document :
cat <<'EOF' > course-web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: course-web
labels:
app: course-web
spec:
replicas: 2
selector:
matchLabels:
app: course-web
template:
metadata:
labels:
app: course-web
spec:
containers:
- name: nginx
image: nginx:1.27-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
EOF
Le Deployment utilise apps/v1, l’API stable des Deployments. Sa section spec introduit trois champs importants :
replicas: 2indique le nombre souhaité de Pods.selector.matchLabelsidentifie les Pods gérés par le Deployment.templateconstitue le modèle utilisé pour créer chaque Pod.
Le sélecteur et template.metadata.labels utilisent tous deux app: course-web. Ils doivent correspondre ; sinon, le Deployment ne pourrait pas identifier les Pods créés à partir de son propre modèle.
Valider le Deployment
Analysez le manifeste sans modifier le cluster :
kubectl apply --dry-run=client -f course-web-deployment.yaml
deployment.apps/course-web created (dry run)
Utilisez kubectl diff pour comparer le manifeste avec l’état actuel du cluster. Un code de sortie différent de zéro signifie simplement que l’objet serait modifié ; || true empêche le shell de considérer cette différence attendue comme une erreur :
kubectl diff -f course-web-deployment.yaml || true
Comme course-web n’existe pas encore, la sortie affiche l’objet complet comme un ajout, avec des lignes commençant par +. Contrairement à apply, diff ne modifie pas le cluster.
Déployer et examiner l’application gérée
Dans cette étape, vous allez appliquer le Deployment, attendre ses deux répliques et examiner les ressources associées en les sélectionnant à l’aide de leur label commun.
Appliquer le Deployment et attendre sa disponibilité
Commencez par accéder au répertoire contenant le manifeste. Appliquez ensuite l’état souhaité enregistré ; -f indique à kubectl de lire ce fichier :
cd /home/labex/project/k8s-manifests
kubectl apply -f course-web-deployment.yaml
deployment.apps/course-web created
Attendez la fin du déploiement progressif. Il s’agit du processus qui amène les Pods du Deployment à respecter le modèle et le nombre de répliques souhaités :
kubectl rollout status deployment/course-web --timeout=60s
deployment "course-web" successfully rolled out
Répertoriez le Deployment :
kubectl get deployment course-web
NAME READY UP-TO-DATE AVAILABLE AGE
course-web 2/2 2 2 ...
READY=2/2 signifie que les deux répliques souhaitées sont prêtes. UP-TO-DATE=2 signifie qu’elles utilisent toutes deux le modèle de Pod actuel, et AVAILABLE=2 indique qu’elles sont toutes deux disponibles.
Examiner les ressources associées
Utilisez le sélecteur de labels -l app=course-web pour répertorier les ressources associées :
kubectl get deployment,replicaset,pods -l app=course-web
La sortie contient un Deployment, un ReplicaSet et deux Pods. Les suffixes générés du ReplicaSet et des Pods varient :
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/course-web 2/2 2 2 ...
NAME DESIRED CURRENT READY AGE
replicaset.apps/course-web-... 2 2 2 ...
NAME READY STATUS RESTARTS AGE
pod/course-web-...-... 1/1 Running ... ...
pod/course-web-...-... 1/1 Running ... ...
Cette vue confirme que les deux répliques souhaitées par le Deployment sont devenues deux Pods prêts. À l’étape suivante, vous suivrez les liens de propriété entre ces ressources.
Point de contrôle
Vous avez appliqué un manifeste de Deployment et attendu que l’état souhaité soit atteint. Kubernetes a créé un ReplicaSet et deux Pods, et le label commun app=course-web vous a permis de les répertorier comme un seul groupe applicatif.
Suivre la propriété des contrôleurs
Dans cette étape, vous allez suivre les références de propriété Kubernetes depuis un Pod géré jusqu’à son ReplicaSet, puis jusqu’au Deployment. Vous réappliquerez également le manifeste afin d’observer l’idempotence du mode déclaratif.
Examiner le propriétaire d’un Pod
Enregistrez le nom d’un Pod généré dans une variable du shell. La syntaxe NAME=$(command) correspond à une substitution de commande : le shell exécute la commande et enregistre sa sortie dans NAME. Ici, -l app=course-web sélectionne les Pods correspondants et JSONPath extrait le nom généré du premier Pod :
POD_NAME=$(kubectl get pods -l app=course-web -o jsonpath='{.items[0].metadata.name}')
Affichez-le pour savoir quel Pod a été sélectionné :
echo "$POD_NAME"
Examinez maintenant son propriétaire direct. Les guillemets autour de "$POD_NAME" transmettent le nom enregistré comme un seul argument sûr pour la commande :
kubectl get pod "$POD_NAME" -o jsonpath='Owner: {.metadata.ownerReferences[0].kind}/{.metadata.ownerReferences[0].name}{"\n"}'
Owner: ReplicaSet/course-web-...
Contrairement au Pod autonome first-nginx, un Pod géré par un Deployment possède un ReplicaSet comme propriétaire. Le ReplicaSet est lui-même détenu par le Deployment.
Affichez le propriétaire du ReplicaSet. La première commande reprend le même modèle de substitution, mais en enregistrant cette fois le nom d’un ReplicaSet dans RS_NAME :
RS_NAME=$(kubectl get replicaset -l app=course-web -o jsonpath='{.items[0].metadata.name}')
kubectl get replicaset "$RS_NAME" -o jsonpath='Owner: {.metadata.ownerReferences[0].kind}/{.metadata.ownerReferences[0].name}{"\n"}'
Owner: Deployment/course-web
Réappliquer l’état souhaité
Appliquez à nouveau le même manifeste :
kubectl apply -f course-web-deployment.yaml
deployment.apps/course-web unchanged
unchanged illustre une propriété importante du mode déclaratif : réappliquer plusieurs fois le même état souhaité est sans danger. Kubernetes n’a besoin d’intervenir que lorsque la configuration souhaitée et la configuration réelle diffèrent.
Point de contrôle
Vous disposez maintenant d’un Pod autonome et d’une application gérée par un Deployment. Tous deux exécutent des conteneurs, mais le Deployment ajoute une hiérarchie de contrôleurs qui maintient deux répliques et fournit une base pour les futures mises à l’échelle et mises à jour progressives.
Résumé
Vous êtes passé de l’exploration en lecture seule du cluster à la gestion déclarative d’une application. Vous avez appris le rôle de apiVersion, kind, metadata et spec, validé des manifestes avec des simulations côté client, créé et examiné un Pod autonome, puis déployé deux répliques gérées par un Deployment.
Plus important encore, vous avez observé la chaîne de propriété des contrôleurs, du Deployment au ReplicaSet, puis aux Pods. Cette base fondée sur l’état souhaité vous permettra ensuite de diagnostiquer des applications, de les exposer via des Services, de mettre les répliques à l’échelle et d’effectuer des mises à jour progressives.


