Secrets and ConfigMaps
What You Will Learn
- How applications get their configuration in Kubernetes
- The difference between Secrets and ConfigMaps
- How Junovy manages secrets with Vault and SOPS
The Problem
Applications need configuration to run. A database needs a password. A web app needs to know its public URL. An email service needs SMTP credentials. You cannot bake these values into the container image because:
- The same image runs in different environments (dev, staging, production)
- Passwords should never be stored in code or container images
- Configuration changes more often than code
Kubernetes solves this with two objects: ConfigMaps and Secrets.
ConfigMaps: Non-Sensitive Configuration
A ConfigMap holds configuration that is not secret. Things like:
- Application URLs
- Feature flags
- Log levels
apiVersion: v1
kind: ConfigMap
metadata:
name: app-settings
namespace: hst-my-client
data:
APP_URL: "https://app.my-client.junovy.com"
LOG_LEVEL: "info"
TIMEZONE: "Europe/Amsterdam"
Secrets: Sensitive Configuration
A Secret holds sensitive data like passwords, API keys, and certificates. Secrets are base64-encoded in Kubernetes (not encrypted by default, which is why we use Vault).
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: hst-my-client
type: Opaque
stringData:
DB_USERNAME: "bookstack"
DB_PASSWORD: "super-secret-password" # in practice, never write passwords in plain YAML
How Apps Use Them
Both ConfigMaps and Secrets are injected into Pods as environment variables or mounted as files:
# Inside a Pod spec (part of a Deployment)
containers:
- name: my-app
image: my-app:v1.0.0
envFrom:
- configMapRef:
name: app-settings # all keys from ConfigMap become env vars
- secretRef:
name: db-credentials # all keys from Secret become env vars
The app then reads DB_PASSWORD as a normal environment variable. It does not know or care whether it came from a Secret, a ConfigMap, or the operating system.
ConfigMap vs Secret: When to Use Which
| Data Type | Use | Example |
|---|---|---|
| Public URLs, settings | ConfigMap | APP_URL, LOG_LEVEL |
| Passwords, tokens, keys | Secret | DB_PASSWORD, API_KEY |
| TLS certificates | Secret (type: kubernetes.io/tls) |
HTTPS certificates |
Rule of thumb: if you would not want someone to see it in a screenshot, it is a Secret.
How Junovy Creates Secrets (Preview)
At Junovy, you almost never write Secret YAML by hand. Instead, you use one of two systems:
| System | How It Works | Status |
|---|---|---|
| Vault + External Secrets | Secrets are stored in HashiCorp Vault. An ExternalSecret resource tells Kubernetes to pull them in automatically. | Preferred (new secrets) |
| SOPS | Secrets are encrypted in Git files using Age keys. Flux decrypts them during deployment. | Legacy (being migrated) |
You will learn both systems in detail in Chapter 7. For now, just know that secrets are managed carefully and never stored as plain text in Git.
Key Takeaways
- ConfigMaps hold non-sensitive settings; Secrets hold sensitive data like passwords
- Both are injected into Pods as environment variables
- Junovy uses Vault + External Secrets (preferred) or SOPS (legacy) to manage secrets safely
What Is Next
Next up: What Is GitOps (Chapter 4) where you will learn how changes get from Git to the cluster automatically.