Skip to main content

Chapter 5.2 - Secrets

Learning Objectives​

By the end of this chapter, you will be able to:

  • Understand what a Secret is and why to use it
  • Create Secrets in different ways
  • Use Secrets in your Pods securely
  • Understand the security limitations of Secrets
  • Apply best practices for secret management

Introduction​

Secrets are similar to ConfigMaps but are designed to store sensitive data such as passwords, API tokens, private keys, and certificates.

Important: Kubernetes Secrets are not encrypted by default. They are only base64-encoded.


What is a Secret?​

A Secret is a Kubernetes object that stores sensitive data. By default, Secrets are base64-encoded (not encrypted).

Secret Types​

Kubernetes supports several types of Secrets:

  • Opaque: Arbitrary data (default)
  • kubernetes.io/dockerconfigjson: Credentials for Docker registries
  • kubernetes.io/tls: TLS certificates
  • kubernetes.io/service-account-token: Service Account tokens

Why Use Secrets?​

Problems Without Secrets​

Problems:

  • Passwords hardcoded in the code
  • Risk of exposure in Git
  • Difficult to rotate
  • No centralized management

Advantages With Secrets​

Advantages:

  • Separated from application code
  • Centralized management
  • Easier rotation
  • Integration with external tools (Vault, etc.)

Creating Secrets​

Method 1: From Literals​

kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=secretpassword123

Method 2: From a File​

Create a password.txt file:

mysecretpassword
kubectl create secret generic db-secret \
--from-file=password=password.txt

Method 3: From a YAML File​

apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # base64 of "admin"
password: cGFzc3dvcmQxMjM= # base64 of "password123"

Important: Values in data must be base64-encoded.

To encode:

echo -n "admin" | base64
# Result: YWRtaW4=

Specialized Secret Types​

Docker Registry Secret​

To access a private Docker registry:

kubectl create secret docker-registry regcred \
--docker-server=docker.io \
--docker-username=myuser \
--docker-password=mypassword \
--docker-email=myuser@example.com

Usage in a Pod:

spec:
containers:
- name: app
image: private-registry.io/myapp:1.0
imagePullSecrets:
- name: regcred

TLS Secret​

For SSL/TLS certificates:

kubectl create secret tls tls-secret \
--cert=tls.crt \
--key=tls.key

Usage in Pods​

Method 1: Environment Variables (Single Key)​

apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password

Method 2: All Keys (envFrom)​

apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
envFrom:
- secretRef:
name: db-secret

Method 3: As a Volume (Files)​

apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: db-secret
defaultMode: 0400 # Permissions: read-only

Result: Each key becomes a file in /etc/secrets/ with the decoded value.


Secret Security​

Important Limitations​

Important:

  • Secrets are base64-encoded, not encrypted
  • Accessible to anyone with access to etcd
  • Visible with kubectl get secret -o yaml
  • Logs can expose secrets

Security Best Practices​

  1. Enable Encryption at Rest

Create an encryption-config.yaml file:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-secret>
- identity: {} # Allows decryption
  1. Use External Secrets Operator

To integrate with Vault, AWS Secrets Manager, etc.

  1. Restrictive RBAC

Limit access to Secrets with RBAC:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-secret"]
verbs: ["get"]
  1. Never Commit Secrets
  • Use .gitignore for secret files
  • Use secret management tools
  • Regular rotation

Complete Example​

Step 1: Create the Secret​

apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
database_url: cG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYjoxMjM0L215ZGI=
api_key: c2VjcmV0X2FwaV9rZXlfMTIzNDU2
jwt_secret: bXlfanN0X3NlY3JldF9rZXlfZm9yX3NpZ25pbmc=

Step 2: Use in a Deployment​

apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: my-app:1.0
envFrom:
- secretRef:
name: app-secrets
volumeMounts:
- name: certs
mountPath: /etc/ssl/certs
readOnly: true
volumes:
- name: certs
secret:
secretName: tls-secret
defaultMode: 0400

Useful Commands​

View a Secret (Encoded)​

kubectl get secret db-secret
kubectl describe secret db-secret
kubectl get secret db-secret -o yaml

Decode a Secret​

# View the decoded value
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d

Modify a Secret​

kubectl edit secret db-secret

Note: Values must be in base64 in the editor.

Delete a Secret​

kubectl delete secret db-secret

Secret Rotation​

Rotation Process​

Steps:

  1. Create a new Secret with a different name
  2. Update the Deployment to reference the new Secret
  3. Wait for Pods to restart
  4. Delete the old Secret

External Secrets Operator​

For advanced management with external tools:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-secret
spec:
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: db-secret
data:
- secretKey: password
remoteRef:
key: production/database/password

Summary​

In this chapter, you learned:

Secret: Kubernetes object for sensitive data (base64, not encrypted by default)
Types: Opaque, docker-registry, TLS, service-account-token
Creation: kubectl create, YAML with base64 values
Usage: Environment variables or volumes
Security: Enable encryption at rest, RBAC, External Secrets
Limitations: Base64 only, visible in etcd, logs
Rotation: Create new secret, update, delete old one


Next Steps​

Chapter 5.3: Injection into Pods
Chapter 5.4: Best Practices
Lab 5.2: Managing Secrets


Chapter created: December 2024