
Dans Kubernetes, vous contrôlez quand et comment les images sont téléchargées via imagePullPolicy. Pour accéder à un registre privé, vous créez un Secret de type docker-registry et le référencez avec imagePullSecrets. Enfin, pour garantir que vos Pods utilisent toujours la même version d'image, préférez les digests aux tags mutables comme latest, un digest (ex: sha256:abc123...) identifie de façon unique et immuable une version précise de l'image.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre les trois valeurs d'
ImagePullPolicyet leur comportement - Distinguer tags et digests pour garantir la reproductibilité
- Configurer l'accès aux registres privés avec des Secrets
- Déboguer les erreurs
ImagePullBackOffetErrImagePull - Appliquer des policies d'admission pour sécuriser vos déploiements
Prérequis : connaître les bases des Pods et avoir compris comment construire une image.
Les trois mécanismes clés
Section intitulée « Les trois mécanismes clés »Avant d'entrer dans le détail, comprenons les trois mécanismes distincts qui interviennent :
| Question | Mécanisme | Exemple |
|---|---|---|
| Quelle image exacte exécuter ? | Tag ou digest | nginx:1.30.2 ou nginx@sha256:... |
| Quand contacter le registre ? | imagePullPolicy | Always, IfNotPresent, Never |
| Comment s'authentifier ? | imagePullSecrets | Secret de type docker-registry |
Ces trois mécanismes sont indépendants : vous pouvez utiliser un digest avec n'importe quelle pull policy, et imagePullSecrets n'affecte que l'authentification, pas la décision de pull.
Anatomie d'une référence d'image
Section intitulée « Anatomie d'une référence d'image »Avant de configurer le pull d'images, comprenons la structure d'une référence d'image complète :
[registre/][namespace/]nom[:tag][@digest]| Composant | Exemple | Description |
|---|---|---|
| Registre | registry.k8s.io, ghcr.io | Serveur hébergeant l'image. Par défaut : Docker Hub (docker.io) |
| Namespace | library, myorg | Organisation ou utilisateur. library pour les images officielles |
| Nom | nginx, myapp | Nom de l'image |
| Tag | :1.30.2, :latest | Version de l'image. Par défaut : latest |
| Digest | @sha256:abc123... | Hash unique et immuable de l'image |
nginx→ équivalent àdocker.io/library/nginx:latestregistry.k8s.io/pause:3.9→ image pause version 3.9 du registre Kubernetesmyregistry.azurecr.io/myapp@sha256:1ff6c18f...→ image avec digest (immuable)
ImagePullPolicy : contrôler le téléchargement
Section intitulée « ImagePullPolicy : contrôler le téléchargement »Le champ imagePullPolicy définit quand le kubelet tente de télécharger l'image depuis le registre.
Les trois valeurs possibles
Section intitulée « Les trois valeurs possibles »| Politique | Comportement | Cas d'usage typique |
|---|---|---|
| Always | Résout l'image auprès du registre à chaque démarrage du conteneur. Si l'image résolue existe déjà localement avec le même digest, les couches peuvent être réutilisées (pas de re-téléchargement complet). | Images avec tag latest, CI/CD |
| IfNotPresent | Utilise l'image locale si elle existe, sinon télécharge. Attention : en contexte supply chain strict, cette policy peut utiliser une image en cache sans vérifier si une version plus récente existe. | Production avec tags versionnés |
| Never | N'utilise que l'image locale, échoue si absente | Images pré-chargées, air-gapped |
imagePullPolicy: Always ne signifie pas "retélécharger tous les octets à chaque fois". Le kubelet interroge le registre pour résoudre le tag vers un digest, puis le runtime (containerd, CRI-O) peut réutiliser les couches déjà présentes si le digest correspond. C'est une vérification, pas forcément un téléchargement complet.
Comportement par défaut (important pour le CKAD)
Section intitulée « Comportement par défaut (important pour le CKAD) »Kubernetes applique une politique implicite selon le tag spécifié :
Quatre formes de référence, quatre comportements. Les deux premières lignes sont des contre-exemples, à ne pas reproduire :
| Référence écrite | imagePullPolicy appliqué |
|---|---|
nginx:latest ❌ | Always, à cause du tag latest |
nginx ❌ | Always, l'absence de tag valant latest |
nginx:1.30.2 | IfNotPresent, tag explicite |
nginx@sha256:… | IfNotPresent, digest |
Si vous omettez imagePullPolicy avec un tag latest ou sans tag, Kubernetes applique Always. Cela peut causer des échecs si le registre est inaccessible, même si l'image est présente localement.
Ce calcul implicite a une seconde conséquence, plus sournoise, parce qu'elle ne
se manifeste qu'après coup : la valeur est déterminée à la création de
l'objet, une fois pour toutes. Si vous passez plus tard de myapp:v1.0 à
myapp:latest, Kubernetes ne recalcule pas la pull policy, et votre Pod
continue de tourner en IfNotPresent sur un tag mutable. Le symptôme est un
déploiement qui « ne prend pas » alors que l'image a bien été republiée.
La démonstration tient en deux commandes sur un Deployment créé avec un tag explicite :
kubectl create deployment dep --image=nginx:1.30.2kubectl set image deployment/dep nginx=nginx:latestkubectl get deployment dep \ -o jsonpath='{.spec.template.spec.containers[0].imagePullPolicy}'IfNotPresentLa valeur est inscrite dans le template au moment de la création et n'en
bouge plus. Dès que vous changez de forme de tag, déclarez imagePullPolicy
explicitement.
Exemple complet avec imagePullPolicy
Section intitulée « Exemple complet avec imagePullPolicy »Le manifeste ci-dessous réunit les trois décisions qui portent sur l'image : quelle image, quand la retélécharger, et avec quels identifiants l'obtenir.
apiVersion: v1kind: Podmetadata: name: app-pod namespace: productionspec: containers: - name: app image: myregistry.example.com/myapp:v2.1.0 imagePullPolicy: IfNotPresent ports: - containerPort: 8080Garantir l'identité de l'image
Section intitulée « Garantir l'identité de l'image »Selon votre objectif, différents mécanismes s'appliquent :
imagePullPolicy: Always force le kubelet à contacter le registre à chaque démarrage pour résoudre le tag. Utile avec des tags mutables comme latest.
spec: containers: - name: app image: myapp:v1.0 imagePullPolicy: AlwaysUn digest garantit que vous exécutez exactement l'image voulue, sans ambiguïté. Le digest ne force pas un re-pull, si l'image est déjà en cache avec le bon digest, Kubernetes la réutilise.
spec: containers: - name: app image: myapp@sha256:1ff6c18fbef2045...L'admission controller AlwaysPullImages force tous les Pods du cluster à vérifier le registre. Utile en environnement multi-tenant pour empêcher un Pod de réutiliser une image privée déjà tirée par un autre workload.
# Dans les options kube-apiserver--enable-admission-plugins=AlwaysPullImagesTags vs Digests : garantir l'immutabilité
Section intitulée « Tags vs Digests : garantir l'immutabilité »Une référence d'image répond à deux questions différentes, et c'est pourquoi la forme canonique en porte deux parties. Le tag dit quelle version vous voulez, il reste lisible et c'est lui que vous reconnaîtrez. Le digest dit quel contenu exact vous voulez, et lui seul est immuable.
Le problème des tags mutables
Section intitulée « Le problème des tags mutables »Un tag est un alias vers une version d'image. Le problème : il peut être déplacé vers une autre version.
Jour 1 : myapp:latest → sha256:abc123 (version 1.0)Jour 2 : myapp:latest → sha256:def456 (version 1.1)Conséquence : deux Pods déployés à des moments différents avec myapp:latest peuvent exécuter du code différent.
La solution : les digests
Section intitulée « La solution : les digests »Un digest est un hash SHA256 du contenu de l'image. Il est immuable par définition.
# ❌ Risqué en productionimage: myapp:latest
# ✅ Reproductible et vérifiableimage: myapp@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07Récupérer le digest d'une image
Section intitulée « Récupérer le digest d'une image »Crane est l'outil le plus fiable pour manipuler les registres OCI :
# Installer cranego install github.com/google/go-containerregistry/cmd/crane@latest
# Récupérer le digestcrane digest nginx:1.30.2# sha256:6926dd802f40...skopeo inspect docker://nginx:1.30.2 | jq -r '.Digest'# sha256:6926dd802f40...Si l'image est déjà pullée localement :
docker inspect --format='{{index .RepoDigests 0}}' nginx:1.30.2# nginx@sha256:6926dd802f40...Note : Cette commande retourne le digest du manifest, qui est celui à utiliser dans vos références d'image Kubernetes.
- Interdisez
latesten production via une policy d'admission (voir section suivante) - Utilisez des tags sémantiques :
v1.2.3, passtableouproduction - Épinglez les digests pour les workloads critiques
- Signez vos images avec Cosign et vérifiez les signatures à l'admission
Une réserve s'impose sur le troisième point, car la confusion est fréquente. Un digest garantit l'immutabilité, c'est-à-dire que vous exécutez toujours la même image ; il ne garantit pas la confiance. Une image malveillante a un digest parfaitement stable, et le figer ne fait que garantir que vous réexécuterez la même image malveillante.
Ce sont les signatures (Cosign) et les attestations (SLSA) qui portent la provenance. Retenez le partage : le digest assure la reproductibilité, la signature assure l'authenticité. Les deux sont nécessaires, aucun ne remplace l'autre.
Accéder aux registres privés
Section intitulée « Accéder aux registres privés »Par défaut, Kubernetes ne peut télécharger que les images publiques. Pour accéder à un registre privé, vous devez fournir des credentials.
Créer un Secret docker-registry
Section intitulée « Créer un Secret docker-registry »-
Créez le Secret avec vos credentials
Fenêtre de terminal kubectl create secret docker-registry regcred \--docker-server=myregistry.example.com \--docker-username=myuser \--docker-password=mypassword \--docker-email=myuser@example.com \-n production -
Vérifiez le Secret créé
Fenêtre de terminal kubectl get secret regcred -n production -o yamlLe champ
.dockerconfigjsoncontient vos credentials encodés en base64. -
Référencez le Secret dans votre Pod
apiVersion: v1kind: Podmetadata:name: private-appnamespace: productionspec:containers:- name: appimage: myregistry.example.com/myapp:v1.0imagePullSecrets:- name: regcred
Automatiser avec un ServiceAccount
Section intitulée « Automatiser avec un ServiceAccount »Pour éviter d'ajouter imagePullSecrets à chaque Pod, attachez le Secret au ServiceAccount par défaut :
apiVersion: v1kind: ServiceAccountmetadata: name: default namespace: productionimagePullSecrets:- name: regcredTous les Pods du namespace utilisant ce ServiceAccount hériteront automatiquement du Secret.
Structure d'un Secret docker-registry
Section intitulée « Structure d'un Secret docker-registry »Ce type de Secret n'a rien d'un conteneur à identifiants libre : il porte une seule clé, .dockerconfigjson, dont le contenu a exactement le format du fichier de configuration de Docker. C'est ce qui permet au kubelet de le lire sans transformation.
apiVersion: v1kind: Secretmetadata: name: regcred namespace: productiontype: kubernetes.io/dockerconfigjsondata: .dockerconfigjson: eyJhdXRocyI6eyJteXJlZ2lzdHJ5LmV4YW1wbGUuY29tIjp7InVzZXJuYW1lIjoibXl1c2VyIiwicGFzc3dvcmQiOiJteXBhc3N3b3JkIiwiZW1haWwiOiJteXVzZXJAZXhhbXBsZS5jb20iLCJhdXRoIjoiYlhsMWMyVnlPbTE1Y0dGemMzZHZjbVE9In19fQ==Pour décoder et vérifier le contenu :
kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jqDéboguer les erreurs d'image
Section intitulée « Déboguer les erreurs d'image »Trois messages couvrent la quasi-totalité des échecs, et chacun désigne une étape différente : trouver l'image, s'authentifier, la télécharger. Lire le bon message évite de chercher des identifiants quand c'est le nom qui est faux.
ImagePullBackOff et ErrImagePull
Section intitulée « ImagePullBackOff et ErrImagePull »Ces erreurs indiquent que Kubernetes n'arrive pas à télécharger l'image.
kubectl describe pod my-podImagePullBackOff signifie que Kubernetes continue d'essayer avec un délai croissant (backoff exponentiel), jusqu'à un maximum de 5 minutes (300 secondes). Si vous corrigez le problème (credentials, nom d'image), le Pod ne redémarre pas immédiatement, attendez le prochain retry ou supprimez/recréez le Pod.
Causes fréquentes :
| Erreur | Cause probable | Solution |
|---|---|---|
ImagePullBackOff | Échecs répétés de pull | Vérifiez les credentials et la connectivité |
ErrImagePull | Image introuvable ou accès refusé | Vérifiez le nom de l'image et les droits |
InvalidImageName | Syntaxe d'image incorrecte | Corrigez le format (registre/nom:tag) |
ErrImageNeverPull | imagePullPolicy: Never et image absente du nœud | Pré-chargez l'image sur le nœud, ou changez de politique |
La dernière ligne se distingue des autres : le kubelet n'a rien tenté, donc rien ne sert de vérifier le registre ou les identifiants. Le message le dit sans ambiguïté :
Container image "monapp:v1" is not present with pull policy of NeverChecklist de diagnostic
Section intitulée « Checklist de diagnostic »Ces vérifications vont de la plus fréquente à la plus rare, et c'est l'ordre qui fait gagner du temps : la faute de frappe dans le nom de l'image cause plus d'incidents que tous les autres points réunis.
-
Vérifiez que l'image existe
Fenêtre de terminal # Depuis une machine avec accès au registredocker pull myregistry.example.com/myapp:v1.0# oucrane manifest myregistry.example.com/myapp:v1.0 -
Vérifiez le Secret imagePullSecrets
Fenêtre de terminal # Le Secret existe-t-il dans le bon namespace ?kubectl get secret regcred -n production# Le Pod le référence-t-il ?kubectl get pod my-pod -o jsonpath='{.spec.imagePullSecrets}' -
Testez les credentials
Fenêtre de terminal # Décodez et testez manuellementkubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d -
Consultez les events du Pod
Fenêtre de terminal kubectl describe pod my-pod | grep -A 10 Events
Erreur FailedToRetrieveImagePullSecret
Section intitulée « Erreur FailedToRetrieveImagePullSecret »Events: Reason: FailedToRetrieveImagePullSecret Message: Unable to retrieve some image pull secrets (regcred)Cette erreur signifie que le Secret référencé dans imagePullSecrets n'existe pas dans le namespace du Pod. Vérifiez :
- Le nom du Secret est correct
- Le Secret existe dans le même namespace que le Pod
Ne remontez cette piste que si le registre exige vraiment une authentification.
Un imagePullSecrets pointant vers un Secret absent ne fait pas échouer un
Pod dont l'image est publique : le kubelet la tire anonymement et le Pod démarre
normalement. Chercher du côté du Secret quand l'image vient de Docker Hub ou de
registry.k8s.io fait perdre du temps.
Images multi-architecture
Section intitulée « Images multi-architecture »Les images modernes supportent plusieurs architectures (amd64, arm64) via un manifest index (ou "fat manifest").
# Voir les architectures supportéescrane manifest nginx:1.30.2 | jq '.manifests[].platform'Kubernetes sélectionne automatiquement la bonne architecture selon le node. Attention : le pull réussit automatiquement uniquement si l'image publiée supporte l'architecture du nœud cible. Si vous déployez une image amd64 sur un nœud arm64 sans manifest multi-arch, le conteneur échouera avec une erreur exec format error.
Commandes impératives CKAD
Section intitulée « Commandes impératives CKAD »L'épreuve est chronométrée : ces commandes doivent sortir sans hésitation, et surtout sans ouvrir un éditeur. --dry-run=client -o yaml est la plus rentable : elle produit un manifeste correct en une seconde, au lieu de l'écrire de mémoire.
Pour l'examen CKAD, maîtrisez ces commandes :
# Créer un Pod avec une image spécifiquekubectl run nginx --image=nginx:1.30@sha256:d5792f71a9496b833bc08ea834a758c46e2b6a6306c10f4be926f38a656cdc1c
# Générer le YAML sans créer le Podkubectl run nginx --image=nginx:1.30@sha256:d5792f71a9496b833bc08ea834a758c46e2b6a6306c10f4be926f38a656cdc1c --dry-run=client -o yaml > pod.yaml
# Changer l'image d'un Deploymentkubectl set image deployment/myapp myapp=myapp:v2.0
# Créer un Secret docker-registrykubectl create secret docker-registry regcred \ --docker-server=registry.example.com \ --docker-username=user \ --docker-password=pass
# Voir les événements d'un Pod en erreurkubectl describe pod my-pod | tail -20À retenir
Section intitulée « À retenir »| Concept | Points clés |
|---|---|
| ImagePullPolicy | Always (latest), IfNotPresent (tags versionnés), Never (local only) |
| Tags | Mutables, pratiques pour le dev, risqués en prod |
| Digests | Immuables (sha256:...), garantissent la reproductibilité |
| imagePullSecrets | Secret de type docker-registry dans le même namespace |
| ImagePullBackOff | Vérifiez image, credentials, et connectivité réseau |
Testez vos connaissances
Section intitulée « Testez vos connaissances »Sept questions sur ce qui coûte cher en production : un tag republié sans prévenir, un Secret de registre créé dans le mauvais namespace, et le comportement par défaut du téléchargement.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Supply Chain Security : La signature et l'attestation des images que vous venez d'apprendre à référencer.
- Image Scanning : La recherche de CVE dans ces mêmes images, avec Grype et Trivy.
- Diagnostiquer un ImagePullBackOff : La marche à suivre quand le kubelet n'arrive pas à récupérer l'image demandée.