Solución de problemas
Síntomas habituales al operar kubelatch, su causa y cómo arreglarlos. Los problemas de quien usa una credencial están en Si algo falla, y todos los mensajes de error en Errores.
Para localizar una petición concreta, usa la cabecera Audit-ID de la respuesta (kubectl -v=8 la muestra). Es el id de la fila en «Auditoría», el que aparece en el log de kubelatch y el que recibe el cluster en su propio audit.
Instalación y arranque
| Síntoma |
Causa |
Solución |
| El pod no arranca y el log lista errores de configuración |
kubelatch valida todas las variables al arrancar y muestra todos los errores juntos. |
Corrígelos en config.env o en los Secrets. Detalle de cada variable en Configuración. |
KUBELATCH_KUBECONFIG_CA: … contains a … block |
El fichero tiene algo más que certificados, por ejemplo una clave privada. |
Apunta solo al ca.crt (o al tls.crt si es autofirmado). |
KUBELATCH_TRUSTED_PROXIES: … is not a CIDR o … is broader than the minimum |
Una IP suelta, o un prefijo más amplio que /8 (IPv4) o /16 (IPv6). |
Usa CIDR (10.0.0.1/32) y el rango más estrecho posible. |
GITHUB_APP_PRIVATE_KEY: not a PEM private key |
La variable no tiene el PEM completo, con sus cabeceras, o se perdieron los saltos de línea. |
Crea el Secret con --from-file=GITHUB_APP_PRIVATE_KEY=<fichero>.pem. |
… is required when GitHub login is configured |
Hay alguna variable GITHUB_* pero faltan otras. |
Pon las cinco obligatorias, o quita todas. Ver Login con GitHub. |
/readyz responde 503 database unavailable |
Postgres no responde. |
Revisa DATABASE_URL y la red hasta Postgres. Mientras tanto, el proxy responde 503; las sesiones abiertas no se cortan. |
tls: reload failed tras renovar el certificado |
La pareja nueva es inconsistente, o cert-manager aún no ha escrito los dos ficheros. kubelatch sigue con la anterior. |
Espera a la siguiente comprobación (10 s). Si persiste, revisa el Secret kubelatch-tls. |
tls: the served certificate expires soon |
Quedan menos de 30 días. |
Renueva el certificado; kubelatch lo recarga sin reiniciar. |
GitHub login is enabled but no admin can log in |
Activaste GitHub sin cuenta de emergencia ni admin vinculado. |
kubelatch user set-break-glass <login>: ver Cuentas y recuperación. |
Ingress y red
| Síntoma |
Causa |
Solución |
kubectl get pods -w, logs -f o exec se cortan a los 60 s detrás de un Ingress |
Faltan los timeouts del controlador. |
Aplica los ajustes de deploy/k8s/overlays/ingress/ingress.yaml: Ingress. Con un LoadBalancer L4 no ocurre. |
kubectl apply de un manifiesto grande responde 413 |
El límite de cuerpo del controlador (1 MiB por defecto). |
proxy-body-size: "0". |
Toda la auditoría muestra la misma IP, o el login responde 429 a todo el mundo |
Falta KUBELATCH_TRUSTED_PROXIES con el CIDR del controlador. |
Ver Proxies de confianza. |
La API responde 403 petición de otro origen rechazada |
El navegador envía un Origin distinto de KUBELATCH_BASE_URL. |
Sirve la interfaz desde esa misma URL. Revisa que KUBELATCH_BASE_URL coincida con la URL pública. |
Un rollout cortó un exec o un port-forward |
Es lo esperado: al parar, kubelatch cierra los streams tras 3 s. |
Relanza el comando. kubectl reintenta solo los watch. Ver Actualizar. |
Clusters y reconciliación
| Síntoma |
Causa |
Solución |
El one-liner dice no aparece el token de …: ¿aplicaste el manifiesto en este contexto? |
El bootstrap no está aplicado en el cluster del contexto actual. |
Aplica el bootstrap y ejecuta el one-liner con el mismo KUBECONFIG. |
400 falta la CA del cluster (ca) |
El kubeconfig usa certificate-authority: <fichero> y el one-liner solo lee certificate-authority-data. |
Pon en ca el fichero en base64: base64 -w0 < /ruta/ca.crt (en macOS, base64 -i). |
400 … el token pertenece a … |
Los tokens del JSON están cruzados o son de otro cluster. |
Vuelve a ejecutar el one-liner con el kubeconfig correcto. |
400 la ServiceAccount … no tiene el permiso … al pegar el JSON |
El bootstrap no está aplicado entero, o es de otra versión. Los tokens no se guardaron. |
Descarga el bootstrap de nuevo, aplícalo y vuelve a pegar el JSON con «Guardar tokens». |
| Cluster en «Error» con «… deniega la operación a la ServiceAccount kubelatch-reconciler: vuelve a aplicar el manifiesto bootstrap» |
Al reconciliador le falta algún permiso del bootstrap. |
Aplica el bootstrap de nuevo y pulsa «Reconciliar». |
| El cluster está en «Error» |
La última reconciliación falló; el motivo sale bajo el estado (API server inalcanzable, … vuelve a aplicar el manifiesto bootstrap, un namespace que ya no existe…). |
Corrige la causa. kubelatch reintenta con espera creciente; «Reconciliar» fuerza una pasada. Un namespace borrado con permisos vigentes deja el «Error» hasta revocarlos. |
«Reconciliar» responde 502 |
El cluster sigue fallando. |
El mensaje trae el motivo. |
«Reconciliar» responde 409 |
Ya hay otra pasada en curso, o el cluster no tiene tokens. |
Espera unos segundos, o pega los tokens. |
reconciler: pass failed … terminating connection due to idle-in-transaction timeout |
El idle_in_transaction_session_timeout de Postgres es menor que una pasada. |
Súbelo por encima de 3 minutos o desactívalo para el rol de kubelatch. |
409 … ¿cambió KUBELATCH_ENCRYPTION_KEY? o «vuelve a pegar los tokens del cluster» |
La clave de cifrado cambió o se perdió. |
Vuelve a pegar los tokens de cada cluster: Actualizar. |
Permisos y proxy
| Síntoma |
Causa |
Solución |
kubectl responde Forbidden aunque el permiso existe |
La reconciliación aún no ha pasado. Si el cluster dice cannot impersonate, kubelatch-proxy aún no incluye a esa persona. |
Mira «Última reconciliación» y el estado en «Clusters», o pulsa «Reconciliar». |
403 … no tiene permisos activos en el cluster |
Sin ningún permiso vigente en ese cluster (revocados o caducados). |
Concede el permiso en «Permisos». |
403 esta credencial está restringida al cluster … |
La credencial se emitió para otro cluster. |
Emite otra sin restricción o para ese cluster. |
403 la cuenta está deshabilitada |
El sujeto está deshabilitado. |
«Habilitar» en «Usuarios» y emitir credencial nueva. |
401 credencial revocada o credencial caducada |
Las credenciales no se reactivan. |
Emitir otra. |
400 kubelatch no admite cabeceras Impersonate-* |
Se usó kubectl --as. |
No está soportado: ver Comprobar qué puede hacer alguien. |
400 ruta no válida: segmentos vacíos, '.' o '..' o caracteres escapados… |
La ruta lleva //, ., .. o algún % (un nombre codificado por el cliente). |
kubectl no codifica nombres válidos; con curl u otras herramientas, pon el nombre sin codificar. |
502 no se pudo hablar con el API server del cluster: … |
kubelatch no llega a la URL registrada. |
Revisa la red o el túnel (Clusters privados). El error completo está en el log. |
503 kubelatch no puede consultar su base de datos |
Postgres no responde o, si solo pasa en un cluster, sus tokens no se descifran (log proxy: load cluster). |
Revisa Postgres, o vuelve a pegar los tokens. |
GET /api/audit responde 400 |
Un filtro no es válido; el mensaje dice cuál. |
subject y credential son uuid, cluster un slug, from/to RFC 3339 con from anterior, page entre 1 y 10000. |
Filas de auditoría con estado 499 o 403 sin motivo aparente: ver Auditoría.
Cuentas
| Síntoma |
Causa |
Solución |
El login responde 429 demasiados intentos |
5 fallos seguidos (bloqueo de 15 min) o más de 10 intentos por minuto desde esa IP. |
Espera, o un «Enlace de reset», o kubelatch user set-password. |
| Nadie puede entrar |
Contraseña olvidada, cuenta bloqueada o único admin deshabilitado. |
La CLI por kubectl exec: Cuando nadie puede entrar. |
Nadie puede entrar tras configurar GITHUB_* |
Solo las cuentas de emergencia conservan la contraseña. |
kubelatch user set-break-glass <login> y entra desde «Cuenta de emergencia (contraseña)». |
409 al quitar el rol o deshabilitar a un admin |
Es el último administrador que puede entrar. |
Nombra antes otro admin. |
Login con GitHub
| Síntoma |
Causa |
Solución |
GitHub muestra redirect_uri is not associated with this application |
La Callback URL de la App no coincide exactamente con <KUBELATCH_BASE_URL>/api/auth/github/callback. |
Corrige esquema, host, puerto y barra final en la App. |
app not installed in the organization en el log de la sincronización |
La App no está instalada, o GITHUB_ORG no es el login exacto de la organización. |
Instálala y revisa GITHUB_ORG. |
Todo el mundo ve «no es miembro activo de la organización» (not_member) |
La App no tiene Organization → Members: read, o la organización no es la de GITHUB_ORG. |
Revisa los permisos de la App y GITHUB_ORG. |
no_2fa al entrar |
La organización no exige 2FA. |
Actívalo en GitHub y espera hasta 10 minutos (caché). Si de verdad no quieres exigirlo, GITHUB_REQUIRE_ORG_2FA=false. |
«no está vinculada a ninguna cuenta de kubelatch» (unknown_account) |
No hay alta automática. |
Crea la cuenta o genera un «Enlace de vinculación». |
github_taken al vincular |
Esa cuenta de GitHub ya está vinculada a otra persona. |
«Desvincular GitHub» en la otra cuenta primero. |
membership sync: pass failed; nobody was disabled |
Error de GitHub, App desinstalada o cero miembros. |
Revisa el mensaje. La siguiente pasada lo reintenta. |
El webhook responde 401 firma no válida |
El secreto de la App y GITHUB_WEBHOOK_SECRET no coinciden. |
Corrígelo. GitHub reintenta entregas desde la pestaña Advanced de la App. |
El webhook responde 415 |
El webhook no usa Content type: application/json. |
Cámbialo en la configuración del webhook de la App. |
El webhook responde 413 |
La entrega supera 1 MiB. |
No debería ocurrir con entregas normales de GitHub. |
El webhook responde 404 |
Falta GITHUB_WEBHOOK_SECRET. |
Configúralo, o desactiva el webhook en la App. |
CI con GitHub Actions
| Síntoma |
Causa |
Solución |
El intercambio responde 401 token no válido |
El id_token no pasa la verificación: firma, iss, aud distinto de KUBELATCH_BASE_URL, caducado o jti ya canjeado. |
El motivo está en el log (ci: token rejected reason=…, o ci: token replayed si el jti ya se canjeó) y en el plano de control (ci.exchange.failure). Típico: KUBELATCH_URL del workflow no coincide letra por letra, el token se canjeó dos veces, o el reloj del servidor va desviado más de 30 s. |
403 ninguna trust rule coincide … |
No hay regla para ese repositorio, ref y environment. |
El mensaje trae repository_owner_id, repository_id, ref y environment: crea la regla con esos valores, o quita la ref o el environment. |
403 que nombra al bot |
El bot está deshabilitado o no tiene permisos activos. |
Habilítalo o concédele permisos. |
429 |
Más de 60 intercambios por minuto desde la misma IP. |
Reduce la frecuencia. |
curl: (7) o (35) en el workflow |
El runner no llega a kubelatch por https, o no confía en su certificado. |
Hace falta un nombre alcanzable desde los runners y un certificado de confianza (o KUBELATCH_KUBECONFIG_CA). |
Qué vigilar
kubelatch no expone /metrics todavía. Con lo que hay:
/readyz en tu monitorización externa: 503 significa Postgres inaccesible.
- El log en JSON (
kubectl logs): tls: the served certificate expires soon, tls: reload failed, reconciler: pass failed (con el cluster y el motivo), retention: pass failed, membership sync: pass failed, ci: token rejected.
GET /api/clusters: status y last_error de cada cluster (lo mismo que «Clusters»).
GET /api/control-events: varios login.failure seguidos desde una misma IP.