Docker / Kubernetes - Configure a Pod to Use a ConfigMap
ConfigMaps allow us to decouple configuration artifacts from image content to keep containerized applications portable. This post provides a series of usage examples demonstrating how to create ConfigMaps and configure Pods using data stored in ConfigMaps.
Picture from Kubernetes Engine - ConfigMap
ConfigMaps bind configuration files, command-line arguments, environment variables, port numbers, and other configuration artifacts to our Pods' containers and system components at runtime.
ConfigMaps allow us to separate our configurations from our Pods and components, which helps keep our workloads portable, makes their configurations easier to change and manage, and prevents hardcoding configuration data to Pod specifications.
ConfigMaps are useful for storing and sharing non-sensitive, unencrypted configuration information. - Kubernetes Engine - ConfigMap
We can use the kubectl create configmap command to create configmaps from directories, files, or literal values:
Pictures from ConfigMap in Kubernetes | Concept & Demo (Review) | Kubernetes Tutorial
where <map-name> is the name we want to assign to the ConfigMap and <data-source> is the directory, file, or literal value to draw the data from.
The data source corresponds to a key-value pair in the ConfigMap, where
- key = the file name or the key we provided on the command line, and
- value = the file contents or the literal value we provided on the command line.
We can use kubectl describe or kubectl get to retrieve information about a ConfigMap.
Create ConfigMaps from directories
We can use kubectl create configmap to create a ConfigMap from multiple files in the same directory.
# Create the local directory $ mkdir -p configure-pod-container/configmap/ # Download the sample files into `configure-pod-container/configmap/` directory $ wget https://k8s.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties $ wget https://k8s.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties
.
└── configure-pod-container
└── configmap
├── game.properties
└── ui.properties
$ cat game.properties enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true
$ cat ui.properties color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice
# Create the configmap $ kubectl create configmap game-config --from-file=configure-pod-container/configmap/ configmap/game-config created $ kubectl get configmap -o wide NAME DATA AGE game-config 2 10s
Note that kubectl create configmap command combines the contents of the configure-pod-container/configmap/ directory (game.properties and ui.properties) into the game-config configmap:
$ kubectl describe configmaps game-config Name: game-config Namespace: default Labels: <none> Annotations: <none> Data ==== ui.properties: ---- color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 Events: <none>
The game.properties and ui.properties files in the configure-pod-container/configmap/ directory are represented in the data section of the ConfigMap.
Let's get the yaml file:
$ kubectl get configmaps game-config -o yaml
apiVersion: v1
data:
game.properties: |-
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
creationTimestamp: "2019-03-26T03:39:03Z"
name: game-config
namespace: default
resourceVersion: "1019330"
selfLink: /api/v1/namespaces/default/configmaps/game-config
uid: b36f6f8f-4f78-11e9-8571-080027c35fa9
Create ConfigMaps from files - 1
We can use kubectl create configmap to create a ConfigMap from an individual file, or from multiple files.
$ kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties configmap/game-config-2 created
The configmap produced looks like this:
$ kubectl describe configmaps game-config-2 Name: game-config-2 Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 Events: <none>
We can pass in the "--from-file" argument multiple times to create a ConfigMap from multiple data sources:
$ kubectl delete configmap game-config-2 configmap "game-config-2" deleted $ kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties configmap/game-config-2 created
Describe the above game-config-2 configmap created:
$ kubectl describe configmaps game-config-2 Name: game-config-2 Namespace: default Labels: <none> Annotations: <none> Data ==== game.properties: ---- enemies=aliens lives=3 enemies.cheat=true enemies.cheat.level=noGoodRotten secret.code.passphrase=UUDDLRLRBABAS secret.code.allowed=true secret.code.lives=30 ui.properties: ---- color.good=purple color.bad=yellow allow.textmode=true how.nice.to.look=fairlyNice Events: <none>
Create ConfigMaps from files - 2: Redis
Unlike the previous section, with redis sample, we'll provide a real world example of how to configure Redis using a ConfigMap.
Ref: Configuring Redis using a ConfigMap.
We'll create a ConfigMap, create a pod specification using the ConfigMap, create the pod, and then verify that the configuration was correctly applied.
We may want to follow the steps below to configure a Redis cache using data stored in a ConfigMap.
First create a ConfigMap from the redis-config file:
$ curl -OL https://k8s.io/examples/pods/config/redis-config $ cat redis-config maxmemory 2mb maxmemory-policy allkeys-lru $ kubectl create configmap example-redis-config --from-file=redis-config configmap/example-redis-config created
Examine the created ConfigMap:
$ kubectl get configmap example-redis-config -o yaml
apiVersion: v1
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lru
kind: ConfigMap
metadata:
creationTimestamp: "2019-03-26T15:43:37Z"
name: example-redis-config
namespace: default
resourceVersion: "1029909"
selfLink: /api/v1/namespaces/default/configmaps/example-redis-config
uid: eb90de22-4fdd-11e9-a4f4-080027c35fa9
Now, let's create a pod specification (redis-pod.yaml) that uses the config data stored in the ConfigMap. In this post, we'll use volumes with configMap type:
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: kubernetes/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
resources:
limits:
cpu: "0.1"
volumeMounts:
- mountPath: /redis-master-data
name: data
- mountPath: /redis-master
name: config
volumes:
- name: data
emptyDir: {}
- name: config
configMap:
name: example-redis-config
items:
- key: redis-config
path: redis.conf
In the example, the config volume is mounted at /redis-master via volumeMounts and the volume name is config. The configMap contains two items: key (nothing but a file name) and path (target location where data resides inside the pod). It uses path to add the redis-config key to a file named redis.conf.
The file path for the redis config, therefore, is /redis-master/redis.conf.
This is where the image will look for the config file for the redis master.
Let's create the pod:
$ kubectl create -f redis-pod.yaml pod/redis created $ kubectl get pod NAME READY STATUS RESTARTS AGE redis 1/1 Running 0 4s
Use kubectl exec to enter the pod and run the redis-cli tool to verify that the configuration was correctly applied:
$ kubectl logs redis
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 2.8.19 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in stand alone mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
| `-._ `._ / _.-' | PID: 6
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
[6] 26 Mar 16:46:18.762 # Server started, Redis version 2.8.19
[6] 26 Mar 16:46:18.766 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
[6] 26 Mar 16:46:18.766 * The server is now ready to accept connections on port 6379
$ kubectl exec -it redis redis-cli
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "2097152"
127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-lru"
127.0.0.1:6379>
Another sample of volume mount configMap from Configure a Pod to Use a ConfigMap.
configmap-multikeys.yaml:
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: SPECIAL_LEVEL: very SPECIAL_TYPE: charm
In the following pod-configmap-volume.yaml file, we're adding the ConfigMap name under the volumes section of the Pod specification. This adds the ConfigMap data to the directory specified as volumeMounts.mountPath (in this case, /etc/config). The command section lists directory files with names that match the keys in ConfigMap:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
ConfigMap:
# provide the name of the ConfigMap containing the files
# we want to add to the container
name: special-config
restartPolicy: Never
$ kubectl apply -f configmap-multikeys.yaml configmap/special-config created $ kubectl apply -f pod-configmap-volume.yaml pod/test-pod created
When the pod runs, the command ls /etc/config/ produces the output below:
SPECIAL_LEVEL SPECIAL_TYPE
$ kubectl describe cm special-config
Name: special-config
Namespace: default
Labels: <none>
Annotations:
Data
====
SPECIAL_LEVEL:
----
very
SPECIAL_TYPE:
----
charm
Events: <none>
$ kubectl describe pods test-pod
Name: test-pod
Namespace: default
Priority: 0
Node: minikube/172.17.0.2
Start Time: Mon, 05 Apr 2021 18:51:39 -0700
Labels: <none>
Annotations: Status: Succeeded
IP: 172.18.0.3
IPs:
IP: 172.18.0.3
Containers:
test-container:
Container ID: docker://f05888f6cb923f77a9ae1b8a2281f32667f812f70b95e18278c9795cd8626688
Image: k8s.gcr.io/busybox
Image ID: docker-pullable://gcr.io/google_containers/busybox@sha256:d8d3bc2c183ed2f9f10e7258f84971202325ee6011ba137112e01e30f206de67
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
ls /etc/config/
State: Terminated
Reason: Completed
Exit Code: 0
Started: Mon, 05 Apr 2021 18:51:42 -0700
Finished: Mon, 05 Apr 2021 18:51:42 -0700
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/etc/config from config-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-x768k (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
config-volume:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: special-config
Optional: false
default-token-x768k:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-x768k
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> Successfully assigned default/test-pod to minikube
Normal Pulling 24m kubelet, minikube Pulling image "k8s.gcr.io/busybox"
Normal Pulled 24m kubelet, minikube Successfully pulled image "k8s.gcr.io/busybox" in 645.8707ms
Normal Created 24m kubelet, minikube Created container test-container
Normal Started 24m kubelet, minikube Started container test-container
Create ConfigMaps from literal values
We can use kubectl create configmap with the --from-literal argument to define a literal value from the command line:
$ kubectl create configmap special-config \ --from-literal=special.how=very \ --from-literal=special.type=charm configmap/special-config created
We can pass in multiple key-value pairs. Each pair provided on the command line is represented as a separate entry in the data section of the ConfigMap. Note that this time the pod will look for "key" from env variables rather than from volumes.
apiVersion: v1
kind: Pod
metadata:
name: config-literal-test-pod
spec:
containers:
- name: config-literal-test-container
image: k8s.gcr.io/busybox
command: ["/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
restartPolicy: Never
Let's create a pod and check if it gets the value, "very":
$ kubectl create -f config-literal-test-pod.yaml pod/config-literal-test-pod created $ kubectl logs config-literal-test-pod | grep SPECIAL SPECIAL_LEVEL_KEY=very
kubectl supports kustomization.yaml since 1.14. We can also create a ConfigMap from generators and then apply it to create the object on the Apiserver. The generators should be specified in a kustomization.yaml inside a directory.
Generate ConfigMaps from files
To generate a ConfigMap from files configure-pod-container/configmap/kubectl/game.properties:
# Create a kustomization.yaml file with ConfigMapGenerator $ cat <<EOF >./kustomization.yaml configMapGenerator: - name: game-config-4 files: - configure-pod-container/configmap/kubectl/game.properties EOF
$ cat ./kustomization.yaml configMapGenerator: - name: game-config-4 files: - configure-pod-container/configmap/kubectl/game.properties
Apply the kustomization directory to create the ConfigMap object:
. ├── configure-pod-container │ └── configmap │ ├── game.properties │ └── ui.properties └── kustomization.yaml $ kubectl apply -k .
But I'm currently using 1.13.4, and kubectl does not support kustomization.yaml with the version.
Docker & K8s
- Docker install on Amazon Linux AMI
- Docker install on EC2 Ubuntu 14.04
- Docker container vs Virtual Machine
- Docker install on Ubuntu 14.04
- Docker Hello World Application
- Nginx image - share/copy files, Dockerfile
- Working with Docker images : brief introduction
- Docker image and container via docker commands (search, pull, run, ps, restart, attach, and rm)
- More on docker run command (docker run -it, docker run --rm, etc.)
- Docker Networks - Bridge Driver Network
- Docker Persistent Storage
- File sharing between host and container (docker run -d -p -v)
- Linking containers and volume for datastore
- Dockerfile - Build Docker images automatically I - FROM, MAINTAINER, and build context
- Dockerfile - Build Docker images automatically II - revisiting FROM, MAINTAINER, build context, and caching
- Dockerfile - Build Docker images automatically III - RUN
- Dockerfile - Build Docker images automatically IV - CMD
- Dockerfile - Build Docker images automatically V - WORKDIR, ENV, ADD, and ENTRYPOINT
- Docker - Apache Tomcat
- Docker - NodeJS
- Docker - NodeJS with hostname
- Docker Compose - NodeJS with MongoDB
- Docker - Prometheus and Grafana with Docker-compose
- Docker - StatsD/Graphite/Grafana
- Docker - Deploying a Java EE JBoss/WildFly Application on AWS Elastic Beanstalk Using Docker Containers
- Docker : NodeJS with GCP Kubernetes Engine
- Docker : Jenkins Multibranch Pipeline with Jenkinsfile and Github
- Docker : Jenkins Master and Slave
- Docker - ELK : ElasticSearch, Logstash, and Kibana
- Docker - ELK 7.6 : Elasticsearch on Centos 7
- Docker - ELK 7.6 : Filebeat on Centos 7
- Docker - ELK 7.6 : Logstash on Centos 7
- Docker - ELK 7.6 : Kibana on Centos 7
- Docker - ELK 7.6 : Elastic Stack with Docker Compose
- Docker - Deploy Elastic Cloud on Kubernetes (ECK) via Elasticsearch operator on minikube
- Docker - Deploy Elastic Stack via Helm on minikube
- Docker Compose - A gentle introduction with WordPress
- Docker Compose - MySQL
- MEAN Stack app on Docker containers : micro services
- MEAN Stack app on Docker containers : micro services via docker-compose
- Docker Compose - Hashicorp's Vault and Consul Part A (install vault, unsealing, static secrets, and policies)
- Docker Compose - Hashicorp's Vault and Consul Part B (EaaS, dynamic secrets, leases, and revocation)
- Docker Compose - Hashicorp's Vault and Consul Part C (Consul)
- Docker Compose with two containers - Flask REST API service container and an Apache server container
- Docker compose : Nginx reverse proxy with multiple containers
- Docker & Kubernetes : Envoy - Getting started
- Docker & Kubernetes : Envoy - Front Proxy
- Docker & Kubernetes : Ambassador - Envoy API Gateway on Kubernetes
- Docker Packer
- Docker Cheat Sheet
- Docker Q & A #1
- Kubernetes Q & A - Part I
- Kubernetes Q & A - Part II
- Docker - Run a React app in a docker
- Docker - Run a React app in a docker II (snapshot app with nginx)
- Docker - NodeJS and MySQL app with React in a docker
- Docker - Step by Step NodeJS and MySQL app with React - I
- Installing LAMP via puppet on Docker
- Docker install via Puppet
- Nginx Docker install via Ansible
- Apache Hadoop CDH 5.8 Install with QuickStarts Docker
- Docker - Deploying Flask app to ECS
- Docker Compose - Deploying WordPress to AWS
- Docker - WordPress Deploy to ECS with Docker-Compose (ECS-CLI EC2 type)
- Docker - WordPress Deploy to ECS with Docker-Compose (ECS-CLI Fargate type)
- Docker - ECS Fargate
- Docker - AWS ECS service discovery with Flask and Redis
- Docker & Kubernetes : minikube
- Docker & Kubernetes 2 : minikube Django with Postgres - persistent volume
- Docker & Kubernetes 3 : minikube Django with Redis and Celery
- Docker & Kubernetes 4 : Django with RDS via AWS Kops
- Docker & Kubernetes : Kops on AWS
- Docker & Kubernetes : Ingress controller on AWS with Kops
- Docker & Kubernetes : HashiCorp's Vault and Consul on minikube
- Docker & Kubernetes : HashiCorp's Vault and Consul - Auto-unseal using Transit Secrets Engine
- Docker & Kubernetes : Persistent Volumes & Persistent Volumes Claims - hostPath and annotations
- Docker & Kubernetes : Persistent Volumes - Dynamic volume provisioning
- Docker & Kubernetes : DaemonSet
- Docker & Kubernetes : Secrets
- Docker & Kubernetes : kubectl command
- Docker & Kubernetes : Assign a Kubernetes Pod to a particular node in a Kubernetes cluster
- Docker & Kubernetes : Configure a Pod to Use a ConfigMap
- AWS : EKS (Elastic Container Service for Kubernetes)
- Docker & Kubernetes : Run a React app in a minikube
- Docker & Kubernetes : Minikube install on AWS EC2
- Docker & Kubernetes : Cassandra with a StatefulSet
- Docker & Kubernetes : Terraform and AWS EKS
- Docker & Kubernetes : Pods and Service definitions
- Docker & Kubernetes : Service IP and the Service Type
- Docker & Kubernetes : Kubernetes DNS with Pods and Services
- Docker & Kubernetes : Headless service and discovering pods
- Docker & Kubernetes : Scaling and Updating application
- Docker & Kubernetes : Horizontal pod autoscaler on minikubes
- Docker & Kubernetes : From a monolithic app to micro services on GCP Kubernetes
- Docker & Kubernetes : Rolling updates
- Docker & Kubernetes : Deployments to GKE (Rolling update, Canary and Blue-green deployments)
- Docker & Kubernetes : Slack Chat Bot with NodeJS on GCP Kubernetes
- Docker & Kubernetes : Continuous Delivery with Jenkins Multibranch Pipeline for Dev, Canary, and Production Environments on GCP Kubernetes
- Docker & Kubernetes : NodePort vs LoadBalancer vs Ingress
- Docker & Kubernetes : MongoDB / MongoExpress on Minikube
- Docker & Kubernetes : Load Testing with Locust on GCP Kubernetes
- Docker & Kubernetes : MongoDB with StatefulSets on GCP Kubernetes Engine
- Docker & Kubernetes : Nginx Ingress Controller on Minikube
- Docker & Kubernetes : Nginx Ingress Controller for Dashboard service on Minikube
- Docker & Kubernetes : Nginx Ingress Controller on GCP Kubernetes
- Docker & Kubernetes : Kubernetes Ingress with AWS ALB Ingress Controller in EKS
- Docker & Kubernetes : Setting up a private cluster on GCP Kubernetes
- Docker & Kubernetes : Kubernetes Namespaces (default, kube-public, kube-system) and switching namespaces (kubens)
- Docker & Kubernetes : StatefulSets on minikube
- Docker & Kubernetes : RBAC
- Docker & Kubernetes Service Account, RBAC, and IAM
- Docker & Kubernetes - Kubernetes Service Account, RBAC, IAM with EKS ALB, Part 1
- Docker & Kubernetes : Helm Chart
- Docker & Kubernetes : My first Helm deploy
- Docker & Kubernetes : Readiness and Liveness Probes
- Docker & Kubernetes : Helm chart repository with Github pages
- Docker & Kubernetes : Deploying WordPress and MariaDB with Ingress to Minikube using Helm Chart
- Docker & Kubernetes : Deploying WordPress and MariaDB to AWS using Helm 2 Chart
- Docker & Kubernetes : Deploying WordPress and MariaDB to AWS using Helm 3 Chart
- Docker & Kubernetes : Helm Chart for Node/Express and MySQL with Ingress
- Docker & Kubernetes : Deploy Prometheus and Grafana using Helm and Prometheus Operator - Monitoring Kubernetes node resources out of the box
- Docker & Kubernetes : Istio (service mesh) sidecar proxy on GCP Kubernetes
- Docker & Kubernetes : Istio on EKS
- Docker & Kubernetes : Deploying .NET Core app to Kubernetes Engine and configuring its traffic managed by Istio (Part I)
- Docker & Kubernetes : Deploying .NET Core app to Kubernetes Engine and configuring its traffic managed by Istio (Part II - Prometheus, Grafana, pin a service, split traffic, and inject faults)
- Docker & Kubernetes : Helm Package Manager with MySQL on GCP Kubernetes Engine
- Docker & Kubernetes : Deploying Memcached on Kubernetes Engine
- Docker & Kubernetes : EKS Control Plane (API server) Metrics with Prometheus
- Docker & Kubernetes : Spinnaker on EKS with Halyard
- Docker & Kubernetes : Continuous Delivery Pipelines with Spinnaker and Kubernetes Engine
- Docker & Kubernetes : Multi-node Local Kubernetes cluster : Kubeadm-dind (docker-in-docker)
- Docker & Kubernetes : Multi-node Local Kubernetes cluster : Kubeadm-kind (k8s-in-docker)
- Docker & Kubernetes : nodeSelector, nodeAffinity, taints/tolerations, pod affinity and anti-affinity - Assigning Pods to Nodes
- Docker & Kubernetes : Jenkins-X on EKS
- Docker & Kubernetes : ArgoCD App of Apps with Heml on Kubernetes
- Docker & Kubernetes : ArgoCD on Kubernetes cluster
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization