You’ve got a bunch of sensitive stuff like API keys, database passwords, and certificates floating around in your Kubernetes applications. Keeping those safe is a big deal. You could try stuffing them into Kubernetes Secrets, but that gets complicated quickly, especially when you have lots of them or need to manage them across different environments. That’s where HashiCorp Vault comes in.
Integrating Vault with Kubernetes can make managing your secrets a whole lot more streamlined and secure.
Let’s walk through how to do it.
Let’s be honest, the default Kubernetes Secret object is handy for simple cases. You can base64 encode your sensitive data and store it. But as your applications grow and your security needs become more sophisticated, you’ll hit some limitations.
The Limitations of Native Kubernetes Secrets
Kubernetes Secrets are, at their core, just base64 encoded data stored within the Kubernetes API. This means:
- Limited Encryption: By default, secrets are stored encrypted at rest in etcd, but this is Kubernetes’ own encryption at rest mechanism. It’s good, but it doesn’t offer the fine-grained control or advanced features you might need.
- No Dynamic Secrets: You have to manually create and update secrets. If a database user needs to be rotated, you’re doing it manually.
- Auditing Challenges: While Kubernetes has audit logs, tracking specific secret access and usage across your cluster can be a fragmented experience.
- Complexity at Scale: Managing hundreds or thousands of secrets across multiple clusters, teams, and environments becomes a significant operational burden. Who has access to what? How do you rotate them?
Vault’s Core Benefits for Secret Management
HashiCorp Vault offers a more robust and centralized approach. It acts as a dedicated secrets management system with features specifically designed for dynamic and secure secret handling.
- Centralized Secrets Management: One place to manage all your secrets, regardless of where your applications are running.
- Dynamic Secrets: Vault can generate secrets on demand. Think temporary database credentials, short-lived TLS certificates, or API keys that expire automatically.
- Advanced Encryption: Strong encryption for secrets at rest and in transit, with configurable encryption keys.
- Auditing and Policy Control: Comprehensive audit logs track every access and operation. Fine-grained policies dictate who or what can access which secrets.
- Secret Leasing and Renewal: Secrets can be issued with a Time-To-Live (TTL), automatically revoking them when the lease expires. Applications can renew leases if they still need access.
- Identity-Based Access: Vault integrates with various identity providers (like Kubernetes Service Accounts, cloud IAM, LDAP) to authenticate and authorize access to secrets.
In the realm of securing sensitive information within Kubernetes, the article “Managing Secrets in Kubernetes: A Step-by-Step Guide to HashiCorp Vault Integration” provides invaluable insights. For those looking to enhance their presentation skills while discussing such technical topics, you might find the article on the best software for presentations in 2023 particularly useful. This resource offers a comprehensive overview of tools that can elevate your presentation game, ensuring that your audience remains engaged and informed. You can read more about it here: best software for presentation in 2023.
Key Takeaways
- Clear communication is essential for effective teamwork
- Active listening is crucial for understanding team members’ perspectives
- Setting clear goals and expectations helps to keep the team focused
- Regular feedback and open communication can help address any issues early on
- Celebrating achievements and milestones can boost team morale and motivation
Setting Up HashiCorp Vault in Kubernetes
Before you can integrate Vault with Kubernetes, you need to have a running Vault instance. While you could run Vault outside your Kubernetes cluster, it’s often most convenient and secure to run it inside the cluster itself, especially for applications running in that same cluster.
Installing Vault using Helm
The easiest and most recommended way to get Vault up and running in Kubernetes is by using its official Helm chart. Helm is a package manager for Kubernetes, making deployment and management much simpler.
- Add the HashiCorp Helm Repository:
“`bash
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
“`
- Create a Namespace for Vault: It’s good practice to isolate Vault.
“`bash
kubectl create namespace vault
“`
- Install Vault: You’ll want to configure Vault for production. This involves setting up storage, TLS, and replication. For a basic setup, you can use something like this (but always review and adjust for production):
“`bash
helm install vault hashicorp/vault \
–namespace vault \
–values – < server: dataStorage: enabled: true size: 10Gi # Adjust as needed ha: enabled: true replicas: 3 # Recommended for HA dev: enabled: false # For production, disable dev mode tlsDisable: false # Ensure TLS is enabled for production ui: enabled: true serviceType: ClusterIP EOF “` “`bash kubectl get pods -n vault “` Wait for all Vault pods to be in a When Vault starts for the first time, it needs to be initialized and unsealed. “`bash kubectl exec -n vault vault-0 — vault operator init -tls-skip-verify > vault_init.txt “` This command will output something like: “`bash kubectl exec -n vault vault-0 — vault operator unseal kubectl exec -n vault vault-0 — vault operator unseal kubectl exec -n vault vault-0 — vault operator unseal “` You can check the status with: “`bash kubectl exec -n vault vault-0 — vault status “` Once unsealed, the status will change. This is the crucial step that allows your Kubernetes applications to authenticate with Vault. Vault uses a “secrets engine” for this purpose. “`bash kubectl exec -n vault vault-0 — vault secrets enable \ -path=kubernetes \ -community=true \ -description=”Kubernetes Auth” \ auth “` This command enables the “`bash kubectl cluster-info | grep ‘Kubernetes control plane’ | awk ‘/http/ {print $2}’ “` This will give you something like “`bash kubectl get secret -n default “` You might need to find the correct secret that holds the CA certificate for your cluster. Often, it’s in the “`bash VAULT_ADDR=”http://vault.vault.svc. cluster. local:8200″ # Or your Vault service address K8S_API_URL=”https:// K8S_CA_CERT_PATH=”./ca.crt” vault write auth/kubernetes/config \ token_reviewer_jwt=”$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)” \ kubernetes_host=”$K8S_API_URL” \ kubernetes_ca_cert=@”$K8S_CA_CERT_PATH” \ issuer=”https://kubernetes.default.svc.cluster.local” # Adjust if your issuer is different “` Now that Vault is configured to trust Kubernetes Service Accounts, you need to define which Service Accounts can access which secrets. This is done through Vault policies and role bindings. Policies in Vault define what actions (read, write, list, delete) are allowed on specific paths within Vault.Other production-ready configurations would go here, e.g.,
ingress:
enabled: true
hostname: vault.example.com
tlsSpec:
secretName: vault-tls-secret
If ingress is enabled above, you might configure it here too.
dataStorage: Configures persistent storage for Vault. You’ll need this for production.ha: Enables High Availability, crucial for production to avoid single points of failure.dev.enabled: false: Disables the development mode, which is insecure and not for production.tlsDisable: false: Ensures Vault is configured with TLS. You’ll typically manage TLS certificates for Vault itself, either through Kubernetes Ingress or by providing your own.ui.enabled: Enables the Vault UI, which is very helpful for initial setup and management.
Running state.Initializing and Unsealing Vault
Example for unsealing with 3 keys (replace key values)
Configuring Vault for Kubernetes Authentication
kubernetes auth method at the path kubernetes/.
https://192.168.1.100:6443.
kube-system namespace, named something like kubernetes-ca. If you’re unsure, kubectl get secrets -n kube-system and look for a CA certificate.
Replace with your actual API server URL and the path to your ca.crt file
Login to Vault if needed (using your root token)
export VAULT_TOKEN=”your_root_token”
Configure the kubernetes auth method
token_reviewer_jwt: This is the JWT token of the Service Account that Vault will use to authenticate with the Kubernetes API. By default, when Vault is running inside Kubernetes, it has access to its own Service Account token in /var/run/secrets/kubernetes.io/serviceaccount/token.kubernetes_host: The URL of your Kubernetes API server.kubernetes_ca_cert: The CA certificate of your Kubernetes API server.issuer: A URL that Vault uses to verify the issuer of Kubernetes tokens. This should typically match your cluster’s issuer.Granting Kubernetes Service Accounts Access to Vault

Creating a Vault Policy for Secret Access
“`bash
Example policy content
cat <
path “secret/data/myapp/*” {
capabilities = [“read”, “list”]
}
path “kv/data/myapp/*” { # If using the newer KV v2 engine
capabilities = [“read”, “list”]
}
EOF
Write the policy to Vault
vault policy write app-read-policy app-read-policy.hcl
“`
- We’re assuming you’ll be storing your application’s secrets under the
secret/data/myapp/path (for KV v1) orkv/data/myapp/(for KV v2). You can usevault kv enable-path secret/orvault secrets enable -path=kv kvto set up the KV secrets engine. capabilities:readallows fetching data,listallows listing available secrets under a path.
Creating a Vault Role for Kubernetes Authentication
A Vault “role” links a Kubernetes Service Account (or other identity) to a Vault policy.
- Create a Kubernetes Auth Role:
“`bash
Replace ‘default’ with the namespace your app runs in
Replace ‘my-app-sa’ with your application’s Service Account name
Replace ‘app-read-policy’ with the name of the Vault policy you created
vault write auth/kubernetes/role/my-app-role \
bound_service_account_names=”my-app-sa” \
bound_service_account_namespaces=”default” \
policies=”app-read-policy” \
ttl=24h # Optional: How long a token is valid for.
Shorter is generally better.
“`
bound_service_account_names: Specifies which Kubernetes Service Account(s) this role applies to.bound_service_account_namespaces: Specifies which Kubernetes Namespace(s) the Service Account must reside in.policies: The Vault policy (or policies) to grant to authenticated Service Accounts matching the bounds.
Integrating Your Application with Vault

Now that Vault is set up and configured, your applications running in Kubernetes need to be able to request secrets from it.
The Vault Agent Injector (Recommended)
The most seamless way to integrate Vault is by using the Vault Agent Injector. This is a Kubernetes admission controller that automatically injects a Vault Agent sidecar container into your pods. This agent handles authentication, fetches secrets, and makes them available to your application.
- Enable the Vault Agent Injector: The Helm chart for Vault typically deploys the injector. You’ll need to ensure it’s enabled and configured. Look for
injector.enabledand related settings in yourhelm installorhelm upgradecommand.
- Annotate Your Pods/Deployments: To tell the injector which pods to inject into, you annotate your Deployment, Pod, or StatefulSet.
“`yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
annotations:
vault.hashicorp.com/agent-inject: “true”
Point to the Vault role created earlier
vault.hashicorp.com/role: “my-app-role”
Specify which secrets to mount and where
vault.hashicorp.com/secret-volumes: “kv/data/myapp/db-credentials,secret/data/myapp/api-key”
Optional: Specify mount path for secrets if not default
vault.hashicorp.com/secret-mount-path: “/etc/secrets”
Optional: specify the KV version if not the default
vault.hashicorp.com/kv-v2-enabled: “true”
… rest of your deployment spec
“`
vault.hashicorp.com/agent-inject: "true": This annotation tells the injector to proceed with injecting the sidecar.vault.hashicorp.com/role: "my-app-role": This links the pod to the Vault role you previously created, ensuring it uses the correct authentication and policy.vault.hashicorp.com/secret-volumes: This is where you specify the actual secrets you want to retrieve from Vault. You provide the path within Vault and the name you want the secret file to have. You can list multiple secrets separated by commas.vault.hashicorp.com/secret-mount-path: This defines the directory where the secrets will be mounted within the application container. The default is/vault/secrets.vault.hashicorp.com/kv-v2-enabled: "true": Explicitly tells the injector you’re using the KV v2 secrets engine. If you don’t specify this and are using KV v2, it might assume KV v1.
- Application Container: Your application container will then find its secrets as files within the specified
secret-mount-path. For example, if you requestedkv/data/myapp/db-credentials, the secrets would be available in/etc/secrets/db-credentials(or/vault/secrets/db-credentialsif you didn’t specify a custom mount path).
Manually Fetching Secrets (Less Recommended for Production)
While the injector is preferred, you can also manually fetch secrets from within your application using the Vault API or a Vault client library.
- Configure Kubernetes Service Account for Vault Authentication:
You need to create a Service Account in Kubernetes and then bind it to a Vault role as described earlier.
“`bash
In Kubernetes
kubectl create serviceaccount my-app-sa -n default
“`
Then, create the Vault role binding as shown in the previous section.
- Provide Vault Address to Your Application: Your application needs to know where to find the Vault server. This is often done via environment variables.
- Authenticate with Vault: Your application will need to get its Kubernetes Service Account token and use it to authenticate with Vault.
“`go
// Example using HashiCorp Vault Go Client
import (
“io/ioutil”
“os”
vaultapi “github.com/hashicorp/vault/api”
)
// …
vaultAddr := os.Getenv(“VAULT_ADDR”) // e.g., “http://vault.vault.svc.cluster.local:8200”
client, err := vaultapi.NewClient(&vaultapi.Config{Address: vaultAddr})
if err != nil {
// handle error
}
// Read Kubernetes Service Account token
k8sToken, err := ioutil.ReadFile(“/var/run/secrets/kubernetes.io/serviceaccount/token”)
if err != nil {
// handle error
}
// Authenticate using Kubernetes auth method
authPath := “auth/kubernetes/login”
loginData := map[string]interface{}{
“jwt”: string(k8sToken),
“role”: “my-app-role”, // The Vault role name
}
resp, err := client.Logical().Write(authPath, loginData)
if err != nil {
// handle error
}
// Get the Vault token from the response
clientToken := resp.Auth.ClientToken
client.SetToken(clientToken)
// Now you can use the client to read secrets
“`
- Read Secrets: Once authenticated, you can read secrets from Vault.
“`go
// Example reading a secret
secret, err := client.Logical().Read(“secret/data/myapp/db-credentials”)
if err != nil {
// handle error
}
// Access secret data, e.g., secret.Data[“data”][“username”]
“`
In the realm of Kubernetes security, managing sensitive information is crucial, and integrating HashiCorp Vault can significantly enhance your approach. For those looking to explore additional tools that can aid in managing secrets effectively, you might find it helpful to read about the best free software for voice recording, which can be a useful resource for capturing important meetings or discussions related to your Kubernetes projects. You can check it out here. This combination of tools can streamline your workflow while ensuring that your secrets remain secure.
Managing Secrets Lifecycle and Rotation
“`html
| Metrics | Value |
|---|---|
| Number of Secrets Managed | 500 |
| Number of Kubernetes Clusters Integrated | 10 |
| Number of Vault Policies Defined | 20 |
| Number of Access Control Rules Implemented | 100 |
“`
Vault isn’t just about storing secrets; it’s about managing their entire lifecycle.
Dynamic Secrets Generation
This is where Vault truly shines. Instead of storing static credentials, Vault can generate them on demand.
- Enable Dynamic Secrets Engines: Vault has specific engines for generating dynamic secrets, such as:
- Database Secrets Engine: For generating temporary database credentials.
- AWS Secrets Engine: For generating temporary IAM user credentials.
- PKI Secrets Engine: For generating short-lived TLS certificates.
- Configure Dynamic Secret Roles: You create roles within these engines that define the parameters for generated secrets (e.g., database username format, password complexity, lease duration, allowed roles/permissions).
- Example (PostgreSQL Database):
“`bash
Assuming you have the database secrets engine enabled at ‘database’
vault write database/config/my-pg-db \
plugin_name=”postgresql-database-plugin” \
allowed_roles=”my-app-db-role” \
connection_urls=”postgresql://vault:vault-password@pg-host:5432/mydatabase” \
username=”vault” \
password=”vault-password”
vault write database/roles/my-app-db-role \
db_name=”my-pg-db” \
creation_statements=”CREATE USER {{name}} WITH PASSWORD ‘{{password}}’ VALID UNTIL ‘{{ttl}}’; GRANT CONNECT ON DATABASE mydatabase TO {{name}};” \
default_ttl=”10m” \
max_ttl=”30m”
“`
This configures Vault to talk to your PostgreSQL instance and defines a role that can create users with specific permissions and TTLs.
- Application Integration: Your application authenticates with Vault (as shown previously) and then requests a credential for the
my-app-db-role. Vault generates a username and password, grants it a lease, and returns it. The application uses these credentials to connect to the database. When the lease expires, Vault automatically revokes the credential. The application can also renew the lease if it needs to continue using the credential.
Secret Rotation and Renewal
- Automatic Rotation: For dynamic secrets, rotation is handled by Vault based on the defined TTLs and renewal policies.
- Manual Rotation: For static secrets (those not generated dynamically), you’ll still need a process for rotation. Vault’s audit logs and policies can help enforce rotation requirements, but the actual secret update might need an external automation or manual intervention.
- Application Renewal: When using the Vault Agent Injector or client libraries, applications can be programmed to detect when a secret’s lease is nearing expiration and request a renewal from Vault, preventing unexpected access failures.
Advanced Considerations and Best Practices
As you move beyond basic integration, there are several advanced topics and best practices to keep in mind.
Centralized Auditing and Monitoring
- Vault Audit Devices: Configure Vault to send audit logs to various destinations (file, syslog, Kafka, Splunk, etc.). This is crucial for compliance and security investigations.
- Kubernetes Audit Logs: Complement Vault’s logs with Kubernetes audit logs to correlate access attempts and understand the full picture of what’s happening in your cluster.
- Monitoring Vault: Set up Prometheus metrics for Vault and monitor its health, performance, and key statistics.
Multi-Cluster and Multi-Datacenter Deployments
- Vault Replication: For high availability across multiple data centers or regions, configure Vault replication. This ensures that secrets are available even if one datacenter is down.
- Kubernetes Multi-Cluster: When managing secrets across multiple Kubernetes clusters, each cluster can authenticate with a single, replicated Vault instance. The Vault Agent Injector and Kubernetes auth method work well in this scenario.
Secure Storage Backend for Vault
- Production Storage: For production, always use a robust storage backend for Vault, such as Consul, integrated storage (Raft), or cloud provider-specific storage solutions. Avoid
insecurestorage. - Encryption at Rest: Ensure your storage backend is also configured with encryption at rest, adding another layer of security.
Least Privilege Principle
- Fine-Grained Policies: Always apply the principle of least privilege. Grant only the necessary permissions to Service Accounts and roles. Avoid using broad wildcards in Vault policies unless absolutely necessary.
- Dedicated Roles: Create specific roles for each application or team, rather than a single super-role.
Managing Vault Itself
- Root Token Security: Secure your Vault root token. Store it offline in a password manager or secure vault. Use it only for initial setup and critical administration tasks.
- Unseal Key Management: Distribute unseal keys securely among trusted individuals or systems. Consider automated unsealing solutions if your operational model supports it.
- Regular Backups: Regularly back up your Vault data and ensure you have a tested recovery procedure.
Integrating HashiCorp Vault with Kubernetes provides a powerful and secure way to manage your sensitive credentials. By following these steps, you can move from basic Kubernetes Secrets to a dynamic, auditable, and highly secure secrets management system that scales with your applications. Remember that security is an ongoing process, so regularly review your Vault configuration, policies, and audit logs.
FAQs
What is Kubernetes?
Kubernetes is an open-source platform designed to automate deploying, scaling, and operating application containers.
What is HashiCorp Vault?
HashiCorp Vault is a tool for securely accessing and managing secrets. It provides a centralized place to store sensitive data such as API keys, passwords, and certificates.
Why integrate HashiCorp Vault with Kubernetes?
Integrating HashiCorp Vault with Kubernetes allows for secure management and distribution of secrets within a Kubernetes environment. This integration helps to ensure that sensitive data is protected and accessed only by authorized applications and users.
What are the benefits of managing secrets in Kubernetes with HashiCorp Vault?
Managing secrets in Kubernetes with HashiCorp Vault provides benefits such as centralized secret management, dynamic secret generation, audit logging, and fine-grained access control. This helps to enhance security and compliance within Kubernetes deployments.
What are the steps for integrating HashiCorp Vault with Kubernetes?
The steps for integrating HashiCorp Vault with Kubernetes typically involve installing and configuring the Vault Kubernetes Auth method, creating policies and roles for Kubernetes service accounts, and enabling applications running in Kubernetes to access secrets from Vault.

