Vaultic
Integrations

Kubernetes

A controller-runtime operator that materializes a Vaultic environment as a native v1.Secret, refreshed on an interval.

The Vaultic Kubernetes operator materializes an environment as a native v1.Secret, kept in sync on a poll interval — so workloads consume an ordinary Kubernetes Secret, with Vaultic as the source of truth behind it.

Built with controller-runtime, following standard kubebuilder project conventions, as a standalone Go module.

The CRD: VaulticSecret

apiVersion: vaultic.dev/v1alpha1
kind: VaulticSecret
metadata:
  name: backend-api-production
spec:
  serverURL: http://vaultic-server.default.svc.cluster.local:4000
  workspace: acme
  project: backend-api
  environment: production
  tokenSecretRef:
    name: vaultic-token   # an existing Secret holding a Vaultic service token
    key: token
  targetSecretName: backend-api-production   # the v1.Secret this controller creates/updates
  refreshIntervalSeconds: 60

What the controller does on each reconcile

Read the service token

From spec.tokenSecretRef, in the same namespace as the VaulticSecret — the token is never stored inline in the CR spec.

Fetch the resolved environment

Calls the same fully-resolved (inheritance + ${...} reference) export endpoint vaultic export and vaultic run use.

Create or update the target Secret

Named spec.targetSecretName (defaults to the CR's own name), owned by the VaulticSecret via OwnerReference — deleting the CR garbage-collects the Secret automatically, no finalizer needed.

Report status

Sets a standard Ready condition and status.syncedKeyCount on the CR.

Requeue

After spec.refreshIntervalSeconds (default 60, min 5) — this is what makes refresh happen even with zero Kubernetes-side events, since the API server has no way to know a secret changed purely on the Vaultic side. Errors back off to a shorter retry instead of waiting a full interval.

A single controller replica needs no leader election (a --leader-elect flag exists if you run more than one).

Deploying

# 1. CRD
kubectl apply -f config/crd/vaultic.dev_vaulticsecrets.yaml

# 2. RBAC + namespace
kubectl apply -f config/manager/namespace.yaml
kubectl apply -f config/rbac/service_account.yaml
kubectl apply -f config/rbac/role.yaml
kubectl apply -f config/rbac/role_binding.yaml

# 3. Load the image into your cluster (it isn't pushed to a registry)
kind load docker-image vaultic/k8s-operator:dev          # kind
# or: minikube image load vaultic/k8s-operator:dev        # minikube

# 4. Deploy
kubectl apply -f config/manager/deployment.yaml

# 5. Your VaulticSecret + its token Secret
kubectl apply -f config/samples/vaultic_v1alpha1_vaulticsecret.yaml
kubectl get vaulticsecret
kubectl get secret backend-api-production -o yaml

To iterate without rebuilding a container image each time, the manager runs fine as a plain local process against any cluster your kubeconfig points at: go run ./cmd.

Building

cd k8s-operator
go build -o manager ./cmd          # local binary
docker build -t vaultic/k8s-operator:dev .   # container image

On this page