En el anterior Hemos revisado los componentes básicos del Service Mesh Istio, nos hemos familiarizado con el sistema y hemos respondido a las preguntas más comunes que suelen surgir al inicio del trabajo con Istio. En esta parte, veremos cómo organizar la recopilación de información de tracing a través de la red.

Lo primero que viene a la mente de muchos desarrolladores y administradores de sistemas cuando escuchan las palabras Service Mesh es el tracing. Y en efecto, añadimos un proxy especial a cada nodo de la red, a través del cual pasa todo el tráfico TCP. Parece que ahora sería fácil enviar información sobre todas las interacciones de red en la red. Sin embargo, en la realidad surgen muchos matices que deben tenerse en cuenta. Veamos algunos de ellos.
Mito número uno: podemos obtener datos sobre el tráfico de red de forma gratuita.
En realidad, relativamente gratis solo podemos obtener los nodos de nuestro sistema conectados por flechas y la tasa de datos que pasa entre los servicios (en esencia, solo la cantidad de bytes por unidad de tiempo). Sin embargo, en la mayoría de los casos, nuestros servicios se comunican a través de algún protocolo de nivel de aplicación, como HTTP, gRPC, Redis, entre otros. Y, por supuesto, queremos ver la información de tracing precisamente por estos protocolos, queremos conocer la tasa de solicitudes, no la tasa de datos. Queremos entender la latencia de las solicitudes en nuestro protocolo. Finalmente, queremos ver el camino completo que sigue una solicitud desde su entrada en nuestro sistema hasta que el usuario recibe una respuesta. Esta tarea no es tan sencilla de resolver.
Para empezar, veamos cómo se envían los spans de trazado desde la perspectiva de la arquitectura en Istio. Como recordamos en la primera parte, Istio tiene un componente separado para la recolección de telemetría, que se llama Mixer. Sin embargo, en la versión actual 1.0.*, el envío se realiza directamente desde los servidores proxy, es decir, desde el proxy de Envoy. El proxy de Envoy soporta el envío de spans de trazado a través del protocolo Zipkin de forma nativa. Es posible añadir otros protocolos, pero solo mediante un plugin. Con Istio, obtenemos inmediatamente un proxy de Envoy configurado y listo, que solo soporta el protocolo Zipkin. Si queremos usar, por ejemplo, el protocolo Jaeger y enviar spans de trazado a través de UDP, necesitaremos construir nuestra propia imagen de istio-proxy. Hay soporte para plugins personalizados para istio-proxy, pero todavía está en versión alfa. Por lo tanto, si queremos evitar una gran cantidad de configuraciones personalizadas, el rango de tecnologías utilizadas para almacenar y recibir spans de trazado se reduce. Desde los sistemas principales, actualmente podemos usar Zipkin mismo o Jaeger, pero enviando toda la información a través de un protocolo compatible con Zipkin (lo cual es significativamente menos eficiente). El propio protocolo Zipkin supone el envío de toda la información de trazado a los recolectores a través del protocolo HTTP, lo que es bastante costoso.
Como ya mencioné, queremos trazar los protocolos de nivel de aplicación. Esto significa que los servidores proxy que están al lado de cada servicio deben comprender qué tipo de interacción está ocurriendo actualmente. Por defecto, Istio configura todos los puertos como tipo TCP simple, lo que significa que no se enviarán trazas. Para que se envíen trazas, primero es necesario habilitar esta opción en la configuración principal de mesh y, lo que es muy importante, nombrar todos los puertos de las entidades de servicio de Kubernetes de acuerdo con el protocolo que se utiliza en el servicio. Es decir, por ejemplo, de esta manera:
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
targetPort: 80
name: http
selector:
app: nginxTambién se pueden usar nombres compuestos, como http-magic (Istio verá http y reconocería este puerto como un endpoint http). El formato es: proto-extra.
Para evitar tener que parchear una gran cantidad de configuraciones para definir el protocolo, se puede utilizar una solución alternativa sucia: parchear el componente Pilot en el momento justo en que está Al final, por supuesto, será necesario cambiar esta lógica a la estándar y adoptar la convención de nombres para todos los puertos.
Para entender si el protocolo está realmente definido correctamente, hay que acceder a cualquiera de los contenedores sidecar con el proxy envoy y hacer una solicitud al puerto de la interfaz de administración de envoy con la ubicación /config_dump. En la configuración resultante, hay que revisar el campo de operación del servicio deseado. Este se utiliza en Istio como un identificador de hacia dónde va la solicitud. Para personalizar el valor de este parámetro en Istio (luego lo veremos en nuestro sistema de trazado), es necesario indicar el flag serviceCluster al iniciar el contenedor sidecar. Por ejemplo, se puede calcular así a partir de las variables obtenidas de la API descendente de Kubernetes:
--serviceCluster ${POD_NAMESPACE}.$(echo ${POD_NAME} | sed -e 's/-[a-z0-9]*-[a-z0-9]*$//g')
Un buen ejemplo para entender cómo funciona el trazado en envoy es .
El endpoint para enviar los spans de trazado también debe indicarse en los flags de inicio del proxy envoy, por ejemplo: --zipkinAddress tracing-collector.tracing:9411
Mito número dos: podemos obtener trazas completas del paso de solicitudes por el sistema de forma económica y sin complicaciones.
Desafortunadamente, eso no es cierto. La dificultad de implementación depende de cómo ya esté establecido el intercambio de servicios. ¿Por qué es así?
El hecho es que para que el istio-proxy pueda entender la correspondencia entre las solicitudes entrantes en un servicio y las salientes de ese mismo servicio, no basta con interceptar todo el tráfico. Es necesario tener algún identificador de la conexión. En HTTP, el proxy envoy utiliza cabeceras especiales que permiten a envoy entender qué solicitud al servicio origina solicitudes específicas a otros servicios. La lista de tales cabeceras es:
- x-request-id,
- x-b3-traceid,
- x-b3-spanid,
- x-b3-parentspanid,
- x-b3-sampled,
- x-b3-flags,
- x-ot-span-context.
Si tienes un único punto, por ejemplo, un cliente base, donde se puede añadir dicha lógica, entonces está bien, solo tendrás que esperar a que se actualice esta biblioteca en todos los clientes. Pero si tienes un sistema muy heterogéneo y no hay homogenización en el paso de servicios a través de la red, probablemente será un gran problema. Sin añadir dicha lógica, toda la información de trazado será solo "unidimensional". Es decir, obtendremos todas las interacciones entre servicios, pero no estarán unidas en cadenas únicas de paso a través de la red.
Conclusión
Istio proporciona una herramienta conveniente para la recopilación de información de trazado en la red, sin embargo, es importante entender que su implementación requerirá adaptar su sistema y tener en cuenta las particularidades de la implementación de Istio. En última instancia, hay dos aspectos principales a resolver: definir el protocolo de la capa de aplicación (que debe ser compatible con el proxy envoy) y configurar el paso de información sobre la conectividad de las solicitudes desde el servicio hacia las solicitudes en el servicio (utilizando encabezados, en el caso del protocolo HTTP). Cuando estas cuestiones están resueltas, obtenemos una poderosa herramienta que permite recopilar información de la red de manera transparente incluso en sistemas muy heterogéneos, escritos en múltiples lenguajes y marcos diferentes.
En el próximo artículo sobre Service Mesh, abordaremos uno de los mayores problemas de Istio: el alto consumo de memoria RAM por cada contenedor proxy sidecar y discutiremos cómo se puede abordar este problema.
Fuente: habr.com
