Projecting an environment

With the operator running, each environment you want in your cluster is one small resource. Applying it creates a Secret; deleting it takes that Secret away.

Ask for an environment

apiVersion: connectors.kyvlt.sh/v1alpha1
kind: KyvltSync
metadata:
  name: kyvlt-secrets
spec:
  # <your-project> / <your-environment>
  environmentId: <your-environment-id>
  apiBaseUrl: https://api.kyvlt.sh
  tokenRef:
    name: kyvlt-token
  intervalSeconds: 300

Save it and kubectl apply -f it, in the namespace your workloads read from. Within one interval a Secret appears beside it, holding every key in <your-environment> as an entry.

The manifest names no namespace: kubectl puts it where you are pointing, and the Secret follows the resource, so the two cannot disagree. That namespace must be one the operator was installed to serve — otherwise the resource reports NamespaceNotServed.

Everything else has a default. The full set:

FieldDefault
environmentIdWhich environment. An identifier, so renaming one in kyvlt.sh cannot repoint a live Secret. Or name project and environment instead.
apiBaseUrlrequiredHTTPS unless allowInsecureApi.
tokenRef.namerequiredA Secret in this namespace.
tokenRef.keytokenThe key within it.
target.namethe resource's nameWhat your pods mount.
target.typeOpaqueImmutable once created.
target.namespaceRefused at apply time: a projection lands beside its resource, always. Removed in 0.10.0.
target.labelsPut on the Secret. So are target.annotations, where the connectors.kyvlt.sh/ prefix is reserved.
intervalSeconds300Minimum 30.
pruneRemovedKeystrueWhether a key removed in kyvlt.sh leaves the Secret.
expiryWarningDays7When the token's expiry starts showing in the status.
allowInsecureApifalsePermits a plaintext apiBaseUrl. Named rather than inferred from the hostname.
resyncTokenChange it to force a full resync.
scopeall collectionsScoping to collections.
transformnoneChanging key names.

Use it

envFrom:
  - secretRef:
      name: kyvlt-cayote-studio-production

That is the whole integration. Your application reads environment variables and does not know kyvlt.sh exists.

Check it worked

kubectl get kvsync
kubectl get secret kyvlt-secrets

When a value changes

The operator checks on an interval and rewrites the Secret when the environment has changed. When nothing has changed it does nothing: no value is read, no audit record is written, and the Secret is not touched.

Keys that leave

A key removed in kyvlt.sh is removed from the Secret. A retired credential that lingers in a cluster is the thing you retired it to avoid.

Keys the operator did not write are left alone. It tracks what it put there, so anything else writing into the same Secret is neither disturbed nor deleted.

Naming the Secret something else

Workloads that already mount a name should keep it. Say so, and the resource and the Secret part company:

spec:
  target:
    name: app-secrets

Everything else is unchanged: still one Secret, still in this namespace, still every key in the environment.

A readable manifest

If you would rather not carry an identifier, name the project and environment:

spec:
  project: Cayote Studio
  environment: production

Names are resolved on every sync. If the environment is later renamed the resource reports Unresolvable and stops, rather than following the rename to something you did not name.