Injecting Vault Secrets into Kubernetes Pod Environment Variables
To inject Vault secrets into Kubernetes pod environment variables, we can use different ways. We can use the Vault Agent Sidecar, Kubernetes Init Containers, and the External Secrets Operator. Each way has its own method to safely get and inject secrets into our apps on Kubernetes. This means we can keep our sensitive information safe without putting it directly in our application code. This guide will help us understand these methods and how to use them well.
In this article, we will look at how HashiCorp Vault helps us manage secrets in Kubernetes. We will talk about some easy solutions to inject Vault secrets into Kubernetes pod environment variables. We will discuss the following topics:
- How to Use Vault Agent Sidecar to Inject Secrets into Pod Environment Variables
- How to Set Up Kubernetes to Use Vault for Secrets Injection
- How to Use Kubernetes Init Containers to Inject Vault Secrets
- How to Use External Secrets Operator for Injecting Vault Secrets
By the end of this article, we will understand better how to manage secrets safely in our Kubernetes environment.
What is the Role of HashiCorp Vault in Kubernetes Secrets Management?
HashiCorp Vault is a key tool for safely managing secrets in Kubernetes. It gives us a central place to store, access, and control sensitive data like API keys, passwords, and certificates. Let’s see how Vault works with Kubernetes for secrets management.
Dynamic Secrets: Vault can create secrets instantly for different services. This way, credentials are temporary. It lowers the risk of using long-lasting secrets.
Identity-Based Access: With Kubernetes service accounts, Vault can check if pods are allowed to access secrets. It uses role-based access control (RBAC). This means only the right applications can get sensitive information.
Encryption: Vault keeps secrets safe by encrypting them both when they are stored and when they are sent. This keeps the data secure all the time.
Audit Logging: Vault keeps detailed records of who accessed the secrets. This is very important for security checks and following rules.
Seamless Integration: With the Vault Kubernetes Auth method, applications in Kubernetes can log in and get secrets without needing help. This makes workflows automated.
Here is an example of how to set up Vault with Kubernetes:
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-auth
namespace: default
---
apiVersion: v1
kind: Pod
metadata:
name: my-app
namespace: default
spec:
serviceAccountName: vault-auth
containers:
- name: app
image: my-app-image
env:
- name: MY_SECRET
valueFrom:
secretKeyRef:
name: my-secret
key: secret-keyIn this example, we create a Kubernetes service account. This account can log in to HashiCorp Vault. The application pod takes secrets from Vault. This way, we manage sensitive data safely and effectively. For more info on managing secrets in Kubernetes, check this article on Kubernetes secrets management.
How to Use Vault Agent Sidecar to Inject Secrets into Pod Environment Variables?
To use the Vault Agent Sidecar for putting secrets into Kubernetes pod environment variables, we can follow these steps:
Set Up HashiCorp Vault:
First, we need to have HashiCorp Vault running. We also need to store the secrets we want in it.Create a Kubernetes Service Account:
We create a service account for the Vault Agent. This account helps the agent connect with the Kubernetes API.apiVersion: v1 kind: ServiceAccount metadata: name: vault-agentConfigure Vault with Kubernetes Authentication:
We enable Kubernetes authentication in Vault. Then we set it up to allow our service account to use it.vault auth enable kubernetes vault write auth/kubernetes/config \ token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ kubernetes_host="https://<K8S_API_SERVER>" \ kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crtNext, we create a role in Vault. This role connects the service account to the right policies for accessing secrets.
vault write auth/kubernetes/role/my-role \ bound_service_account_names=vault-agent \ bound_service_account_namespaces=default \ policies=my-policy \ ttl=24hCreate a Pod with Vault Agent Sidecar:
We define our pod specifications. We add the Vault Agent Sidecar container. This container gets secrets from Vault and shares them with the main application container.apiVersion: v1 kind: Pod metadata: name: my-app spec: serviceAccountName: vault-agent containers: - name: my-app-container image: my-app-image env: - name: MY_SECRET valueFrom: fieldRef: fieldPath: metadata.annotations['vault.hashicorp.com/my-secret'] - name: vault-agent image: vault:latest command: ["vault", "agent", "-config=/etc/vault/config.hcl"] volumeMounts: - name: vault-config mountPath: /etc/vault volumes: - name: vault-config configMap: name: vault-configCreate a ConfigMap for Vault Agent Configuration:
We make a ConfigMap that has the Vault Agent settings. This tells the agent how to work.apiVersion: v1 kind: ConfigMap metadata: name: vault-config data: config.hcl: | exit_after_auth = false pid_file = "/tmp/vault-agent.pid" auto_auth { method "kubernetes" { mount_path = "auth/kubernetes" config = { role = "my-role" } } sink "file" { config = { path = "/tmp/vault-token" } } } template { source = "/etc/vault/my-template.ctmpl" destination = "/home/my-app/.env" }Create a Template for Environment Variables:
We need to define a template file. This file will show how to change the secrets into environment variables.{{ with secret "secret/myapp" }} export MY_SECRET="{{ .Data.data.value }}" {{ end }}
When we deploy the pod, the Vault Agent Sidecar will connect to Vault. It will get the secrets and put them into the file we specified. Then our main application can use them as environment variables.
For more details on handling secrets in Kubernetes, check the article on managing secrets in Kubernetes securely.
How to Configure Kubernetes to Use Vault for Secrets Injection?
To set up Kubernetes with HashiCorp Vault for secrets injection, we can follow these easy steps.
- Install and Configure Vault:
First, we need to install HashiCorp Vault in our Kubernetes cluster. We can use Helm for simple installation.
Here is an example Helm command:
helm repo add hashicorp https://helm.releases.hashicorp.com helm install vault hashicorp/vault --set "server.dev.enabled=true"
- Enable Kubernetes Authentication in Vault:
Next, we log in to Vault and enable the Kubernetes auth method:
vault login <your-vault-token> vault auth enable kubernetes
- Configure Kubernetes Auth Method:
Now, we set the Kubernetes API server URL and the CA certificate:
vault write auth/kubernetes/config \ token_reviewer_jwt=<JWT_TOKEN> \ kubernetes_host=https://<KUBERNETES_API_SERVER> \ kubernetes_ca_cert=@/path/to/ca.crt
- Create a Role in Vault:
We need to create a role that shows which Kubernetes service accounts can access certain secrets:
vault write auth/kubernetes/role/my-role \ bound_service_account_names=my-service-account \ bound_service_account_namespaces=my-namespace \ policies=my-policy \ ttl=24h
- Define Vault Policies:
Now, we create a policy that allows access to the secrets we need:
path "secret/data/myapp/*" { capabilities = ["read"] }Then, we apply the policy:
vault policy write my-policy my-policy.hcl
- Inject Vault Secrets into Kubernetes Pods:
Next, we change our Pod or Deployment YAML to add the Vault agent as a sidecar container. Here is an example with a sidecar:
apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: replicas: 1 selector: matchLabels: app: myapp template: metadata: labels: app: myapp spec: serviceAccountName: my-service-account containers: - name: myapp image: myapp:latest env: - name: MY_SECRET valueFrom: secretKeyRef: name: myapp-secret key: secret-key - name: vault-agent image: vault:latest command: ["vault", "agent", "-config=/etc/vault/config.hcl"] volumeMounts: - name: vault-config mountPath: /etc/vault volumes: - name: vault-config configMap: name: vault-config
- Configure Environment Variables:
- Finally, we set environment variables in our application to get the secrets from the Vault agent.
This setup helps Kubernetes to securely get secrets from HashiCorp Vault and put them into our pods. It makes sure that sensitive data is handled correctly. For more details, we can check this article on managing secrets in Kubernetes.
How to Use Kubernetes Init Containers to Inject Vault Secrets?
We can use Kubernetes Init Containers to add HashiCorp Vault secrets into our application pods. We do this before the main application containers start. This method lets us securely get secrets while our application runs. We can set these secrets as environment variables for our application.
Step 1: Create a Kubernetes Secret
First, we need to save our Vault token or other important credentials in a Kubernetes Secret:
apiVersion: v1
kind: Secret
metadata:
name: vault-token
type: Opaque
data:
token: <base64_encoded_vault_token>Step 2: Define the Init Container
Next, we define an Init Container in our pod specification. This Init
Container will use a Vault client like vault-cli to get
secrets from Vault. It will store them in environment variables or
files.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
initContainers:
- name: vault-init
image: vault:latest
command: ['sh', '-c', 'vault login -token=${VAULT_TOKEN} && vault kv get -format=json secret/mysecret | jq -r .data.data | sed "s/^/export /" > /vault/secrets.sh']
env:
- name: VAULT_TOKEN
valueFrom:
secretKeyRef:
name: vault-token
key: token
volumeMounts:
- name: vault-secrets
mountPath: /vault
containers:
- name: my-app
image: my-app:latest
env:
- name: MY_SECRET
valueFrom:
configMapKeyRef:
name: my-config
key: mysecret
volumeMounts:
- name: vault-secrets
mountPath: /vault
volumes:
- name: vault-secrets
emptyDir: {}Step 3: Use the Injected Secrets
Now we can access the secrets in our main application container. We can do this through environment variables or from the files made by the Init Container. If we choose to export them in a script, we can source that script in our application container.
source /vault/secrets.shStep 4: Deploy the Application
Finally, we deploy our application by applying the Kubernetes manifest:
kubectl apply -f my-app-deployment.yamlThis makes sure that the Init Container runs before the main application container. It fetches and injects the needed Vault secrets securely into our Kubernetes pods.
For more tips on managing secrets in Kubernetes, you can check this article on managing secrets in Kubernetes securely.
How to Use External Secrets Operator for Injecting Vault Secrets
The External Secrets Operator (ESO) is a tool for Kubernetes. It helps us use secret management systems like HashiCorp Vault to handle secrets in Kubernetes. It makes it easier to put secrets into Kubernetes pods as environment variables or volumes.
Prerequisites
- We need a running Kubernetes cluster.
- We must have HashiCorp Vault installed and set up.
- We also need to install External Secrets Operator in our Kubernetes cluster.
Step 1: Install External Secrets Operator
We can install the External Secrets Operator with this command:
kubectl apply -f https://github.com/external-secrets/external-secrets/releases/latest/download/external-secrets-operator.yamlStep 2: Configure Vault
We should make sure our Vault has the right secrets. Also, we need to set up the right policies for the Kubernetes authentication method. Here is a simple policy for a secret:
# Sample Vault policy for secrets access
path "secret/data/myapp" {
capabilities = ["read"]
}
Step 3: Create a Kubernetes Secret Store
We need to define a ClusterSecretStore or
SecretStore. This tells the External Secrets Operator how
to connect to Vault. Here is an example of a
ClusterSecretStore:
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: my-vault-store
spec:
provider:
vault:
server: "https://vault.example.com"
path: "secret/data/myapp"
auth:
type: kubernetes
mountPath: "auth/kubernetes"
role: "my-app-role"
token: "your-k8s-token"Step 4: Create an External Secret
Next, we need to define an ExternalSecret. This resource
tells which secrets to get from Vault and how to put them into our
Kubernetes environment. Here is an example:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: myapp-secret
spec:
refreshInterval: 1h
secretStoreRef:
name: my-vault-store
kind: ClusterSecretStore
target:
name: myapp-config
creationPolicy: Owner
# Specify the type of Kubernetes secret to create
type: Opaque
data:
- secretKey: my-env-var
remoteRef:
key: secret/data/myapp
property: valueStep 5: Deploy Your Application
After we create the ExternalSecret, we can deploy our
application. We will use the generated secret in our pod specification.
Here is an example of a deployment that uses the secret as an
environment variable:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
env:
- name: MY_ENV_VAR
valueFrom:
secretKeyRef:
name: myapp-config
key: my-env-varConclusion
By using the External Secrets Operator, we can easily inject secrets from HashiCorp Vault into Kubernetes pod environment variables. This helps us keep our data safe and makes it easier to manage sensitive information in our Kubernetes apps. For more details, we can check how to manage secrets in Kubernetes securely.
Frequently Asked Questions
1. How can we securely manage Vault secrets in Kubernetes?
To manage Vault secrets securely in Kubernetes, we can use HashiCorp Vault with tools like the Vault Agent Sidecar, Kubernetes Init Containers, or External Secrets Operator. Each method helps us put secrets directly into our pod environment variables. This way, we keep sensitive data safe during our application lifecycle. For more detailed help, check out this article on managing secrets in Kubernetes.
2. What is the Vault Agent Sidecar, and how does it work?
The Vault Agent Sidecar runs next to our application containers in a Kubernetes pod. It helps us log in to Vault, get secrets, and put them into the application’s environment variables or files. This setup makes our secrets more secure. It keeps secrets out of our codebase and allows us to get them when we need. For a practical guide, look at our guide on using the Vault Agent Sidecar.
3. How do Kubernetes Init Containers help in secrets injection?
Kubernetes Init Containers are special containers that run before our main application containers in a pod. We can use them to get secrets from Vault and set them as environment variables or write them to files that our main application can reach. This way, we cleanly separate tasks and make sure secrets are ready before the application starts. Learn more about Kubernetes Init Containers in our article.
4. Can we use the External Secrets Operator for managing Vault secrets?
Yes, we can use the External Secrets Operator to bring Vault secrets into Kubernetes pods. This operator helps us manage secrets in Kubernetes by syncing them from outside secret management systems like HashiCorp Vault. This makes them available as Kubernetes Secrets or ConfigMaps. This method makes managing secrets easier and safer. For a full guide, check the External Secrets Operator documentation.
5. What are best practices for injecting Vault secrets into Kubernetes?
Best practices for injecting Vault secrets into Kubernetes include using the Vault Agent Sidecar or External Secrets Operator for dynamic secret management. We should not hardcode secrets in our application code and use Kubernetes RBAC to control who can access secrets. Also, we should always check our secret management practices to keep security strong. For more ideas, see our article on managing secrets in Kubernetes securely.