Engineering

La importancia de los metadatos en tus iniciativas de observabilidad de Kubernetes

Este blog se publicó originalmente en tfir.io.

Kubernetes es un sistema de orquestación de contenedores popular que es la esencia de los proyectos de Cloud Native Computing Foundation. Automatiza el despliegue, ciclo de vida y operaciones de contenedores, aplicaciones en contenedores y "pods", que son grupos de uno o más contenedores. La plataforma en sí, junto con cada una de estas cargas de trabajo, pueden generar datos de eventos. Existen diferentes tipos de datos asociados con estos procesos. Los logs pueden variar desde mensajes de depuración simples como "sí, llegó aquí" hasta logs detallados de acceso al servidor web que proporcionan información sobre transacciones. Las métricas, o Datos temporales, son valores numéricos que se miden a un intervalo regular; por ejemplo, la cantidad de operaciones instantáneas por segundo, las tasas de coincidencia en caché, el recuento de clientes que acceden a tu sitio o cuestiones básicas como la cantidad de CPU o memoria que ha estado usando un contenedor en los últimos cinco segundos.

La observabilidad toma estos logs y métricas y los convierte en buscables, generalmente en un almacén de datos correlativo, y suelen estar combinados con datos de rastreo de las aplicaciones. Estos datos de rastreo, o información detallada de monitoreo de rendimiento de aplicaciones (APM), captura dónde dedican su tiempo las aplicaciones o servicios, cómo y con qué interactúan, y cualquier error que surja. Los logs y las métricas proporcionan una vista de caja negra de una aplicación, mientras que los datos de APM muestran lo que sucede dentro de las aplicaciones.  

Los logs, métricas y datos de rastreo de las aplicaciones combinados pueden ayudar a reducir el tiempo promedio de detección y resolución o errores o incidentes, pero a medida que evolucionan los modelos de despliegue de aplicaciones (como con despliegues de Kubernetes), se vuelve muy importante comprender dónde están sucediendo realmente las cosas en un entorno dinámico. Allí entran en juego los metadatos.

¿Qué son exactamente los metadatos?

Según la definición de Webster, los metadatos son "datos que proporcionan información sobre otros datos". Parece bastante sencillo, ¿no? Hay muchos lugares comunes donde encontrarás metadatos: la página que hospeda este blog tiene metadatos. Tiene etiquetas SEO, sugerencias para ayudar a los distintos navegadores a dar el formato correcto a la página y palabras clave para ayudar a describir la página. Del mismo modo, una imagen en tu dispositivo móvil tiene muchísimos metadatos; este es solo un fragmento:

ExifTool Version Number         : 11.11 
File Name                       : 60398459048__A20828DD-FAA4-4133-BA1F-059DEC9E7332.jpeg 
Directory                       : . 
File Size                       : 2.8 MB 
File Modification Date/Time     : 2020:02:21 08:30:01-05:00 
File Access Date/Time           : 2020:02:21 08:30:23-05:00 
File Inode Change Date/Time     : 2020:02:21 08:30:22-05:00 
MIME Type                       : image/jpeg 
JFIF Version                    : 1.01 
Acceleration Vector             : -0.03239090369 -0.9104139204 -0.3862404525 
Exif Byte Order                 : Big-endian (Motorola, MM) 
Make                            : Apple 
Camera Model Name               : iPhone XS 
Orientation                     : Rotate 90 CW 
X Resolution                    : 72 
Y Resolution                    : 72 
Exif Image Width                : 4032 
Exif Image Height               : 3024

Podrías preguntarte "¿cómo me ayuda con mis iniciativas de observabilidad conocer el tipo MIME de una foto de un iPhone?". No lo hace, porque los metadatos de una imagen no son para eso, pero debería darte una idea de lo que aportan los metadatos. Los metadatos del iPhone te permiten filtrar según el tamaño, la orientación o cuánto te moviste cuando tomaste la foto (aparentemente debo mejorar eso). Veamos algunas cosas que te ayudarán a correlacionar y navegar tus datos de observabilidad, como los logs, las métricas y los datos de rastreo de las aplicaciones de tu entorno.  

Tendencias de despliegue de software y hardware

Las aplicaciones monolíticas en servidores con un solo propósito y de metal expuesto en un único centro de datos son cosa del pasado. Sí, todavía es común verlas ejecutando cargas de trabajo dedicadas, y no tiene nada de malo; muchos productos y aplicaciones a gran escala demandan todo el procesamiento que puedan obtener. En general, sin embargo, las tendencias de la industria en cuanto a modelos de despliegue de software y hardware se inclinan hacia los microservicios y contenedores.

trends-increasingly-complex-systems.png

Esta tendencia "de cambio a la derecha" no es universal; muchas tiendas tendrán varios modelos de despliegue de software trabajando en paralelo, junto con diversos patrones de hardware. Las máquinas virtuales o instancias en el cloud ejecutan aplicaciones SOA o cliente/servidor, mientras que los contenedores ejecutan imágenes de sus microservicios, orquestados por Kubernetes o Docker. En muchos casos, las aplicaciones y servicios en un modelo de despliegue aprovechan servicios en otro; ese nuevo microservicio sofisticado quizá todavía use una base de datos hospedada en metal expuesto.

La naturaleza de estos sistemas heterogéneos hace que los metadatos sean incluso más importantes. En el cambio hacia los contenedores, pods y microservicios programados de forma dinámica, se vuelve aún más difícil entrar al centro de datos, señalar una caja y decir "mi aplicación está ahí". Es posible, pero también es posible que esté en esos otros cuatro servidores detrás tuyo. 

Allí entran en juego los metadatos de ubicación. No nos referimos a latitud y longitud (aunque podría ser útil), sino a un esquema de direcciones, algo que te permita mínimamente ver de forma lógica de dónde viene un dato (ya sea un log, métrica o dato de rastreo de aplicaciones).  

Características de la infraestructura

Ubicación, ubicación, ubicación

Lo que necesitas variará según tu configuración, pero deberías planificar para el futuro. Cuánto puedes capturar dependerá de sobre qué se ejecuta un trabajo dado; si es una aplicación monolítica en metal expuesto, no capturarás detalles del pod de Kubernetes, lo cual está bien. Básicamente debemos proporcionar rutas de navegación para poder ver dónde se están ejecutando las cosas. Veremos la razón en breve.

Con la ubicación nuestro objetivo es una jerarquía de metadatos, hasta llegar al nivel de la aplicación, donde se ejecuta físicamente el trabajo.  

Centro de datos

Los metadatos del centro de datos deben incluir un identificador único para cada centro de datos, por ejemplo, el nombre de la ciudad. Esta información puede volverse un poco imprecisa cuando hablamos de Proveedores Cloud, pero existen algunas analogías paralelas. En esta situación podemos aprovechar el Proveedor Cloud y la región en los que estamos ejecutando, por ejemplo, GCP, europe-west1 y zona de disponibilidad b.

Si tienes niveles dedicados en tus centros de datos (quizás hay hosts específicos reservados para producción o pruebas, o divididos entre proyectos) asegúrate de agregar eso también a tus metadatos.  Es como una parte delimitada de tu centro de datos o un centro de datos dentro de un centro de datos.

Información del host

Ya sea que ejecutemos en metal expuesto, de forma virtualizada o en una instancia en el cloud, tenemos cierta información del host disponible regularmente para nosotros. Cada host tendrá atributos de nombre de host, dirección(es) IP, modelo de hardware o tipo de instancia, RAM y almacenamiento configurados, e incluso información del sistema operativo. Puedes hasta incluir información aún más detallada, como dónde reside este host: el número de piso en el centro de datos, el rack, la fila y también el estante. No sería la primera vez que un rack completo se viera afectado por problemas eléctricos o de cableado.

Detalles de aplicaciones

En este punto, tenemos información suficiente para identificar dónde se está ejecutando cada cosa; pero solo hasta el nivel del host, y cada host puede estar ejecutando muchos servicios o aplicaciones diferentes. Cuando comenzamos a hablar sobre las aplicaciones y los servicios, necesitamos agregar el nivel correspondiente de metadatos. Aquí es donde se empieza a tornar un poco como si-entonces-sino, así que lo mantendremos a un nivel alto y trabajaremos con la situación más compleja, con microservicios orquestados por Kubernetes. Aplicar esto en aplicaciones de metal expuesto y entornos virtualizados debería ser bastante sencillo.

Los contenedores en Kubernetes y Docker tienen automáticamente cierto nivel de metadatos disponible, que debería incluirse. Como mínimo, debemos incluir el nombre del pod o contenedor, la imagen y versión usadas como base del contenedor y la hora de inicio. Idealmente también incluiremos el nombre de la red y la información de IP, junto con cualquier cuota de almacenamiento, memoria o red. ¿Observas las paralelas en la información del host? Los contenedores y las máquinas virtuales son básicamente hosts que se ejecutan en otro host, por lo que tiene sentido que queramos extraer la misma información.

Dicho esto, cuando trabajamos con un entorno virtualizado podemos sacar las mismas analogías. Un host virtual tendrá el mismo nivel alto de detalles (un nombre, dirección IP y límites de memoria y almacenamiento) que los hosts.

En este punto nos enfrentamos a un dilema: tenemos algunos nombres de campo duplicados. Es importante recordar que queremos mantener una jerarquía. Los metadatos del host se encuentran más arriba en esa jerarquía que un contenedor o una máquina virtual:

├── NYC DC 1 
│   ├── Host 1 
│   │   ├── vm 1 
│   │   ├── vm 2 
│   │   └── vm 3 
│   └── Host 2 
│       ├── vm 1 
│       └── vm 2 
└── NYC DC 2 
    └── Host 1 
        ├── vm 1 
        ├── vm 2 
        ├── vm 3 
        └── vm 4

Con esto, es bastante obvio que debemos poner los valores en espacios de nombres diferentes y predecibles para asegurarnos de que no colisionen. Una buena forma de hacerlo es pasarlos como pares de clave/valor; por ejemplo, los metadatos de vm 2 en Host 1 en nuestro NYC DC 1 pueden incluir lo siguiente:

dc.name: "NYC DC 1" 
dc.floor: 2 
 
host.name:  "Host 1" 
host.IP: … 
host.available_memory_mb: 16384 
vm.name: "vm 1" 
vm.IP: …

Los contenedores son un poco diferentes cuando hablamos de una jerarquía, dado que un cluster de Kubernetes puede abarcar hosts. En este caso, nos interesa no solo la información de ubicación de un pod o contenedor dado, sino también los metadatos de orquestación correspondientes, como mencionamos antes. A continuación, veremos cómo los metadatos nos ayudan a lograr una mejor visibilidad de nuestras aplicaciones.

Observabilidad de las aplicaciones

Ahora que sabemos cómo abordar por completo lo que se ejecuta en nuestros sistemas, podemos comenzar a hablar de reunir los datos en sí (recuerda que los metadatos describen otros datos). Los "tres pilares de la observabilidad" son los logs, las métricas y los datos de rastreo de las aplicaciones (conocidos como datos de APM), ocasionalmente los datos de tiempo de actividad aparecen como el cuarto "pilar". Cuando reunimos logs y métricas debemos hacerlo en cada nivel de nuestro ecosistema, como se indica en el diagrama siguiente, que incluye información sobre los tipos de datos de observabilidad que deberían reunirse de cada abstracción:

what-to-monitor.png

Por ejemplo, debemos reunir logs, métricas y datos de disponibilidad de cada host o elemento de red en nuestros centros de datos, pero agregar APM para las aplicaciones y servicios.

Enriquecemos todo lo anterior con los metadatos correspondientes de cada nivel para aumentar la visibilidad de nuestras aplicaciones, infraestructura y ecosistema completo. Existen muchas formas de lograrlo: podemos enviarlos con cada evento o rastreo, lo que permite búsqueda y filtrado rápidos, o almacenar los metadatos de las partes estáticas de nuestro ecosistema y después establecer una referencia cruzada. Si bien el segundo método ahorraría un poco de espacio, corre el riesgo de quedar desactualizado u obsoleto, especialmente en ecosistemas dinámicos.

Combinar todas las partes

Con nuestros datos de observabilidad enriquecidos con metadatos podemos dividir en partes según las facetas que elegimos; no estamos limitados a mirar logs o datos de APM específicos. Por ejemplo, podemos desglosar el uso de CPU actual por host, por servicio:

infra-viewer.png

U observar el mismo parámetro en el tiempo:

metrics-explorer.png

Esto nos permite elegir los detalles según los cuales queremos reorganizar, respondiendo preguntas que de otra forma no podríamos, como las siguientes:

  • ¿Se está sobreusando mi centro de datos de EE. UU. en comparación con mi centro de datos de EMEA?
  • ¿Algún rack de mi ecosistema se está enfrentando a más errores que los otros?
  • ¿Puedo redestinar cierta infraestructura de desarrollo a producción?
  • ¿En qué hosts físicos se ejecutan los contenedores y pods de mi app de comercio electrónico?
  • Y, por último, ¿por qué las fotos de mi iPhone salen siempre borrosas?

Resumen

Los metadatos agregan nuevas dimensiones a tus análisis, proporcionan formas nuevas de agregar y dividir tus datos para ayudar a responder tus preguntas comerciales y de operaciones. Asegúrate de que la solución que usas para tus iniciativas de observabilidad esté preparada para crecer contigo y que tenga en cuenta los metadatos navegables, como Elastic Common Schema para que puedas asegurarte de que los metadatos lleguen donde esperas.