Todos los productos
Search
Centro de documentos

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

Última actualización: Sep 04, 2026

Un sleep en preStop retrasa la señal SIGTERM para que el controlador de ALB Ingress pueda dar de baja el pod antes de su apagado.

Requisitos previos

Antes de empezar, asegúrese de contar con lo siguiente:

Para usar un ALB Ingress con un clúster dedicado ACK, authorize the cluster primero para el controlador de ALB Ingress.

Funcionamiento

Ciclo de vida del pod

Un pod contiene dos tipos de contenedores:

  • Contenedor de inicialización: Se ejecuta antes del contenedor principal para realizar tareas de inicialización.

  • Contenedor principal: Ejecuta la aplicación. postStart se ejecuta después del inicio, las comprobaciones de liveness y readiness se ejecutan durante el tiempo de vida del contenedor, y preStop se ejecuta antes de la terminación.

La siguiente figura muestra el ciclo de vida del pod.

image

Por qué ocurren errores: dos procedimientos se ejecutan en paralelo

Eliminar un pod desencadena dos procedimientos paralelos —la terminación del pod y la actualización del enrutamiento de tráfico—, lo que provoca errores 502/504.

Procedimiento de terminación del pod

  1. kube-apiserver marca el pod como Terminating.

  2. El sistema ejecuta el hook preStop, si está configurado.

  3. El clúster envía una señal SIGTERM al contenedor.

  4. El sistema espera a que el contenedor se detenga o a que expire el período de gracia (terminationGracePeriodSeconds, predeterminado: 30 segundos).

  5. Si el pod sigue ejecutándose después del período de gracia, kubelet espera 2 segundos adicionales y envía una señal SIGKILL.

  6. Se elimina el pod.

Procedimiento de actualización de reglas de enrutamiento de tráfico

  1. kube-apiserver marca el pod como Terminating.

  2. El controlador de endpoints elimina la dirección IP del pod del endpoint.

  3. El controlador de ALB Ingress reconcilia los servidores backend y elimina el endpoint del Service del grupo de servidores backend.

Dado que ambos procedimientos se ejecutan en paralelo, es posible que el controlador de ALB Ingress no termine la reconciliación antes de que el pod se apague, lo que dirige el tráfico a un pod en proceso de terminación.

Cómo evita errores un hook preStop

Sin un hook preStop, pueden ocurrir estos errores durante las actualizaciones continuas:

Código de estado

Causa

504

El pod estaba procesando una solicitud no idempotente cuando se terminó.

502

El pod se apagó después de recibir SIGTERM, pero el controlador de ALB Ingress aún no lo había eliminado del grupo de servidores backend.

Un hook preStop añade un retraso de sleep que comienza cuando kube-apiserver marca el pod como Terminating, lo que da tiempo al controlador de ALB Ingress para dar de baja el pod antes de que reciba SIGTERM.

Presupuesto de tiempo

El sleep de preStop y el apagado del contenedor comparten el mismo período de gracia (terminationGracePeriodSeconds). Con sleep 10 y un apagado del programa de 5 segundos, establezca terminationGracePeriodSeconds como mínimo en 15, más un margen de seguridad. Este tema utiliza sleep 10 y terminationGracePeriodSeconds: 45.

Si la duración de preStop más el tiempo de apagado del programa supera terminationGracePeriodSeconds , se agota el tiempo de espera del apagado controlado y kubelet envía SIGKILL después de una espera de 2 segundos. Aumente terminationGracePeriodSeconds para cubrir ambos procesos.

Paso 1: Desplegar la aplicación con un hook preStop

  1. Cree tea-service.yaml con el siguiente contenido. El campo lifecycle.preStop configura el 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. Despliegue el Deployment y el Service.

    kubectl apply -f tea-service.yaml
  3. Cree tea-ingress.yaml con el siguiente contenido.

    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. Cree el Ingress.

    kubectl apply -f tea-ingress.yaml
  5. Obtenga la dirección ALB del Ingress.

    kubectl get ingress

    Salida esperada:

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

    Tome nota del valor de ADDRESS para el siguiente paso.

Paso 2: Comprobar que el hook preStop evita interrupciones del servicio

  1. Cree test.sh con el siguiente contenido. El script envía una solicitud por segundo y registra cada código de estado 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. Ejecute el script.

    bash test.sh
  3. Desencadene un reinicio continuo.

    kubectl rollout restart deploy tea
  4. Supervise el progreso del despliegue. Las siguientes capturas de pantalla muestran los estados esperados de los pods durante cada fase de la actualización.

    image

    image

    image

    image

  5. Revise el registro de la prueba. Todas las solicitudes deben devolver 200, lo que confirma cero interrupciones del servicio.

    cat log.txt

    Salida esperada:

    image

Siguientes pasos