Docker Certified Associate Exam Course
Kubernetes
Secrets
Welcome to this lesson on Kubernetes Secrets. In this guide, we’ll refactor a simple Python web app that connects to MySQL and demonstrate how to replace hardcoded credentials with Kubernetes Secrets.
Warning
Hardcoding sensitive data like database passwords in your application is insecure. Always store secrets in a dedicated secret store rather than plain text files or code.
1. Application Overview
Here’s the original Flask application with hardcoded credentials:
import mysql.connector
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def main():
mysql.connector.connect(
host="mysql",
database="mysql",
user="root",
password="paswrd"
)
return render_template("hello.html", color=fetchcolor())
if __name__ == "__main__":
app.run(host="0.0.0.0", port="8080")
By externalizing configuration into ConfigMaps and Secrets, we improve security and flexibility.
2. Storing Non-sensitive Configuration
Use a ConfigMap for non-sensitive data such as hostnames and users:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_Host: mysql
DB_User: root
Avoid placing DB_Password
here—this belongs in a Secret.
3. Creating Kubernetes Secrets
There are two ways to create Secrets in Kubernetes:
Method | Command Pattern | Description |
---|---|---|
Imperative | kubectl create secret generic <name> --from-literal=<key>=<value> | Quick, ad-hoc creation from the CLI |
Declarative | Create a YAML manifest with base64-encoded values and apply via kubectl apply -f <manifest>.yaml | Version-controlled, repeatable deployment manifests |
3.1 Imperative Method
Generate a generic Secret directly:
kubectl create secret generic app-secret \
--from-literal=DB_Host=mysql \
--from-literal=DB_User=root \
--from-literal=DB_Password=paswrd
Or load from files:
kubectl create secret generic app-secret \
--from-file=DB_Host=./db_host.txt \
--from-file=DB_User=./db_user.txt \
--from-file=DB_Password=./db_password.txt
3.2 Declarative Method
Base64-encode each value:
echo -n 'mysql' | base64 # bXlzcWw= echo -n 'root' | base64 # cm9vdA== echo -n 'paswrd' | base64 # cGFzd3Jk
Create
app-secret.yaml
:apiVersion: v1 kind: Secret metadata: name: app-secret type: Opaque data: DB_Host: bXlzcWw= DB_User: cm9vdA== DB_Password: cGFzd3Jk
Apply the manifest:
kubectl apply -f app-secret.yaml
Note
The type: Opaque
is the default Secret type for arbitrary user-defined data.
Learn more in the Kubernetes Secrets documentation.
4. Viewing Secrets
- List all Secrets:
kubectl get secrets
- Describe a Secret (values are masked):
kubectl describe secret app-secret
- View encoded data in YAML:
kubectl get secret app-secret -o yaml
- Decode a specific value:
echo -n 'bXlzcWw=' | base64 --decode # mysql
5. Injecting Secrets into Pods
5.1 As Environment Variables
Inject all keys at once:
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp
spec:
containers:
- name: simple-webapp
image: simple-webapp:latest
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: app-secret
Or inject specific keys:
env:
- name: DB_Password
valueFrom:
secretKeyRef:
name: app-secret
key: DB_Password
5.2 As Files in a Volume
Mount the Secret as a read-only volume; each key becomes a file:
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp
spec:
containers:
- name: simple-webapp
image: simple-webapp:latest
volumeMounts:
- name: app-secret-volume
mountPath: /etc/secrets
readOnly: true
volumes:
- name: app-secret-volume
secret:
secretName: app-secret
Inside the container:
ls /etc/secrets
cat /etc/secrets/DB_Password
# paswrd
Links and References
Watch Video
Watch video content