Instalación manual: terminal
Instala el agente orden a orden, en el terminal del router: para un router sin ningún ordenador que
ejecute la CLI, o para ver y adaptar cada objeto. Las órdenes son las que ejecuta install, con
marcadores en mayúsculas. Para las mismas órdenes con tus valores ya puestos, usa el
Generador de scripts.
Antes de empezar
Sección titulada «Antes de empezar»Elige un valor para cada marcador. Los valores por defecto son los que usa install:
| Marcador | Por defecto | Significado |
|---|---|---|
NAME |
mikroscope |
el nombre de la instalación |
TAG |
mikroscope:NAME (managed by mikroscope) |
el comentario de cada objeto; conserva esta forma para que la CLI reconozca la instalación |
VETH |
veth-mikroscope |
el nombre de la veth |
NET/30 |
172.30.10.0/30 |
una /30 IPv4 en su dirección de red, sin usar en el router |
GW_IP |
172.30.10.1 |
el extremo del router en la /30: la dirección de red + 1 |
AGENT_IP |
172.30.10.2 |
el extremo del agente en la /30: la dirección de red + 2 |
PORT |
9123 |
el puerto HTTP del agente |
IFACE_LIST |
LAN |
la lista de interfaces a la que se une la veth; none en el manifiesto si te saltas la pertenencia |
ADDR_LIST |
LANs |
la lista de direcciones a la que se une la /30; none en el manifiesto si te saltas la pertenencia |
ENVLIST |
NAME-env |
la envlist del contenedor |
DISK |
vacío (flash interna) | un slot de disco, como tmpfs o usb1; precede a las tres rutas de abajo |
MANIFEST_DIR |
mikroscope |
DISK/mikroscope en un disco |
MANIFEST_FILE |
mikroscope/ |
el manifiesto de la instalación |
ROOT_DIR |
mikroscope/NAME |
la raíz del contenedor |
IMAGE_REF |
registry-1. |
la imagen que descarga el router (descarga del registro) |
IMAGE_FILE |
NAME.tar |
el tar de imagen subido (ruta del tar); DISK/NAME.tar en un disco |
RATE_HZ |
10 |
la tasa de muestreo, 1–100 Hz |
BUFFER_S |
60 |
el anillo, 10–3600 s |
MEM_LIMIT_MB |
16 |
el límite de memoria de Go del agente, abajo |
CAPTURE_MB |
4 |
el presupuesto de capturas por disparo, 0–256 MiB; 0 las desactiva |
MEMORY_MAX |
64M |
el límite de memoria del contenedor |
START_ON_BOOT |
yes |
no para una raíz en un disco en RAM, que un reinicio vacía |
PRIVILEGED |
yes |
no pierde el log del kernel, las cuentas del slab, los contadores de la flash y la PMU |
RESTART_MAX_COUNT |
5 |
reinicios tras un fallo |
RESTART_INTERVAL |
10s |
la espera entre ellos |
EXTRACT_TIMEOUT_S |
120 |
cuánto esperar a que RouterOS extraiga el tar (ruta del tar) |
FLOOR_HZ |
ninguno | opcional: una sola cadencia para todas las fuentes de nivel |
TRIGGERS |
ninguno | opcional: las condiciones de disparo (Captura por disparo) |
TOKEN |
ninguno | opcional: el token que pide el agente; un secreto |
CONTAINER_NAME |
vacío (lo pone RouterOS) | opcional: el name= del contenedor |
LAN_IP |
ninguno | solo con --expose: la dirección LAN del router |
Desliza en horizontal para ver todas las columnas
Un valor por defecto vacío se queda vacío: en la flash interna la línea del manifiesto es disk=, y
sin nombre de contenedor container-name=, sin nada tras el =.
MEM_LIMIT_MB es RATE_HZ × BUFFER_S × lo que ocupa una muestra en el anillo × 2,5, redondeado
hacia arriba, como mínimo 16 y como máximo ¾ de MEMORY_MAX mientras eso deje sitio al anillo. Con
un MEMORY_MAX de 64M da 16 a 10 Hz y 60 s, 25 a 50 Hz y 60 s, y 48 a 100 Hz y 60 s. El generador
lo calcula por ti.
Comprueba el router. Lee la versión y la arquitectura, el paquete container y device mode:
/system/resource/print/system/package/print where name="container"/system/device-mode/printversion tiene que ser 7.24 o posterior y architecture-name uno de arm64, arm o x86_64; el
paquete tiene que aparecer y no estar deshabilitado; device mode tiene que mostrar
container: yes. Requisitos tiene los arreglos: el paso de
device mode necesita pulsar el botón reset o mode, o cortar la alimentación, en menos de 5 minutos;
en CHR, apaga y enciende la máquina virtual.
Comprueba las colisiones. Cada una de estas tiene que no imprimir nada, o una cuenta de 0:
/interface/veth/print where name="VETH"/container/envs/print count-only where list="ENVLIST"/ip/address/print where address in NET/30/ip/route/print where dst-address in NET/30/file/print where name="MANIFEST_FILE"Y estas tienen que encontrar lo que nombras: la lista de interfaces, y el disco si usas uno.
/interface/list/print where name="IFACE_LIST"/disk/printPara una raíz en un disco en RAM, crea uno antes: /disk/add type=tmpfs tmpfs-max-size=64M slot=tmpfs,
y usa DISK tmpfs y START_ON_BOOT no. Si el firewall descarta las respuestas del agente está
en Listas del firewall.
Escribir el manifiesto
Sección titulada «Escribir el manifiesto»El manifiesto enumera cada objeto que crean los pasos siguientes, para que
mikroscope uninstall y la retirada de abajo los encuentren todos. Quita la línea object= de
cualquier paso que te saltes; para una pertenencia a lista que te saltes, escribe además none tras
su iface-list= o addr-list=.
:local m "mikroscope-manifest=1\nname=NAME\ntag=TAG\ndisk=DISK\nveth=VETH\nsubnet=NET/30\nport=PORT\niface-list=IFACE_LIST\naddr-list=ADDR_LIST\nexpose=\ncontainer-name=CONTAINER_NAME\nremote-image=IMAGE_REF\ntoken=no\ndir=MANIFEST_DIR\nfile=MANIFEST_FILE\nobject=/interface/veth name=VETH\nobject=/ip/address interface=VETH\nobject=/interface/list/member interface=VETH list=IFACE_LIST\nobject=/ip/firewall/address-list list=ADDR_LIST address=NET/30\nobject=/container/envs list=ENVLIST\nobject=/container interface=VETH\ndir=ROOT_DIR\n"; :if ([:len [/file/find name="MANIFEST_FILE"]] > 0) do={ /file/set [find name="MANIFEST_FILE"] contents=$m } else={ /file/add name="MANIFEST_FILE" contents=$m }:local m "mikroscope-manifest=1\nname=NAME\ntag=TAG\ndisk=DISK\nveth=VETH\nsubnet=NET/30\nport=PORT\niface-list=IFACE_LIST\naddr-list=ADDR_LIST\nexpose=\ncontainer-name=CONTAINER_NAME\nremote-image=\ntoken=no\ndir=MANIFEST_DIR\nfile=MANIFEST_FILE\nobject=/interface/veth name=VETH\nobject=/ip/address interface=VETH\nobject=/interface/list/member interface=VETH list=IFACE_LIST\nobject=/ip/firewall/address-list list=ADDR_LIST address=NET/30\nfile=IMAGE_FILE\nobject=/container/envs list=ENVLIST\nobject=/container interface=VETH\ndir=ROOT_DIR\n"; :if ([:len [/file/find name="MANIFEST_FILE"]] > 0) do={ /file/set [find name="MANIFEST_FILE"] contents=$m } else={ /file/add name="MANIFEST_FILE" contents=$m }El manifiesto del tar deja vacío remote-image= y nombra el tar en una línea file=, para que
uninstall retire también un tar que una extracción dejó atrás.
Léelo con :put [/file/get [find name="MANIFEST_.
Script de RouterOS explica cada línea.
Crear la veth
Sección titulada «Crear la veth»/interface/veth/add name="VETH" address=AGENT_IP/30 gateway=GW_IP comment="TAG"Añadir la dirección
Sección titulada «Añadir la dirección»/ip/address/add address=GW_IP/30 interface="VETH" comment="TAG"Añadir las pertenencias a listas
Sección titulada «Añadir las pertenencias a listas»Opcional. Dejan pasar las respuestas del agente por reglas raw del firewall que descartan según una
lista de interfaces o de direcciones; sáltate cualquiera de las dos cuando ninguna regla tuya la
necesite, y quita su línea object= del manifiesto y escribe none tras su iface-list= o
addr-list=. Una pertenencia no se limita a mikroscope: cualquier otra
regla que compare la lista afecta también a la veth o a la /30
(Listas del firewall).
/interface/list/member/add list="IFACE_LIST" interface="VETH" comment="TAG"/ip/firewall/address-list/add list="ADDR_LIST" address=NET/30 comment="TAG"Crear la envlist
Sección titulada «Crear la envlist»/container/envs/add list="ENVLIST" key=MIKROSCOPE_TAG value="TAG"/container/envs/add list="ENVLIST" key=RATE_HZ value="RATE_HZ"/container/envs/add list="ENVLIST" key=BUFFER_S value="BUFFER_S"/container/envs/add list="ENVLIST" key=PORT value="PORT"/container/envs/add list="ENVLIST" key=ADDR value="AGENT_IP"/container/envs/add list="ENVLIST" key=MEM_LIMIT_MB value="MEM_LIMIT_MB"/container/envs/add list="ENVLIST" key=CAPTURE_MB value="CAPTURE_MB"Añade las entradas opcionales que uses:
/container/envs/add list="ENVLIST" key=FLOOR_HZ value="FLOOR_HZ"/container/envs/add list="ENVLIST" key=TRIGGERS value="TRIGGERS"/container/envs/add list="ENVLIST" key=TOKEN value="TOKEN"El valor de TOKEN se guarda en claro: trátalo como legible por cualquier usuario de RouterOS con
read, y deja las demás credenciales fuera de la envlist.
Crear el contenedor
Sección titulada «Crear el contenedor»/container/add remote-image="IMAGE_REF" interface="VETH" root-dir=ROOT_DIR envlist="ENVLIST" logging=yes start-on-boot=START_ON_BOOT restart-policy=on-failure restart-max-count=RESTART_MAX_COUNT restart-interval=RESTART_INTERVAL memory-max=MEMORY_MAX privileged=PRIVILEGED ignore-remote-image-change=yes comment="TAG"RouterOS descarga la imagen de su propia arquitectura. El router tiene que llegar al registro y tener sitio en RAM para las capas.
-
Sube el tar de la arquitectura del router como
IMAGE_FILE, en Files (WebFig o Winbox) o conscp(Instalación sin conexión). -
Crea el contenedor a partir de él:
/container/add file=IMAGE_FILE interface="VETH" root-dir=ROOT_DIR envlist="ENVLIST" logging=yes start-on-boot=START_ON_BOOT restart-policy=on-failure restart-max-count=RESTART_MAX_COUNT restart-interval=RESTART_INTERVAL memory-max=MEMORY_MAX privileged=PRIVILEGED ignore-remote-image-change=yes comment="TAG" -
Espera a que RouterOS lo extraiga y borra el tar. La línea se detiene, y conserva el tar, si la extracción no ha terminado en
EXTRACT_TIMEOUT_S::local w 0; :while ([:len [/container/find comment="TAG" stopped]] = 0 && $w < EXTRACT_TIMEOUT_S) do={ :delay 1s; :set w ($w + 1) }; :if ([:len [/container/find comment="TAG" stopped]] = 0) do={ :error "mikroscope: the image was not extracted within EXTRACT_TIMEOUT_S s; IMAGE_FILE stays" }; /file/remove [find name="IMAGE_FILE"]
Exponer en la LAN
Sección titulada «Exponer en la LAN»Opcional: para llegar al agente en la dirección LAN del router, añade las dos reglas que escribe
--expose (Exponer en la LAN). Necesitan un TOKEN en la
envlist.
Escribe antes otra vez el manifiesto, para que las registre: expose=LAN_IP, token=yes y una línea
object= por regla.
:local m "mikroscope-manifest=1\nname=NAME\ntag=TAG\ndisk=DISK\nveth=VETH\nsubnet=NET/30\nport=PORT\niface-list=IFACE_LIST\naddr-list=ADDR_LIST\nexpose=LAN_IP\ncontainer-name=CONTAINER_NAME\nremote-image=IMAGE_REF\ntoken=yes\ndir=MANIFEST_DIR\nfile=MANIFEST_FILE\nobject=/interface/veth name=VETH\nobject=/ip/address interface=VETH\nobject=/interface/list/member interface=VETH list=IFACE_LIST\nobject=/ip/firewall/address-list list=ADDR_LIST address=NET/30\nobject=/ip/firewall/nat chain=dstnat dst-address=LAN_IP dst-port=PORT protocol=tcp\nobject=/ip/firewall/filter chain=forward dst-address=AGENT_IP dst-port=PORT protocol=tcp\nobject=/container/envs list=ENVLIST\nobject=/container interface=VETH\ndir=ROOT_DIR\n"; :if ([:len [/file/find name="MANIFEST_FILE"]] > 0) do={ /file/set [find name="MANIFEST_FILE"] contents=$m } else={ /file/add name="MANIFEST_FILE" contents=$m }:local m "mikroscope-manifest=1\nname=NAME\ntag=TAG\ndisk=DISK\nveth=VETH\nsubnet=NET/30\nport=PORT\niface-list=IFACE_LIST\naddr-list=ADDR_LIST\nexpose=LAN_IP\ncontainer-name=CONTAINER_NAME\nremote-image=\ntoken=yes\ndir=MANIFEST_DIR\nfile=MANIFEST_FILE\nobject=/interface/veth name=VETH\nobject=/ip/address interface=VETH\nobject=/interface/list/member interface=VETH list=IFACE_LIST\nobject=/ip/firewall/address-list list=ADDR_LIST address=NET/30\nobject=/ip/firewall/nat chain=dstnat dst-address=LAN_IP dst-port=PORT protocol=tcp\nobject=/ip/firewall/filter chain=forward dst-address=AGENT_IP dst-port=PORT protocol=tcp\nfile=IMAGE_FILE\nobject=/container/envs list=ENVLIST\nobject=/container interface=VETH\ndir=ROOT_DIR\n"; :if ([:len [/file/find name="MANIFEST_FILE"]] > 0) do={ /file/set [find name="MANIFEST_FILE"] contents=$m } else={ /file/add name="MANIFEST_FILE" contents=$m }Después añade las dos reglas:
/ip/firewall/nat/add chain=dstnat dst-address=LAN_IP protocol=tcp dst-port=PORT action=dst-nat to-addresses=AGENT_IP to-ports=PORT comment="TAG":local d [/ip/firewall/filter/find chain=forward action=drop]; :if ([:len $d] > 0) do={ /ip/firewall/filter/add chain=forward dst-address=AGENT_IP protocol=tcp dst-port=PORT connection-nat-state=dstnat action=accept comment="TAG" place-before=($d->0) } else={ /ip/firewall/filter/add chain=forward dst-address=AGENT_IP protocol=tcp dst-port=PORT connection-nat-state=dstnat action=accept comment="TAG" }Arrancar y verificar
Sección titulada «Arrancar y verificar»/container/start [find comment="TAG"]En el router:
/container/print where comment="TAG"/log/print where topics~"container":put ([/tool/fetch url="http://AGENT_IP:PORT/healthz" output=user as-value]->"data")Tras una descarga del registro, RouterOS descarga y extrae la imagen antes de arrancar el
contenedor. Hasta que el log muestra *** download/extract done, el contenedor muestra la marca E
(DOWNLOADING/EXTRACTING) y la última orden imprime failure: Invalid argument: vuelve a ejecutar
las tres.
Después el contenedor muestra la marca R (en marcha). El log termina con *** started /mikroscope-agent y
la línea del propio agente, mikroscope-agent <version> …: kernel …, 10 Hz, ring 60 s, listening on AGENT_IP:PORT, …. La última orden imprime {"ok":true,…}. Desde un ordenador de la LAN del router,
curl http:// responde lo mismo, y mikroscope status reconoce la
instalación.
Retirar
Sección titulada «Retirar»Ejecuta las retiradas, de la más nueva a la más antigua. La primera detiene y retira el contenedor,
su raíz y su envlist; la última retira el manifiesto y el directorio MANIFEST_DIR cuando no queda
nada más en él, y se detiene, conservando el manifiesto, si queda algún objeto con la etiqueta. Si
expusiste el agente, retira antes sus dos reglas:
/ip/firewall/filter/remove [find chain=forward dst-address="AGENT_IP" dst-port="PORT" protocol="tcp" comment="TAG"]/ip/firewall/nat/remove [find chain=dstnat dst-address="LAN_IP" dst-port="PORT" protocol="tcp" comment="TAG"]Después el resto:
:local had [:len [/container/find comment="TAG"]]; :do { /container/stop [find comment="TAG"] } on-error={}; :local s 0; :while (([:len [/container/find comment="TAG" running]] + [:len [/container/find comment="TAG" stopping]]) > 0 && $s < 30) do={ :delay 1s; :set s ($s + 1) }; /container/remove [find comment="TAG"]; :local i 0; :while ([:len [/container/find comment="TAG"]] > 0 && $i < 20) do={ :delay 1s; :set i ($i + 1) }; :if ($had > 0) do={ :local r 0; :while ([:len [/file/find name="ROOT_DIR"]] > 0 && ([:len [/container/find root-dir="/ROOT_DIR"]] + [:len [/container/find root-dir="ROOT_DIR"]]) = 0 && $r < 10) do={ :delay 1s; :set r ($r + 1) }; :if ([:len [/file/find name="ROOT_DIR"]] > 0 && ([:len [/container/find root-dir="/ROOT_DIR"]] + [:len [/container/find root-dir="ROOT_DIR"]]) = 0) do={ :do { /file/remove [find name="ROOT_DIR"] } on-error={} } }; :if ([:len [/container/envs/find list="ENVLIST" key="MIKROSCOPE_TAG" value="TAG"]] > 0) do={ /container/envs/remove [find list="ENVLIST" key!="MIKROSCOPE_TAG"]; /container/envs/remove [/container/envs/find list="ENVLIST" key="MIKROSCOPE_TAG" value="TAG"] }/ip/firewall/address-list/remove [find list="ADDR_LIST" address="NET/30" comment="TAG"]/interface/list/member/remove [find interface="VETH" list="IFACE_LIST" comment="TAG"]/ip/address/remove [find interface="VETH" comment="TAG"]/interface/veth/remove [find name="VETH" comment="TAG"]:if (([:len [/ip/firewall/address-list/find comment="TAG"]] + [:len [/interface/list/member/find comment="TAG"]] + [:len [/ip/firewall/nat/find comment="TAG"]] + [:len [/ip/firewall/filter/find comment="TAG"]] + [:len [/ip/firewall/raw/find comment="TAG"]] + [:len [/ip/firewall/mangle/find comment="TAG"]] + [:len [/ip/route/find comment="TAG"]] + [:len [/container/mounts/find comment="TAG"]] + [:len [/ip/address/find comment="TAG"]] + [:len [/interface/veth/find comment="TAG"]] + [:len [/interface/list/find comment="TAG"]] + [:len [/disk/find comment="TAG"]] + [:len [/container/find comment="TAG"]] + [:len [/container/envs/find list="ENVLIST" key="MIKROSCOPE_TAG" value="TAG"]]) > 0) do={ :error "mikroscope: objects tagged TAG remain, so MANIFEST_FILE stays" }; :if ([:len [/file/find name="MANIFEST_FILE"]] > 0) do={ :if ([:typeof [:find [/file/get [find name="MANIFEST_FILE"] contents] "\ntag=TAG\n"]] = "num") do={ :if ([:len [/file/find name="ROOT_DIR"]] > 0 && ([:len [/container/find root-dir="/ROOT_DIR"]] + [:len [/container/find root-dir="ROOT_DIR"]]) = 0) do={ :do { /file/remove [find name="ROOT_DIR"] } on-error={} }; /file/remove [find name="MANIFEST_FILE"] } }; :if ([:len [/file/find name~"^MANIFEST_DIR/"]] = 0) do={ /file/remove [find name="MANIFEST_DIR" type="directory"] }Si todavía queda un tar porque la extracción agotó el tiempo, retíralo también:
/file/remove [find name="IMAGE_. Después comprueba que no queda nada; esto imprime 0:
:put ([:len [/interface/veth/find comment="TAG"]] + [:len [/ip/address/find comment="TAG"]] + [:len [/interface/list/member/find comment="TAG"]] + [:len [/ip/firewall/address-list/find comment="TAG"]] + [:len [/ip/firewall/nat/find comment="TAG"]] + [:len [/ip/firewall/filter/find comment="TAG"]] + [:len [/container/find comment="TAG"]] + [:len [/container/envs/find list="ENVLIST"]] + [:len [/file/find name="MANIFEST_FILE"]])mikroscope uninstall --router … --yes hace lo mismo desde un ordenador con la CLI, y lo verifica:
Actualizar y desinstalar.