There was nothing wrong with the previous deployment. In practical use cases, it would be rare that you would launch an application without some configuration settings. In this case, we are going to set the following configuration settings for redis-master (from the example in https://Kubernetes.io/docs/tutorials/configuration/configure-redis-using-configmap/ ).
Copy and paste the following two lines into the Azure Cloud Shell editor and save it as redis-config:
maxmemory 2mb maxmemory-policy allkeys-lru
The online editor is limited and surprisingly doesn't have support for creating a new file, not to worry. In this case, type touch redis-config. Then code redis-config works. Or you can open the empty file using the open file command on the online code editor.
Now we can create the ConfigMap using the following code:
Data ==== redis-config: ---- maxmemory 2mb maxmemory-policy allkeys-lru Events: <none>
Creating from the command line is not very portable. It would be better if we could describe the preceding code in a yaml file. If only there was a command that would get the same information in yaml format. Not to worry, kubectl has the get command:
kubectl get -o yaml configmap/example-redis-config
The preceding command gets close to what we want as shown:
Use the touch trick to open the file on the online code editor.
kubectl get -o yamlis a useful trick to get a deployable yaml file from a running system. It takes care of tricky yaml indentation and saves you from spending hours trying to get the format right.
ConfigMap is a portable way of configuring containers without having specialized images for each configuration. ConfigMap has a key-value pair for data that needs to be set on a container. In this case, redis-config is the key and maxmemory 2mbmaxmemory-policy allkeys-lru is the value.
Run the following command:
kubectl create -f example-redis-config
The output should be as follows:
configmap/example-redis-config created
Next, run the following command:
kubectl describe configmap/example-redis-config
The preceding command returns the same output as the previous one:
We are using a different image Kubernetes/redis:v1 that reads redis-config from /redis-master/redis.conf (instead of the usual /etc/redis/redis.conf in the other image). As usual, we are going to explain the new sections with line numbers:
The following lines will give a detailed explanation of the preceding code:
Lines 24-26: Show another way of configuring your running container. This method uses environment variables. In Docker form, this would be equivalent to docker run -e "MASTER=TRUE". --name master -p 6379:6379 -m 100M -c 100m -d Kubernetes /redis:v1 # set the environment variable MASTER=TRUE. Your application can read the environment variable settings for its configuration. Check out https://12factor.net/configto see why this is a very powerful idea.
Lines 27-28: Mounts the named volume (config that is defined in lines 36-42) at the /redis-master path on the running container. Since this is bind mount, it will hide whatever is exists on /redis-master on the original container.
In Docker terms, it would be equivalent to docker run -v config:/redis-master. -e "MASTER=TRUE" --name master -p 6379:6379 -m 100M -c 100m -d Kubernetes /redis:v1 # mount the config folder at redis-master on the container.
Line 36-42: Here is where Kubernetes takes the config as ENV vars to the next level.
Line 37: Gives the volume the config.
Line 38-39: Declares this volume should be loaded from the ConfigMap example-redis-config (which has to be already defined [unless declared optional]). We have defined this already, so we are good.
You can see how this works by running the following: kc exec -it redis-master-<pod-id> bash root@redis-master-585bd9d8fb-p9qml:/data# ps bash: ps: command not found root@redis-master-585bd9d8fb-p9qml:/data# cat /proc/1/cmdline sh-c/run.sh root@redis-master-585bd9d8fb-p9qml:/data# cat /run.sh |grep redis.conf redis-server /redis-master/redis.conf perl -pi -e "s/%master-ip%/${master}/" /redis-slave/redis.conf perl -pi -e "s/%master-port%/6379/" /redis-slave/redis.conf redis-server /redis-slave/redis.conf root@redis-master-585bd9d8fb-p9qml:/data# cat /run.sh |grep MASTER if [[ "${MASTER}" == "true" ]]; then root@redis-master-585bd9d8fb-p9qml:/data# cat /redis-master/redis.conf maxmemory 2mb maxmemory-policy allkeys-lru Somehow, in this image, ps is not installed. Not to worry, we can get the info by examining the contents of the cmdline file under pid 1. Now we know that run.sh is the file that is run, so somewhere in that redis.conf file from ConfigMap mounted at /redis-master would be used. So we grep redis.conf. For sure, we can see redis-server when it is started, when MASTER=TRUE uses the config from /redis-master/redis.conf. To make sure that Kubernetes did its magic, we examine the contents of redis.conf by runningcat /redis-master/redis.confand, lo and behold, it is exactly the values we specified in the ConfigMapexample-redis-conf.
To repeat, you have just performed the most important and tricky part of configuring cloud-native applications. You have also noticed that the apps have to be modified to be cloud-friendly to read config dynamically (the old image didn't support dynamic configuration easily).