Kubernetes Federation — pull-from-CV
A partir da v4.3, múltiplos clusters Kubernetes podem federar com um único CipherVault como plano de controle. Cada cluster roda o Operator com configuração de federation, e puxa periodicamente "desired state" do CV — políticas declarativas que descrevem quais secrets/leases/roles devem existir em cada namespace.
Federation usa pull, não push. CV não conecta nos clusters. Cada cluster autentica com seu próprio token e busca o que deve aplicar. Resiliente a air-gap parcial e simplifica firewall/NetworkPolicy.
Modelo
┌────────────────┐
│ CipherVault │
│ (control plane)│
└────────┬───────┘
│ HTTPS pull
┌────────────────┼────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ cluster A│ │ cluster B│ │ cluster C│
│ Operator │ │ Operator │ │ Operator │
└──────────┘ └──────────┘ └──────────┘
│ │ │
materializa materializa materializa
CRDs locais → CRDs locais → CRDs locais →
Secret K8s Secret K8s Secret K8s
Componentes
1. Cluster registration (admin no CV)
curl -X POST https://cv.acme.com.br/clusters \
-H "Authorization: Bearer $CV_TOKEN" \
-d '{
"name": "prd-saopaulo",
"description": "Cluster EKS produção sa-east-1",
"labels": { "env": "prd", "region": "sa-east-1" }
}'
# Retorna { id, token } — guarde o token, ele aparece UMA vez
token é passado para o Operator via env. Auth do Operator → CV usa
header X-Cluster-Token.
2. Cluster Secret Policies
Policies descrevem o que o cluster deve receber:
curl -X POST https://cv.acme.com.br/clusters/1/policies \
-H "Authorization: Bearer $CV_TOKEN" \
-d '{
"name": "billing-prd-secrets",
"kind": "CipherVaultSecret",
"namespace": "billing",
"labels": { "app": "billing-api" },
"spec": {
"vault": "producao",
"path": "api/stripe/secret_key",
"refreshInterval": "5m",
"target": {
"type": "Opaque",
"name": "stripe-credentials",
"keys": [
{ "name": "STRIPE_KEY", "sourcePath": "value" }
]
}
}
}'
Policies podem ser de qualquer um dos 3 CRDs do Operator:
CipherVaultSecret, CipherVaultLease, CipherVaultDynamicRole.
3. Operator polling
Operator no cluster faz GET /clusters/:id/desired-state periodicamente
(default 30s, configurável):
GET /clusters/1/desired-state
X-Cluster-Token: <token>
→ 200
{
"policies": [
{ "id": 12, "kind": "CipherVaultSecret", "spec": {...} },
{ "id": 13, "kind": "CipherVaultLease", "spec": {...} }
],
"version": "abc123"
}
FederationManager no operator:
- Leader election — apenas 1 instância pula CV por vez
- Materializa policies como CRDs locais
- Reconcilers existentes (Secret/Lease/DynamicRole) consomem normalmente
- Auto-cria namespace se não existe
- Label propagation — labels da policy aplicados ao CRD
- Idempotent upsert — versão do desired-state sinaliza mudanças
4. Status report (operator → CV)
POST /clusters/1/status
X-Cluster-Token: <token>
{
"version": "abc123",
"applied": [12, 13],
"errors": [
{ "policy_id": 14, "reason": "namespace 'foo' not found" }
],
"operator_version": "v4.4.0",
"k8s_version": "v1.30.4"
}
CV registra em cluster_apply_log para auditoria.
Configuração — Operator
apiVersion: apps/v1
kind: Deployment
metadata:
name: ciphervault-operator
namespace: ciphervault-system
spec:
replicas: 3
template:
spec:
containers:
- name: manager
image: ghcr.io/martinez1991/ciphervault-k8s-operator:v4.4.0
env:
- name: CV_URL
value: https://cv.acme.com.br
- name: CV_CLUSTER_ID
valueFrom:
secretKeyRef: { name: cv-cluster-creds, key: cluster_id }
- name: CV_CLUSTER_TOKEN
valueFrom:
secretKeyRef: { name: cv-cluster-creds, key: cluster_token }
- name: CV_FEDERATION_POLL_INTERVAL
value: "30s"
- name: CV_FEDERATION_LEADER_ELECTION
value: "true"
CV_CLUSTER_ID e CV_CLUSTER_TOKEN ativam o FederationManager —
sem essas envs, operator roda apenas em modo standalone (consume
CRDs locais sem federation).
Endpoints disponíveis
| Endpoint | Auth | Uso |
|---|---|---|
POST /clusters | JWT (admin) | Registrar cluster |
GET /clusters | JWT | Listar |
DELETE /clusters/:id | JWT (admin) | Remover |
POST /clusters/:id/policies | JWT | Criar policy |
GET /clusters/:id/policies | JWT | Listar policies |
DELETE /clusters/:id/policies/:p | JWT | Remover |
GET /clusters/:id/desired-state | X-Cluster-Token | Operator polling |
POST /clusters/:id/status | X-Cluster-Token | Operator status report |
GET /clusters/:id/audit | JWT | Histórico de aplicações |
Multi-region + Federation
Federation é region-local — endpoints /clusters/* são excluídos
do middleware de region forwarding (ver Multi-region).
Razão: cluster em sa-east-1 deve federar com CipherVault sa-east-1,
não com a primary region.
Em deploys multi-region, registre cada cluster na sua região local.
Air-gap parcial (Phase 3 — deferred)
A v4.3 implementou Phases 1+2 (backend + operator). Phase 3 (cache
incremental para suportar perda de conectividade temporária) e Phase 4
(kind cluster e2e tests) ficaram para v4.5+.
Workaround atual: aumentar CV_FEDERATION_POLL_INTERVAL em clusters com
conectividade intermitente. Operator usa último desired-state válido até
conseguir nova chamada.
Boas práticas
- Token único por cluster — não compartilhe entre clusters
- Rotação trimestral do token —
DELETE /clusters/:id+ recriar (gera novo token) - Labels organizacionais nas policies — facilita filtros e governance
- Replicas: 3 + leader election no operator
- NetworkPolicy restringindo egress do operator apenas pra
cv-url+ DNS + K8s API - Audit cruzado — combine
cluster_apply_logno CV com logs do operator no SIEM