Resolver problemas de inicio de cargas de trabajo en Cloud Service Mesh
En este documento se explican los problemas habituales de Cloud Service Mesh y cómo resolverlos. Si necesitas más ayuda, consulta el artículo Obtener asistencia.
La puerta de enlace no se inicia con el proxy sin distribución cuando se expone un puerto con privilegios
De forma predeterminada, el proxy sin distribución empieza con permisos de no administrador, lo que en algunos casos puede provocar errores de enlace en puertos privilegiados. Si ve errores similares a los siguientes durante el inicio del proxy, deberá aplicar un securityContext adicional para la implementación de la pasarela.
Error adding/updating listener(s) 0.0.0.0_80: cannot bind '0.0.0.0:80': Permission denied
El siguiente ejemplo es el archivo YAML de una implementación de pasarela de salida:
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-egressgateway
spec:
selector:
matchLabels:
app: istio-egressgateway
istio: egressgateway
template:
metadata:
annotations:
# This is required to tell Anthos Service Mesh to inject the gateway with the
# required configuration.
inject.istio.io/templates: gateway
labels:
app: istio-egressgateway
istio: egressgateway
spec:
containers:
- name: istio-proxy
image: auto # The image will automatically update each time the pod starts.
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 100m
memory: 128Mi
# Allow binding to all ports (such as 80 and 443)
securityContext:
sysctls:
- name: net.ipv4.ip_unprivileged_port_start
value: "0"
serviceAccountName: istio-egressgateway
Se rechaza la conexión al acceder a un endpoint de Cloud Service Mesh
Es posible que experimentes errores de conexión rechazada (ECONNREFUSED
) de forma intermitente en la comunicación de tus clústeres con tus endpoints, por ejemplo, Memorystore Redis, Cloud SQL o cualquier servicio externo al que necesite acceder la carga de trabajo de tu aplicación.
Esto puede ocurrir cuando la carga de trabajo de tu aplicación se inicia más rápido que el contenedor istio-proxy (Envoy
) e intenta acceder a un endpoint externo. Como en esta fase ya se ha ejecutado istio-init (initContainer
), hay reglas de iptables que redirigen todo el tráfico saliente a Envoy
. Como istio-proxy aún no está listo, las reglas de iptables redirigirán el tráfico a un proxy sidecar que aún no se ha iniciado y, por lo tanto, la aplicación recibe el error ECONNREFUSED
.
En los pasos siguientes se explica cómo comprobar si se trata del error que estás experimentando:
Consulta los registros de Stackdriver con el siguiente filtro para identificar qué pods han tenido el problema.
En el siguiente ejemplo se muestra un mensaje de error habitual:
Error: failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused [ioredis] Unhandled error event: Error: connect ECONNREFUSED
Busca una instancia del problema. Si usas la versión antigua de Stackdriver, usa
resource.type="container"
.resource.type="k8s_container" textPayload:"$ERROR_MESSAGE$"
Despliega la última aparición para obtener el nombre del pod y, a continuación, anota el
pod_name
enresource.labels
.Obtén la primera aparición del problema en ese pod:
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"
Ejemplo:
E 2020-03-31T10:41:15.552128897Z post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
Anota la marca de tiempo del primer error de este pod.
Usa el siguiente filtro para ver los eventos de inicio del pod.
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"
Ejemplo:
I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Container image "docker.io/istio/proxyv2:1.3.3" already present on machine spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Created container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Started container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{APP-CONTAINER-NAME} Created container spec.containers{APP-CONTAINER-NAME} W 2020-03-31T10:41:17Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:26Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:28Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:31Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:58Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy}
Usa las marcas de tiempo de los errores y los eventos de inicio de istio-proxy para confirmar que los errores se producen cuando
Envoy
no está listo.Si los errores se producen mientras el contenedor istio-proxy aún no está listo, es normal que se produzcan errores de conexión rechazada. En el ejemplo anterior, el pod intentaba conectarse a Redis en cuanto
2020-03-31T10:41:15.552128897Z
pero, en2020-03-31T10:41:58Z
, istio-proxy seguía fallando en las comprobaciones de disponibilidad.Aunque el contenedor istio-proxy se haya iniciado primero, es posible que no se haya preparado lo suficientemente rápido antes de que la aplicación ya intentara conectarse al endpoint externo.
Si este es el problema que tienes, sigue los pasos que se indican a continuación para solucionarlo.
Anota la configuración a nivel de pod. Esta opción solo está disponible a nivel de pod, no a nivel global.
annotations: proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
Modifica el código de la aplicación para que compruebe si
Envoy
está listo antes de intentar hacer cualquier otra solicitud a servicios externos. Por ejemplo, al iniciar la aplicación, inicia un bucle que haga solicitudes al endpoint de comprobación del estado de istio-proxy y solo continúa cuando se obtiene un código 200. El endpoint de comprobación del estado de istio-proxy es el siguiente:http://localhost:15020/healthz/ready
Condición de carrera durante la inyección de sidecar entre Vault y Cloud Service Mesh
Cuando se usa vault
para gestionar secretos, a veces vault
inserta un sidecar
antes de istio
, lo que provoca que los pods se queden en el estado Init
. Cuando esto ocurre, los pods creados se quedan en estado Init después de reiniciar cualquier implementación o de implementar una nueva. Por ejemplo:
E 2020-03-31T10:41:15.552128897Z
post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create
connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect:
connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
Este problema se debe a una condición de carrera. Tanto Istio como vault
insertan el sidecar e Istio debe ser el último en hacerlo. El proxy de istio
no se ejecuta durante los contenedores de inicialización. El contenedor istio
init configura reglas de iptables para
redirigir todo el tráfico al proxy. Como aún no se está ejecutando, esas reglas no redirigen a nada, por lo que bloquean todo el tráfico. Por eso, el contenedor init debe ser el último, de modo que el proxy esté en funcionamiento inmediatamente después de configurar las reglas de iptables. Lamentablemente, el orden no es determinista, por lo que, si se inserta Istio primero, se produce un error.
Para solucionar este problema, permite la dirección IP de vault
para que el tráfico que va a la IP de Vault no se redirija al proxy Envoy, que aún no está listo y, por lo tanto, bloquea la comunicación. Para ello, se debe añadir una nueva anotación llamada excludeOutboundIPRanges
.
En Cloud Service Mesh gestionado, esto solo es posible a nivel de Deployment o Pod en spec.template.metadata.annotations
. Por ejemplo:
apiVersion: apps/v1
kind: Deployment
...
...
...
spec:
template:
metadata:
annotations:
traffic.sidecar.istio.io/excludeOutboundIPRanges:
En el caso de Cloud Service Mesh en clúster, hay una opción para configurarlo como global con un IstioOperator en spec.values.global.proxy.excludeIPRanges
. Por ejemplo:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
proxy:
excludeIPRanges: ""
Después de añadir la anotación, reinicia tus cargas de trabajo.