The goal is to replicate values from a Vault secret to K8S. There is a K8S operator called external-secrets (ESO) for this purpose. It can be deployed quite conveniently with Helm:
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace
Next, we should first create a test secret in Vault.
vault kv put secret/foo my-value=mytopsecretvalue
On to the manifests!
The SecretStore: Connecting Kubernetes to Vault
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: "https://vault.myhomenet.lan"
path: "secret"
version: "v2"
caBundle: "..." # Base64-encoded CA certificate, see explanation below
auth:
tokenSecretRef:
name: "vault-token"
key: "token"
What’s happening here?
kind: SecretStore
This is ESO’s way of defining a connection backend. Here, we’re telling ESO:
“Whenever you need to fetch a secret, talk to this Vault instance.”
Vault provider details:
server: The Vault URL (https://vault.myhomenet.lan).path: The mount path in Vault (secret/ in this case).version: v2: This specifies the KV secrets engine version. Version 2 supports multiple versions of the same secret.caBundle: A base64-encoded CA certificate, ensuring Kubernetes trusts Vault’s TLS connection.auth: How ESO authenticates against Vault. Here we’re using a static token stored in a Kubernetes Secret (vault-token).
The ExternalSecret: Syncing Data from Vault into Kubernetes
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: vault-example
spec:
refreshInterval: "15s"
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: example-sync
data:
- secretKey: foobar
remoteRef:
key: foo
property: my-value
Breaking it down:
kind: ExternalSecretThis is where you declare what you want from Vault and how to present it in Kubernetes.refreshInterval: "15s"ESO checks Vault every 15 seconds to see if the secret changed. If it has, ESO updates the Kubernetes Secret automatically.secretStoreRefTells ESO to use the Vault connection we defined earlier (vault-backend).target.name: example-syncESO will create a native Kubernetes Secret called example-sync.
data section:
secretKey: foobar: Inside the Kubernetes Secret, the key will be foobar.remoteRef.key: foo: Tells ESO to look up the Vault secret at secret/foo.property: my-value: From that secret, only extract the field my-value.
Now, whenever the foo value changes in Vault, ESO will synchronize it into the secret eample-sync.