Chapter 4
Section titled “Chapter 4”So far, our application is running, scalable, and exposed to the world. But we’ve hardcoded our configuration (like the Nginx version) directly into our YAML files. This isn’t flexible. What if we want to change a setting without rebuilding and redeploying the whole application?
Configuration and Secret Management
Section titled “Configuration and Secret Management”So far, our application is running, scalable, and exposed to the world. But we’ve hardcoded our configuration (like the Nginx version) directly into our YAML files. This isn’t flexible. What if we want to change a setting without rebuilding and redeploying the whole application?
A core principle of building portable, cloud-native applications is to separate the application’s code from its configuration. You should be able to promote the exact same container image from a development environment to staging and then to production, with the only difference being the configuration it uses (e.g., the database URL, a feature flag, or an API key).
Kubernetes provides two primary objects for this purpose: ConfigMaps and Secrets.
What is a ConfigMap?
Section titled “What is a ConfigMap?”A ConfigMap is a Kubernetes object used to store non-confidential configuration data in a key-value format. Think of it as a set of properties or environment variables that you manage within Kubernetes and can “inject” into your Pods at runtime.
This allows you to change your application’s behavior without ever touching the application code or
its container image. For example, you could have a ConfigMap for your development environment
with LOG_LEVEL=debug and another ConfigMap for production with LOG_LEVEL=info.
Your Pods can consume ConfigMap data in two main ways:
- As Environment Variables: Each key-value pair in the ConfigMap becomes an environment variable inside your container. This is the most common method.
- As Mounted Files: The ConfigMap can be mounted as a volume, where each key becomes a file name and the value becomes the file’s content. This is useful for legacy applications that expect to read configuration from a file (like a
settings.xmlornginx.conf).
What is a Secret?
Section titled “What is a Secret?”A Secret is very similar to a ConfigMap but is specifically intended for storing sensitive or confidential data, such as:
- Database passwords
- API tokens and keys
- TLS certificates
Like ConfigMaps, Secrets are also consumed by Pods as either environment variables or mounted files.
What’s the difference? When you create a Secret, Kubernetes stores the values as base64-encoded strings. This is encoding, not encryption. It simply prevents someone from casually reading the password by looking over your shoulder or browsing the YAML file. However, it signals the intent that the data is sensitive, and Kubernetes can apply stricter policies to Secrets, such as limiting access and preventing them from being accidentally exposed.
-
Create a ConfigMap We’ll create a ConfigMap to hold some non-sensitive display settings. We can do this easily from the command line.
Terminal window kubectl create configmap my-app-config \--from-literal=APP_COLOR=blue \--from-literal=APP_GREETING="Hello from ConfigMap!"You can inspect the ConfigMap you created (the -o yaml flag shows the full object definition):
Terminal window kubectl get configmap my-app-config -o yaml -
Create a Secret
Next, let’s create aSecretfor some dummy database credentials.Terminal window kubectl create secret generic my-db-credentials \--from-literal=DB_USER=my-admin-user \--from-literal=DB_PASSWORD='S3cr3tP@ssw0rd!!'If you inspect the secret with
kubectl get secret my-db-credentials -o yaml, you’ll see the values are base64 encoded. -
Inject Configuration into the Deployment Now, we need to update our Deployment to use this
ConfigMapandSecret. Create a new file nameddeployment-with-config.yamlwith the following content. Pay close attention to the newenvFromsection.deployment-with-config.yaml apiVersion: apps/v1kind: Deploymentmetadata:name: my-webapp-deploymentspec:replicas: 3selector:matchLabels:app: my-webapptemplate:metadata:labels:app: my-webappspec:containers:- name: webserver-containerimage: nginx:1.21.6ports:- containerPort: 80# This new section injects our configurationenvFrom:- configMapRef:name: my-app-config- secretRef:name: my-db-credentialsApply this updated Deployment configuration:
Terminal window # The 'apply' command is smart enough to update the existing deploymentkubectl apply -f deployment-with-config.yamlThe Deployment will perform a rolling update to launch new Pods containing our configuration.