Inicia sesi贸n en Kubernetes (y no solo) hoy: expectativas y realidad



Era 2019, y todav铆a no tenemos una soluci贸n est谩ndar para la agregaci贸n de registros en Kubernetes. En este art铆culo, nos gustar铆a, utilizando ejemplos de la pr谩ctica real, compartir nuestras b煤squedas, los problemas encontrados y sus soluciones.

Sin embargo, para comenzar, har茅 una reserva para que diferentes clientes comprendan cosas muy diferentes al recopilar registros:

  • alguien quiere ver registros de seguridad y auditor铆a;
  • alguien: registro centralizado de toda la infraestructura;
  • y para alguien es suficiente recopilar solo los registros de la aplicaci贸n, excluyendo, por ejemplo, los equilibradores.

Acerca de c贸mo implementamos varias "Lista de deseos" y qu茅 dificultades encontramos, debajo del corte.

Teor铆a: acerca de las herramientas de registro


Antecedentes sobre los componentes del sistema de registro.


El registro ha recorrido un largo camino, como resultado de lo cual hemos desarrollado metodolog铆as para recopilar y analizar registros, que utilizamos hoy. En la d茅cada de 1950, Fortran introdujo un an谩logo de flujos de E / S est谩ndar que ayud贸 al programador a depurar su programa. Estos fueron los primeros registros de computadora que facilitaron la vida de los programadores de aquellos tiempos. Hoy vemos en ellos el primer componente del sistema de registro: la fuente o "productor" de los registros .

La inform谩tica no se detuvo: aparecieron las redes inform谩ticas, los primeros grupos ... Los sistemas complejos que constaban de varias computadoras comenzaron a funcionar. Ahora los administradores del sistema se vieron obligados a recopilar registros de varias m谩quinas y, en casos especiales, pod铆an agregar mensajes del kernel del sistema operativo en caso de que necesitaran investigar una falla del sistema. Para describir los sistemas centralizados de recopilaci贸n de registros, RFC 3164 sali贸 a principios de la d茅cada de 2000, que estandariz贸 remote_syslog. Entonces apareci贸 otro componente importante: el recolector (recolector) de registros y su almacenamiento.

Con el aumento en el volumen de registros y la adopci贸n generalizada de tecnolog铆as web, surgi贸 la pregunta de qu茅 registros deber铆an mostrarse convenientemente a los usuarios. Las herramientas de consola simples (awk / sed / grep) fueron reemplazadas por visores de registro m谩s avanzados: el tercer componente.

En relaci贸n con el aumento en el volumen de registros, otra cosa qued贸 clara: se necesitan registros, pero no todos. Y diferentes registros requieren diferentes niveles de seguridad: algunos se pueden perder cada dos d铆as, mientras que otros deben almacenarse durante 5 a帽os. Por lo tanto, se agreg贸 un componente de filtraci贸n y enrutamiento para flujos de datos al sistema de registro, llam茅moslo filtro .

Los repositorios tambi茅n dieron un gran salto: cambiaron de archivos normales a bases de datos relacionales y luego a repositorios orientados a documentos (por ejemplo, Elasticsearch). Entonces el almacenamiento se separ贸 del colector.

Al final, el concepto del registro en s铆 se ha expandido a un flujo abstracto de eventos que queremos mantener para la historia. M谩s precisamente, en el caso de que sea necesario realizar una investigaci贸n o elaborar un informe anal铆tico ...

Como resultado, durante un per铆odo de tiempo relativamente corto, la recopilaci贸n de registros se ha convertido en un subsistema importante, que leg铆timamente se puede llamar una de las subsecciones en Big Data.


Si alguna vez las impresiones normales podr铆an ser suficientes para un "sistema de registro", ahora la situaci贸n ha cambiado mucho.

Kubernetes y Registros


Cuando Kubernetes entr贸 en la infraestructura, el problema existente de recolectar registros no pas贸 por alto. En cierto sentido, se ha vuelto a煤n m谩s doloroso: la administraci贸n de la plataforma de infraestructura no solo se simplific贸, sino que tambi茅n fue complicada. Muchos servicios antiguos comenzaron a migrar a pistas de microservicios. En el contexto de los registros, esto dio como resultado un n煤mero creciente de fuentes de registro, su ciclo de vida especial y la necesidad de rastrear a trav茅s de los registros las interconexiones de todos los componentes del sistema ...

Mirando hacia el futuro, puedo decir que ahora, desafortunadamente, no hay una opci贸n de registro estandarizada para Kubernetes que ser铆a favorablemente diferente de todos los dem谩s. Los esquemas m谩s populares en la comunidad son los siguientes:

  • alguien est谩 implementando una pila EFK (Elasticsearch, Fluentd, Kibana);
  • alguien est谩 probando el Loki recientemente lanzado o usando el operador Logging ;
  • nosotros (驴y quiz谩s no solo nosotros?) estamos en gran medida satisfechos con nuestro propio desarrollo: loghouse ...

Como regla, utilizamos tales paquetes en cl煤steres K8 (para soluciones autohospedadas):


Sin embargo, no me detendr茅 en las instrucciones para su instalaci贸n y configuraci贸n. En cambio, me centrar茅 en sus defectos y conclusiones m谩s globales sobre la situaci贸n con los registros en general.

Practica con registros en K8s



"Registros diarios", 驴cu谩ntos de ustedes? ..


La recolecci贸n centralizada de registros con una infraestructura suficientemente grande requiere recursos considerables que se gastar谩n en recolectar, almacenar y procesar registros. Durante la operaci贸n de varios proyectos, enfrentamos varios requisitos y los problemas operativos resultantes.

Probemos ClickHouse


Echemos un vistazo a un repositorio centralizado en un proyecto con una aplicaci贸n que genera muchos registros: m谩s de 5000 l铆neas por segundo. Comencemos a trabajar con sus registros, agreg谩ndolos a ClickHouse.

Tan pronto como se requiera el tiempo real m谩ximo, el servidor ClickHouse de 4 n煤cleos ya estar谩 sobrecargado en el subsistema de disco:



Este tipo de descarga se debe al hecho de que estamos tratando de escribir en ClickHouse lo m谩s r谩pido posible. Y la base de datos responde a esto con una mayor carga de disco, lo que puede causar los siguientes errores:

DB::Exception: Too many parts (300). Merges are processing significantly slower than inserts

El hecho es que las tablas MergeTree en ClickHouse (contienen datos de registro) tienen sus propias dificultades durante las operaciones de escritura. Los datos insertados en ellos generan una partici贸n temporal, que luego se fusiona con la tabla principal. Como resultado, la grabaci贸n es muy exigente en el disco y se aplica la restricci贸n, cuya notificaci贸n recibimos anteriormente: no se pueden fusionar m谩s de 300 subparticiones en 1 segundo (de hecho, esto es 300 insert'ov por segundo).

Para evitar este comportamiento, debe escribir en ClickHouse con la mayor cantidad de fragmentos posible y no m谩s de 1 vez en 2 segundos. Sin embargo, escribir en grandes lotes sugiere que deber铆amos escribir con menos frecuencia en ClickHouse. Esto, a su vez, puede provocar desbordamientos del b煤fer y p茅rdida de registros. La soluci贸n es aumentar el b煤fer de Fluentd, pero luego aumentar谩 el consumo de memoria.

Nota : Otro lado problem谩tico de nuestra soluci贸n ClickHouse fue que la partici贸n en nuestro caso (loghouse) se implement贸 a trav茅s de tablas externas vinculadas por una tabla Merge . Esto lleva al hecho de que al muestrear intervalos de tiempo grandes, se requiere RAM excesiva, ya que la metatabla pasa por todas las particiones, incluso aquellas que obviamente no contienen los datos necesarios. Sin embargo, ahora este enfoque se puede declarar obsoleto de forma segura para las versiones actuales de ClickHouse (desde 18.16 ).

Como resultado, queda claro que ClickHouse no tiene suficientes recursos para cada proyecto para recopilar registros en tiempo real (m谩s precisamente, su distribuci贸n no ser谩 conveniente). Adem谩s, deber谩 usar una bater铆a , a la que volveremos. El caso descrito anteriormente es real. Y en ese momento no pod铆amos ofrecer una soluci贸n confiable y estable que se adaptara al cliente y permitiera recopilar registros con un retraso m铆nimo ...

驴Qu茅 hay de Elasticsearch?


Elasticsearch es conocido por manejar cargas pesadas. Prob茅moslo en el mismo proyecto. Ahora la carga es la siguiente:



Elasticsearch fue capaz de digerir el flujo de datos, sin embargo, escribir tales vol煤menes en 茅l utiliza en gran medida la CPU. Esto lo decide la organizaci贸n del cl煤ster. Desde el punto de vista t茅cnico, esto no es un problema, pero resulta que solo para el funcionamiento del sistema de recopilaci贸n de registros ya utilizamos alrededor de 8 n煤cleos y tenemos un componente adicional altamente cargado en el sistema ...

En pocas palabras: esta opci贸n puede justificarse, pero solo si el proyecto es grande y su administraci贸n est谩 lista para gastar recursos significativos en un sistema de registro centralizado.

Entonces surge una pregunta l贸gica:

驴Qu茅 registros se necesitan realmente?


Intentemos cambiar el enfoque en s铆: los registros deben ser informativos al mismo tiempo y no cubrir todos los eventos del sistema.

Digamos que tenemos una tienda en l铆nea pr贸spera. 驴Qu茅 registros son importantes? Recopilar tanta informaci贸n como sea posible, por ejemplo, de una pasarela de pago es una gran idea. Pero del servicio de corte de im谩genes en el cat谩logo de productos, no todos los registros son cr铆ticos para nosotros: solo los errores y la supervisi贸n avanzada son suficientes (por ejemplo, el porcentaje de 500 errores que genera este componente).

Entonces llegamos a la conclusi贸n de que el registro centralizado est谩 lejos de estar siempre justificado . Muy a menudo, el cliente quiere recopilar todos los registros en un solo lugar, aunque de hecho solo el 5% de los mensajes que son cr铆ticos para el negocio se requieren de todo el registro:

  • A veces es suficiente configurar, por ejemplo, solo el tama帽o del registro del contenedor y el recopilador de errores (por ejemplo, Centinela).
  • Para investigar incidentes, las alertas de error y un gran registro local a menudo pueden ser suficientes.
  • Ten铆amos proyectos que costaban completamente solo pruebas funcionales y sistemas de recolecci贸n de errores. El desarrollador no necesitaba los registros como tales: vieron todo en las trazas de errores.

Ilustraci贸n de la vida


Un buen ejemplo es otra historia. Recibimos una solicitud del equipo de seguridad de uno de los clientes que ya ten铆a una soluci贸n comercial que se desarroll贸 mucho antes de la implementaci贸n de Kubernetes.

Se necesit贸 "hacer amigos" un sistema centralizado de recopilaci贸n de registros con un sensor corporativo para detectar problemas: QRadar. Este sistema puede recibir registros utilizando el protocolo syslog, para tomarlo desde FTP. Sin embargo, integrarlo con el complemento remote_syslog para fluentd no funcion贸 de inmediato (como result贸, no somos los 煤nicos ) . Los problemas con la configuraci贸n de QRadar estaban del lado del equipo de seguridad del cliente.

Como resultado, parte de los registros cr铆ticos para los negocios se cargaron a FTP QRadar, y la otra parte se redirigi贸 a trav茅s de syslog remoto directamente desde los nodos. Para hacer esto, incluso escribimos un gr谩fico simple : tal vez ayude a alguien a resolver un problema similar ... Gracias al esquema resultante, el cliente mismo recibi贸 y analiz贸 registros cr铆ticos (usando sus herramientas favoritas), y pudimos reducir el costo del sistema de registro, manteniendo solo el 煤ltimo mes

Otro ejemplo es bastante indicativo de c贸mo no hacerlo. Uno de nuestros clientes para manejar cada evento proveniente del usuario, realiz贸 una salida de informaci贸n no estructurada multil铆nea al registro. Como puede suponer, tales registros eran extremadamente inconvenientes para leer y almacenar.

Criterios para los registros


Tales ejemplos llevan a la conclusi贸n de que, adem谩s de elegir un sistema para recopilar registros, 隆tambi茅n debe dise帽ar los registros ellos mismos ! 驴Cu谩les son los requisitos aqu铆?

  • Los registros deben estar en un formato legible por m谩quina (por ejemplo, JSON).
  • Los registros deben ser compactos y con la capacidad de cambiar el grado de registro para depurar posibles problemas. Al mismo tiempo, en entornos de producci贸n, debe ejecutar sistemas con un nivel de registro como Advertencia o Error .
  • Los registros deben estar normalizados, es decir, en el objeto de registro, todas las l铆neas deben tener el mismo tipo de campo.

Los registros no estructurados pueden provocar problemas al cargar registros en el repositorio y detener su procesamiento por completo. Para ilustrar, aqu铆 hay un ejemplo con un error 400, que muchos seguramente encontraron en los registros fluidos:

2019-10-29 13:10:43 +0000 [warn]: dump an error event: error_class=Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError error="400 - Rejected by Elasticsearch"

Un error significa que est谩 enviando un campo cuyo tipo es inestable al 铆ndice con una asignaci贸n lista. El ejemplo m谩s simple es un campo en el registro nginx con la variable $upstream_status . Puede tener un n煤mero o una cadena. Por ejemplo:

{ "ip": "1.2.3.4", "http_user": "-", "request_id": "17ee8a579e833b5ab9843a0aca10b941", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staffs/265.png", "protocol": "HTTP/1.1", "status": "200", "body_size": "906", "referrer": "https://example.com/staff", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.001", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "127.0.0.1:9000", "upstream_status": "200", "upstream_response_length": "906", "location": "staff"}
{ "ip": "1.2.3.4", "http_user": "-", "request_id": "47fe42807f2a7d8d5467511d7d553a1b", "time": "29/Oct/2019:16:18:57 +0300", "method": "GET", "uri": "/staff", "protocol": "HTTP/1.1", "status": "200", "body_size": "2984", "referrer": "-", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36", "request_time": "0.010", "cache_status": "-", "upstream_response_time": "0.001, 0.007", "upstream_addr": "10.100.0.10:9000, 10.100.0.11:9000", "upstream_status": "404, 200", "upstream_response_length": "0, 2984", "location": "staff"}


Los registros muestran que el servidor 10.100.0.10 respondi贸 con el error 404 y la solicitud fue a otro almac茅n de contenido. Como resultado, en los registros, el significado se ha convertido as铆:

"upstream_response_time": "0.001, 0.007"

Esta situaci贸n est谩 tan extendida que incluso gan贸 una menci贸n por separado en la documentaci贸n .

驴Y qu茅 hay de la fiabilidad?


Hay momentos en que todos los registros son vitales sin excepci贸n. Y con esto, los esquemas t铆picos de recopilaci贸n de registros para K8 propuestos / discutidos anteriormente tienen problemas.

Por ejemplo, fluentd no puede recolectar registros de contenedores de corta duraci贸n. En uno de nuestros proyectos, el contenedor con la migraci贸n de la base de datos dur贸 menos de 4 segundos y luego se elimin贸, de acuerdo con la anotaci贸n correspondiente:

"helm.sh/hook-delete-policy": hook-succeeded

Debido a esto, el registro de migraci贸n no entr贸 en el repositorio. La pol铆tica de before-hook-creation puede ayudar en este caso.

Otro ejemplo es la rotaci贸n de los registros de Docker. Supongamos que hay una aplicaci贸n que escribe activamente en los registros. En condiciones normales, logramos procesar todos los registros, pero tan pronto como surge un problema, por ejemplo, como se describi贸 anteriormente con el formato incorrecto, el procesamiento se detiene y Docker gira el archivo. En pocas palabras: los registros cr铆ticos para el negocio pueden perderse.

Por eso es importante separar el flujo de registros , integrando el env铆o de los m谩s valiosos directamente en la aplicaci贸n para garantizar su seguridad. Adem谩s, no ser谩 superfluo crear una especie de "acumulador" de registros que pueda sobrevivir a la breve falta de disponibilidad del almacenamiento mientras se mantienen los mensajes cr铆ticos.

Finalmente, no olvide que es importante monitorear cualquier subsistema de manera de calidad . De lo contrario, es f谩cil encontrar una situaci贸n en la que fluentd est茅 en el estado CrashLoopBackOff y no env铆e nada, lo que promete la p茅rdida de informaci贸n importante.

Conclusiones


En este art铆culo, no consideramos soluciones SaaS como Datadog. Muchos de los problemas descritos aqu铆 ya han sido resueltos de una forma u otra por empresas comerciales especializadas en recopilar registros, pero no todos pueden usar SaaS por varias razones (las principales son el costo y el cumplimiento de 152-) .

La colecci贸n centralizada de registros al principio parece una tarea simple, pero no lo es en absoluto. Es importante recordar que:

  • El registro detallado solo es un componente cr铆tico y, para otros sistemas, puede configurar la supervisi贸n y la recopilaci贸n de errores.
  • Los registros en la producci贸n deben minimizarse para no dar una carga adicional.
  • Los registros deben ser legibles por m谩quina, normalizados, tener un formato estricto.
  • Los registros realmente cr铆ticos deben enviarse en una secuencia separada, que debe separarse de las principales.
  • Vale la pena considerar una bater铆a de registro, que puede ahorrar de estallidos de alta carga y hacer que la carga en el almacenamiento sea m谩s uniforme.


Estas reglas simples, si se aplican en todas partes, permitir铆an que los circuitos descritos anteriormente funcionen, a pesar de que carecen de componentes importantes (bater铆a). Si no se adhiere a dichos principios, la tarea lo llevar谩 f谩cilmente a usted y a la infraestructura a otro componente del sistema altamente cargado (y al mismo tiempo ineficaz).

PS


Lea tambi茅n en nuestro blog:

Source: https://habr.com/ru/post/480946/


All Articles