Secure Secret Management: Setting Up HashiCorp Vault on Kubernetes
Discover how to set up HashiCorp Vault on Kubernetes, integrating it with External Secrets to manage your application secrets securely.
Secure Secret Management: Setting Up HashiCorp Vault on Kubernetes
Section 1: Introduction to HashiCorp Vault on Kubernetes
HashiCorp Vault is a powerful tool for securely managing secrets and sensitive data. This guide walks you through setting up Vault on Kubernetes and integrating it with External Secrets to streamline secret management for your applications.
Section 2: Prerequisites
Before you begin, ensure you have the following:
- A Running Kubernetes Cluster: You’ll need access to a Kubernetes cluster.
- kubectl Installed and Configured: Make sure
kubectl
is installed and configured to interact with your cluster. - Helm Installed: Helm is required for deploying Vault and External Secrets. You can find installation instructions on the Helm website (https://helm.sh/docs/intro/install/).
Section 3: Adding the HashiCorp Helm Repository
HashiCorp provides a Helm chart for installing Vault. Add their repository to Helm:
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
This command adds the HashiCorp Helm repository and updates your local Helm chart index.
Section 4: Installing Vault Using Helm
Deploy Vault into your Kubernetes cluster using Helm:
helm install vault hashicorp/vault -n vault --create-namespace
Where:
vault
: The name of the Helm release.hashicorp/vault
: Specifies the Vault Helm chart from the HashiCorp repository.-n vault
: Deploys Vault in thevault
namespace.--create-namespace
: Creates thevault
namespace if it doesn’t exist.
Once deployed, Vault needs to be initialized and unsealed before it can be used.
Section 5: Initializing Vault
Vault must be initialized before it can store and manage secrets. Run the following command to initialize Vault:
kubectl -n vault exec -it vault-0 -- vault operator init
This command generates unseal keys and an initial root token. Important: Securely store these tokens, as they are crucial for accessing Vault.
You’ll see output similar to:
Unseal Key 1: <key1>
Unseal Key 2: <key2>
Unseal Key 3: <key3>
Initial Root Token: <root-token>
Section 6: Unsealing Vault
Vault operates in a “sealed” state by default. To make it operational, you need to “unseal” it using the unseal keys generated earlier. Enter the Vault pod and unseal it:
kubectl -n vault exec -it vault-0 -- sh
Then, run the following commands to unseal Vault:
vault operator unseal
<insert key1>
vault operator unseal
<insert key2>
vault operator unseal
<insert key3>
Paste each unseal key when prompted. Once all keys are entered, Vault will be unsealed and operational.
Section 7: Logging In to Vault
Log in to Vault using the initial root token:
vault login <INITIAL_ROOT_TOKEN>
Replace <INITIAL_ROOT_TOKEN>
with the token you saved earlier.
Section 8: Enabling a Secret Engine
Vault organizes secrets using secret engines. Enable the KV (Key-Value) secret engine:
vault secrets enable --version=2 --path=kv kv
Where:
--version=2
: Specifies version 2 of the KV engine.--path=kv
: Sets the mount path for the engine tokv
.
Section 9: Adding Secrets to Vault
Add secrets to Vault using the KV engine. For example:
vault kv put -mount=kv medium-blog adminUser=test
vault kv put -mount=kv medium-blog adminPass='password'
Where:
-mount=kv
: Refers to the KV engine enabled earlier.medium-blog
: The path under which the secrets are stored.adminUser
andadminPass
: Key-value pairs representing your secrets.
Repeat this process for all the secrets your application needs.
Section 10: Installing External Secrets Operator
External Secrets Operator bridges the gap between Kubernetes and external secret management systems, such as HashiCorp Vault. It syncs secrets from external systems into Kubernetes-native secrets.
Install External Secrets Operator in the external-secrets
namespace:
helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace
Section 11: Creating a Vault Token Secret in Kubernetes
External Secrets Operator needs a Vault token to authenticate with Vault. Create a Kubernetes secret with the token:
apiVersion: v1
data:
token: <your-token-base64>
kind: Secret
metadata:
name: vault-token
namespace: external-secrets
type: Opaque
Replace <your-token-base64>
with the Base64-encoded token (use echo -n "token" | base64
to generate it).
Save this file as vaultTokenSecret.yaml
and apply it:
kubectl -n external-secrets apply -f vaultTokenSecret.yaml
Section 12: Configuring External Secrets Operator to Access Vault
Create a ClusterSecretStore
resource to configure External Secrets Operator to communicate with Vault:
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: vault-backend-access
spec:
provider:
vault:
server: "https://vault.support.tools/"
path: "kv"
version: "v2"
auth:
tokenSecretRef:
name: "vault-token"
key: "token"
namespace: external-secrets
Where:
server
: The Vault server URL.path
: The KV engine path (kv
in this setup).auth.tokenSecretRef
: Points to the secret containing the Vault token.
Save this as clusterSecretStore.yaml
and apply it:
kubectl apply -f clusterSecretStore.yaml
Section 13: Verifying and Using Secrets
Create ExternalSecret
resources to sync Vault secrets into Kubernetes secrets. For example:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: medium-blog-secrets
namespace: medium-blog-ns
spec:
secretStoreRef:
name: vault-backend-access
kind: ClusterSecretStore
target:
name: medium-blog-k8s-secret
data:
- secretKey: ADMIN_USER
remoteRef:
key: kv/medium-blog
property: adminUser
- secretKey: ADMIN_PASS
remoteRef:
key: kv/medium-blog
property: adminPass
Apply this file, and External Secrets Operator will create an ExternalSecret
resource named medium-blog-secrets
and a Kubernetes secret named medium-blog-k8s-secret
in the medium-blog-ns
namespace with the values pulled from Vault.
Verify the resources:
kubectl get externalsecret -n medium-blog-ns -o yaml
kubectl get secret -n medium-blog-ns -o yaml
Section 14: Bonus: Exposing Vault with Ingress Using Traefik
To make Vault accessible externally, expose it using an Ingress. This ensures that Vault is accessible through a domain name (e.g., vault.support.tools
).
Step 1: Ensure Traefik is Deployed
Traefik is a popular Kubernetes Ingress Controller. If you don’t have Traefik installed, follow these steps:
Add the Traefik Helm Repository:
helm repo add traefik https://traefik.github.io/charts helm repo update
Install Traefik:
helm install traefik traefik/traefik --namespace traefik --create-namespace
Verify Installation:
kubectl get pods -n traefik
You should see pods like
traefik-<unique-id>
running successfully.
Step 2: Expose Vault Using IngressRoute
Create an IngressRoute resource to expose Vault using Traefik. Save the following configuration as vaultIngressRoute.yaml
:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: vault-ingressroute
namespace: vault
spec:
entryPoints:
- web
routes:
- match: Host(`vault.support.tools`)
kind: Rule
services:
- name: vault
port: 8200
scheme: http
Where:
entryPoints
:web
indicates the HTTP entry point. Modify towebsecure
for HTTPS.Host(
vault.support.tools)
: The domain that maps to the Vault service. Ensure this domain points to your Kubernetes cluster via DNS.services
:name
:vault
refers to the Vault service created by the Helm chart.port
:8200
is the default Vault port.
Step 3: Apply the IngressRoute
kubectl apply -f vaultIngressRoute.yaml
Step 4: Update DNS or Hosts File
Point your domain (vault.support.tools
) to the external IP of the Traefik LoadBalancer. If testing locally, edit your /etc/hosts
file:
<NODE-IP> vault.support.tools
Step 5: Access Vault
You should now be able to access Vault in your browser using http://vault.support.tools
.
Step 6: Secure with HTTPS (Optional)
For production environments, secure the Ingress with TLS.
- Configure a certificate (e.g., via Let’s Encrypt or a self-signed certificate).
- Update the Traefik entry point to
websecure
. - Modify the IngressRoute to include a
tls
section:
spec:
entryPoints:
- websecure
tls:
secretName: mysecret-cert
routes:
- match: Host(`vault.support.tools`)
kind: Rule
services:
- name: vault
port: 8200
scheme: http
This ensures secure communication with Vault over HTTPS.
Section 15: Wrapping Up
Congratulations! You have successfully set up HashiCorp Vault on Kubernetes, stored secrets, and integrated it with External Secrets for secure secret management in Kubernetes. This setup provides a robust foundation for securely managing application secrets.