Verificación de Salud de Services de Istio

Las sondas de liveness y readiness de Kubernetes describe varias maneras de configurar sondas de liveness y readiness:

  1. Comando
  2. Solicitud HTTP
  3. Sonda TCP
  4. Sonda gRPC

El enfoque de comando funciona sin cambios requeridos, pero las solicitudes HTTP, sondas TCP, y sondas gRPC requieren que Istio haga cambios a la configuración del pod.

Las solicitudes de verificación de salud al Service liveness-http son enviadas por Kubelet. Esto se convierte en un problema cuando mutual TLS está habilitado, porque el Kubelet no tiene un certificado emitido por Istio. Por lo tanto, las solicitudes de verificación de salud fallarán.

Las verificaciones de sonda TCP necesitan manejo especial, porque Istio redirige todo el tráfico entrante hacia el sidecar, y así todos los puertos TCP aparecen abiertos. El Kubelet simplemente verifica si algún proceso está escuchando en el puerto especificado, y así la sonda siempre tendrá éxito mientras el sidecar esté ejecutándose.

Istio resuelve ambos problemas reescribiendo la sonda readiness/liveness de la aplicación PodSpec, para que la solicitud de sonda sea enviada al sidecar agent.

Ejemplo de reescritura de sonda liveness

Para demostrar cómo la sonda readiness/liveness es reescrita a nivel de PodSpec de la aplicación, usemos el ejemplo liveness-http-same-port.

Primero crea y etiqueta un namespace para el ejemplo:

$ kubectl create namespace istio-io-health-rewrite
$ kubectl label namespace istio-io-health-rewrite istio-injection=enabled

Y despliega la aplicación de ejemplo:

$ kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: liveness-http
  namespace: istio-io-health-rewrite
spec:
  selector:
    matchLabels:
      app: liveness-http
      version: v1
  template:
    metadata:
      labels:
        app: liveness-http
        version: v1
    spec:
      containers:
      - name: liveness-http
        image: docker.io/istio/health:example
        ports:
        - containerPort: 8001
        livenessProbe:
          httpGet:
            path: /foo
            port: 8001
          initialDelaySeconds: 5
          periodSeconds: 5
EOF

Una vez desplegado, puedes inspeccionar el contenedor de aplicación del pod para ver la ruta cambiada:

$ kubectl get pod "$LIVENESS_POD" -n istio-io-health-rewrite -o json | jq '.spec.containers[0].livenessProbe.httpGet'
{
  "path": "/app-health/liveness-http/livez",
  "port": 15020,
  "scheme": "HTTP"
}

La ruta livenessProbe original ahora está mapeada contra la nueva ruta en la variable de entorno del contenedor sidecar ISTIO_KUBE_APP_PROBERS:

$ kubectl get pod "$LIVENESS_POD" -n istio-io-health-rewrite -o=jsonpath="{.spec.containers[1].env[?(@.name=='ISTIO_KUBE_APP_PROBERS')]}"
{
  "name":"ISTIO_KUBE_APP_PROBERS",
  "value":"{\"/app-health/liveness-http/livez\":{\"httpGet\":{\"path\":\"/foo\",\"port\":8001,\"scheme\":\"HTTP\"},\"timeoutSeconds\":1}}"
}

Para solicitudes HTTP y gRPC, el sidecar agent redirige la solicitud a la aplicación y quita el cuerpo de respuesta, retornando solo el código de respuesta. Para sondas TCP, el sidecar agent hará entonces la verificación del puerto mientras evita la redirección de tráfico.

La reescritura de sondas problemáticas está habilitada por defecto en todos los perfiles de configuración integrados de Istio pero puede deshabilitarse como se describe a continuación.

Sondas de liveness y readiness usando el enfoque de comando

Istio proporciona un ejemplo de liveness que implementa este enfoque. Para demostrar que funciona con mutual TLS habilitado, primero crea un namespace para el ejemplo:

$ kubectl create ns istio-io-health

Para configurar mutual TLS estricto, ejecuta:

$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: "default"
  namespace: "istio-io-health"
spec:
  mtls:
    mode: STRICT
EOF

Después, cambia el directorio a la raíz de la instalación de Istio y ejecuta el siguiente comando para desplegar el Service de ejemplo:

Zip
$ kubectl -n istio-io-health apply -f <(istioctl kube-inject -f @samples/health-check/liveness-command.yaml@)

Para confirmar que las sondas de liveness están funcionando, verifica el estado del pod de ejemplo para verificar que esté ejecutándose.

$ kubectl -n istio-io-health get pod
NAME                             READY     STATUS    RESTARTS   AGE
liveness-6857c8775f-zdv9r        2/2       Running   0           4m

Sondas de liveness y readiness usando el enfoque HTTP, TCP, y gRPC

Como se mencionó anteriormente, Istio usa reescritura de sonda para implementar sondas HTTP, TCP, y gRPC por defecto. Puedes deshabilitar esta característica ya sea para pods específicos, o globalmente.

Deshabilitar la reescritura de sonda para un pod

Puedes anotar el pod con sidecar.istio.io/rewriteAppHTTPProbers: "false" para deshabilitar la opción de reescritura de sonda. Asegúrate de agregar la anotación al recurso pod porque será ignorada en cualquier otro lugar (por ejemplo, en un recurso deployment envolvente).

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: liveness-http
spec:
  selector:
    matchLabels:
      app: liveness-http
      version: v1
  template:
    metadata:
      labels:
        app: liveness-http
        version: v1
      annotations:
        sidecar.istio.io/rewriteAppHTTPProbers: "false"
    spec:
      containers:
      - name: liveness-http
        image: docker.io/istio/health:example
        ports:
        - containerPort: 8001
        livenessProbe:
          httpGet:
            path: /foo
            port: 8001
          initialDelaySeconds: 5
          periodSeconds: 5
EOF

Este enfoque te permite deshabilitar la reescritura de verificación de salud gradualmente en deployments individuales, sin reinstalar Istio.

Deshabilitar la reescritura de sonda globalmente

Instala Istio usando --set values.sidecarInjectorWebhook.rewriteAppHTTPProbe=false para deshabilitar la reescritura de sonda globalmente. Alternativamente, actualiza el mapa de configuración para el inyector de sidecar de Istio:

$ kubectl get cm istio-sidecar-injector -n istio-system -o yaml | sed -e 's/"rewriteAppHTTPProbe": true/"rewriteAppHTTPProbe": false/' | kubectl apply -f -

Limpieza

Remueve los namespaces usados para los ejemplos:

$ kubectl delete ns istio-io-health istio-io-health-rewrite
¿Fue útil esta información?
¿Tienes alguna sugerencia para mejorar?

¡Gracias por tus comentarios!