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 : Setting up Ingress with NGINX Controller on Minikube (Mac)
- 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 : Deploy Prometheus and Grafana using kube-prometheus-stack Helm Chart
- Docker & Kubernetes : Istio (service mesh) sidecar proxy on GCP Kubernetes
- Docker & Kubernetes : Istio on EKS
- Docker & Kubernetes : Istio on Minikube with AWS EC2 for Bookinfo Application
- 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
- Docker & Kubernetes : GitOps with ArgoCD for Continuous Delivery to Kubernetes clusters (minikube) - guestbook
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization