Arquitectura¶
Aquí ves de qué piezas está hecho kubelatch, dónde vive su estado y cómo se conecta con tus clusters, con GitHub y con tu proveedor de identidad. 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 se ejecutan 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/>suplantació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"]
cp -->|"login OIDC"| idp["Proveedor de identidad<br/>Google · Entra ID · Okta…"]
| Pieza | Qué hace | Por dónde entra |
|---|---|---|
| Plano de control | La API JSON y la interfaz web (SPA en React). Cuentas, clusters, permisos, credenciales, reglas de confianza y auditoría. | /api/... y / |
| Proxy de suplantació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 y de cada rol personalizado, un binding por cada combinación de rol y ámbito con permisos activos, y la lista exacta de usuarios y grupos que el proxy puede suplantar. | 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 se ejecutan tareas de fondo en el mismo proceso: 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), reglas de confianza y la auditoría (peticiones al proxy y acciones administrativas). kubelatch aplica sus migraciones al arrancar.
Las réplicas casi no guardan nada propio. Por eso puedes desplegar una o dos detrás del mismo Service. Con dos, el reconciliador, la retención y la sincronización de miembros se ejecutan en una sola réplica a la vez. Lo que sí se guarda cada réplica (sus límites de peticiones, una clave pegada en «Edición» hasta la comprobación horaria, la última sincronización que muestra, el documento de descubrimiento del proveedor OIDC) está en Varias réplicas.
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 suplantar a los usuarios y grupos que el reconciliador pone en su lista. Es la única identidad que viaja en las peticiones de los clientes.kubelatch-reconcilerescribe RBAC, pero solo objetoskubelatch-*: una política de admisión del mismo manifiesto,kubelatch-reconciler-jail, le rechaza todo lo demás (Modelo de seguridad). 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 de corta duración.
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 cualquier exec, port-forward, watch o logs -f abierto. kubelatch da 3 s de gracia a las peticiones normales, corta los streams (una petición que aún espera al cluster recibe un 503; los streams abiertos se cierran, y sus filas de auditoría terminan con kubelatch restarting) y termina de registrar sus filas de auditoría antes de salir. El Deployment del chart de Helm usa terminationGracePeriodSeconds: 60 y un rollout con maxSurge: 1 y maxUnavailable: 0.
Despliegue de referencia¶
El despliegue por defecto (el chart de Helm con sus values por defecto) es un Deployment de una réplica detrás de un Service LoadBalancer de capa 4, con TLS terminado en el propio binario. replicas: 2 añade un PodDisruptionBudget; exposure: ingress pone kubelatch detrás de un Ingress, con los ajustes que necesitan los streams largos; postgres.mode: cnpg lleva su base de datos a CloudNativePG. Los pasos están en Instalar.