Primeros pasos en Kubernetes (Helm)
El chart de Helm en deploy/helm/olivares despliega el control
plane con los mismos valores por defecto seguros que cualquier otra vía: un
StatefulSet del núcleo (sin root, sistema de ficheros raíz de solo lectura,
todas las capabilities eliminadas), TLS activado, exposición equivalente a
loopback (un Service ClusterIP — nada público hasta que tú lo decidas) y sin
credenciales por defecto. A partir de ahí optas por Postgres, HA
activo-pasivo, copias de seguridad de DR cifradas programadas y el
DaemonSet de colectores para la ingesta distribuida.
Todo lo de abajo se renderizó y comprobó contra el chart de este
repositorio (helm lint + helm template, incluidas las configuraciones de HA y
de copias de seguridad y las propias guard rails del chart). El chart requiere
Kubernetes ≥ 1.25.
1. La instalación por defecto (un solo nodo, SQLite)
Sección titulada «1. La instalación por defecto (un solo nodo, SQLite)»-
Instala desde el checkout:
Ventana de terminal helm install olivares deploy/helm/olivaresEsto renderiza exactamente tres objetos de carga de trabajo — un
StatefulSet(1 réplica, SQLite en un PVC persistente de 8 Gi), unServiceClusterIP(8443 HTTPS, 8444 gRPC) y unServiceAccountsin privilegios sobre la API de Kubernetes. Las probes apuntan a/readyz(readiness — drena cuando el almacén está caído o la réplica no es líder) y/livez(liveness — solo el proceso, nunca una dependencia, así que una caída del almacén nunca puede provocar un bucle de reinicios). -
Lee el token de configuración de un solo uso desde el log del pod (se imprime solo en stdout — en Kubernetes, eso es el log del contenedor):
Ventana de terminal kubectl logs -l app.kubernetes.io/component=core | sed -n '/FIRST-BOOT SETUP/,/========================/p' -
Haz port-forward y completa la configuración de primer arranque (el mismo flujo que en todas partes):
Ventana de terminal # The Service is named <release>-olivares-core:kubectl port-forward svc/olivares-core 8443:8443curl -ksf -X POST https://127.0.0.1:8443/v1/setup \-H 'Content-Type: application/json' \-d '{"token":"<olst_ token>","email":"you@example.com","password":"<strong-password>"}'
Como alternativa, sin Helm en absoluto, el repositorio incluye un manifiesto plano con los mismos valores por defecto seguros de un solo nodo, regenerado desde el chart por CI:
kubectl apply -f deploy/manifests/install.yamlPara Argo CD / Flux / Kustomize (kustomize build --enable-helm), consulta
deploy/gitops/ — envoltorios declarativos sobre este mismo chart.
2. Postgres (multi-tenant)
Sección titulada «2. Postgres (multi-tenant)»El motor requiere un rol de base de datos de mínimo privilegio: LOGIN, sin
superusuario, sin BYPASSRLS — la seguridad a nivel de fila es la red de
seguridad del tenant, y el motor se niega a arrancar contra un rol privilegiado.
Aprovisiona el rol con el canónico deploy/postgres/01-app-role.sql (el chart
puede ejecutarlo por ti como un Job de pre-instalación), pon el DSN en un Secret y
apunta el chart a él:
kubectl create secret generic olivares-pg \ --from-literal=dsn='postgres://olivares_app:***@db:5432/olivares?sslmode=verify-full' \ --from-literal=admin-dsn='postgres://olivares_admin:***@db:5432/olivares?sslmode=verify-full'
helm install olivares deploy/helm/olivares \ --set core.engine=postgres \ --set postgres.dsnSecret=olivares-pg \ --set postgres.adminDsnKey=admin-dsnLa clave admin-dsn del mismo Secret contiene un rol dedicado NOSUPERUSER BYPASSRLS. Es opcional solo si nunca vas a activar las copias de seguridad:
es lo que hace completas las lecturas del sistema entre tenants — la lista de
organizaciones y la cobertura multi-tenant —, y activar la copia de seguridad la
exige (copias de seguridad cifradas
programadas). Crearla ahora
convierte ese paso posterior en un cambio de una sola línea.
3. HA activo-pasivo
Sección titulada «3. HA activo-pasivo»Con Postgres como almacén compartido, ejecuta varias réplicas. Una se elige como
líder (un advisory lock de Postgres); las réplicas en espera responden a /readyz
con 503 {"status":"standby"} para que el Service solo enrute al líder, y una
réplica en espera toma el relevo automáticamente cuando el líder desaparece.
Hay dos cosas estructuralmente obligatorias, y el chart fuerza ambas (verificamos que las guardas se renderizan como fallos duros, no como avisos):
| Requisito | Por qué | Guarda del chart si falta |
|---|---|---|
| core.engine=postgres | El fichero SQLite es local a un solo pod — no puede ser un almacén compartido. | core.replicaCount > 1 requires core.engine=postgres … |
| core.auditSigningKeySecret | Cada réplica debe firmar el ledger de auditoría con la misma clave Ed25519, o la cadena de hashes se bifurca en el failover. | core.replicaCount > 1 requires core.auditSigningKeySecret … |
kubectl create secret generic olivares-audit-key \ --from-file=audit-signing.key=<base64-ed25519-private-key-file>
helm install olivares deploy/helm/olivares \ --set core.engine=postgres \ --set postgres.dsnSecret=olivares-pg \ --set core.replicaCount=3 \ --set core.auditSigningKeySecret=olivares-audit-keyLos tamaños canónicos de HA son 3 o 5 réplicas, activo-pasivo. Este diseño de único escritor es deliberado (encaja con el modelo de consistencia del producto); los números de preparación para producción documentan los niveles de disponibilidad que soporta.
4. Copias de seguridad cifradas programadas
Sección titulada «4. Copias de seguridad cifradas programadas»El chart incluye un CronJob que ejecuta olivares dr backup — un paquete
cifrado y seguro para la continuidad del ledger (instantánea del almacén +
claves de firma selladas bajo tu KEK + manifiesto de la punta de cadena por
tenant):
kubectl create secret generic dr-kek --from-literal=passphrase='<strong passphrase>'
helm upgrade olivares deploy/helm/olivares --reuse-values \ --set backup.enabled=true \ --set backup.kekSecret=dr-kek \ --set postgres.adminDsnKey=admin-dsn # solo Postgres, y OBLIGATORIO con backupsEn Postgres el chart se niega a renderizar sin postgres.adminDsnKey: el
pg_dump de la copia de seguridad mantiene row_security=off y aborta como
rol de aplicación bajo FORCE ROW LEVEL SECURITY, así que un CronJob cableado
al DSN de la aplicación fallaría en cada ejecución y te dejaría sin copia de
seguridad alguna.
Valores por defecto: cada 6 horas (backup.schedule fija tu RPO), retención local
de 14 días, un PVC de destino dedicado. Replica el destino fuera del sitio y
mantén la KEK separada de los paquetes — una copia de seguridad en el mismo
clúster no es recuperación ante desastres. Ensaya restauraciones con
olivares dr verify; el procedimiento completo está en
copia de seguridad y restauración.
5. DaemonSet de colectores (ingesta distribuida)
Sección titulada «5. DaemonSet de colectores (ingesta distribuida)»Para la topología distribuida, un DaemonSet de colectores ejecuta conectores de
fuentes en cada nodo y empuja observaciones al núcleo por gRPC — los colectores
no tienen listener entrante. El chart requiere un token de ingesta y acepta
material mTLS opcional:
helm upgrade olivares deploy/helm/olivares --reuse-values \ --set collectors.enabled=true \ --set collectors.ingestTokenSecret=olivares-ingest-token # ingest:write bearer tokenDa a los colectores sus fuentes mediante collectors.sourcesConfig (el mismo
JSON de fuentes que en todas partes), y activa el mTLS
con verificación de certificado de cliente para el canal colector→núcleo con
tls.grpcClientCaSecret — consulta endurecimiento.
Monitorización
Sección titulada «Monitorización»Activa serviceMonitor si ejecutas el operador de Prometheus; en cualquier caso,
el motor expone /metrics sin autenticación (no transporta datos de tenant) y el
repositorio incluye reglas de alerta listas para usar. Consulta
monitorizar con Prometheus.
Siguientes pasos
Sección titulada «Siguientes pasos»- Cablea fuentes: conectar una fuente y las guías de conectores.
- Ensayos de fallo: resolución de problemas — comportamiento de failover, backpressure, verificación del ledger.
- ¿Clúster air-gapped? Primeros pasos en un sitio air-gapped.