Ir al contenido

Cinco minutos con un router

La pregunta para la que existe esta herramienta: estoy a punto de cambiar algo en el router; ¿qué hace de verdad, a una resolución en la que pueda verlo? Esta página es el camino más corto desde un router que nunca ha visto mikroscope hasta un gráfico que la responde: seis pasos con las órdenes tal cual son, y una grabación real del RB5009 leída línea a línea.

El router necesita lo que la herramienta no le puede dar: RouterOS 7.24 o posterior con el paquete container y device-mode container=yes, que MikroTik protege tras una pulsación del botón de reset o un ciclo de alimentación. El suelo es 7.24 porque el paso del contenedor escribe privileged=, un atributo que MikroTik añadió en esa versión; --privileged=false cambia su valor, no si se escribe, así que una 7.x anterior rechaza la orden igualmente. Todo lo de esta página se midió en 7.24.2. doctor informa de la versión del router en su primera línea, pero no la condiciona. Lo que necesita el router tiene la lista completa, y mikroscope doctor comprueba el resto en solo lectura y nombra el arreglo de lo que falte.

La CLI no lee .env por sí misma, y solo algunas opciones toman su valor por defecto de una variable MIKROSCOPE_*: las de conexión y nombres (ROUTER, SSH_PORT, SSH_KEY, NAME, VETH, SUBNET, IFACE_LIST, ADDR_LIST, DISK, ARCH, TOKEN, LAN_ADDRESS), las de la API (API_ADDR, API_USER, API_PASSWORD), las URL de los destinos como INFLUX_URL, INTERFACES y HOST_TAG. El resto, entre ellas --ephemeral, --rate, --for, --topics y --prom, tiene valores por defecto fijos, diga lo que diga el texto de uso de la CLI. Exporta las variables que necesites, o copia .env.example a .env y carga el fichero con set -a; . ./.env; set +a; variables de entorno las lista todas.

  1. Conseguir mikroscope.

    Ventana de terminal
    tar xzf mikroscope_1.0.0_linux_x86_64.tar.gz # un .zip en Windows
    ./mikroscope version

    La versión publicada trae la CLI como un archivo por plataforma —linux, macOS, Windows y FreeBSD en amd64, arm64 y arm— con checksums.txt, las firmas de cosign y los SBOM al lado. El agente viaja aparte, como un tar de imagen por arquitectura (mikroscope-agent-arm64.tar, mikroscope-agent-arm.tar, mikroscope-agent-amd64.tar) y como imagen de registro, publicada tanto como jmrplens/mikroscope-agent:1.0.0 en Docker Hub como ghcr.io/jmrplens/mikroscope-agent:1.0.0 en GHCR; el paso 2 toma uno de los dos.

    Desde una copia del repositorio, en cambio:

    Ventana de terminal
    git clone https://github.com/jmrplens/mikroscope && cd mikroscope && make build

    Eso necesita Go 1.27 y deja la CLI en bin/mikroscope, que es como están escritas las órdenes de abajo. Es además el único camino que instala un agente construido desde tu propio árbol, porque install lo compila de forma cruzada desde la raíz del módulo.

  2. Instalar, una vez.

    Ventana de terminal
    export MIKROSCOPE_ROUTER=admin@192.168.88.1
    bin/mikroscope plan --ephemeral
    bin/mikroscope doctor --ephemeral && bin/mikroscope install --ephemeral

    plan imprime cada orden de RouterOS y no escribe nada. install pone la imagen del agente en el router, lista los objetos, vuelve a pasar la misma comprobación previa (--no-doctor se la salta), pregunta write the objects above to the router? [y/N] (--yes se salta la pregunta), escribe y después sondea el agente desde tu equipo.

    De dónde sale la imagen lo eliges tú, y es la única diferencia entre las tres instalaciones:

    • tu toolchain de Go, como arriba: la CLI ejecuta go build ./cmd/mikroscope-agent con CGO_ENABLED=0, GOOS=linux y GOARCH tomado de --arch, por lo que tiene que ejecutarse desde la raíz del módulo;
    • el tar publicado, --agent-tar mikroscope-agent-arm64.tar: sin toolchain de Go y sin copia del repositorio. La CLI lee el tar antes de subirlo —tiene que ser una imagen del agente de mikroscope y su arquitectura tiene que coincidir con --arch—, o el verbo se detiene y nombra el fichero que hay que descargar;
    • el registro, --remote-image jmrplens/mikroscope-agent:1.0.0: el router se descarga la imagen él mismo, no se sube nada y uninstall no tiene ningún fichero del que responder. RouterOS toma el host del registro del ajuste global /container/config registry-url, que mikroscope nunca escribe porque lo comparten todos los contenedores del equipo, y que viene puesto en https://registry-1.docker.io: por eso la referencia de Docker Hub de arriba funciona tal cual en un router sin tocar. La referencia de GHCR, ghcr.io/jmrplens/mikroscope-agent:1.0.0, nombra un host propio: doctor compara el ajuste con él e imprime /container/config/set registry-url=https://ghcr.io cuando no coincide, o remite a --agent-tar. La descarga necesita que el router llegue al registro y que haya RAM libre para las capas.

    --arch vale por defecto arm64, la del RB5009; no se detecta a partir del router, pero doctor la compara con la arquitectura que informa el router y nombra el valor de --arch con el que volver a ejecutar si no coinciden.

    En un router al que solo llegas por WinBox o WebFig hay una cuarta vía, sin CLI de tu lado: mikroscope plan --rsc --remote-image jmrplens/mikroscope-agent:1.0.0 --out install.rsc escribe las mismas órdenes, en el mismo orden y con las mismas etiquetas, como un script de RouterOS para pegar en el terminal o hacerle /import. Instalar el agente tiene esa vía y sus dos advertencias al completo.

    --ephemeral pone el tar de la imagen y la raíz del contenedor en el disco RAM tmpfs del router y crea el contenedor con start-on-boot=no, así que el agente no vuelve tras un reinicio. install borra el tar en cuanto el contenedor lo ha extraído. No se escribió nada en la flash: write-sect-since-reboot se quedó en 58 279 durante la instalación, la ejecución y la retirada (verificado en RB5009UG+S+, RouterOS 7.24.2, ). Quítalo para una instalación persistente. El disco tmpfs tiene que existir; el RB5009 tiene uno, y doctor --ephemeral lo comprueba e imprime el /disk/add que lo crea si no existe. Pasa --ephemeral también a doctor: sin él, doctor comprueba en su lugar la flash libre.

    install termina sondeando al agente desde tu equipo, e imprime una línea:

    direct transport ok: agent 1.0.0 (9ddd760) built 2026-09-16T08:38:27Z, 10 Hz, seq 29, 0 slipped, 7ms round trip

    El primer campo es la identidad de compilación del agente: la versión, que una publicación graba desde el fichero VERSION, y después el commit y la fecha de compilación. Un go build sin grabar dentro de una copia del repositorio informa de esa misma versión con el commit y la hora que registra la toolchain de Go, así que el campo nunca dice dev ni un hash a secas. Un agente que sale del tar o del registro informa de lo que grabó la compilación publicada; uno que install construye desde tu árbol lleva la marca de la propia CLI, así que ambos informan de la misma cadena. El resto de la línea es el sondeo: la cadencia del muestreador, la secuencia a la que había llegado el agente, los ticks que se le escaparon y el tiempo de ida y vuelta. En el RB5009 el sondeo respondió a los tres segundos con 7 ms de ida y vuelta, y con 5 ms tras un upgrade ese mismo día (2026-09-12).

    El sondeo espera hasta 30 s. Si tu equipo no llega a la /30 del agente, primero pregunta al router si el contenedor está en marcha y solo entonces sugiere alternativas; consulta llegar al agente.

  3. Grabar mientras haces el cambio.

    Ventana de terminal
    bin/mikroscope record --for 70s --out burst

    Escribe una línea y pulsa Intro cada vez que hagas algo que merezca recordarse; se convierte en un marcador con la marca de tiempo del agente. Funciona cuando la entrada estándar es un terminal, y la CLI lo dice: type a line and press Enter to add a marker; Ctrl-C stops. Desde otra shell,

    Ventana de terminal
    bin/mikroscope mark --out burst "queue tree applied"

    hace lo mismo: mark añade al final de <prefijo>.markers.csv mientras record mantiene el fichero abierto, así que una nota desde un segundo terminal y otra escrita en el del grabador acaban en el mismo fichero. --for 0, el valor por defecto, graba hasta Ctrl-C. Al final record imprime el número de muestras, el rango de secuencia, los huecos, los marcadores y el transporte que usó, y nombra cualquier tramo de muestras que ya no estaba en el anillo del agente.

  4. Añadir el propio log del router.

    Este paso habla con la API de RouterOS, no con el agente, así que necesita una cuenta en el router con la que hablar. Basta una de solo lectura, y el usuario de la API trae las dos órdenes que crean el grupo y el usuario; la CLI no necesita admin para esto.

    Ventana de terminal
    export MIKROSCOPE_API_ADDR=192.168.88.1:8728 MIKROSCOPE_API_USER=mikroscope MIKROSCOPE_API_PASSWORD=
    bin/mikroscope mark --out burst --log-markers --router-tz Europe/Madrid

    (O pon esas tres en .envcp .env.example .env— y carga el fichero, como arriba.)

    Cada línea de log de la ventana de la grabación (desde su inicio hasta su última muestra, en el reloj del agente) cuyo tema sea system, interface o container se convierte en un marcador; añade firewall o script con --topics cuando sus líneas sean la historia. El router informa ahí de errores y de ejecuciones del planificador, y el log a menudo explica un transitorio que no provocaste tú.

    MIKROSCOPE_API_ADDR tiene la opción --api y MIKROSCOPE_API_USER la opción --api-user; la contraseña no tiene opción. --router-tz es la zona IANA que muestra el reloj del router, porque las horas del log de RouterOS no llevan zona; por defecto es la de tu máquina. record --log-markers hace lo mismo al final de una grabación, y mark --log-markers lo hace después, como aquí (el propio log del router como marcadores).

  5. Mirar.

    Ventana de terminal
    bin/mikroscope plot --in burst

    Esto escribe burst.svg: tres paneles sobre un mismo eje de tiempo (proporción de ocupación por núcleo, descartes de softnet y time squeezes por segundo, memoria disponible) con cada marcador como una vertical discontinua dibujada panel a panel, de modo que ningún título de panel queda tachado. Los marcadores del log que caen en el mismo segundo se pliegan en una sola línea cuya etiqueta dice y el primer mensaje; un hueco en las muestras se dibuja como una línea roja; una etiqueta de más de 40 caracteres se corta a 37 y unos puntos suspensivos, y una etiqueta a la que no le queda sitio se acorta más hasta que cabe en vez de montarse sobre la de al lado, y se queda solo con su vertical cuando ya no queda nada legible; un marcador fuera del intervalo de la grabación no se dibuja. La misma grabación produce siempre los mismos bytes. --title fija el encabezado y --svg otra ruta de salida.

  6. Dejarlo en marcha (opcional).

    Ventana de terminal
    bin/mikroscope forward --prom :9124 --influx "$MIKROSCOPE_INFLUX_URL" --interfaces bridge,ether1

    Esto ejecuta el colector: la capa del kernel desde el agente y, con las variables MIKROSCOPE_API_* del paso 4 en el entorno, la capa de la API de RouterOS a su lado. Con el --api-mode full por defecto esa capa lee /system/resource, /system/resource/cpu, /system/health, monitor-traffic cada segundo para las interfaces nombradas en --interfaces, los contadores acumulados de cada puerto cada 10 s y qué es cada interfaz —su comentario, su tipo, sus listas de interfaces, su bridge y su MTU— al arrancar y cada 5 min; la capa de la API de RouterOS dice cuáles de ellos puede leer el propio agente. Sin esas variables la capa de la API queda desactivada con un aviso y la capa del kernel sigue funcionando. Ambas van a una exposición de Prometheus en :9124 y a InfluxDB 3. A partir de ahí, importar y comprobar monta los dos paneles de Grafana, el campo del origen de datos que necesita una importación de InfluxDB 3 y los dos trabajos de scrape de Prometheus.

RB5009UG+S+, 70 s a 10 Hz: 700 muestras en 69,9 s sobre cuatro núcleos, con tres marcadores discontinuos: «baseline, router idle» a los 12 s, «dashboards check started» a los 30 s y «check finished» a los 50 s. La ocupación por núcleo se mantiene baja, con excursiones de una sola muestra al 100 %; el panel de softnet muestra time squeezes y un cero plano en los descartes; la memoria disponible se mantiene entre 662 y 671 MiB.

Abre el gráfico a tamaño completo (SVG, 1200 × 754) para leer sus etiquetas en un móvil. Los rótulos de los paneles van en inglés porque plot los escribe así: el título lo pones tú con --title, el resto es el vocabulario del kernel.

Medido en RB5009UG+S+ · 4 × 1,4 GHz Cortex-A72 · RouterOS 7.24.2 · · un record de 70 s a 10 Hz, 700 muestras en 69,9 s, el router por lo demás en reposo, tres notas escritas en el terminal de record

Es una grabación real de un router en reposo, la forma contra la que se lee todo lo demás. Las tres líneas discontinuas son las notas escritas en el terminal de record durante ella; las etiquetas las llevan enteras porque caben, y una más larga se acorta en vez de montarse sobre la siguiente.

  • t = 12 s, baseline, router idle. No pasa nada, y los paneles lo dicen: cada núcleo promedia menos del 10 % en toda la grabación, y en el tramo tranquilo que sigue a esta nota los cuatro juntos promedian un 3,9 %.
  • t = 30 a 50 s, entre dashboards check started y check finished. Un navegador cargando los dos paneles de Grafana contra el colector de este mismo router. Los cuatro núcleos juntos promedian un 5,0 % en ese tramo, y el trabajo llega en dos ráfagas cortas justo después de la nota: el núcleo 0 al 50 % o por encima durante 0,6 s desde los 32,3 s, y otros 0,3 s a los 33,2 s.
  • El trabajo está en excursiones cortas. 76 de las 700 muestras tienen un núcleo al 50 % o por encima, en 46 tramos separados; 38 de ellos duran una sola muestra, y el más largo dura 1,4 s, al principio de la grabación y antes de la primera nota. El planificador del kernel pone cada excursión en el núcleo que esté libre. Una muestra aislada —un núcleo al 100 % durante 100 ms— mueve una media de un segundo sobre cuatro núcleos en un 2,5 %.
  • softnet: dropped plano en cero, time_squeeze entre 0 y unos 20 por segundo. No se perdió nada en 70 s. Los squeezes son el fondo de este equipo, no un suceso; lo que el colector llama microburst es un racimo de ellos —tres muestras marcadas en un mismo núcleo dentro de 60 s—, y nunca uno solo.
  • Memoria disponible, de 662 a 671 MiB. Unos 9 MiB de vaivén normal en toda la grabación, sin ningún escalón en ninguno de los dos extremos de la comprobación de los paneles.

El propio cpu-load de RouterOS, a 1 s, da este minuto por un puñado plano de puntos porcentuales. La grabación muestra de qué está hecho ese puñado: qué núcleo se llevó cada excursión, cuánto duró y dónde caen las notas frente a ella.

Lo que escribió el paso 2, y cómo quitarlo

Sección titulada «Lo que escribió el paso 2, y cómo quitarlo»

Lo que install escribe en tu router

  • una veth
  • una dirección
  • una pertenencia a lista de interfaces
  • una entrada de address-list
  • una envlist
  • el tar de la imagen, salvo que --remote-image haga que el router se la baje
  • el contenedor

Cada objeto lleva el comentario mikroscope:<name> (managed by mikroscope)

mikroscope plan imprime cada orden antes de escribir nada.

uninstall elimina por etiqueta exacta más identidad, nunca por patrón, y falla nombrando el paso si queda algo.

Ventana de terminal
bin/mikroscope uninstall --ephemeral

Pasa los mismos --ephemeral, --disk y --name con los que instalaste: uninstall y status reconstruyen el plan a partir de sus propias opciones, y sin --ephemeral buscan el tar de la imagen en la flash en lugar de en tmpfs. uninstall deshace cada paso del plan en orden inverso, por etiqueta exacta, luego cuenta lo que queda en el router a nombre de mikroscope y falla, nombrando los objetos, si queda algo. bin/mikroscope status --ephemeral imprime esos mismos recuentos de propiedad en cualquier momento, más la salud del agente cuando se puede llegar a él.