How to Create a Secret in Kubernetes¶
This guide explains how to create and manage Secrets in Kubernetes to handle sensitive information like passwords, OAuth tokens, and SSH keys.
Prerequisites¶
- Running Kubernetes cluster
- kubectl installed and configured
- Basic understanding of Kubernetes resources
Types of Secrets¶
- Opaque (generic): Arbitrary user-defined data (default)
- Most commonly used type
- Suitable for passwords, keys, and configuration
-
Can store any kind of sensitive data
-
kubernetes.io/dockerconfigjson:
- Docker registry credentials
- Used for pulling images from private registries
-
Created with
kubectl create secret docker-registry -
kubernetes.io/service-account-token:
- Service account authentication tokens
- Automatically created for service accounts
-
Used for API authentication
-
kubernetes.io/tls:
- TLS certificates and private keys
- Used for securing ingress and services
-
Must contain tls.crt and tls.key
-
kubernetes.io/ssh-auth:
- SSH private keys
- Used for git operations or SSH authentication
- Created from SSH private key files
Creating Secrets¶
Method 1: From Files¶
# Create files containing secrets
echo -n 'admin' > ./username.txt
echo -n 'S3cret!' > ./password.txt
# Create secret from files
kubectl create secret generic db-credentials \
--from-file=./username.txt \
--from-file=./password.txt
Method 2: From Literal Values¶
# Create secret directly from command line
kubectl create secret generic api-credentials \
--from-literal=api-key=myapikey123 \
--from-literal=api-secret=mysecretkey456
Method 3: Using YAML¶
First, encode your secrets:
echo -n 'admin' | base64 # Output: YWRtaW4=
echo -n 'S3cret!' | base64 # Output: UzNjcmV0IQ==
Create secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4=
password: UzNjcmV0IQ==
Apply the secret:
kubectl apply -f secret.yaml
Using Secrets¶
1. As Environment Variables¶
apiVersion: v1
kind: Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: myapp-container
image: myapp:1.0
env:
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: db-credentials
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
2. As Mounted Files¶
apiVersion: v1
kind: Pod
metadata:
name: secret-vol-pod
spec:
containers:
- name: myapp-container
image: myapp:1.0
volumeMounts:
- name: secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secret-volume
secret:
secretName: db-credentials
Common Secret Types Examples¶
1. Docker Registry Credentials¶
kubectl create secret docker-registry regcred \
--docker-server=https://index.docker.io/v1/ \
--docker-username=your-username \
--docker-password=your-password \
--docker-email=your-email@domain.com
Using in Pod:
apiVersion: v1
kind: Pod
metadata:
name: private-image-pod
spec:
containers:
- name: private-app
image: private-registry/app:1.0
imagePullSecrets:
- name: regcred
2. TLS Secret¶
kubectl create secret tls tls-secret \
--cert=path/to/tls.cert \
--key=path/to/tls.key
Using in Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
tls:
- hosts:
- myapp.example.com
secretName: tls-secret
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
Production Secret Example¶
# production-secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: production-secrets
namespace: production
labels:
environment: production
app: myapp
type: Opaque
stringData: # Values will be automatically encoded
database-url: "postgresql://prod-db:5432/myapp"
database-user: "app_user"
database-password: "${DB_PASSWORD}" # Use environment variable
api-key: "${API_KEY}"
jwt-secret: "${JWT_SECRET}"
redis-url: "redis://redis-master:6379/0"
Best Practices¶
1. Security Fundamentals¶
- Never store secrets in version control
- Enable encryption at rest using
EncryptionConfiguration - Use namespaces to isolate secrets
- Implement strict RBAC policies
- Rotate secrets regularly (at least every 90 days)
- Use service accounts with minimal permissions
- Implement network policies to restrict secret access
Example Encryption Configuration:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
metadata:
name: encryption-config
spec:
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <32-byte-key>
- identity: {}
2. Secret Management¶
# Example RBAC for Secret Access
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"]
resourceNames: ["db-credentials"]
3. Mounting Secrets¶
- Mount as read-only
- Use specific paths
- Mount only required secrets
spec:
containers:
- name: app
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: app-secrets
defaultMode: 0400 # Read-only for owner
Secret Rotation¶
1. Manual Rotation¶
# Create new secret
kubectl create secret generic db-credentials-new \
--from-literal=username=admin \
--from-literal=password=newpassword
# Update deployment to use new secret
kubectl set env deployment/myapp \
DATABASE_PASSWORD=\$(kubectl get secret db-credentials-new -o jsonpath='{.data.password}' | base64 --decode)
2. Automated Rotation¶
Using Kubernetes Secrets Store CSI Driver:
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: aws-secrets
spec:
provider: aws
parameters:
objects: |
- objectName: "myapp-secret"
objectType: "secretsmanager"
Troubleshooting¶
Common Issues and Solutions¶
-
Secret Not Found
# Verify secret exists kubectl get secret secret-name kubectl describe secret secret-name -
Permission Issues
# Check RBAC permissions kubectl auth can-i get secrets kubectl auth can-i create secrets -
Mounting Issues
# Check pod events kubectl describe pod pod-name # Check pod logs kubectl logs pod-name
Security Considerations¶
1. Network Security¶
Implement NetworkPolicies to restrict access to pods that use secrets:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: secret-network-policy
namespace: production
spec:
podSelector:
matchLabels:
role: secret-consumer
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: authorized
ports:
- port: 443
protocol: TCP
egress:
- to:
- namespaceSelector:
matchLabels:
purpose: production
ports:
- port: 443
protocol: TCP
- Pod Security
apiVersion: v1 kind: Pod metadata: name: secure-pod spec: securityContext: runAsNonRoot: true runAsUser: 1000 containers: - name: app securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true
Next Steps¶
- Implement external secret management (HashiCorp Vault, AWS Secrets Manager)
- Set up automated secret rotation
- Implement secret encryption at rest
- Configure audit logging for secrets
- Study advanced security patterns