Registrar un cluster¶
Registrar un cluster le da a kubelatch dos ServiceAccounts en él: una para hacer de proxy y otra para mantener el RBAC. Al terminar, el cluster aparece como «Listo» en «Clusters» y ya puedes conceder permisos sobre él.
Antes de empezar¶
- Un administrador de kubelatch (Instalar).
- Un kubeconfig de administrador del cluster que vas a registrar.
- Red: los pods de kubelatch deben llegar por https al API server. Si es privado, mira Clusters privados.
- Kubernetes 1.28 o superior en el cluster: la validación usa
SelfSubjectReview.
flowchart LR
A[«Registrar» en Clusters] --> B[Aplicar bootstrap.yaml]
B --> C[Ejecutar el one-liner]
C --> D[Pegar el JSON]
D --> E[kubelatch valida y cifra]
E --> F[Primera reconciliación]
Registrar el cluster¶
-
En «Clusters», rellena «Identificador» y «Nombre» y pulsa «Registrar». El identificador es un slug (minúsculas, dígitos y guiones, hasta 63 caracteres) y va en la URL del proxy:
https://<kubelatch>/clusters/<id>. El cluster queda en «Sin tokens» y se abre el diálogo de bootstrap. -
Descarga el manifiesto («descargar bootstrap.yaml») y aplícalo con el kubeconfig de administrador de ese cluster:
kubectl --kubeconfig <kubeconfig-del-cluster> apply -f kubelatch-bootstrap-<id>.yamlCrea el namespace
kubelatch-system, las ServiceAccountskubelatch-proxyykubelatch-reconcilercon un Secret de token cada una, el ClusterRole estático del reconciliador y el ClusterRolekubelatch-proxy. -
Copia el one-liner del diálogo y ejecútalo con el mismo kubeconfig. Usa el contexto actual de
kubectl, así que fíjalo en una subshell:(export KUBECONFIG=<kubeconfig-del-cluster>; <one-liner>)Espera hasta un minuto a que Kubernetes rellene los tokens e imprime un JSON con
server,ca,proxyTokenyreconcilerToken. -
Pega el JSON en «JSON de los tokens» y pulsa «Guardar tokens».
kubelatch valida los tokens contra el cluster, los guarda cifrados y lanza la primera reconciliación. Los tokens nunca se vuelven a mostrar.
Qué valida kubelatch¶
- La URL del API server: solo
https, sin usuario, query ni fragmento, y nunca una IP literal link-local, de metadatos o multicast (los nombres no se resuelven para comprobarlo). - La CA: el PEM en base64 (
certificate-authority-data) o el PEM tal cual. - La identidad de cada token con
SelfSubjectReview:proxyTokendebe serkubelatch-proxyyreconcilerToken,kubelatch-reconciler. - Los permisos de cada ServiceAccount con
SelfSubjectAccessReview: el proxy debe poder impersonaruids; el reconciliador, leer los objetos RBAC, escribir sus nombres fijos,bindde los roles de cada nivel, listar namespaces y crearSubjectAccessReviews.
Si algo falla, el 400 dice qué: proxyToken: el token pertenece a …, la ServiceAccount kubelatch-reconciler no tiene el permiso …: aplica el manifiesto bootstrap de nuevo. Más casos en Solución de problemas.
Si el cluster es el propio cluster de gestión¶
El server de tu kubeconfig puede no ser alcanzable desde dentro del pod. Usa https://kubernetes.default.svc con la misma CA:
kubectl --kubeconfig "$MGMT_KUBECONFIG" apply -f kubelatch-bootstrap-<id>.yaml
printf '{"server":"%s","ca":"%s","proxyToken":"%s","reconcilerToken":"%s"}\n' \
https://kubernetes.default.svc \
"$(kubectl --kubeconfig "$MGMT_KUBECONFIG" config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}')" \
"$(kubectl --kubeconfig "$MGMT_KUBECONFIG" -n kubelatch-system get secret kubelatch-proxy-token -o jsonpath='{.data.token}' | base64 -d)" \
"$(kubectl --kubeconfig "$MGMT_KUBECONFIG" -n kubelatch-system get secret kubelatch-reconciler-token -o jsonpath='{.data.token}' | base64 -d)"
Si el kubeconfig usa un fichero de CA¶
El one-liner lee certificate-authority-data. Si tu kubeconfig usa certificate-authority: /ruta/ca.crt (habitual con kubeadm o minikube), imprime "ca":"" y kubelatch responde 400 falta la CA del cluster (ca). Pon en ca el fichero en base64: base64 -w0 < /ruta/ca.crt (en macOS, base64 -i /ruta/ca.crt).
Comprueba que funciona¶
- En «Clusters», el estado es «Listo», con la versión de Kubernetes bajo la URL y una fecha en «Última reconciliación».
- «Namespaces» lista los namespaces con su nivel PSA (
PSA restricted,sin PSA…). -
En el cluster aparecen los ClusterRoles de cada nivel:
kubectl --kubeconfig <kubeconfig-del-cluster> get clusterroles -l app.kubernetes.io/managed-by=kubelatch
La reconciliación¶
El reconciliador mantiene en el cluster los ClusterRoles de cada nivel, un binding por cada nivel y ámbito con permisos activos, y la lista exacta de usuarios y grupos que el proxy puede impersonar. kubelatch-proxy nace permitiendo impersonar solo uids; el reconciliador le añade usuarios y grupos cuando hay permisos. Pasa por cada cluster:
- Al cambiar algo: conceder o revocar un permiso, pegar tokens, deshabilitar o rehabilitar una cuenta. Suele tardar menos de un segundo.
- Cada 10 minutos. Esta pasada retira los bindings de permisos que han caducado (el proxy deja de aceptarlos en el instante en que caducan).
- A petición: el botón «Reconciliar» en «Clusters», o
POST /api/clusters/<id>/reconcile.
La llamada manual responde 200 con el cluster, 502 con el motivo si el cluster falla y 409 si ya hay otra pasada en curso.
Si una pasada falla, el cluster pasa a «Error» con el motivo, y kubelatch reintenta con espera creciente: 1, 2, 4… minutos, hasta 10. Un namespace borrado con permisos vigentes deja el cluster en «Error» hasta revocarlos, pero el resto de bindings se siguen aplicando. El detalle del mecanismo está en Arquitectura.
Todo lo que kubelatch crea lleva las etiquetas app.kubernetes.io/managed-by=kubelatch y kubelatch.io/instance=<KUBELATCH_INSTANCE_ID>. Solo borra bindings con esas etiquetas y sus propios nombres, y nunca borra nada tras un error de lectura. Para añadir CRDs a un nivel, mira Conceder permisos.
Rotar los tokens de las ServiceAccounts¶
Los tokens viven en los Secrets kubelatch-proxy-token y kubelatch-reconciler-token del cluster. Para cambiarlos:
-
Borra los dos Secrets. Los tokens antiguos dejan de valer y el proxy falla en ese cluster hasta el paso 4.
kubectl --kubeconfig <kubeconfig-del-cluster> -n kubelatch-system delete secret kubelatch-proxy-token kubelatch-reconciler-token -
Vuelve a aplicar el bootstrap («Volver a pegar tokens» → «descargar bootstrap.yaml»). Kubernetes crea tokens nuevos.
- Ejecuta el one-liner.
- Pega el JSON con «Volver a pegar tokens» y pulsa «Guardar tokens».
Volver a aplicar el bootstrap devuelve kubelatch-proxy a la regla de solo uids: el proxy no puede impersonar a nadie hasta la siguiente reconciliación. Guardar los tokens ya lanza una reconciliación que devuelve la lista; «Reconciliar» solo sirve para confirmar que el cluster vuelve a «Listo».
Endurecer el cluster (opcional)¶
Un admin de namespace, concedido por kubelatch o nativo, puede crear un RoleBinding a kubelatch-developer para quien quiera. Eso no da acceso a través de kubelatch, pero sí a una credencial nativa de ese sujeto, y confunde al reconciliador.
deploy/k8s/hardening/vap-kubelatch-bindings.yaml es una ValidatingAdmissionPolicy (Kubernetes 1.30 o superior). Solo deja a kubelatch-system/kubelatch-reconciler crear o cambiar bindings cuyo roleRef empiece por kubelatch-. Aplícala en cada cluster gestionado, con su kubeconfig:
kubectl --kubeconfig <kubeconfig-del-cluster> apply -f deploy/k8s/hardening/vap-kubelatch-bindings.yaml
Aplícala después del bootstrap. make e2e-install comprueba que deniega un binding manual y que el reconciliador sigue funcionando.
La política también frena al propio bootstrap. Sus ClusterRoleBindings kubelatch-proxy y kubelatch-reconciler apuntan a roles kubelatch-*, y quien aplica el bootstrap es un administrador, no el reconciliador. Rotar tokens funciona porque esos bindings no cambian. Pero un bootstrap que tenga que crearlos o cambiarlos falla con Forbidden:
- mover el cluster a otra instancia (cambia su etiqueta
kubelatch.io/instance); - registrarlo de nuevo después de quitar el bootstrap.
En esos casos, quita antes el binding de la política, aplica el bootstrap y vuelve a aplicar la política:
kubectl --kubeconfig <kubeconfig-del-cluster> delete validatingadmissionpolicybinding kubelatch-bindings
kubectl --kubeconfig <kubeconfig-del-cluster> apply -f kubelatch-bootstrap-<id>.yaml
kubectl --kubeconfig <kubeconfig-del-cluster> apply -f deploy/k8s/hardening/vap-kubelatch-bindings.yaml
Borrar un cluster¶
Pulsa «Borrar» en «Clusters» (o DELETE /api/clusters/<id>). kubelatch:
- Intenta limpiar el RBAC del cluster con el token del reconciliador, durante 15 s como mucho. Borra los bindings y los ClusterRoles de nivel de esta instancia y deja
kubelatch-proxycon la regla de solouids. - Borra el cluster, sus permisos y las credenciales restringidas a él. Las filas de auditoría se conservan.
El diálogo final dice cómo fue la limpieza: cuántos bindings y ClusterRoles borró, que no se pudo intentar (sin tokens, o tokens que no se descifran) o por qué falló. Si avisa de una reconciliación en curso, comprueba que no quede nada.
Si la limpieza no se hizo, retira lo que quede con el kubeconfig del cluster. Esto no toca el bootstrap:
kubectl --kubeconfig <kubeconfig-del-cluster> delete clusterroles,clusterrolebindings -l 'app.kubernetes.io/managed-by=kubelatch,kubelatch.io/kind in (binding,tier)'
kubectl --kubeconfig <kubeconfig-del-cluster> delete rolebindings -A -l 'app.kubernetes.io/managed-by=kubelatch,kubelatch.io/kind in (binding,tier)'
Con varias instancias de kubelatch, añade ,kubelatch.io/instance=<id> al selector.
Quita también el bootstrap
Borrar el cluster no borra el namespace kubelatch-system, las ServiceAccounts ni el ClusterRole del reconciliador, que conserva sus permisos. Para darlo de baja del todo:
kubectl --kubeconfig <kubeconfig-del-cluster> delete namespace kubelatch-system
kubectl --kubeconfig <kubeconfig-del-cluster> delete clusterroles,clusterrolebindings kubelatch-proxy kubelatch-reconciler
Si aplicaste la política de endurecimiento, bórrala también (no lleva las etiquetas de kubelatch):
kubectl --kubeconfig <kubeconfig-del-cluster> delete validatingadmissionpolicybinding,validatingadmissionpolicy kubelatch-bindings
Mover un cluster a otra instancia¶
Un cluster se registra en una sola instancia de kubelatch. La etiqueta KUBELATCH_INSTANCE_ID hace que cada instancia solo toque sus objetos. Para moverlo:
- Si aplicaste la política de endurecimiento, quita su binding: el bootstrap nuevo cambia la etiqueta de sus ClusterRoleBindings.
- Regístralo en la instancia nueva.
- Bórralo en la antigua. La limpieza solo retira los bindings y ClusterRoles etiquetados con la instancia antigua, pero devuelve
kubelatch-proxya la regla de solouids. - Pulsa «Reconciliar» en la instancia nueva justo después.
No sirve para compartir un cluster entre dos instancias a la vez, porque el bootstrap es un único juego por cluster.