Skip to main content

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:

  1. The same image runs in different environments (dev, staging, production)
  2. Passwords should never be stored in code or container images
  3. 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.