Tous les produits
Search
Centre de documentation

Container Service for Kubernetes:Use preStop hooks to prevent 502/504 errors during ALB Ingress rolling updates

Dernière mise à jour :Aug 11, 2026

Une mise en veille preStop retarde l'envoi du signal SIGTERM afin que le contrôleur ALB Ingress puisse désinscrire le pod avant son arrêt.

Prérequis

Avant de commencer, assurez-vous de disposer des éléments suivants :

Pour utiliser un ALB Ingress avec un cluster ACK dédié, autorisez le cluster pour le contrôleur ALB Ingress au préalable.

Fonctionnement

Cycle de vie d'un pod

Un pod contient deux types de conteneurs :

  • Conteneur d'initialisation : s'exécute avant le conteneur principal pour l'initialisation.

  • Conteneur principal : exécute l'application. Le hook postStart s'exécute après le démarrage, les vérifications de vitalité (liveness) et de disponibilité (readiness) s'exécutent pendant la durée de vie du conteneur, et le hook preStop s'exécute avant l'arrêt.

La figure suivante illustre le cycle de vie d'un pod.

image

Causes des erreurs : exécution parallèle de deux procédures

La suppression d'un pod déclenche deux procédures parallèles — l'arrêt du pod et la mise à jour du routage du trafic — ce qui provoque des erreurs 502 ou 504.

Procédure d'arrêt du pod

  1. kube-apiserver marque le pod comme étant en état Terminating.

  2. Le système exécute le hook preStop, s'il est configuré.

  3. Le cluster envoie un signal SIGTERM au conteneur.

  4. Le système attend l'arrêt du conteneur ou l'expiration de la période de grâce (terminationGracePeriodSeconds, par défaut : 30 secondes).

  5. Si le pod est toujours en cours d'exécution après la période de grâce, kubelet attend 2 secondes supplémentaires puis envoie un signal SIGKILL.

  6. Le pod est supprimé.

Procédure de mise à jour des règles de routage du trafic

  1. kube-apiserver marque le pod comme étant en état Terminating.

  2. Le contrôleur d'endpoint supprime l'adresse IP du pod de l'endpoint.

  3. Le contrôleur ALB Ingress réconcilie les serveurs backend et supprime l'endpoint du service du groupe de serveurs backend.

Étant donné que ces deux procédures s'exécutent en parallèle, il est possible que le contrôleur ALB Ingress ne termine pas la réconciliation avant l'arrêt du pod, ce qui entraîne le routage du trafic vers un pod en cours d'arrêt.

Comment un hook preStop permet d'éviter les erreurs

En l'absence de hook preStop, les erreurs suivantes peuvent survenir lors des mises à jour progressives :

Code d'état Cause
504 Le pod traitait une requête non idempotente au moment de son arrêt.
502 Le pod s'est arrêté après avoir reçu le signal SIGTERM, mais le contrôleur ALB Ingress ne l'avait pas encore retiré du groupe de serveurs backend.

Un hook preStop ajoute un délai de mise en veille qui démarre lorsque kube-apiserver marque le pod comme étant en état Terminating, offrant ainsi au contrôleur ALB Ingress le temps nécessaire pour désinscrire le pod avant qu'il ne reçoive le signal SIGTERM.

Budget temporel

La mise en veille preStop et l'arrêt du conteneur partagent la même période de grâce (terminationGracePeriodSeconds). Avec une commande sleep 10 et un temps d'arrêt du programme de 5 secondes, définissez terminationGracePeriodSeconds à au moins 15, plus une marge de sécurité. Cette rubrique utilise sleep 10 et terminationGracePeriodSeconds: 45.

Si la durée du preStop ajoutée au temps d'arrêt du programme dépasse terminationGracePeriodSeconds , l'arrêt gracieux expire et kubelet envoie un signal SIGKILL après une attente de 2 secondes. Augmentez la valeur de terminationGracePeriodSeconds pour couvrir les deux durées.

Étape 1 : Déployer l'application avec un hook preStop

  1. Créez le fichier tea-service.yaml avec le contenu suivant. Le champ lifecycle.preStop configure le hook.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tea
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: tea
      template:
        metadata:
          labels:
            app: tea
        spec:
          containers:
          - name: tea
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
            ports:
            - containerPort: 80
            lifecycle:
              preStop:          # Delay SIGTERM by 10 seconds to allow the ALB Ingress controller
                exec:           # to finish deregistering the pod from the backend server group.
                  command:
                  - /bin/sh
                  - -c
                  - "sleep 10"
          terminationGracePeriodSeconds: 45   # Must exceed preStop duration + program shutdown time.
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: tea-svc
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: tea
      type: NodePort
  2. Déployez le Deployment et le Service.

    kubectl apply -f tea-service.yaml
  3. Créez le fichier tea-ingress.yaml avec le contenu suivant.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: tea-ingress
    spec:
      ingressClassName: alb
      rules:
      - host: demo.ingress.top
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: tea-svc
                port:
                  number: 80
  4. Créez l'Ingress.

    kubectl apply -f tea-ingress.yaml
  5. Récupérez l'adresse ALB de l'Ingress.

    kubectl get ingress

    Résultat attendu :

    NAME          CLASS   HOSTS              ADDRESS                                              PORTS   AGE
    tea-ingress   alb     demo.ingress.top   alb-110zvs5nhsvfv*****.cn-chengdu.alb.aliyuncs.com   80      7m5s

    Notez la valeur ADDRESS pour l'étape suivante.

Étape 2 : Vérifier que le hook preStop empêche les interruptions de service

  1. Créez le fichier test.sh avec le contenu suivant. Ce script envoie une requête par seconde et consigne chaque code d'état HTTP.

    #!/bin/bash
    HOST="demo.ingress.top"
    DNS="alb-110zvs5nhsvfv*****.cn-chengdu.alb.aliyuncs.com"  # Replace with your ADDRESS value.
    printf "Response Code|| TIME \n" >> log.txt
    
    while true; do
      RESPONSE=$(curl -H Host:$HOST -s -o /dev/null -w "%{http_code}" -m 1 http://$DNS/)
      TIMESTAMP=$(date +%Y-%m-%d_%H:%M:%S)
      echo "$TIMESTAMP - $RESPONSE" >> log.txt
      sleep 1
    done
  2. Exécutez le script.

    bash test.sh
  3. Déclenchez un redémarrage progressif.

    kubectl rollout restart deploy tea
  4. Surveillez la progression du déploiement. Les captures d'écran suivantes montrent les états attendus des pods durant chaque phase de la mise à jour.

    image

    image

    image

    image

  5. Vérifiez le journal de test. Toutes les requêtes doivent retourner le code 200, confirmant l'absence d'interruption de service.

    cat log.txt

    Résultat attendu :

    image

Étapes suivantes