Ir al contenido

Reglas de detección

Una detección es un evento discreto que el colector pone en la línea temporal: un «mira aquí», nunca una serie continua y nunca un veredicto. Para cada una de las once reglas: cuándo salta, qué tiene que aportar el despliegue para que pueda saltar y qué no te puede decir. Los valores derivados en los que se apoyan algunas reglas están en Valores derivados.

Toda detección tiene los mismos campos:

Campo Significado
rule la regla que saltó
key la CPU, el núcleo, la zona o el puerto al que se refiere; vacío para una regla de todo el equipo
seq, wall_ns la muestra que la provocó
value la cantidad que comparó la regla
threshold contra qué la comparó: el umbral propio de la regla, escrito en cada evento
message el evento en palabras

Una vez por regla y clave cada 10 s. Tras saltar una regla para una clave, la misma regla y clave quedan suprimidas durante 10 s del reloj de pared de las muestras, así que una condición que persiste salta cada 10 s en vez de en cada muestra. La etapa cuenta lo que suprimió, pero ningún destino exporta esa cuenta.

Las reglas se ejecutan en el proceso del colector y su historia vive allí. Un colector que se reinicia empieza desde cero cada ventana móvil, cada intervalo y cada valor anterior.

Destino Forma
InfluxDB, Telegraf, stdout lp mikroscope_detection{rule,key} con value, threshold, seq, message
SQL (--sql, --postgres) una fila de mikroscope_detection
file, stdout json una línea {"detection":…}
Prometheus mikroscope_collector_detections_total{rule}, cada regla a 0 desde el primer scrape
Loki una línea en el stream source="detection", level="warn"
OTLP un sum de deltas mikroscope.detection{rule} de 1
Graphite detection.<rule> = 1 en el segundo del evento
Elasticsearch un documento con kind: detection

Los paneles dibujan cada detección como una anotación, y una de las reglas de alerta salta con cualquier detección salvo microburst e ipc-collapse: esas dos describen cómo lleva el tráfico un router sano, y se dibujan y se guardan pero no avisan.

Regla Clave Salta cuando Necesita
counter-reset — la muestra informa de un contador que retrocedió sin un desbordamiento de 32 bits cualquier despliegue
agent-restart — el número de secuencia retrocedió cualquier despliegue
agent-oom — el cgroup propio del contenedor registró un OOM kill cgroup2 en el contenedor
microburst cpu<N> tres muestras burst en una CPU en 60 s softnet
reboot — cambió el identificador de arranque del kernel, o el reloj desde el arranque de un registro del log del kernel es menor que el del registro anterior cualquier despliegue; la vía del log del kernel requiere privileged=yes
link-flap puerto dos o más registros de enlace up/down en un puerto en 60 s requiere privileged=yes
conntrack-cliff — nf_conntrack cayó por debajo de la mitad de su valor guardado anterior requiere privileged=yes
conntrack-high — ocupación por encima del 80 % de nf_conntrack_max y en aumento durante los últimos 60 s requiere privileged=yes
thermal-high zona una zona a menos del 15 % de su propio disparo crítico declarado una zona térmica que declare un disparo
thermal-rising zona tres subidas consecutivas de un minuto de más de 1 °C cada una una zona térmica
ipc-collapse core<N> el IPC de un segundo de un núcleo por debajo de la mitad de su mediana móvil mientras su tasa de ciclos está por encima de su mediana la PMU

Salta cuando el resets de la muestra del kernel es mayor que 0: el agente encontró un contador más bajo que su lectura anterior sin un desbordamiento de 32 bits que lo explique, y usó el valor del contador tras el reinicio como delta de ese tick, una cota inferior. value es el número de esos contadores, threshold 0.

Necesita solo una muestra. La misma condición marca la muestra como suspect, y los valores derivados por paquete se omiten para ella.

No puede afirmar qué contador se reinició, ni por qué. Cada delta de esa muestra es una cota inferior.

Salta cuando el número de secuencia de una muestra es menor que el de la muestra anterior. value es el nuevo número de secuencia, threshold el anterior.

Dice lo que el colector tenía de los 30 s anteriores al reinicio, al final del mensaje: la parte ocupada de la CPU en todos los núcleos y la del núcleo más cargado, MemAvailable (la última y la más baja) frente a MemTotal, nf_conntrack frente a su límite, las caídas y los time_squeeze de softnet, cualquier muerte por OOM o espera de asignación, y cuánto tiempo no llegó ninguna muestra después de la última. Un reinicio se lleva el anillo del agente y el log del propio RouterOS, pero no lo que el colector ya había leído. El tiempo sin muestras se omite cuando el reloj del router tras el reinicio es anterior al de antes, como en un router cuyo reloj aún no ha puesto en hora NTP. Cuando el agente informa del identificador de arranque del kernel, el mensaje dice también si cambió: el mismo identificador significa que el router no se reinició, y que se reinició solo el contenedor del agente (una actualización, una parada y un arranque, su política de reinicio). Solo lo dice con dos identificadores que comparar: el primer agente que da uno, después de uno que no lo daba, no dice nada de ello.

Necesita que el colector haya visto al menos una muestra antes del reinicio. La secuencia del agente vuelve a empezar desde 1 en cada arranque, así que así es como se ve un reinicio desde fuera. En su siguiente lectura de salud, como mucho un minuto, el colector retrocede su cursor de lectura a la muestra más antigua del anillo nuevo y registra agent restarted: its newest sample is N and the cursor was M; resuming from K; la secuencia baja del agente nuevo frente a la anterior es lo que casa esta regla (TestResyncAfterAgentRestart cubre el lado del colector).

No puede afirmar por qué se reinició el agente. El resumen da lecturas, no una causa. Un colector reiniciado a la vez no tiene número de secuencia anterior y no ve nada.

Salta cuando el cgroup propio del contenedor registra un OOM kill en la muestra — el kernel mató un proceso dentro del contenedor de mikroscope. value es el número de kills.

Necesita cgroup2 legible en el contenedor; sin él, el agente no informa de eventos de cgroup y esta regla no puede saltar.

No puede afirmar nada sobre los números que la rodean: todos los números de esa ventana son sospechosos. Cómo dimensionar la memoria del contenedor según el anillo del agente está en el coste del observador.

Salta cuando la muestra de una CPU lleva la marca burst — un descarte, o squeezes por encima del percentil 90 móvil de esa CPU y al menos 3, mientras su cuenta de paquetes estaba en su mediana móvil o por debajo — y esa CPU tiene ya al menos tres muestras marcadas en los últimos 60 s. value es el número de muestras marcadas en la ventana, threshold 3; el mensaje lleva los squeezes, descartes y paquetes de la última muestra y la mediana móvil.

Necesita /proc/net/softnet_stat, que lee todo despliegue, y diez muestras de historia por CPU antes de su primera marca. Las referencias abarcan diez segundos de reloj de pared a cualquier cadencia del muestreador.

Falsos positivos. El squeeze puede ser el fondo de un router, no un suceso. En el router medido, la mayoría de las muestras por CPU no llevan ningún squeeze, y time_squeeze es 1 en el 11,2 %, 2 en el 1,2 % y 3 en el 0,21 %. Una ventana móvil de una distribución que es casi toda ceros tiene un percentil 90 de 1, así que «por encima de p90» lo cumple cualquier 2 — por eso quien manda es el suelo de 3 y no el percentil. Reejecutada sobre muestras almacenadas, con suelo 2 salta 77,7 /h y con suelo 3 salta 0,5 /h. Un descarte marca por sí solo, con cualquier cuenta de squeezes.

No puede afirmar el tamaño de la ráfaga, ni el flujo ni la interfaz que la causó. Dice que el kernel se quedó sin presupuesto más de lo habitual mientras llevaba menos paquetes de lo habitual — prueba de algo más corto que el intervalo de muestreo.

Salta cuando el identificador de arranque del kernel difiere del que el colector leyó antes. El agente lo lee una vez al arrancar y lo publica en /healthz; el kernel genera uno nuevo en cada arranque y lo mantiene hasta el siguiente, y un contenedor comparte el kernel del router, así que un identificador nuevo significa que el router se reinició, no solo el contenedor del agente. El colector registra router rebooted: the kernel's boot id went from … to … en la lectura de salud que lo ve, y la regla salta con la primera muestra del agente que volvió. value y threshold son 0.

También salta cuando la marca de tiempo de un registro del log del kernel, en microsegundos desde el arranque, es menor que la del registro anterior, la única vía para un agente que no informa del identificador; entonces value y threshold son las marcas nueva y anterior en segundos. Un reinicio del que ya informó el identificador de arranque no la hace saltar una segunda vez. En ambos casos el mensaje lleva el mismo resumen de los 30 s anteriores que el agent-restart que llegó con él.

Dice, cuando el colector tiene capa de API, lo que RouterOS escribió sobre el arranque, entre comillas tras el motivo: quién o qué lo reinició (RouterOS logged at boot: "router rebooted by ssh-cmd:admin@192.168.88.10/reboot"), o que cayó sin apagarse ("router was rebooted without proper shutdown"). La detección espera esa lectura, dos minutos como mucho, porque la conexión de la API vuelve después que el router (Log de arranque). Sin capa de API salta con la primera muestra del agente, sin esa parte.

Necesita un colector que siga en marcha durante el reinicio mientras el agente vuelve, y ninguna credencial de la API de RouterOS. El agente que vuelve es un proceso nuevo; el colector lee su identificador de arranque en la misma lectura de salud que retrocede el cursor al anillo nuevo, en menos de un minuto (ver agent-restart). La vía del log del kernel necesita privileged=yes, que exige el log del kernel. En el laboratorio, un /system/reboot la hizo saltar por el identificador de arranque, y una parada y un arranque del contenedor del agente no (Probado en).

No puede afirmar que se vea cada reinicio, ni por qué se reinició el router: la línea de RouterOS nombra quién lo reinició o dice que cayó sin apagarse, no por qué se fue la corriente o se colgó el router. Un colector arrancado después del reinicio no tiene un identificador anterior con el que comparar, y dos reinicios entre dos lecturas de salud, separadas un minuto, son un solo cambio de identificador. La vía del log del kernel solo ve lo que el agente lee desde el final del log después de arrancar: cuando el primer registro tras un reinicio tiene un tiempo desde el arranque posterior al del último antes de él, por esa vía no salta nada.

Salta cuando un registro del log del kernel que nombra una interfaz se clasifica como link-up o link-down —el mismo clasificador que pone un kind en cada registro de puerto— y ese puerto tiene ya dos o más de esos registros en los últimos 60 s. key es el nombre actual del puerto en RouterOS cuando el inventario de interfaces de la capa de la API lo da, el nombre por defecto de la placa cuando la tabla de puertos del agente traduce el nombre del kernel, y el nombre del kernel en otro caso. value es el número de registros en la ventana, threshold 2.

Necesita privileged=yes. Un nombre de RouterOS necesita que la placa esté en la tabla de puertos del agente, y el nombre actual necesita además la capa de la API; consulta Nombres de puertos.

No puede afirmar una avería. Un cable desenchufado y vuelto a enchufar en menos de un minuto son un registro de down y uno de up, y salta. La regla ha saltado con flaps no provocados sin decir si los causó el cable, el equipo del otro lado u otra cosa; no se ha capturado ningún flap provocado con ella en marcha (Probado en).

Salta cuando la cuenta de objetos activos de la caché slab nf_conntrack está por debajo de la mitad de su valor guardado anterior. value es la nueva cuenta, threshold la anterior.

Necesita privileged=yes, para /proc/slabinfo. El slab se lee a unos 6 Hz y se guarda al cambiar, así que «anterior» es la muestra guardada anterior, no el tick anterior.

Tampoco puede afirmar una avería: el mensaje dice «a flush or a reset», y un vaciado deliberado de la tabla de conexiones la hace saltar.

Salta cuando los objetos activos de nf_conntrack están por encima de 0,8 del nf_conntrack_max del kernel, y la cuenta es mayor que el valor guardado más antiguo de los últimos 60 s. value es la ocupación como fracción, threshold 0,8.

Necesita privileged=yes, el techo publicado por el kernel y al menos dos muestras guardadas en los últimos 60 s.

No puede afirmar cuándo se llenará la tabla: a propósito, no se adjunta ningún tiempo hasta el llenado. Como escala, la tabla de un router medido tenía 6 287 entradas, un 0,65 % del techo de su kernel.

Salta cuando la lectura de una zona está en 0,85 o más del punto de disparo crítico declarado más bajo de esa misma zona. value es la lectura en °C, threshold 0,85 × el disparo.

Necesita una zona térmica que declare un disparo crítico. Una zona que no declara ninguno nunca salta; no se compara nada con un número compilado.

No puede afirmar que haya fallado la refrigeración, ni nada sobre una zona que la placa no informa.

Salta cuando las últimas cuatro medias de un minuto completas de una zona superan cada una a la anterior en más de 1 °C — tres subidas consecutivas. value es la subida desde la primera de las cuatro medias hasta la última, threshold 3. Un intervalo de un minuto se cierra con la primera muestra al menos 60 s después de abrirse, y la regla se comprueba cada vez que se cierra uno, así que lo antes que puede saltar es tras unos cuatro minutos de lecturas.

Necesita una zona térmica. Las medias son sobre las lecturas que llevaban las muestras; la temperatura se lee a la cadencia de sondeo declarada por la zona (mikroscope_thermal_polling_seconds).

Resolución. Un sensor que cuantiza a unos 0,42 °C, como el medido, resuelve 1 °C por minuto en 2,4 escalones.

No puede afirmar una causa, ni una subida más lenta que 1 °C por minuto.

Salta cuando, en un núcleo, se cierra un intervalo de un segundo con instrucciones por ciclo por debajo de la mitad de la mediana de los intervalos móviles de ese núcleo mientras su tasa de ciclos está por encima de la mediana de sus tasas móviles. key es core<N>, value el IPC del intervalo, threshold la mitad de la mediana.

Necesita los cycles e instructions de la PMU por CPU (con privileged=yes), y veinte intervalos de un segundo completos de historia para ese núcleo antes de poder saltar; la historia móvil guarda hasta sesenta.

No puede afirmar inactividad, ni nada agregado: la conjunción con la tasa de ciclos es lo que separa un régimen de bloqueo por memoria de un núcleo que se queda quieto, y la regla es por núcleo, nunca entre núcleos.

doctor a secas lee el anillo del agente en marcha y hace cuatro comprobaciones propias: layer2-loop, stp-churn, link-flap y softnet-drops, descritas en Comprobaciones de salud. No son detecciones: se ejecutan una vez, cuando doctor las pide, sobre lo que guarde el anillo hasta sus 10 000 muestras más recientes, 60 s por defecto, y no escriben nada en ningún destino.

Un nombre se comparte y la regla no. El link-flap de doctor cuenta solo las caídas de enlace, dos o más en un puerto en cualquier punto del anillo; la detección cuenta subidas y caídas juntas, dos o más en 60 s, así que un cable desenchufado y vuelto a enchufar una vez hace saltar la detección y no la comprobación. Un bucle de capa 2 no es ninguna de las once reglas: el layer2-loop de doctor lo señala en el anillo, y sobre el histórico lo vigila en el almacén la regla de alerta mikroscope-l2-loop.

Cuatro de las once reglas han saltado en un router real, y solo de microburst se ha medido el comportamiento contra las muestras. Las otras siete solo las ejercitan las pruebas unitarias de la etapa de derivación contra muestras construidas, y no se ha provocado ningún fallo con las reglas en marcha (Probado en).