Pular para o conteúdo principal

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

EndpointAuthUso
POST /clustersJWT (admin)Registrar cluster
GET /clustersJWTListar
DELETE /clusters/:idJWT (admin)Remover
POST /clusters/:id/policiesJWTCriar policy
GET /clusters/:id/policiesJWTListar policies
DELETE /clusters/:id/policies/:pJWTRemover
GET /clusters/:id/desired-stateX-Cluster-TokenOperator polling
POST /clusters/:id/statusX-Cluster-TokenOperator status report
GET /clusters/:id/auditJWTHistó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 tokenDELETE /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_log no CV com logs do operator no SIEM