Arquitectura¶
Aquí ves de qué piezas está hecho kubelatch, dónde vive su estado y cómo se conecta con tus clusters y con GitHub. Sirve para entender qué pasa si una pieza falla y por qué el despliegue es tan pequeño.
Un binario, tres piezas¶
kubelatch es un único binario en Go con la interfaz web embebida. Dentro del mismo proceso corren tres piezas:
flowchart LR
dev["Personas<br/>navegador y kubectl"] -->|HTTPS| kl
ci["CI<br/>GitHub Actions"] -->|HTTPS| kl
subgraph kl["kubelatch (1-2 réplicas)"]
cp["Plano de control<br/>+ SPA"]
px["Proxy de<br/>impersonación"]
rc["Reconciliador<br/>RBAC"]
end
kl --> pg[("Postgres")]
px -->|"SA kubelatch-proxy"| api["API servers<br/>EKS · GKE · AKS · k3s…"]
rc -->|"SA kubelatch-reconciler"| api
cp <-->|"login, miembros,<br/>webhook"| gh["GitHub"]
| Pieza | Qué hace | Por dónde entra |
|---|---|---|
| Plano de control | La API JSON y la interfaz web (SPA en React). Cuentas, clusters, permisos, credenciales, trust rules y auditoría. | /api/... y / |
| Proxy de impersonación | Recibe las peticiones de kubectl, k9s, Lens, Helm o la CI, valida el token, registra la petición y la reenvía al API server actuando como quien la hace. | /clusters/<id>/... |
| Reconciliador RBAC | Mantiene en cada cluster los ClusterRoles de cada nivel, un binding por cada combinación de nivel y ámbito con permisos activos, y la lista exacta de usuarios y grupos que el proxy puede impersonar. | Hacia fuera: habla con cada API server |
Además hay dos rutas fuera de /api sin sesión: el intercambio de tokens de GitHub Actions (/v1/ci/github-actions/token) y el webhook de GitHub (/v1/github/webhook). Las describe la referencia de la API.
Junto a esas piezas corren tareas de fondo en cada réplica: la pasada periódica del reconciliador (cada 10 minutos), la tarea de retención de la auditoría (cada hora) y, con GitHub configurado, la sincronización de miembros de la organización (cada hora).
Dónde vive el estado¶
Todo el estado está en Postgres: sujetos, clusters (con sus tokens de ServiceAccount cifrados), permisos, credenciales (solo su hash), trust rules y las dos tablas de auditoría. kubelatch aplica sus migraciones al arrancar.
Las réplicas no guardan nada propio. Por eso puedes correr una o dos detrás del mismo Service. Con dos, el reconciliador, la retención y la sincronización de miembros se turnan con advisory locks de Postgres. Lo único que no se comparte son los limitadores por IP en memoria: cada réplica cuenta los suyos.
Sin Postgres, kubelatch no valida ningún token: el proxy responde 503 y nadie entra. Es un fallo cerrado a propósito.
Cómo encaja con todo lo demás¶
kubelatch habla con cada cluster con dos ServiceAccounts distintas, que crea el manifiesto de bootstrap en el namespace kubelatch-system:
kubelatch-proxysolo puede impersonar (impersonate) a los usuarios y grupos que el reconciliador pone en su lista (resourceNames). Es la única identidad que viaja en las peticiones de los clientes.kubelatch-reconcilerescribe RBAC, pero solo sobre los nombres fijos que kubelatch gestiona. Nunca está en el camino de una petición de cliente.
GitHub aparece dos veces. Para las personas, como proveedor de login (una GitHub App de tu organización, ver Identidad). Para la CI, como emisor de los tokens OIDC de GitHub Actions que kubelatch canjea por credenciales cortas.
Por qué funciona en cualquier cluster¶
El proxy y el reconciliador solo usan la API estándar de Kubernetes y RBAC. No hace falta tocar flags del API server, instalar nada dentro de los nodos ni un agente por cluster. Por eso el mismo mecanismo sirve en clusters gestionados (EKS, GKE, AKS) y autogestionados (kubeadm, k3s, RKE2, Talos). La página sobre el proxy explica qué alternativas se descartaron.
El cluster sigue decidiendo con su RBAC nativo. kubelatch no autoriza cada verbo: dice al API server quién es la persona y a qué grupos pertenece, y el API server aplica los bindings que el reconciliador creó.
Qué pasa si kubelatch cae¶
Las cargas de trabajo de tus clusters no dependen de kubelatch. Si se cae, solo se pierde el acceso de personas y CI a través de él. Por eso kubelatch nunca debe ser la única vía a un cluster: guarda un acceso nativo de emergencia (ver Cuentas y recuperación).
Un reinicio o un rollout corta los exec, port-forward, watch y logs -f abiertos. kubelatch da 3 s de gracia a las peticiones normales, corta los streams y termina de registrar sus filas de auditoría antes de salir. El manifiesto de despliegue usa terminationGracePeriodSeconds: 60 y un rollout con maxSurge: 1 y maxUnavailable: 0.
Despliegue de referencia¶
El despliegue por defecto (deploy/k8s/base) es un Deployment de una réplica detrás de un Service de tipo LoadBalancer L4, con TLS terminado en el propio binario. El overlay ha sube a dos réplicas con un PodDisruptionBudget. El overlay ingress pone kubelatch detrás de un Ingress, con los ajustes que necesitan los streams largos. Los pasos están en Instalar.