ConfigMaps & Secrets
Understanding Kubernetes configuration and secrets management
Configuration Management
Kubernetes provides ConfigMaps and Secrets to decouple configuration from pod specifications. This separation of concerns allows you to change application configuration without rebuilding container images, making your applications more portable and easier to manage across different environments (development, staging, production).
ConfigMaps
ConfigMaps store non-confidential configuration data in key-value pairs. They can contain entire configuration files or individual properties, and are suitable for environment-specific settings, configuration files, command-line arguments, and other non-sensitive configuration data.
Basic ConfigMap
You can create ConfigMaps using the kubectl command:
Using ConfigMaps
ConfigMaps can be consumed by pods in several ways: as environment variables, as command-line arguments, or as configuration files in a volume.
Each method has its use cases:
- Environment variables: Simple configurations easily accessed by applications
- Command-line arguments: Dynamic application configuration at startup
- Volume mounts: For applications that need to read configuration files
Secrets
Secrets are similar to ConfigMaps but are specifically designed for storing sensitive information such as passwords, OAuth tokens, and SSH keys. Kubernetes provides additional security measures for Secrets, although they should be used in conjunction with other security controls for production environments.
Creating Secrets
You can create Secrets using kubectl:
For production environments, consider integration with external secret management systems like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault.
Using Secrets
Secrets can be used in pods similar to ConfigMaps, but with additional security considerations.
Security considerations:
- Secrets are stored unencrypted by default in etcd
- Anyone with API access can retrieve or modify secrets
- Anyone with access to the pods can view secrets
- Secret data is exposed to any container in a pod that requests it
For production, consider:
- Enabling encryption at rest for etcd
- Using RBAC to restrict secret access
- Using external secret management systems
- Implementing proper pod security policies
Configuration Best Practices
- Keep configurations separate from code
- Enables independent updates to configuration without code changes
- Supports the Twelve-Factor App methodology
- Allows different configurations per environment
- Use meaningful names
- Follow a consistent naming convention (e.g.,
<app>-<type>-<environment>
) - Add descriptive labels and annotations
- Document the purpose of each ConfigMap and Secret
- Follow a consistent naming convention (e.g.,
- Version control configs
- Store configuration templates in version control
- Use CI/CD pipelines to apply configuration changes
- Consider GitOps approaches for configuration management
- Implement proper RBAC
- Restrict access to ConfigMaps and Secrets with RBAC
- Use separate service accounts with minimal permissions
- Regularly audit access to configuration resources
- Encrypt sensitive data
- Enable encryption at rest for etcd
- Consider external secret management systems
- Use envelope encryption for additional security layers
- Regular rotation of secrets
- Implement automated secret rotation processes
- Monitor secret age and usage
- Have clear procedures for emergency credential rotations
- Minimize secret scope
- Use namespaces to limit secret visibility
- Only mount secrets in pods that need them
- Use environment-specific secrets
- Validate configurations
- Implement validation in CI/CD pipelines
- Use schema validation for complex configurations
- Test configuration changes before production deployment
Environment Variables
Environment variables are the most common way to pass configuration to containers in Kubernetes, as most applications are already designed to read configuration from environment variables.
From ConfigMap
From Multiple Sources
You can inject all values from multiple ConfigMaps and Secrets as environment variables at once, which is useful for applications that expect a large number of configuration parameters.
When using envFrom
:
- Invalid keys (those that don't conform to environment variable naming rules) are skipped
- Variable names are created directly from ConfigMap/Secret keys
- Values are automatically converted to strings
- If multiple sources define the same key, the last one wins
Volume Mounts
Mounting ConfigMaps and Secrets as volumes creates files inside your container, with each key becoming a file and its value becoming the file content. This is ideal for applications that expect to read configuration from files.
ConfigMap as Volume
When mounted as a volume:
- Each key in the ConfigMap becomes a file in the specified directory
- File content is exactly the value from the ConfigMap
- For binary data, use the
binaryData
field in the ConfigMap - You can mount at specific paths using the
items
field - File permissions can be controlled with
defaultMode
Secret as Volume
Mounting Secrets as volumes is similar to ConfigMaps but with additional security considerations.
Benefits of mounting Secrets as volumes:
- Applications can read credentials from familiar locations
- Permissions can be tightly controlled
- Files are automatically updated when Secrets change (though with some delay)
- Ideal for TLS certificates, SSH keys, and configuration files containing secrets
For sensitive data like TLS certificates, using the Secret volume approach is often better than environment variables, as environment variables:
- May be exposed in logs
- May be inadvertently shared in child processes
- Are visible to anyone who can execute commands in the container
Dynamic Updates
Understanding how configuration updates propagate to running containers is crucial for managing applications in Kubernetes.
- ConfigMaps update automatically in the Kubernetes API when changed
- Volume-mounted ConfigMaps sync periodically to running containers (typically within 60 seconds)
- This creates a file for each key in the ConfigMap
- Updates are eventually consistent, not immediate
- Atomic updates are not guaranteed (some files may update before others)
- Applications need to handle file changes properly (reload configuration)
- Environment variables don't update after the container starts
- Environment variables are set only at container start time
- Changes to ConfigMaps/Secrets won't affect environment variables in running containers
- Pods may need restart for changes to take effect
- For environment variables, pod restarts are required
- For volume mounts, applications may need to watch for file changes
- Consider using a ConfigMap reload sidecar for automatic application reloads
- Immutable ConfigMaps and Secrets (Kubernetes 1.19+) can't be updated after creation
- Prevents accidental updates
- Requires deletion and recreation to change
- Set with
immutable: true
in the ConfigMap/Secret spec
Usage considerations:
- For configuration that changes frequently, use volume mounts
- For configuration that rarely changes, environment variables are simpler
- For critical configuration, consider immutable ConfigMaps with explicit version labeling
- Applications should handle configuration reloads gracefully
Secret Types
Kubernetes supports several built-in Secret types for common use cases, each with specific expected data fields.
Built-in Types
- Opaque (default): Generic arbitrary data with no schema enforcement
- kubernetes.io/service-account-token: Service account authentication tokens
- Required fields:
token
,ca.crt
,namespace
- Required fields:
- kubernetes.io/dockercfg: Legacy Docker registry authentication (
.dockercfg
format)- Contains a serialized
~/.dockercfg
file
- Contains a serialized
- kubernetes.io/dockerconfigjson: Docker registry authentication (modern format)
- Contains a serialized
~/.docker/config.json
file - Create with:
kubectl create secret docker-registry my-registry-creds --docker-server=REGISTRY_SERVER --docker-username=USERNAME --docker-password=PASSWORD
- Contains a serialized
- kubernetes.io/basic-auth: Basic authentication credentials
- Expected fields:
username
,password
- Expected fields:
- kubernetes.io/ssh-auth: SSH authentication credentials
- Expected field:
ssh-privatekey
- Expected field:
- kubernetes.io/tls: TLS certificates and keys
- Expected fields:
tls.crt
(certificate),tls.key
(private key) - Create with:
kubectl create secret tls my-tls --cert=path/to/cert.pem --key=path/to/key.pem
- Expected fields:
- bootstrap.kubernetes.io/token: Bootstrap token for cluster initialization
Custom Secret Type
You can define custom Secret types for organization-specific purposes:
Custom Secret types:
- Help with organization and validation
- Enable type-specific handling in custom controllers
- Support specialized tooling for specific secret formats
- Should use domain-prefixed names to avoid collisions
Configuration Management Tools
As applications grow in complexity, manual management of ConfigMaps and Secrets becomes cumbersome. Kubernetes ecosystem offers several tools to manage configuration at scale.
Helm
Helm is the most popular package manager for Kubernetes, with a rich ecosystem of charts.
- Package manager: Distribute and install pre-configured applications
- Template engine: Generate Kubernetes manifests from parameterized templates
- Release management: Track deployments, rollbacks, and history
- Configuration reuse: Share common configurations across deployments
Kustomize
Kustomize is built into kubectl and provides a declarative approach to configuration customization.
- Configuration customization: Modify base configurations without editing them
- No templates: Pure YAML approach without a template language
- Overlay-based: Layer configurations for different environments
- Native Kubernetes: Integrated with kubectl (
kubectl apply -k ./overlay/production
)
External Secret Operators
For production environments, consider external secret operators that integrate with secure secret stores:
- Kubernetes External Secrets: Sync from external providers like AWS Secrets Manager, HashiCorp Vault
- Sealed Secrets: Encrypt secrets that can be safely stored in git
- Vault Operator: Deep integration with HashiCorp Vault
- Azure Key Vault to Kubernetes: Sync secrets from Azure Key Vault
Security Considerations
Configuration and secret management require careful security considerations to prevent data exposure.
- Limit access to ConfigMaps/Secrets
- Use RBAC to restrict who can read and modify configurations
- Example RBAC rule for limiting Secret access:
- Separate application-specific configurations into different objects
- Use encryption at rest
- Enable etcd encryption for Secrets
- Configure the API server with encryption providers
- Consider external secret management solutions for sensitive data
- Rotate secrets regularly
- Implement automated rotation processes
- Use short-lived credentials where possible
- Design applications to reload credentials without restarts
- Monitor access patterns
- Enable audit logging for Secret access
- Set up alerts for unusual access patterns
- Track which pods and users access sensitive configurations
- Implement least privilege
- Each application should only access the configurations it needs
- Use service accounts with minimal permissions
- Implement Pod Security Policies to restrict secret access
- Use proper namespaces
- Segregate configurations by namespace
- Secrets are only accessible within their own namespace
- Implement namespace-level resource quotas and limits
- Avoid secret sprawl
- Centralize and standardize secret management
- Document the purpose of each Secret
- Regularly audit and clean up unused Secrets
- Never store secrets in container images
- Always inject secrets at runtime
- Scan images for accidentally included secrets
- Use multi-stage builds to avoid leaking secrets during build
Troubleshooting
Configuration-related issues are common in Kubernetes deployments. Here are the most frequent problems and their solutions:
Common issues and solutions:
- ConfigMap not updating
- Symptoms: Changes to ConfigMap not reflected in application
- Causes:
- Environment variables don't update automatically
- Volume propagation delay (can take up to 60 seconds)
- Application not reloading configuration
- Solutions:
- Restart pods for environment variable updates
- Add a configuration reload mechanism to your application
- Use a sidecar container to watch for changes and signal the application
- Check if ConfigMap is marked as immutable
- Secret mounting issues
- Symptoms: Application can't access secrets, missing files
- Causes:
- Secret doesn't exist in the namespace
- Secret key doesn't match expected name
- Incorrect mount path
- Solutions:
- Verify Secret exists:
kubectl get secret <name> -n <namespace>
- Check pod events:
kubectl describe pod <pod-name>
- Inspect volume mounts:
kubectl describe pod <pod-name> | grep -A 10 Mounts
- Debug with a temporary pod:
kubectl run debug --image=busybox -- sleep 3600
- Verify Secret exists:
- Permission problems
- Symptoms: Forbidden errors, RBAC denials
- Causes:
- Insufficient RBAC permissions
- Service account doesn't have access
- Pod security policies blocking access
- Solutions:
- Check pod service account:
kubectl get pod <pod-name> -o jsonpath='{.spec.serviceAccountName}'
- Verify permissions:
kubectl auth can-i --as=system:serviceaccount:<namespace>:<sa-name> get secrets
- Review audit logs for RBAC failures
- Update RBAC roles and bindings as needed
- Check pod service account:
- Encoding/decoding errors
- Symptoms: Garbled configuration data, application errors
- Causes:
- Improper base64 encoding in Secrets
- Non-UTF8 characters in configuration
- Line ending issues
- Solutions:
- Ensure proper base64 encoding:
echo -n 'my-value' | base64
- Use the
stringData
field in Secrets to avoid manual encoding - Check encoding with:
kubectl get secret <name> -o jsonpath='{.data.<key>}' | base64 --decode
- Use
kubectl create secret
commands instead of manual YAML
- Ensure proper base64 encoding:
- Volume mount failures
- Symptoms: Pod stuck in init or won't start
- Causes:
- ConfigMap or Secret doesn't exist
- Volume path conflicts
- Permission issues on the mounted directory
- Solutions:
- Check pod events:
kubectl describe pod <pod-name>
- Verify the ConfigMap/Secret exists before the pod starts
- Add
optional: true
for non-critical configurations - Fix path conflicts or use subdirectories
- Check pod events:
- Too large ConfigMaps or Secrets
- Symptoms: API server rejection, pod startup failure
- Causes:
- Kubernetes limits size of ConfigMaps/Secrets (typically 1MB)
- Too many keys or large values
- Solutions:
- Split large configurations into multiple objects
- Store large files externally (S3, Git, etc.)
- Use init containers to fetch configuration at startup
- Consider ConfigMap/Secret projection with specific keys
Advanced Usage
Immutable ConfigMaps
Kubernetes 1.19+ supports immutable ConfigMaps and Secrets, which prevents accidental modifications and improves performance by reducing watches.
Benefits of immutable configurations:
- Prevent accidental changes
- Improve performance (kube-apiserver load reduction)
- Simplify auditing and compliance
- Enable easier tracking of which configuration version is deployed
Secret Data Keys
Different Secret types require specific keys. For TLS Secrets:
Init Containers
For complex configuration scenarios, init containers can be used to prepare or transform configuration before the main container starts.
Init containers can:
- Download configuration from external sources
- Merge multiple configuration sources
- Transform configuration into application-specific formats
- Generate dynamic configuration values (e.g., passwords)
- Validate configuration before application starts
Best Practices Checklist
- Use descriptive names
- Follow naming conventions that indicate purpose and environment
- Example:
app-name-db-credentials-production
- Include version information when appropriate
- Implement proper RBAC
- Restrict read/write access to ConfigMaps and Secrets
- Use separate service accounts for different applications
- Apply the principle of least privilege consistently
- Version control non-sensitive configs
- Store ConfigMap templates in git
- Use labels to track configuration versions
- Document the purpose of each configuration option
- Separate sensitive data
- Never store credentials in ConfigMaps
- Split configurations to minimize Secret size and scope
- Consider external secret management for production
- Regular secret rotation
- Implement automated processes for credential rotation
- Design applications to handle credential changes gracefully
- Monitor secret age and usage patterns
- Monitor usage patterns
- Track which pods are using which configurations
- Set up alerts for unusual configuration access
- Audit configuration changes regularly
- Document configurations
- Document the structure and purpose of each ConfigMap/Secret
- Maintain a registry of configuration options
- Provide examples for each environment
- Use namespaces
- Keep configurations isolated in appropriate namespaces
- Avoid sharing Secrets across namespaces
- Implement namespace-level access controls
- Implement immutability when needed
- Use immutable ConfigMaps for stable configurations
- Create new versions instead of modifying existing ones
- Label versions to track what's deployed where
- Regular audits
- Review all ConfigMaps and Secrets periodically
- Remove unused or outdated configurations
- Verify that security best practices are followed
- Check for configuration drift between environments