Day 33: Taming Kubernetes ConfigMaps and Secrets for My Flask + Redis App!

Usman JapUsman Jap
4 min read

Why ConfigMaps and Secrets? 🤔

Picture this: my Flask + Redis app is humming along in Kubernetes, with pods and services set up from Days 31 and 32. But my Flask app needs settings like FLASK_ENV=production and REDIS_HOST=redis-service, and my Redis pod might need a password. Hardcoding these in my Docker image or scattering them in YAML files? Yawn—that’s so Day 6 (when I learned Docker environment variables). Kubernetes ConfigMaps and Secrets are here to save the day! ConfigMaps handle non-sensitive settings, while Secrets lock up sensitive data like passwords. Both make my app flexible and secure, like giving it a superhero utility belt. 🦸‍♂️

I kicked off by asking Grok (my AI sidekick from xAI, accessed via grok.com): “What are Kubernetes ConfigMaps and Secrets, and how do they differ?” Using DeepSearch mode, Grok explained that ConfigMaps store plain-text key-value pairs for things like environment settings, while Secrets use base64 encoding for sensitive stuff like passwords. It’s like ConfigMaps are your app’s public to-do list, and Secrets are the locked diary. With that clarity, I was ready to roll!

Step 1: Setting the Stage

First, I fired up my Minikube cluster on my Ubuntu machine:

minikube start --driver=docker

I checked my Flask and Redis pods and services from Day 32:

kubectl get pods,svc
minikube service flask-service --url

Everything was up—my Flask app was chatting with Redis via a ClusterIP service. I opened my notes file with vi (because who needs fancy editors?):

vi ~/flask-redis-app/notes/Day_33_Activities.txt

I jotted down: “Day 33: Kubernetes ConfigMaps and Secrets - July 3, 2025”. To warm up, I recalled why I used ClusterIP for Redis (internal pod communication) and NodePort for Flask (external access). It’s like setting up a private phone line for Redis and a public website for Flask!

Step 2: ConfigMaps—Organizing App Settings

Time to tidy up my Flask app’s settings with a ConfigMap. I created a file called flask-configmap.yaml:

vi ~/flask-redis-app/k8s/flask-configmap.yaml

Here’s what I wrote:

apiVersion: v1
kind: ConfigMap
metadata:
  name: flask-app-config
data:
  FLASK_ENV: "production"
  REDIS_HOST: "redis-service"
  APP_PORT: "5000"

This ConfigMap is like a settings menu for my app—environment, Redis host, and port, all in one place. I applied it:

kubectl apply -f ~/flask-redis-app/k8s/flask-configmap.yaml

Next, I updated my Flask deployment to use these settings:

vi ~/flask-redis-app/k8s/flask-deployment.yaml

I swapped out hardcoded env values for ConfigMap references:

spec:
  containers:
  - name: flask
    image: <my-username>/flask-app:latestdnsutils
      valueFrom:
        configMapKeyRef:
          name: flask-app-config
          key: REDIS_HOST
    - name: APP_PORT
      valueFrom:
        configMapKeyRef:
          name: flask-app-config
          key: APP_PORT

I reapplied the deployment:

kubectl apply -f ~/flask-redis-app/k8s/flask-deployment.yaml

Then, I tested it:

minikube service flask-service --url
curl <flask-service-url>

Boom! My Flask app was running smoothly, pulling settings from the ConfigMap. I checked the ConfigMap details with:

kubectl describe configmap flask-app-config

It felt like organizing a messy drawer—everything was neat and accessible! I asked Grok: “How can ConfigMaps be mounted as volumes?” In think mode, Grok explained that I could mount ConfigMaps as files in a pod’s filesystem, which I noted for Day 34 exploration.

Step 3: Secrets—Locking Down Sensitive Data

Now for the juicy part: securing a Redis password with a Secret. First, I encoded my password (redis-password) in base64:

echo -n 'redis-password' | base64

Output: cmVkaXMtcGFzc3dvcmQ=. I created a Secret manifest:

vi ~/flask-redis-app/k8s/redis-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: redis-secret
type: Opaque
data:
  REDIS_PASSWORD: cmVkaXMtcGFzc3dvcmQ=

I applied it:

kubectl apply -f ~/flask-redis-app/k8s/redis-secret.yaml

Then, I updated my Redis deployment:

vi ~/flask-redis-app/k8s/redis-deployment.yaml

Added:

spec:
  containers:
  - name: redis
    image: redis:latest
    env:
    - name: REDIS_PASSWORD
      valueFrom:
        secretKeyRef:
          name: redis-secret
          key: REDIS_PASSWORD

I also updated my Flask deployment to use the same Secret:

vi ~/flask-redis-app/k8s/flask-deployment.yaml

Added:

- name: REDIS_PASSWORD
  valueFrom:
    secretKeyRef:
      name: redis-secret
      key: REDIS_PASSWORD

I reapplied both deployments:

kubectl apply -f ~/flask-redis-app/k8s/redis-deployment.yaml
kubectl apply -f ~/flask-redis-app/k8s/flask-deployment.yaml

I tested the app with Redis:

curl <flask-service-url>/set_key?key=test&value=123
curl <flask-service-url>/get_key?key=test

It worked like a charm! The Secret kept my password safe, and I verified it with:

kubectl get secret redis-secret -o yaml

I asked Grok: “What are best practices for securing Kubernetes Secrets?” DeepSearch revealed tips like using external tools (e.g., Sealed Secrets) for production, which I jotted down in my notes.

Step 4: Enhancing the App

To make my app chatty, I added logging:

vi ~/flask-redis-app/app.py
import os
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
logger.info(f"FLASK_ENV: {os.getenv('FLASK_ENV')}")
logger.info(f"REDIS_HOST: {os.getenv('REDIS_HOST')}")

I rebuilt and pushed the Docker image:

cd ~/flask-redis-app
docker build -t <my-username>/flask-app:latest .
docker push <my-username>/flask-app:latest

Redeployed:

kubectl apply -f ~/flask-redis-app/k8s/flask-deployment.yaml

Checked logs:

kubectl logs -l app=flask

The logs confirmed my ConfigMap settings were in action!

I committed everything to GitHub:

git add .
git commit -m "Day 33: ConfigMaps and Secrets for Flask + Redis"
git push origin main
0
Subscribe to my newsletter

Read articles from Usman Jap directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Usman Jap
Usman Jap