8.0 KiB
Argos Core
Argos Core es el backend central de una plataforma de videovigilancia distribuida. Está diseñado para recibir eventos desde edges (sitios remotos con Frigate), capturar/ingestar vídeo bajo demanda, almacenarlo de forma fiable y ofrecer un panel web seguro para consulta y reproducción, todo encapsulado en Kubernetes y oculto tras una VPN WireGuard.
Visión general
[Edge / Frigate] --(VPN/WG + MQTT eventos)--> [Argos Core]
├─ Mosquitto (MQTT)
├─ Orchestrator (ingesta clips)
│ ├─ Pull clip nativo de Frigate
│ └─ Fallback: captura RTSP temporal
├─ MediaMTX (live/retransmisión)
├─ MinIO (S3, almacenamiento)
└─ Panel (FastAPI + Uvicorn)
Objetivo clave: los edges no envían flujo constante; sólo cuando hay evento. El core ingesta y guarda el clip, y ofrece visualización on‑demand.
Componentes
-
WireGuard (wg-easy): servidor VPN del clúster. Todo el tráfico de edges → core circula por WG.
-
Mosquitto (
eclipse-mosquitto:2): broker MQTT interno (ClusterIP). Topic de eventos (p. ej.frigate/events). -
Orchestrator (Python):
- Se suscribe a MQTT.
- Tras un evento, intenta descargar el clip nativo desde la API del Frigate del edge.
- Si no existe, hace captura RTSP temporal con
ffmpeg(duración configurada) contra la cámara/edge. - Sube el resultado a MinIO (
s3://argos/...) y registra metadatos en SQLite embebido.
-
MinIO (S3 compatible): almacenamiento de clips y miniaturas.
-
MediaMTX: redistribución de flujos (RTSP/WHIP/SRT) y posible live view on-demand.
-
Panel (FastAPI/Uvicorn):
- Lista eventos desde MinIO (sin exponer MinIO: proxy de objetos).
- Página de reproducción (
/view?key=…). - Endpoints simples (
/file,/api/events,/health).
-
CoreDNS: DNS interno con split-horizon (resolución diferente desde LAN/VPN/cluster cuando aplica).
-
Ingress NGINX (interno/externo) + cert‑manager: TLS para el panel; HTTP‑01 servido por el controlador externo.
-
MetalLB: IPs para servicios tipo LoadBalancer en la red
192.168.200.0/24(p. ej. MediaMTX).
Flujo de datos (evento → clip)
- Edge detecta (Frigate) y publica en MQTT
frigate/events. - Orchestrator recibe el evento, localiza la cámara/edge en su
settings.yaml. - Intenta pull del clip nativo vía API Frigate del edge (VPN).
- Si no hay clip, ejecuta
ffmpegpara capturar RTSP temporal (fallback). - Sube el fichero a MinIO con una clave tipo:
camX/YYYY/MM/DD/TS_eventId.mp4y optional thumb. - Panel lo muestra en la lista y permite reproducir vía
/file?key=…(stream proxy desde MinIO).
Para live, MediaMTX publica
/conpath=<cam>; puedes incrustar un reproductor WebRTC/RTSP en el panel.
Despliegue
Requisitos previos
-
Kubernetes operativo con:
- MetalLB (rango
192.168.200.0/24). - NGINX Ingress interno y externo (split-horizon DNS).
- cert‑manager +
ClusterIssuer(p. ej.letsencrypt-prod). - wg-easy funcionando (con NAT/iptables para alcanzar
200.x,0.x, etc.).
- MetalLB (rango
Estructura
argos/
├─ configmaps/ # mediamtx, mosquitto, orchestrator, panel
├─ deployments/ # mediamtx, minio, mosquitto, orchestrator, panel
├─ ingress/ # minio (opcional), panel (TLS)
├─ policies/ # network-policy, allow-same-namespace
├─ pvc/ # pvc-minio
├─ secrets/ # minio, orchestrator, panel
└─ services/ # mediamtx tcp/udp, minio, mosquitto, panel
Variables/Secrets esperados
- MinIO (
secrets/secret-minio.yaml):MINIO_ACCESS_KEY,MINIO_SECRET_KEY. - Orchestrator (
secrets/secret-orchestrator.yaml):MINIO_ENDPOINT,MINIO_ACCESS_KEY,MINIO_SECRET_KEY,MINIO_SECURE. - Panel (
secrets/secret-panel.yaml):MINIO_*yMINIO_BUCKET.
Servicios y puertos
- MinIO:
ClusterIP:9000 (API), :9001 (console, opcional). No expuesto fuera. - Mosquitto:
ClusterIP:1883. - MediaMTX:
LoadBalancer(MetalLB) en192.168.200.16(RTSP 8554 TCP, WHIP 8889 TCP/HTTP 8880, SRT 8189 UDP). - Panel:
ClusterIP:8000 → Ingress (TLS)https://argos.panel.c2et.net/(ajusta FQDN).
Kustomize
kubectl apply -k .
Nota: evitamos
commonLabelsglobales para no romper los selectors.
Configuración relevante
Orchestrator (configmaps/configmap-orchestrator.yaml)
mqtt.host:mosquitto.argos-core.svc.cluster.localmqtt.port:1883mqtt.topic:frigate/eventsminio.endpoint:minio.argos-core.svc.cluster.local:9000edges: lista de edges y cámaras (URLs de Frigate, RTSP principal, etc.).
Mosquitto (configmaps/configmap-mosquitto.yaml)
-
Config mínimo:
persistence true persistence_location /mosquitto/data/ listener 1883 0.0.0.0 allow_anonymous true # RECOMENDACIÓN: pasar a autenticación/TLS más adelante
MediaMTX
- Ejecutar sin
/bin/sh -c …y pasando solo la ruta del YAML comoargs. - Corrige warnings como
sourceOnDemandsegún el modo (publisherorecord).
MinIO (seguridad/permisos)
- Ejecuta como no-root con
runAsUser: 1000y un initContainer que hacechown/chmod/ACLdel PVC. - Estrategia de despliegue Recreate para evitar doble pod en updates cuando la
readinessProbetarda.
Ingress + cert-manager
-
El Certificate del panel debe forzar el solver HTTP‑01 por el ingress externo:
- Anotación:
acme.cert-manager.io/http01-ingress-class: nginx-external(o ajusta enClusterIssuer).
- Anotación:
Operación
Comandos útiles
# Estado general
kubectl -n argos-core get pods,svc,ingress,endpoints
# Endpoints vacíos (<none>)
kubectl -n argos-core get endpoints <svc> -o wide
# Revisa selector del Service y labels del Pod
# Logs
kubectl -n argos-core logs -f deploy/<nombre>
# Reinicios controlados
kubectl -n argos-core rollout restart deploy/<nombre>
# Diff del Service en vivo vs manifiesto
kubectl -n argos-core get svc argos-panel -o yaml --show-managed-fields=false
Problemas típicos y fixes
- Service con
ENDPOINTS <none>: selector ≠ labels, o pod not Ready (probe fallando). Ajusta selector a{app: …}y corrige readiness. - Dos pods tras update: rolling update atascado. Usa
strategy: Recreatemientras estabilizas. - MinIO
file access denied: permisos del PVC. AñadeinitContainerque hacechown -R 1000:1000 /data+ ACL. - Mosquitto
Connection refuseddesde Orchestrator: Service sin endpoints o broker no escucha en 1883. Ver logsmosquittoyss -lnt. - Panel
ASGI app not found:uvicorn app:app --app-dir /appy asegúrate de montarapp.pyconapp = FastAPI(). - MediaMTX
unknown flag -c: no usar/bin/sh -c …; pasarargs: ["/config/mediamtx.yml"].
Edge (resumen de mañana)
- WireGuard cliente (IP del edge en la VPN; DNS apuntando al core).
- Frigate en Docker +
mqtt.host=mosquitto.argos-core.svc.cluster.local. - API de Frigate accesible desde el core por la VPN (p. ej.
http://10.20.0.10:5000). - Opcional: MediaMTX local si se quiere “empujar” live al core durante la alarma.
Seguridad y siguientes pasos
- Endurecer Mosquitto (usuarios/TLS), MinIO (políticas/buckets versionados), y el Panel (auth detrás de Ingress o login propio).
- Métricas y dashboards (Prometheus/Grafana), y mover metadatos a PostgreSQL para búsquedas ricas.
- Live WebRTC integrado en el panel (MediaMTX WHIP/WHEP).
Licencia / Créditos
- MediaMTX (Bluenviron), MinIO, Eclipse Mosquitto, Frigate (en los edges).
- Argos Core: composición y orquestación Kubernetes + servicios auxiliares.