Aller au contenu
Conteneurs & Orchestration medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Gérer les images conteneurs dans Kubernetes

15 min de lecture

logo kubernetes

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.

  • Comprendre les trois valeurs d’ImagePullPolicy et 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 ImagePullBackOff et ErrImagePull
  • 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.

Avant d’entrer dans le détail, comprenons les trois mécanismes distincts qui interviennent :

QuestionMécanismeExemple
Quelle image exacte exécuter ?Tag ou digestnginx:1.25.3 ou nginx@sha256:...
Quand contacter le registre ?imagePullPolicyAlways, IfNotPresent, Never
Comment s’authentifier ?imagePullSecretsSecret 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.

Avant de configurer le pull d’images, comprenons la structure d’une référence d’image complète :

[registre/][namespace/]nom[:tag][@digest]
ComposantExempleDescription
Registreregistry.k8s.io, ghcr.ioServeur hébergeant l’image. Par défaut : Docker Hub (docker.io)
Namespacelibrary, myorgOrganisation ou utilisateur. library pour les images officielles
Nomnginx, myappNom de l’image
Tag:1.25.3, :latestVersion de l’image. Par défaut : latest
Digest@sha256:abc123...Hash unique et immuable de l’image

Le champ imagePullPolicy définit quand le kubelet tente de télécharger l’image depuis le registre.

PolitiqueComportementCas d’usage typique
AlwaysRé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
IfNotPresentUtilise 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
NeverN’utilise que l’image locale, échoue si absenteImages pré-chargées, air-gapped

Kubernetes applique une politique implicite selon le tag spécifié :

# imagePullPolicy NON spécifié
spec:
containers:
- name: app
image: nginx:latest # → Always (tag latest)
image: nginx # → Always (pas de tag = latest implicite)
image: nginx:1.25.3 # → IfNotPresent (tag explicite)
image: nginx@sha256:... # → IfNotPresent (digest)
apiVersion: v1
kind: Pod
metadata:
name: app-pod
namespace: production
spec:
containers:
- name: app
image: myregistry.example.com/myapp:v2.1.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080

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: Always

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.

Un digest est un hash SHA256 du contenu de l’image. Il est immuable par définition.

# ❌ Risqué en production
image: myapp:latest
# ✅ Reproductible et vérifiable
image: myapp@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07

Crane est l’outil le plus fiable pour manipuler les registres OCI :

Fenêtre de terminal
# Installer crane
go install github.com/google/go-containerregistry/cmd/crane@latest
# Récupérer le digest
crane digest nginx:1.25.3
# sha256:6926dd802f40...

Par défaut, Kubernetes ne peut télécharger que les images publiques. Pour accéder à un registre privé, vous devez fournir des credentials.

  1. 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
  2. Vérifiez le Secret créé

    Fenêtre de terminal
    kubectl get secret regcred -n production -o yaml

    Le champ .dockerconfigjson contient vos credentials encodés en base64.

  3. Référencez le Secret dans votre Pod

    apiVersion: v1
    kind: Pod
    metadata:
    name: private-app
    namespace: production
    spec:
    containers:
    - name: app
    image: myregistry.example.com/myapp:v1.0
    imagePullSecrets:
    - name: regcred

Pour éviter d’ajouter imagePullSecrets à chaque Pod, attachez le Secret au ServiceAccount par défaut :

apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: production
imagePullSecrets:
- name: regcred

Tous les Pods du namespace utilisant ce ServiceAccount hériteront automatiquement du Secret.

apiVersion: v1
kind: Secret
metadata:
name: regcred
namespace: production
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: eyJhdXRocyI6eyJteXJlZ2lzdHJ5LmV4YW1wbGUuY29tIjp7InVzZXJuYW1lIjoibXl1c2VyIiwicGFzc3dvcmQiOiJteXBhc3N3b3JkIiwiZW1haWwiOiJteXVzZXJAZXhhbXBsZS5jb20iLCJhdXRoIjoiYlhsMWMyVnlPbTE1Y0dGemMzZHZjbVE9In19fQ==

Pour décoder et vérifier le contenu :

Fenêtre de terminal
kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d | jq

Ces erreurs indiquent que Kubernetes n’arrive pas à télécharger l’image.

Fenêtre de terminal
kubectl describe pod my-pod

Causes fréquentes :

ErreurCause probableSolution
ImagePullBackOffÉchecs répétés de pullVérifiez les credentials et la connectivité
ErrImagePullImage introuvable ou accès refuséVérifiez le nom de l’image et les droits
InvalidImageNameSyntaxe d’image incorrecteCorrigez le format (registre/nom:tag)
  1. Vérifiez que l’image existe

    Fenêtre de terminal
    # Depuis une machine avec accès au registre
    docker pull myregistry.example.com/myapp:v1.0
    # ou
    crane manifest myregistry.example.com/myapp:v1.0
  2. 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}'
  3. Testez les credentials

    Fenêtre de terminal
    # Décodez et testez manuellement
    kubectl get secret regcred -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d
  4. Consultez les events du Pod

    Fenêtre de terminal
    kubectl describe pod my-pod | grep -A 10 Events
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

Les images modernes supportent plusieurs architectures (amd64, arm64) via un manifest index (ou “fat manifest”).

Fenêtre de terminal
# Voir les architectures supportées
crane manifest nginx:1.25.3 | 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.

Pour l’examen CKAD, maîtrisez ces commandes :

Fenêtre de terminal
# Créer un Pod avec une image spécifique
kubectl run nginx --image=nginx:1.25.3
# Générer le YAML sans créer le Pod
kubectl run nginx --image=nginx:1.25.3 --dry-run=client -o yaml > pod.yaml
# Changer l'image d'un Deployment
kubectl set image deployment/myapp myapp=myapp:v2.0
# Créer un Secret docker-registry
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass
# Voir les événements d'un Pod en erreur
kubectl describe pod my-pod | tail -20
ConceptPoints clés
ImagePullPolicyAlways (latest), IfNotPresent (tags versionnés), Never (local only)
TagsMutables, pratiques pour le dev, risqués en prod
DigestsImmuables (sha256:...), garantissent la reproductibilité
imagePullSecretsSecret de type docker-registry dans le même namespace
ImagePullBackOffVérifiez image, credentials, et connectivité réseau

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

10 questions
10 min.
70% requis

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

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn