<p>Bonjour,</p>
<p>L’erreur <strong>“exceeded its progress deadline”</strong> dans Azure Kubernetes Service (AKS) est l’une des erreurs les plus frustrantes car elle peut avoir de nombreuses causes sous-jacentes. Elle indique qu’une opération (déploiement, mise à l’échelle, mise à jour) n’a pas abouti dans le délai imparti. Je vais vous guider à travers un diagnostic systématique et les solutions pour chaque cause possible.</p>
<h2><a name="p-34587-comprendre-lerreur-exceeded-its-progress-deadline-1" class="anchor" href="#p-34587-comprendre-lerreur-exceeded-its-progress-deadline-1" aria-label="Heading link"></a>Comprendre l’erreur “exceeded its progress deadline”</h2>
<h3><a name="p-34587-origine-de-lerreur-2" class="anchor" href="#p-34587-origine-de-lerreur-2" aria-label="Heading link"></a>Origine de l’erreur</h3>
<p>Cette erreur provient du <strong>progressDeadlineSeconds</strong> configuré dans votre Deployment Kubernetes. Par défaut, cette valeur est de <strong>600 secondes (10 minutes)</strong>. Si Kubernetes ne peut pas faire progresser le déploiement (amener les pods à l’état Running) dans ce délai, il marque le déploiement avec la condition <code>Progressing: False</code> et le message <code>exceeded its progress deadline</code>.</p>
<pre data-code-wrap="yaml"><code class="lang-yaml"># Exemple de spec de Deployment avec progressDeadlineSeconds explicite
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-application
spec:
progressDeadlineSeconds: 600 # 10 minutes par défaut
replicas: 3
selector:
matchLabels:
app: mon-application
template:
spec:
containers:
- name: mon-application
image: monregistry.azurecr.io/mon-app:latest
</code></pre>
<h3><a name="p-34587-symptmes-caractristiques-3" class="anchor" href="#p-34587-symptmes-caractristiques-3" aria-label="Heading link"></a>Symptômes caractéristiques</h3>
<pre data-code-wrap="bash"><code class="lang-bash"># L'erreur apparaît dans la description du deployment
kubectl describe deployment mon-deployment -n mon-namespace
Vous verrez quelque chose comme :
Conditions:
Type Status Reason
---- ------ ------
Available False MinimumReplicasUnavailable
Progressing False ProgressDeadlineExceeded
Events:
Normal ScalingReplicaSet ... Scaled up replica set to 3
Warning ProgressDeadlineExceeded ... Deployment exceeded its progress deadline
</code></pre>
<h2><a name="p-34587-diagnostic-systmatique-4" class="anchor" href="#p-34587-diagnostic-systmatique-4" aria-label="Heading link"></a>Diagnostic systématique</h2>
<h3><a name="p-34587-tape-1-identifier-les-pods-problmatiques-5" class="anchor" href="#p-34587-tape-1-identifier-les-pods-problmatiques-5" aria-label="Heading link"></a>Étape 1 : Identifier les pods problématiques</h3>
<pre data-code-wrap="bash"><code class="lang-bash"># Lister tous les pods avec leur état
kubectl get pods -n mon-namespace -o wide
Filtrer les pods qui ne sont pas Running/Completed
kubectl get pods -n mon-namespace --field-selector=status.phase!=Running
Voir les événements récents
kubectl get events -n mon-namespace --sort-by='.lastTimestamp' | tail -20
</code></pre>
<h3><a name="p-34587-tape-2-analyser-les-logs-et-ltat-des-pods-6" class="anchor" href="#p-34587-tape-2-analyser-les-logs-et-ltat-des-pods-6" aria-label="Heading link"></a>Étape 2 : Analyser les logs et l’état des pods</h3>
<pre data-code-wrap="bash"><code class="lang-bash"># Décrire un pod en erreur
kubectl describe pod <nom-du-pod> -n mon-namespace
Voir les logs du pod
kubectl logs <nom-du-pod> -n mon-namespace
Logs du conteneur d'init si applicable
kubectl logs <nom-du-pod> -n mon-namespace -c init-container-name
Logs du conteneur précédent (si le pod a redémarré)
kubectl logs <nom-du-pod> -n mon-namespace --previous
</code></pre>
<h2><a name="p-34587-causes-frquentes-et-solutions-7" class="anchor" href="#p-34587-causes-frquentes-et-solutions-7" aria-label="Heading link"></a>Causes fréquentes et solutions</h2>
<h3><a name="p-34587-cause-1-problme-dimage-docker-imagepullbackoff-errimagepull-8" class="anchor" href="#p-34587-cause-1-problme-dimage-docker-imagepullbackoff-errimagepull-8" aria-label="Heading link"></a>Cause 1 : Problème d’image Docker (ImagePullBackOff / ErrImagePull)</h3>
<p>C’est la cause la plus courante. Le pod ne peut pas télécharger l’image depuis le registre.</p>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier l'état des pods
kubectl get pods -n mon-namespace
STATUS: ImagePullBackOff ou ErrImagePull
Diagnostiquer
kubectl describe pod <pod-name> -n mon-namespace | grep -A 10 "Events"
</code></pre>
<p><strong>Solutions :</strong></p>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier que l'image existe dans Azure Container Registry
az acr repository show-tags \
--name MonACR \
--repository mon-application \
--output table
Vérifier l'intégration ACR-AKS
az aks check-acr \
--name MonClusterAKS \
--resource-group MonResourceGroup \
--acr MonACR.azurecr.io
Recréer l'intégration ACR si nécessaire
az aks update \
--name MonClusterAKS \
--resource-group MonResourceGroup \
--attach-acr MonACR
</code></pre>
<p>Si vous utilisez un imagePullSecret :</p>
<pre data-code-wrap="yaml"><code class="lang-yaml"># Créer un secret pour l'authentification au registre
kubectl create secret docker-registry acr-secret \
--docker-server=monacr.azurecr.io \
--docker-username=MonACR \
--docker-password=$(az acr credential show --name MonACR --query passwords[0].value -o tsv) \
-n mon-namespace
</code></pre>
<h3><a name="p-34587-cause-2-ressources-insuffisantes-pending-pods-9" class="anchor" href="#p-34587-cause-2-ressources-insuffisantes-pending-pods-9" aria-label="Heading link"></a>Cause 2 : Ressources insuffisantes (Pending pods)</h3>
<p>Les pods restent en état <code>Pending</code> car les nœuds n’ont pas assez de CPU/mémoire.</p>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier les ressources des nœuds
kubectl top nodes
kubectl describe nodes | grep -A 5 "Allocated resources"
Voir les demandes de ressources des pods
kubectl describe pod <pod-name> -n mon-namespace | grep -A 10 "Requests"
</code></pre>
<p><strong>Solutions :</strong></p>
<pre data-code-wrap="bash"><code class="lang-bash"># Augmenter le nombre de nœuds dans le nodepool
az aks nodepool scale \
--resource-group MonResourceGroup \
--cluster-name MonClusterAKS \
--name nodepool1 \
--node-count 5
Ou activer l'autoscaling
az aks nodepool update \
--resource-group MonResourceGroup \
--cluster-name MonClusterAKS \
--name nodepool1 \
--enable-cluster-autoscaler \
--min-count 2 \
--max-count 10
</code></pre>
<p>Revoyez également les limites dans le manifest :</p>
<pre data-code-wrap="yaml"><code class="lang-yaml">resources:
requests:
memory: "256Mi" # Réduire si trop élevé
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
</code></pre>
<h3><a name="p-34587-cause-3-livenessreadiness-probes-trop-strictes-10" class="anchor" href="#p-34587-cause-3-livenessreadiness-probes-trop-strictes-10" aria-label="Heading link"></a>Cause 3 : Liveness/Readiness Probes trop strictes</h3>
<p>Si les probes échouent, Kubernetes redémarre le pod ou ne le marque jamais comme Ready.</p>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier les probes dans la description du pod
kubectl describe pod <pod-name> -n mon-namespace | grep -A 10 "Liveness|Readiness"
</code></pre>
<p>Exemple de configuration trop stricte à corriger :</p>
<pre data-code-wrap="yaml"><code class="lang-yaml"># AVANT (trop strict)
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5 # Trop court si l'app démarre lentement
periodSeconds: 10
failureThreshold: 3
APRÈS (plus tolérant)
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 60 # Laisser le temps à l'application de démarrer
periodSeconds: 15
failureThreshold: 5
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
successThreshold: 1
</code></pre>
<h3><a name="p-34587-cause-4-problmes-de-rseau-ou-de-dns-dans-aks-11" class="anchor" href="#p-34587-cause-4-problmes-de-rseau-ou-de-dns-dans-aks-11" aria-label="Heading link"></a>Cause 4 : Problèmes de réseau ou de DNS dans AKS</h3>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier la connectivité réseau depuis un pod de debug
kubectl run debug --image=busybox --restart=Never -it --rm -- sh
Dans le pod de debug
nslookup kubernetes.default
wget -qO- http://mon-service:8080/health
</code></pre>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier l'état du CoreDNS
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns
</code></pre>
<h3><a name="p-34587-cause-5-configmaps-ou-secrets-manquants-12" class="anchor" href="#p-34587-cause-5-configmaps-ou-secrets-manquants-12" aria-label="Heading link"></a>Cause 5 : ConfigMaps ou Secrets manquants</h3>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier les volumes montés
kubectl describe pod <pod-name> -n mon-namespace | grep -A 5 "Mounts|Volumes"
Vérifier que les secrets existent
kubectl get secrets -n mon-namespace
kubectl get configmaps -n mon-namespace
</code></pre>
<h3><a name="p-34587-cause-6-problme-de-persistentvolumeclaim-pvc-13" class="anchor" href="#p-34587-cause-6-problme-de-persistentvolumeclaim-pvc-13" aria-label="Heading link"></a>Cause 6 : Problème de PersistentVolumeClaim (PVC)</h3>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier l'état des PVC
kubectl get pvc -n mon-namespace
Si un PVC est Pending
kubectl describe pvc mon-pvc -n mon-namespace
</code></pre>
<pre data-code-wrap="bash"><code class="lang-bash"># Vérifier les StorageClass disponibles
kubectl get storageclass
Vérifier que la StorageClass AKS est disponible
az aks show \
--name MonClusterAKS \
--resource-group MonResourceGroup \
--query storageProfile
</code></pre>
<h2><a name="p-34587-augmenter-le-dlai-progressdeadlineseconds-14" class="anchor" href="#p-34587-augmenter-le-dlai-progressdeadlineseconds-14" aria-label="Heading link"></a>Augmenter le délai progressDeadlineSeconds</h2>
<p>Si votre application nécessite plus de temps pour démarrer (légitimement), augmentez le délai :</p>
<pre data-code-wrap="yaml"><code class="lang-yaml">apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-application
spec:
progressDeadlineSeconds: 1800 # 30 minutes pour une app lente
minReadySeconds: 30 # Attendre 30s que le pod soit stable
</code></pre>
<pre data-code-wrap="bash"><code class="lang-bash"># Patcher le deployment existant
kubectl patch deployment mon-deployment -n mon-namespace \
-p '{"spec":{"progressDeadlineSeconds":1800}}'
</code></pre>
<h2><a name="p-34587-surveillance-continue-avec-azure-monitor-15" class="anchor" href="#p-34587-surveillance-continue-avec-azure-monitor-15" aria-label="Heading link"></a>Surveillance continue avec Azure Monitor</h2>
<p>Pour éviter que ce problème passe inaperçu à l’avenir, configurez des alertes :</p>
<pre data-code-wrap="bash"><code class="lang-bash"># Activer le monitoring AKS avec Azure Monitor
az aks enable-addons \
--resource-group MonResourceGroup \
--name MonClusterAKS \
--addons monitoring \
--workspace-resource-id "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.OperationalInsights/workspaces/{workspace}"
Requête KQL pour détecter les déploiements en échec
Dans Log Analytics Workspace :
KubeEvents
| where Reason == "ProgressDeadlineExceeded"
| project TimeGenerated, Namespace, Name, Message
| order by TimeGenerated desc
</code></pre>
<h2><a name="p-34587-checklist-de-rsolution-rapide-16" class="anchor" href="#p-34587-checklist-de-rsolution-rapide-16" aria-label="Heading link"></a>Checklist de résolution rapide</h2>
<pre data-code-wrap="bash"><code class="lang-bash">#!/bin/bash
Script de diagnostic rapide
NAMESPACE="mon-namespace"
DEPLOYMENT="mon-deployment"
echo "=== État du Deployment ==="
kubectl rollout status deployment/$DEPLOYMENT -n $NAMESPACE --timeout=30s
echo "=== Pods en cours ==="
kubectl get pods -n $NAMESPACE -l app=$DEPLOYMENT -o wide
echo "=== Événements récents ==="
kubectl get events -n $NAMESPACE --sort-by='.lastTimestamp' | tail -15
echo "=== Ressources des nœuds ==="
kubectl top nodes
echo "=== Description du deployment ==="
kubectl describe deployment $DEPLOYMENT -n $NAMESPACE | grep -A 20 "Conditions:"
</code></pre>
<h2><a name="p-34587-rollback-durgence-17" class="anchor" href="#p-34587-rollback-durgence-17" aria-label="Heading link"></a>Rollback d’urgence</h2>
<p>Si le déploiement bloque la production :</p>
<pre data-code-wrap="bash"><code class="lang-bash"># Rollback vers la version précédente
kubectl rollout undo deployment/mon-deployment -n mon-namespace
Rollback vers une version spécifique
kubectl rollout history deployment/mon-deployment -n mon-namespace
kubectl rollout undo deployment/mon-deployment --to-revision=3 -n mon-namespace
Vérifier le statut après rollback
kubectl rollout status deployment/mon-deployment -n mon-namespace
</code></pre>
<hr>
<p>Pour vous aider plus précisément, pourriez-vous partager :</p>
<ol>
<li>La sortie de <code>kubectl describe deployment <nom> -n <namespace></code></li>
<li>La sortie de <code>kubectl get pods -n <namespace></code></li>
<li>Les logs du pod problématique (<code>kubectl logs <pod-name></code>)</li>
</ol>
<p>Ces informations permettront d’identifier la cause exacte dans votre environnement spécifique et d’appliquer la solution la plus adaptée.</p>