- ClickHouse 24.8 — almacén canónico de análisis de eventos y evaluaciones (StatefulSet con volumen persistente de 100 Gi). Obligatorio: el servidor no arranca sin él.
- PostgreSQL 16 — almacén relacional/de metadatos para organizaciones, claves de API, usuarios, paneles, consultas guardadas y autenticación (StatefulSet con volumen persistente de 50 Gi)
- Redis 7.2 — caché compartida opcional y backend de límite de tasa; el servidor y el panel degradan con elegancia si no está disponible
- AgentEye Server — API en Rust para ingestión de eventos, análisis y gestión de claves (2 réplicas)
- AgentEye Dashboard — interfaz web en Next.js (2 réplicas)
- AI assistant (servicio de agente) — asistente opcional de solo lectura en el panel en el puerto 9100; inactivo hasta que se configure un endpoint de LLM
- Traefik (público) — controlador de ingreso para el tráfico del colector, protegido con mTLS
- Traefik (panel) — controlador de ingreso para el panel, solo accesible desde VPN/lista de IPs permitidas
- cert-manager — certificados TLS y CA de mTLS
- Backup CronJob — volcado diario combinado de PostgreSQL + ClickHouse a las 03:00 UTC
- Cert Renewal Monitor — alerta cuando los certificados de cliente están próximos a caducar
Requisitos previos
Ejecuta cada comando de verificación antes de comenzar. Todas las comprobaciones deben pasar.| Requisito | Mínimo | Comando de verificación | Resultado esperado |
|---|---|---|---|
| Clúster de Kubernetes | 1.27+ | kubectl version | Server Version >= v1.27 |
| Kustomize (incluido con kubectl) | Kustomize v1.14+ (incluido en kubectl 1.27+) | kubectl kustomize --help | Muestra texto de uso |
| Helm | v3 | helm version | Version:"v3.x.x" |
| cluster-admin RBAC | — | kubectl auth can-i create namespaces | yes |
| StorageClass por defecto | — | kubectl get storageclass | Al menos una fila marcada como (default) |
| Soporte de LoadBalancer | — | Depende del proveedor (EKS, GKE, AKS lo soportan por defecto) | — |
| GitHub PAT | — | echo $AGENTEYE_TOKEN | No vacío (ver enterprise-docs/github-token.md) |
| openssl | — | openssl version | OpenSSL 1.x o 3.x |
| Bucket de almacenamiento en la nube | — | Para copias de seguridad de PostgreSQL + ClickHouse (S3, GCS o Azure Blob) | — |
Ejecutar todas las comprobaciones a la vez
Estructura del despliegue
El endpoint de ingestión se sirve en un nombre de host que controlas (por ejemplo,ingest.tu-empresa.example). cert-manager solicita un certificado TLS de confianza pública a Let’s Encrypt mediante HTTP-01, de modo que los colectores verifican el certificado del servidor contra el almacén de confianza del sistema, sin necesidad de anclar una CA por cliente.
El endpoint del panel funciona de la misma manera: se sirve en un segundo nombre de host que controlas (por ejemplo, agenteye.tu-empresa.example) apuntando al LoadBalancer de Traefik del panel, y cert-manager emite su certificado Let’s Encrypt a través de ese LoadBalancer. Los navegadores obtienen un certificado de confianza sin advertencias.
La emisión y renovación de certificados se validan mediante HTTP-01, por lo que ambos LoadBalancers deben ser accesibles desde internet en el puerto 80. Si necesitas restringir el LoadBalancer del panel por IP, coordina primero con soporte un solver DNS-01, de lo contrario las renovaciones fallarán silenciosamente y el certificado caducará.
Obtener los manifiestos
AGENTEYE_TOKEN.
Estructura de directorios:
Monitorización de salud (opcional): la sonda de disponibilidad del servidor ya refleja el estado de Postgres + ClickHouse, y third-party/robusta/ añade alertas opcionales de fallo de pod en Kubernetes nativas a Slack. Consulta enterprise-docs/health-monitoring.md.
Fase 1 — Infraestructura de terceros (~30 min)
1.1 Instalar cert-manager
cert-manager gestiona los certificados TLS para HTTPS y la CA privada utilizada para los certificados de cliente mTLS.Running — cert-manager, cert-manager-cainjector, cert-manager-webhook.
certificates.cert-manager.io, clusterissuers.cert-manager.io, issuers.cert-manager.io.
Si falla: Los pods en CrashLoopBackOff normalmente indican que los CRDs no se instalaron. Vuelve a ejecutar con --set crds.install=true. Si los pods del webhook fallan en la verificación de disponibilidad, espera 30 segundos y vuelve a comprobar — pueden tardar un momento en arrancar.
1.2 Instalar Traefik — Controlador de ingestión público
Esta instancia de Traefik gestiona el tráfico del colector en un LoadBalancer externo. Termina TLS y aplica mTLS (verificación de certificado de cliente) en el endpoint de ingestión.Running.
kubectl describe pod -n traefik-public <nombre-pod> para errores de descarga de imagen o restricciones de recursos.
1.3 Instalar Traefik — Controlador del panel
Esta instancia de Traefik sirve el panel en un LoadBalancer dedicado, restringido por lista de IPs permitidas.Esta instancia incluye dos mecanismos de lista de permitidos. Esta guía utilizaAntes de instalar, editavalues-dashboard.yaml, que restringe el acceso con el campo portableservice.loadBalancerSourceRanges. También se proporciona unvalues-internal.yamlparalelo para entornos AWS que prefieren la anotaciónservice.beta.kubernetes.io/aws-load-balancer-source-ranges. Elige uno y úsalo de forma consistente; los pasos siguientes asumenvalues-dashboard.yaml.
third-party/traefik/values-dashboard.yaml para establecer las IPs de origen permitidas. El campo loadBalancerSourceRanges controla qué IPs pueden acceder al panel. Por defecto está configurado como 0.0.0.0/0 (todas las IPs); restrínguelo a tu VPN, oficina o IPs de salida conocidas.
Permitir una sola IP
Permitir múltiples IPs
Añade una entrada por IP o bloque CIDR. Un sufijo/32 coincide con una sola dirección IPv4; un bloque CIDR (por ejemplo, /24) coincide con un rango. Puedes mezclar IPs individuales y rangos libremente:
- Mantén una entrada por línea y añade un comentario
#breve que identifique el propietario o propósito de cada IP; esto es lo que los futuros operadores usarán para decidir si una entrada sigue siendo necesaria. - Usa siempre notación CIDR. Una IP sin sufijo como
203.0.113.10es rechazada por el proveedor de nube; usa203.0.113.10/32. - Para rangos IPv6, usa el equivalente
/128(dirección única) o un CIDR mayor, por ejemplo2001:db8::1/128. No todos los proveedores de nube admiten rangos de origen IPv6; consulta la documentación de LoadBalancer de tu proveedor. - La lista es un OR: el tráfico se permite si el origen coincide con cualquier entrada.
helm install a continuación. Si el controlador ya está instalado, ejecuta helm upgrade con las mismas opciones, o parchea el Service en tiempo de ejecución (sección siguiente).
Actualizar la lista de permitidos en tiempo de ejecución
Puedes cambiar las IPs permitidas sin actualizar Helm parcheando el Service directamente. El parche reemplaza la lista completa; incluye siempre todas las IPs que quieras conservar, no solo la nueva. Para reemplazar la lista con un nuevo conjunto de IPs:
Los parches en tiempo de ejecución no se persisten en values-dashboard.yaml. Para mantener el cambio en futuras actualizaciones de Helm, actualiza también el archivo de valores y confírmalo en el repositorio.
Luego instala:
Running.
1.4 Esperar a los LoadBalancers
Ambas instancias de Traefik necesitan IPs externas antes de continuar.EXTERNAL-IP (no <pending>).
Si aún están pendientes, espera a que se asigne:
Ctrl+C cuando aparezca la IP. La asignación de IP suele tardar entre 2 y 5 minutos.
Si falla: <pending> después de 10 minutos normalmente significa que el proveedor de nube no puede aprovisionar un LoadBalancer. Comprueba: etiquetas de subred (EKS requiere kubernetes.io/role/elb), configuración de VPC, cuotas de servicio y que la anotación correcta del LB interno esté configurada para la instancia interna.
Fase 2 — Crear secretos (~10 min)
Todos los secretos se crean manualmente antes de desplegar la aplicación. Esto garantiza que los valores sensibles nunca aparezcan en los archivos de manifiesto.2.1 Crear el namespace
Active.
2.2 Secreto de extracción de imagen
Este secreto autentica conghcr.io para extraer las imágenes de contenedor de AgentEye. Consulta enterprise-docs/github-token.md para saber cómo generar tu PAT.
kubernetes.io/dockerconfigjson.
Verificación profunda — comprueba que el token puede extraer imágenes realmente:
Usa la etiqueta de imagen server fijada en el kustomization.yaml de tu overlay (actualmente v0.0.1-beta.48 tanto en el overlay acme incluido como en el despliegue base). Sustituye la etiqueta en el comando siguiente por la que estés desplegando para que esta comprobación no quede desactualizada entre versiones:
ok impreso en los logs.
Si falla: ErrImagePull o 401 Unauthorized significa que el PAT no es válido o no tiene el permiso read:packages. Revisa enterprise-docs/github-token.md.
2.3 Credenciales de PostgreSQL
Importante: Usamos-hex(no-base64) para generar la contraseña. La salida en base64 puede contener+,/y=, que rompen la cadena de conexiónDATABASE_URL. Consulta enterprise-docs/troubleshooting.md para más detalles.
Guarda POSTGRES_PASSWORD en tu gestor de secretos inmediatamente. La necesitarás si alguna vez restauras desde una copia de seguridad o te conectas directamente a la base de datos.
Verificación:
48 (24 bytes hexadecimales = 48 caracteres).
2.4 Clave de API de administrador
Guarda ADMIN_KEY en tu gestor de secretos inmediatamente.
Verificación:
2.5 Configuración de autenticación (inicio de sesión en el panel)
El panel utiliza email + OTP para el inicio de sesión de usuarios. Sin este secreto, el servidor sigue arrancando y la ruta de API deADMIN_KEY sigue funcionando, pero ningún usuario puede iniciar sesión a través de la interfaz de usuario.
Todas las claves están referenciadas como optional: true en el manifiesto base, por lo que los secretos parciales (o ningún secreto) son válidos; el servidor recurre a los valores predeterminados documentados. Agrupar todo en un único secreto agenteye-auth permite rotar toda la superficie de autenticación en un solo lugar.
| Clave | Propósito |
|---|---|
ADMIN_EMAIL | Usuario administrador inicial. Se inserta o actualiza en cada inicio con todos los permisos y está protegido contra eliminación/edición de permisos desde el panel. Sin él, no se crea ningún administrador y el primer inicio de sesión es imposible. |
ALLOWED_EMAILS | Lista de permitidos separada por comas. Admite direcciones exactas (user@example.com) y comodines de dominio (*@example.com). Sin él, ningún usuario puede iniciar sesión ni ser creado. |
SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, SMTP_FROM | Relay SMTP para enviar códigos OTP. Si SMTP_HOST no está configurado, los códigos OTP se registran en stdout del servidor en lugar de enviarse por email (útil para pruebas de humo en el primer arranque). Proporciona todas las claves SMTP juntas para el envío real de emails. |
SMTP_TLS | Uno de starttls (por defecto), tls o none. |
DEFAULT_ORG_NAME, DEFAULT_ORG_SLUG | Opcional. Asigna un nombre de visualización amigable y un slug de URL a la organización default integrada, de modo que viva en, por ejemplo, /acme en lugar de /default. Se aplica solo en el primer arranque; una vez que renombres la organización con agenteye-orgctl org rename (ver §7.6) se ignoran. El slug debe tener entre 1 y 40 caracteres alfanuméricos en minúsculas con guiones internos simples. Déjalos sin configurar para mantener el default genérico. |
Guarda las credenciales SMTP en tu gestor de secretos.Verificación:
2.6 Clave de aislamiento de organizaciones multi-tenant (opcional)
Omite esto para un despliegue de un solo tenant; el servidor funciona con un valor de desarrollo integrado y sirve correctamente a la organizacióndefault. Antes de crear una segunda organización, configura un ORG_CH_SECRET fuerte y estable: la contraseña de ClickHouse de cada organización se deriva como HMAC(ORG_CH_SECRET, org_id), de modo que el valor de desarrollo por defecto, que es público, generaría credenciales por organización derivables públicamente. El comando agenteye-orgctl org create (ver §7.6 Aprovisionar organizaciones) se niega a ejecutarse mientras el servidor siga usando el valor de desarrollo integrado.
secretKeyRef opcional, por lo que un clúster de un solo tenant que nunca lo crea sigue arrancando normalmente. Mantén el valor estable e idéntico en todas las réplicas; rotarlo invalida la contraseña de ClickHouse derivada de cada organización hasta que la reconciliación al arrancar vuelva a aprovisionar los usuarios (un reinicio gradual con el valor consistente en todas partes lo soluciona). Consulta deploy/base/server/secret.example.yaml.
Guarda ORG_CH_SECRET en tu gestor de secretos y no lo rotes sin motivo.
2.7 Verificar todos los secretos
agenteye-admin-key, agenteye-auth, agenteye-image-pull, agenteye-postgres) deben estar presentes antes de continuar. agenteye-org-ch-secret solo es necesario para despliegues multi-tenant (ver §2.6).
Fase 3 — Desplegar la aplicación (~5 min)
3.1 Configurar los nombres de host públicos
cert-manager necesita los nombres de host de ingestión y del panel antes de poder solicitar sus certificados Let’s Encrypt. Copia la plantilla y configura ambos:domain.env está en el gitignore; permanece local a cada despliegue. La compilación de kustomize falla con un error claro si falta cualquiera de las claves.
El DNS debe resolver primero. No es necesario apuntar el DNS a los LBs todavía (no existen hasta que se complete la Fase 1.2), pero la emisión de ACME en el paso 3.2 reintentará hasta que cada nombre de host resuelva a su LoadBalancer. Puedes configurar el DNS ahora (usando los nombres de host de LB capturados en la Fase 1.4) o continuar y añadir los registros en la Fase 4.
3.2 Aplicar los manifiestos
Aplica la base directamente para una instalación nueva, o un overlay si has creado uno para este entorno (los overlays solo fijan etiquetas de imagen, variables de entorno y límites de recursos; heredan los certificados y el enrutamiento de la base):3.3 Esperar a los pods
agent (asistente de IA) y redis arrancan junto a ellos; el asistente permanece inactivo hasta que le proporciones su endpoint de LLM (ver enterprise-docs/assistant.md), y Redis es una caché de mejor esfuerzo, por lo que ninguno de los dos necesita estar listo para que la plataforma sirva tráfico.
Verificación:
agent y redis también aparecen y alcanzan el estado Running):
| Estado del pod | Causa probable | Comando de diagnóstico |
|---|---|---|
ImagePullBackOff | Secreto de extracción de imagen o PAT incorrecto | kubectl describe pod <nombre> -n agenteye |
CrashLoopBackOff | Variables de entorno incorrectas (por ejemplo, DATABASE_URL) | kubectl logs <nombre> -n agenteye |
Pending | CPU/memoria insuficiente o sin nodos | kubectl describe pod <nombre> -n agenteye (revisa Events) |
3.4 Verificar el almacenamiento
Bound:
| PVC | Capacidad | Respaldo |
|---|---|---|
postgres-data-postgres-0 | 50Gi | Almacén relacional/de metadatos de PostgreSQL |
clickhouse-data-clickhouse-0 | 100Gi | Almacén de análisis de eventos + evaluaciones de ClickHouse |
redis-data-redis-0 (1 Gi) para la caché opcional.
Si falla: Pending significa que ninguna StorageClass puede aprovisionar el volumen. Comprueba kubectl get storageclass y asegúrate de que existe una por defecto. Para producción, sobrescribe el volumen de ClickHouse en tu overlay con una StorageClass de SSD rápida (por ejemplo, gp3 en AWS, pd-ssd en GCP); el rendimiento de compactación se degrada en discos lentos.
3.5 Verificar los certificados
Ready: True:
| Nombre | Emisor | Propósito |
|---|---|---|
mtls-ca | selfsigned | CA privada para emitir certificados de cliente mTLS (validez de 10 años) |
ingest-tls | letsencrypt-prod | Certificado TLS público para el endpoint de ingestión (90 días, renovación automática) |
dashboard-tls | letsencrypt-prod | Certificado TLS público para el panel (90 días, renovación automática) |
ingest-tls o dashboard-tls no están listos:
Ejecuta kubectl describe certificate <nombre> -n agenteye y lee los Events. Las causas más comunes son:
- DNS aún no apunta al LB. Let’s Encrypt resuelve el nombre de host y accede al puerto 80 para validar —
INGEST_DOMAINdebe resolver al LB público yDASHBOARD_DOMAINal LB del panel. Hasta que se propague el CNAME/Alias, la orden permanece enpending. Una vez que el DNS sea correcto, cert-manager reintentará automáticamente (no es necesario eliminar el Certificate). - Nombre de host no sustituido. Si
dnsNamessigue mostrandoINGEST_DOMAIN_PLACEHOLDER/DASHBOARD_DOMAIN_PLACEHOLDER, omitiste el paso 3.1 — creabase/certificates/domain.envy vuelve a aplicar. - Traefik del panel no puede servir el desafío (solo
dashboard-tls). La instancia de Traefik del panel debe instalarse con el archivo de valores incluido (Fase 1.2), que habilita el proveedor de Ingress con alcance limitado que sirve el solver HTTP-01 de cert-manager. Una instancia instalada sin él deja el desafío sin ruta y la orden enpendingindefinidamente.
mtls-ca no está listo: cert-manager en sí está en mal estado. Revisa los pods de cert-manager del paso 1.1.
3.6 Verificar los CronJobs
| Nombre | Programación | Propósito |
|---|---|---|
agenteye-backup | 0 3 * * * | Copia de seguridad diaria de Postgres + ClickHouse a las 03:00 UTC |
cert-renewal-check | 0 3,15 * * * | Alertas de caducidad de certificados a las 03:00 y 15:00 UTC |
3.7 Verificar que el servidor arrancó correctamente
POSTGRES_PASSWORD que contiene caracteres no seguros para URLs que rompen la DATABASE_URL. Consulta enterprise-docs/troubleshooting.md.
3.8 Verificar que el panel se conectó al servidor
Ready en la salida sin errores ECONNREFUSED ni similares.
Si falla: Comprueba que el Service server existe (kubectl get svc server -n agenteye) y que AGENTEYE_SERVER_URL está configurado como http://server:8080 en el despliegue del panel.
Fase 4 — Acceso de red (~5 min)
4.1 Obtener las direcciones de los LoadBalancers
En AWS EKS, los LoadBalancers devuelven un nombre de host en lugar de una IP. ReemplazaVerificación:.ippor.hostnameen los comandos anteriores.
4.2 Apuntar el DNS a los LoadBalancers
Crea registros DNS para que los nombres de host debase/certificates/domain.env resuelvan a sus LoadBalancers — INGEST_DOMAIN al LB de Traefik público, DASHBOARD_DOMAIN al LB de Traefik del panel:
- AWS Route 53: registro
AconAlias = Yes, destino = el nombre de host del LB. No uses A → IP simple; las IPs de ELB rotan. - Cualquier otro proveedor:
CNAMEdesde el nombre de host al nombre de host del LB.
$PUBLIC_IP y $INTERNAL_IP respectivamente (o, en EKS, resolver a los mismos nombres de host *.elb.amazonaws.com).
Una vez que el DNS resuelva, cert-manager completará las órdenes ACME pendientes de la Fase 3.5 en un minuto. Vuelve a ejecutar kubectl get certificates -n agenteye hasta que tanto ingest-tls como dashboard-tls muestren Ready: True.
4.3 Acceder al endpoint de ingestión
El endpoint de ingestión público aplica mutual TLS, por lo que cada solicitud (incluyendo/health) debe presentar un certificado de cliente. Emites tu primer certificado de cliente en la Fase 5; si ya tienes uno, verifica la accesibilidad ahora:
{"status":"ok"}. No se necesita -k — el certificado del servidor encadena a una CA pública para INGEST_DOMAIN, por lo que se valida contra el almacén de confianza del sistema. Accede al endpoint de ingestión por su nombre de host INGEST_DOMAIN (que coincide con el certificado emitido), no por la IP/nombre de host bruto del LoadBalancer.
El endpoint del panel se sirve en DASHBOARD_DOMAIN con un certificado de confianza pública y no está detrás de mTLS, por lo que no se necesita -k ni certificado de cliente:
DASHBOARD_DOMAIN, por lo que la dirección bruta mostrará un error de nombre en el certificado.
Si falla: Si curl se cuelga, comprueba que el LB es accesible desde tu máquina (VPN, grupos de seguridad, reglas de firewall). Un error de handshake certificate required en el nombre de host de ingestión significa que no se presentó ningún certificado de cliente; completa primero la Fase 5. Un error de validación TLS en el nombre de host de ingestión significa que el certificado del servidor aún no ha terminado de emitirse; vuelve a la Fase 3.5 y resuelve el problema allí.
Fase 5 — Emitir certificados de cliente mTLS (~10 min por clúster)
Los colectores se autentican con dos factores: un certificado de cliente (capa de transporte, demuestra que la solicitud proviene de un clúster autorizado) y una clave de API (capa de aplicación, demuestra que la solicitud es de un colector con permisoevents:add). Una clave filtrada es inútil sin el certificado; un certificado robado es inútil sin una clave válida.
5.1 Emitir un certificado
Cada clúster que ejecuta colectores necesita su propio certificado de cliente. Desde el directorio de manifiestos:<nombre-clúster> con un identificador significativo (por ejemplo, us-east-1-prod, staging).
Verificación: El script imprime ==> Done! y lista los archivos de salida.
Ready: True.
Archivos de salida en issued/<nombre-clúster>/:
| Archivo | Propósito |
|---|---|
client.crt | Certificado de cliente (validez de 90 días) |
client.key | Clave privada del cliente |
ca.crt | Certificado de CA para verificación del servidor |
collector-mtls-secret.yaml | Secret de Kubernetes listo para aplicar en el clúster del colector |
5.1b Entrega alternativa: AWS Secrets Manager
Si el consumidor del certificado es un Pod de Kubernetes que necesitaclient.crt y client.key en disco — el caso típico cuando ejecutas el agenteye-collector como sidecar en tu pod de aplicación — envía el bundle del certificado a AWS Secrets Manager. El pod de la aplicación lo monta entonces mediante el Secrets Store CSI Driver con IRSA, y la rotación del certificado es completamente automática.
PutSecretValue en el mismo secreto, de modo que el ARN y el nombre permanecen estables. El CSI Driver recoge la nueva versión en su próximo ciclo de rotación y reescribe los archivos dentro del pod.
Requisitos previos:
- CLI de
awsv2 autenticado en tu cuenta de AWS. jqinstalado.- Variable de entorno
AWS_REGIONconfigurada. - Permisos IAM en tu identidad (limita
Resourceaarn:aws:secretsmanager:<región>:<cuenta>:secret:agenteye/mtls-client/*):secretsmanager:CreateSecretsecretsmanager:DescribeSecretsecretsmanager:PutSecretValuesecretsmanager:TagResource
| Paso | Acción |
|---|---|
| 1 | Emite o reextrae el certificado mediante cert-manager (igual que el modo por defecto). |
| 2 | Llama a DescribeSecret en agenteye/mtls-client/<nombre-clúster> para decidir si crear o actualizar. |
| 3 | En la primera ejecución: CreateSecret con un payload JSON de tres claves (client.crt, client.key, ca.crt), etiquetado con AgentEyeCluster=<nombre-clúster>. En ejecuciones posteriores: PutSecretValue para publicar una nueva versión; etiqueta actualizada mediante TagResource. |
| 4 | Elimina issued/<nombre-clúster>/ solo después de una carga exitosa. En caso de error, el directorio se conserva para poder reintentar. |
aws secretsmanager restore-secret --secret-id agenteye/mtls-client/<nombre-clúster> antes de reintentar.
Para la configuración completa del pod (SecretProviderClass, configuración de IRSA, comportamiento de rotación y solución de problemas), consulta enterprise-docs/single-pod-deployment.md.
5.2 Verificar que el certificado funciona
Prueba el certificado emitido contra el ingreso mTLS:{"status":"ok"}
Si falla:
| Error | Causa | Solución |
|---|---|---|
certificate required | El certificado no se está presentando | Verifica las rutas de archivo en el comando curl |
bad certificate | Discrepancia de CA | Verifica que mtls-ca-issuer emitió el certificado: kubectl describe certificate mtls-client-<nombre> -n agenteye |
connection refused | Nombre de host incorrecto o LB no accesible | Comprueba /etc/hosts o DNS |
5.3 Entregar al clúster del colector
Envíacollector-mtls-secret.yaml al equipo que opera el clúster del colector. Ellos lo aplican:
client.crt, client.key, ca.crt).
5.4 Ciclo de vida del certificado
| Propiedad | Valor |
|---|---|
| Validez del certificado de cliente | 90 días |
| Renovación automática | cert-manager renueva 15 días antes de la caducidad |
| Validez de la CA | 10 años |
| Alertas de caducidad | CronJob alerta 30 días antes de la caducidad (Fase 6) |
issue-client-cert.sh y vuelve a aplicar collector-mtls-secret.yaml antes de que caduque el certificado antiguo.
Si estás usando --save-to aws-secrets-manager (ver §5.1b), vuelve a ejecutar el mismo comando. El script llama a PutSecretValue en el mismo secreto; los pods que montan el secreto mediante el Secrets Store CSI Driver recogen la nueva versión en su próximo ciclo de rotación (por defecto: cada hora), sin necesidad de reiniciar el pod.
5.5 Revocar un certificado
Para bloquear inmediatamente el acceso del colector de un clúster:curl del paso 5.2 ahora falla con un error de handshake TLS.
Fase 6 — Monitorización de renovación de certificados (~2 min)
Un CronJob integrado se ejecuta cada 12 horas (03:00 y 15:00 UTC) y comprueba todos los certificados de cliente etiquetados conagenteye.io/cert-type=mtls-client. Alerta cuando algún certificado está a menos de 30 días de caducar.
6.1 Habilitar notificaciones de Slack (opcional)
6.2 Probar el CronJob
get, list en los recursos Certificate de cert-manager. Verifica con: kubectl describe role cert-renewal-check -n agenteye.
Limpia el job de prueba:
Fase 7 — Verificar el funcionamiento end-to-end
Esta fase confirma que toda la cadena funciona: comprobación de salud, creación de clave, ingestión de eventos y visualización en el panel.Nota: Los ejemplos siguientes acceden al endpoint de ingestión por su dirección bruta del LoadBalancer (${PUBLIC_IP}) por comodidad, por lo que se pasa-k; el certificado del servidor está vinculado aINGEST_DOMAIN, no a la IP del LB, por lo que se omite la verificación del nombre de host. El endpoint de ingestión aplica mutual TLS en todas las rutas, por lo que cada llamada también debe presentar un certificado de cliente (--cert/--key). Para validar también el certificado público, apunta ahttps://ingest.tu-empresa.example/...en lugar de${PUBLIC_IP}y elimina el-k.
7.1 Comprobación de salud
{"status":"ok"} con HTTP 200.
7.2 Crear claves de colector con permisos restringidos
La clave de administrador es para el arranque inicial y la gestión. Crea claves dedicadas con permisoevents:add para los colectores:
"id", "name": "prod-collector", "permissions": ["events:add"], "created_at".
Verificación: Comprueba que la clave aparece en la lista de claves:
prod-collector aparece en la respuesta.
Consulta enterprise-docs/api-keys.md para la referencia completa de gestión de claves.
7.3 Ingestar un evento de prueba
{"accepted":1,"skipped":0} con HTTP 200.
Si falla:
| Estado HTTP | Causa |
|---|---|
| 401 | Clave de API inválida o ausente |
| 403 | La clave no tiene el permiso events:add |
| Error de handshake TLS | Problema con el certificado de cliente — ver solución de problemas de la Fase 5 |
7.4 Verificar que el evento aparece en el panel
Abrehttps://agenteye.tu-empresa.example (tu DASHBOARD_DOMAIN) en un navegador. El certificado tiene confianza pública, por lo que no hay advertencias.
Si el LoadBalancer del panel está restringido por lista de IPs y no puedes conectarte, verifica que tu IP está permitida:Verificación: El evento de prueba debe aparecer en la lista de eventos con la sesiónTen en cuenta que Let’s Encrypt renueva el certificado del panel mediante HTTP-01 en el puerto 80, y los rangos de origen se aplican a todo el LoadBalancer — antes de restringirlo a rangos corporativos, coordina un solver DNS-01 con soporte o las renovaciones fallarán silenciosamente.
test y el agente smoke-test.
Si falla: Comprueba los logs del panel (kubectl logs -n agenteye -l app=dashboard --tail=50). Verifica que AGENTEYE_SERVER_URL y AGENTEYE_API_KEY están configurados correctamente.
7.5 Probar el CronJob de copia de seguridad
Backup created: agenteye-YYYYMMDD-HHMMSS.tar.gz (NNN) en los logs; el archivo agrupa el volcado de Postgres y las tablas de ClickHouse.
El paso de carga a S3 viene integrado en el CronJob y se ejecuta siempre queLimpieza:BACKUP_BUCKETesté configurado (la base incluye un valor de bucket por defecto). Solo se omite cuandoBACKUP_BUCKETestá vacío o literalmente esPLACEHOLDER. Apúntalo a tu propio bucket y concede al ServiceAccountagenteye-backupacceso de escritura antes de confiar en él (ver la sección de Copias de seguridad más abajo).
7.6 Aprovisionar organizaciones (multi-tenant)
Omite esto para un despliegue de un solo tenant; todos los datos viven en la organizacióndefault integrada y nada aquí es necesario.
Si ejecutas múltiples tenants aislados, las organizaciones y sus miembros se crean con la CLI agenteye-orgctl. Esta herramienta se incluye dentro de la imagen del servidor (junto a agenteye-server) y se ejecuta dentro del Deployment server existente con kubectl exec; no hay pod, Job ni Deployment separado, y no hay API HTTP ni botón en el panel para el ciclo de vida del tenant. Ejecutarla en el pod del servidor significa que reutiliza la DATABASE_URL, CLICKHOUSE_URL y el ORG_CH_SECRET del §2.6 del pod.
Requisito previo: completa primero el §2.6.Crear una organización y añadir su primer administrador:org createse niega a ejecutarse mientras el servidor siga usando elORG_CH_SECRETde desarrollo integrado, y el usuario de ClickHouse por organización que aprovisiona depende de que ese secreto sea fuerte y estable.
/acme/...).
Otros comandos (se ejecutan de la misma manera con kubectl -n agenteye exec deploy/server -- agenteye-orgctl …):
| Comando | Qué hace |
|---|---|
org list | Lista las organizaciones y su estado. |
org rename --slug <slug> --name <nuevo nombre> | Renombra una organización (el slug no cambia). |
org delete --slug <slug> | Eliminación suave + eliminación del usuario de ClickHouse de la organización; los datos se conservan. |
org purge --slug <slug> | Borrado irreversible de datos; la organización debe estar eliminada primero; nunca para la organización default. |
member list --org <slug> | Lista los miembros y sus permisos. |
member update --org <slug> --email <email> [--set ...] [--add ...] [--remove ...] | Cambia los permisos de un miembro. |
member remove --org <slug> --email <email> | Elimina un miembro de la organización. |
admin, standard y read-only. Las claves de API por organización se siguen creando en el panel/API por los miembros de la organización (el §7.2 muestra la API de claves); solo el ciclo de vida de la organización y los miembros es exclusivo para operadores. Referencia completa y un ejemplo detallado: enterprise-docs/tenant-management.md.
Lista de verificación post-despliegue
Usa esta lista para confirmar que todo funciona. Cada elemento debe estar comprobado antes de entregar a los colectores.- Todos los pods en estado
Runningen el namespaceagenteye - PVC de PostgreSQL vinculado (50 Gi) y PVC de ClickHouse vinculado (100 Gi)
- Los 3 certificados con
Ready: True - Ambas IPs de LoadBalancer asignadas
- DNS o
/etc/hostsconfigurado y resolviendo -
/healthdevuelve HTTP 200 - Prueba de certificado mTLS superada (
curlcon certificado de cliente a/health) - Clave de colector con permisos restringidos creada y probada
- Evento de prueba ingestado (
accepted: 1) - Evento visible en el panel
- Certificados de cliente emitidos para cada clúster de colector
- CronJob de copia de seguridad probado manualmente
- CronJob de renovación de certificados probado manualmente
- Webhook de Slack para alertas de certificados configurado (opcional)
- Bucket de copia de seguridad configurado en el overlay (ver más abajo)
- Clave de administrador y contraseña de Postgres guardadas en el gestor de secretos
Copias de seguridad
Un único CronJobagenteye-backup se ejecuta diariamente a las 03:00 UTC. Vuelca ambos almacenes: PostgreSQL (estado relacional) y ClickHouse (las tablas de análisis events + evaluations), en un archivo comprimido en el pod, y luego lo carga en el almacenamiento de objetos que configures en tu overlay.
Cada ejecución produce un objeto, agenteye-<timestamp>.tar.gz, que se descomprime en:

