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