Project Secrets into RKE2 Using External Secrets Operator and Azure Key Vault¶
This HOWTO shows how to project secrets from Azure Key Vault (AKV) into an RKE2 cluster using External Secrets Operator (ESO) in HybridOps.Studio.
You will:
- Create and name secrets in Azure Key Vault.
- Configure ESO to read from AKV.
- Define
ExternalSecretresources in Git. - Verify that Kubernetes
Secretobjects are created and used by workloads.
It aligns with:
- ADR-0202 – Adopt RKE2 as Primary Runtime for Platform and Applications
- ADR-0502 – Use External Secrets Operator with Azure Key Vault for Application Secrets
- Evidence 4 – Delivery Platform, GitOps and Cluster Operations
1. Objectives¶
By the end of this HOWTO you will be able to:
- Store application secrets centrally in Azure Key Vault.
- Configure ESO to access AKV securely.
- Represent secret needs declaratively via
ExternalSecretmanifests in Git. - Confirm that pods in RKE2 consume the projected Kubernetes
Secretwithout handling raw values in manifests.
2. Prerequisites¶
2.1 Platform¶
You should have:
- An RKE2 cluster as described in Evidence 4.
- External Secrets Operator installed and running in the cluster.
- Network connectivity from the cluster to Azure Key Vault endpoints.
2.2 Azure¶
- An Azure subscription.
- An Azure Key Vault instance created for HybridOps.Studio secrets.
- An Azure AD identity that ESO can use:
- Managed identity, or
- Service principal with access to Key Vault secrets.
2.3 Access and tools¶
kubectlconfigured for the RKE2 cluster.- Access to the Git repository containing your deployment manifests.
- Azure CLI or Portal access for Key Vault.
3. Phase 1 – Create a secret in Azure Key Vault¶
- Choose a secret name
Use a clear naming convention, for example:
netbox-db-password-
demo-api-jwt-secret -
Create the secret
Using Azure CLI (example):
az keyvault secret set --vault-name "<YOUR_KEYVAULT_NAME>" --name "netbox-db-password" --value "<STRONG_PASSWORD_VALUE>"
Or create it via the Azure Portal with the same name.
- Record the secret identifier
Note:
- Key Vault name
- Secret name
You will reference these from the ESO configuration.
4. Phase 2 – Configure ESO to access Azure Key Vault¶
If ESO is already configured for AKV in your environment, review and reuse the existing
SecretStoreorClusterSecretStorerather than creating duplicates.
- Create a Kubernetes Secret for credentials (if using client credentials)
For a service principal:
kubectl create secret generic akv-sp-credentials -n external-secrets --from-literal=client-id="<APP_ID>" --from-literal=client-secret="<APP_SECRET>" --from-literal=tenant-id="<TENANT_ID>"
Adjust the namespace to match where ESO expects credentials (for example, external-secrets).
If you use workload identity or managed identity, this Secret may not be necessary; follow ESO’s AKV authentication guidance instead.
- Define a SecretStore or ClusterSecretStore
Example ClusterSecretStore for AKV:
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: akv-hybridops
spec:
provider:
azurekv:
vaultUrl: "https://<YOUR_KEYVAULT_NAME>.vault.azure.net/"
authType: ServicePrincipal
tenantId:
valueFrom:
secretKeyRef:
name: akv-sp-credentials
namespace: external-secrets
key: tenant-id
clientId:
valueFrom:
secretKeyRef:
name: akv-sp-credentials
namespace: external-secrets
key: client-id
clientSecret:
valueFrom:
secretKeyRef:
name: akv-sp-credentials
namespace: external-secrets
key: client-secret
Apply it:
kubectl apply -f infra/rke2/secrets/clustersecretstore_akv-hybridops.yaml
Adjust the path to fit your repo structure.
-
Verify ESO and store status
-
Confirm ESO pods are running.
- Check that the
ClusterSecretStorereports a ready status in ESO logs or viakubectl describe.
5. Phase 3 – Define an ExternalSecret in Git¶
You will now declare which AKV secret should appear as a Kubernetes Secret in a specific namespace.
- Create a directory for application secrets
For example, for netbox:
mkdir -p deploy/netbox/secrets
- Create an ExternalSecret manifest
Example for NetBox DB password:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: netbox-db-password
namespace: netbox
spec:
refreshInterval: "1h"
secretStoreRef:
kind: ClusterSecretStore
name: akv-hybridops
target:
name: netbox-db-credentials
creationPolicy: Owner
data:
- secretKey: DB_PASSWORD
remoteRef:
key: "netbox-db-password"
Notes:
remoteRef.keyis the AKV secret name.target.nameis the KubernetesSecretthat will be created.-
data.secretKeyis the key inside the KubernetesSecret(for example,DB_PASSWORD). -
Commit and push
Commit deploy/netbox/secrets/externalsecret-netbox-db-password.yaml and push to the repo.
6. Phase 4 – Apply and validate in RKE2¶
If you use GitOps (Argo CD):
- Ensure the path
deploy/netbox/secrets/is included in the Application’s manifest path or Kustomize configuration. - Allow Argo CD to sync the changes.
If you are applying directly (for a lab scenario):
kubectl apply -f deploy/netbox/secrets/externalsecret-netbox-db-password.yaml
Then validate:
- Check ExternalSecret status
kubectl get externalsecret -n netbox
kubectl describe externalsecret netbox-db-password -n netbox
- Check the projected Kubernetes Secret
kubectl get secret netbox-db-credentials -n netbox
kubectl get secret netbox-db-credentials -n netbox -o yaml
Confirm that:
- The
Secretexists. -
It has a
DB_PASSWORDkey (value should be base64 encoded; do not decode or log it in plain text in shared artefacts). -
Capture evidence
Create a proof folder:
mkdir -p output/artifacts/secrets/eso-akv-netbox-<date>/
Store:
- Redacted
kubectloutput. - Screenshots, if appropriate.
7. Phase 5 – Wire the Secret into the workload¶
Update the NetBox deployment (or another application) to consume the netbox-db-credentials Secret.
Example (fragment):
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: netbox-db-credentials
key: DB_PASSWORD
- Commit and push the deployment manifest change.
- Allow Argo CD to sync or apply directly in a lab context.
- Confirm the application starts correctly using the secret from AKV via ESO.
8. Phase 6 – Rotate the secret¶
To demonstrate rotation:
- Update the secret in Azure Key Vault
az keyvault secret set --vault-name "<YOUR_KEYVAULT_NAME>" --name "netbox-db-password" --value "<NEW_STRONG_PASSWORD>"
- Wait for ESO refresh
ESO will reconcile on the defined refreshInterval or when forced.
-
Verify the Kubernetes Secret changed
-
Check the
resourceVersionor annotations onnetbox-db-credentials. -
Avoid printing plaintext values; confirm via metadata and application behaviour (for example, app restarts or reconnects successfully if needed).
-
Capture rotation evidence
Store relevant kubectl outputs and short notes under the same output/artifacts/secrets/eso-akv-netbox-<date>/ folder.
9. Validation checklist¶
- [ ] Azure Key Vault secret created with a clear name (for example,
netbox-db-password). - [ ] ESO is installed and a
SecretStoreorClusterSecretStorefor AKV is configured and ready. - [ ] An
ExternalSecretmanifest in Git references the AKV secret and desired KubernetesSecret. - [ ] A Kubernetes
Secretis created in the target namespace and used by the application deployment. - [ ] The application runs correctly using the projected secret.
- [ ] Secret rotation in AKV leads to an updated Kubernetes
Secretwithout Git changes. - [ ] Proof artefacts stored under
output/artifacts/secrets/eso-akv-<app>-<date>/.
References¶
- ADR-0202 – Adopt RKE2 as Primary Runtime for Platform and Applications
- ADR-0502 – Use External Secrets Operator with Azure Key Vault for Application Secrets
- Evidence 4 – Delivery Platform, GitOps and Cluster Operations
Maintainer: HybridOps.Studio
License: MIT-0 for code, CC-BY-4.0 for documentation