Introduction
Sensitive information like API keys, database credentials, or SSH keys must be handled securely to protect your systems and data. Kubernetes Secrets provide a mechanism to manage such information effectively by decoupling sensitive data from application logic.
This article covers the fundamentals of Kubernetes Secrets, how to create and use them, and best practices for secure management. By the end, you'll be able to integrate Secrets into your applications securely and efficiently.
What Are Kubernetes Secrets?
A Kubernetes Secret is an object that stores sensitive data in key-value pairs. Unlike ConfigMaps, Secrets are designed specifically for confidential data, and their content is base64-encoded.
Why Use Secrets?
- Security: Secrets are not visible in plaintext in configurations or logs.
- Decoupling: Sensitive data is kept separate from application code and images.
- Dynamic Updates: Secrets can be updated without requiring a container image rebuild.
Types of Data Managed by Secrets
Common examples of data stored in Kubernetes Secrets:
- Database Credentials: Username and password for database access.
- API Keys: Access keys for third-party services.
- SSH Keys: Secure Shell keys for remote server access.
- TLS Certificates: Certificates and private keys for HTTPS communication.
- OAuth Tokens: Authentication tokens for services like GitHub or Google.
Creating a Secret in Kubernetes
1. Using the kubectl
Command
Create a secret using literal values:
kubectl create secret generic my-secret \
--from-literal=username=myuser \
--from-literal=password=mypassword
Verify the secret:
kubectl get secret my-secret -o yaml
2. Defining Secrets in a YAML File
Define a Secret in secret.yaml
:
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: bXl1c2Vy # Base64 encoded value of 'myuser'
password: bXlwYXNzd29yZA== # Base64 encoded value of 'mypassword'
Create the Secret:
kubectl apply -f secret.yaml
3. From a File
Create a file username.txt
with the content myuser
:
kubectl create secret generic file-secret --from-file=username=username.txt
Using a Secret in Pods and Deployments
1. Accessing Secrets as Environment Variables
Define a Pod using the Secret:
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: app-container
image: busybox
command: ["sh", "-c", "echo $DB_USERNAME && echo $DB_PASSWORD && sleep 3600"]
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: my-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-secret
key: password
restartPolicy: Never
Apply the Pod and view the output:
kubectl apply -f pod-env.yaml
kubectl logs secret-env-pod
2. Mounting Secrets as Volumes
Define a Pod that mounts the Secret as a volume:
apiVersion: v1
kind: Pod
metadata:
name: secret-volume-pod
spec:
containers:
- name: app-container
image: busybox
command: ["sh", "-c", "cat /etc/secret-volume/username && cat /etc/secret-volume/password && sleep 3600"]
volumeMounts:
- name: secret-volume
mountPath: /etc/secret-volume
volumes:
- name: secret-volume
secret:
secretName: my-secret
Apply the Pod and inspect the mounted files:
kubectl apply -f pod-volume.yaml
kubectl exec -it secret-volume-pod -- ls /etc/secret-volume
kubectl exec -it secret-volume-pod -- cat /etc/secret-volume/username
Managing Existing Secrets
Updating a Secret
To update a Secret, recreate it:
kubectl delete secret my-secret
kubectl create secret generic my-secret --from-literal=username=newuser --from-literal=password=newpassword
Rolling Updates
If a Deployment uses Secrets, updating the Secret will not trigger a Pod restart. To ensure changes take effect, manually restart the Pods:
kubectl rollout restart deployment my-deployment
Accessing Secrets in Applications
Secrets can be accessed programmatically using environment variables or mounted files. Here's an example in Python:
import os
username = os.getenv("DB_USERNAME")
password = os.getenv("DB_PASSWORD")
print(f"Username: {username}, Password: {password}")
Best Practices for Managing Secrets
- Encrypt Secrets at Rest: Use encryption mechanisms like Kubernetes Encryption at Rest.
- Use RBAC: Restrict access to Secrets using Role-Based Access Control (RBAC).
- Avoid Hardcoding: Never hardcode sensitive data in application code.
- Automate Secret Rotation: Use tools like HashiCorp Vault or AWS Secrets Manager for automatic rotation.
- Audit Access: Regularly audit access logs for Secrets.
- Namespace Isolation: Create Secrets in the same namespace as their consumers.
Hands-On Tutorial: Deploying a Sample Application
Step 1: Create a Secret
kubectl create secret generic sample-secret --from-literal=username=appuser --from-literal=password=apppassword
Step 2: Deploy a Sample App
Create a deployment.yaml
file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
spec:
replicas: 1
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: app-container
image: nginx
env:
- name: APP_USERNAME
valueFrom:
secretKeyRef:
name: sample-secret
key: username
Apply the Deployment:
kubectl apply -f deployment.yaml
Step 3: Verify the Secret
Access the Pod:
kubectl exec -it <pod-name> -- printenv | grep APP_USERNAME
Troubleshooting Common Issues
- Base64 Encoding Errors: Ensure all values in YAML files are base64-encoded.
- Access Denied: Check RBAC policies to ensure the Pod has access to the Secret.
- Missing Keys: Verify the key names in the Secret definition match those used in Pod specifications.
Conclusion
Kubernetes Secrets provide a secure and efficient way to manage sensitive information in containerized applications. By following the practices outlined in this guide, you can ensure the security and integrity of your applications while simplifying configuration management. Start incorporating Secrets into your Kubernetes projects today!
For further learning, refer to the official Kubernetes Secrets documentation.
Top comments (0)