Skip to content

Commit b7197d0

Browse files
authored
Merge pull request #186 from Phantom-Intruder/master
ConfigMaps 101
2 parents d1abe86 + a1e959b commit b7197d0

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# ConfigMaps
2+
3+
ConfigMaps are a fundamental part of any Kubernetes infrastructure. You are unlikely to find any major Kubernetes applications, be it a library, support infrastructure, or cloud provider that doesn't rely on ConfigMaps. So what are they?
4+
5+
[ConfigMaps](https://kubernetes.io/docs/concepts/configuration/configmap/) is simply a key-value store that keeps your data in plain text. This is in contrast to [secrets](../secerts_configmaps101/secrets-configmaps.md) which also do the same thing, but also encrypt your data. As the name implies, you would generally use ConfigMaps to store configurations that would be separate from your actual application. This way, if you wanted to change a configuration (such as an API endpoint your pod was calling), you could do it by simply changing the ConfigMap without having to change the actual application or deployment yaml, thereby removing the need to re-deploy your application once again.
6+
7+
ConfigMaps needs to have a structure that specifies which type of resource it is. For example, the ConfigMap for a MongoDB object would look like this:
8+
9+
```yaml
10+
apiVersion: v1
11+
kind: ConfigMap
12+
metadata:
13+
name: my-configmap
14+
namespace: my-namespace
15+
data:
16+
# Key-value pairs representing configuration data
17+
DATABASE_URL: "mongodb://localhost:27017/mydatabase"
18+
API_KEY: "your-api-key-here"
19+
LOG_LEVEL: "info"
20+
```
21+
22+
As you can see, the `kind: ConfigMap` is specified here and it follows a general Kubernetes resource pattern. However, unlike most other Kubernetes objects, there is a certain amount of flexibility allowed in this resource, where you could define all sorts of things inside the `data` attribute. For example, if you have a MySQL database and you want a SQL command to run when the database starts, you could have that SQL command as a value in the ConfigMap:
23+
24+
```
25+
data:
26+
initdb.sql: |-
27+
INSERT INTO users (username, email) VALUES ('john_doe', '[email protected]');
28+
```
29+
30+
There are numerous examples of different file structures being used within ConfigMaps across Kubelabs. For example, if you look at the [logging section](../Logging101/fluentd.md), you will see that the fluentd configuration file gets defined in a ConfigMaps with its own format. Meanwhile, if you wanted to add a user to an EKS cluster, you would do so by adding the user in a YAML format into the aws_auth ConfigMap. In this manner, just about every type of file can be defined within a ConfigMap.
31+
32+
So now you have a pretty good idea of what ConfigMaps are and what they are capable of, as well as knowledge of how you define them. So let's move on to how you would use a ConfigMap that has already been defined. As a resource that holds multiple values, there are several ways you could use the resource in a pod. One of the most popular methods is to add the ConfigMap as a volume mount. In the deployment yaml, simply specify the name of the ConfigMap as a volume, and your pod would have access to the ConfigMap the same way it would have access to any other volume. Another method of accessing the ConfigMap is to pass it as a command line argument. This is useful if you have multiple ConfigMaps, and which one you want available to your pod gets decided at runtime. You could also have the ConfigMap placed as an environment variable for a container and get it to read the environment variable and subsequently the value from the ConfigMap.
33+
34+
Now that you have a pretty good idea of the flexibility ConfigMaps provide, let's take a look at a full example. We will begin by defining a ConfigMap and then proceed to show all the different ways the ConfigMap can be used in a pod. We will use the same MongoDB example from before:
35+
36+
```
37+
# configmap.yaml
38+
39+
apiVersion: v1
40+
kind: ConfigMap
41+
metadata:
42+
name: example-configmap
43+
data:
44+
# Key-value pairs for configuration data
45+
DATABASE_URL: "mongodb://mongo-server:27017/mydatabase"
46+
API_KEY: "your_api_key_here"
47+
DEBUG_MODE: "true"
48+
```
49+
50+
You can see the ConfigMap defined with the database URL, API key, and debug mode turned on. As with all Kubernetes resources, you will have to deploy this file into your cluster:
51+
52+
```
53+
kubectl apply -f configmap.yaml
54+
```
55+
56+
Finally, let's reference it in a sample deployment:
57+
58+
```
59+
# pod.yaml
60+
61+
apiVersion: v1
62+
kind: Pod
63+
metadata:
64+
name: example-pod
65+
spec:
66+
containers:
67+
- name: my-container
68+
image: your-image
69+
env:
70+
- name: DATABASE_URL
71+
valueFrom:
72+
configMapKeyRef:
73+
name: example-configmap
74+
key: DATABASE_URL
75+
- name: API_KEY
76+
valueFrom:
77+
configMapKeyRef:
78+
name: example-configmap
79+
key: API_KEY
80+
- name: DEBUG_MODE
81+
valueFrom:
82+
configMapKeyRef:
83+
name: example-configmap
84+
key: DEBUG_MODE
85+
```
86+
87+
In this case, `valueFrom` is used to reference the values from the ConfigMap for each environment variable. Therefore, we are referencing the ConfigMap as env variables. Inside the `valueFrom` key, we also provide the `configMapKeyRef`, with the name of the key being passed in so that the value can be retrieved as a parameter. Since here we only have 3 variables, it wasn't really complicated. However, in a case where there were a large number of vars, you can imagine the deployment yaml would end up getting very repetitive and long, which would eventually make it unreadable. So, let's look at how you can mount the ConfigMap as a volume:
88+
89+
```
90+
apiVersion: apps/v1
91+
kind: Deployment
92+
metadata:
93+
name: my-app
94+
spec:
95+
replicas: 1
96+
selector:
97+
matchLabels:
98+
app: my-app
99+
template:
100+
metadata:
101+
labels:
102+
app: my-app
103+
spec:
104+
containers:
105+
- name: my-container
106+
image: my-nodejs-app:latest
107+
env:
108+
- name: MONGODB_CONFIG_FILE
109+
value: "/etc/mongodb-config/mongodb-configmap.properties"
110+
volumeMounts:
111+
- name: config-volume
112+
mountPath: "/etc/mongodb-config"
113+
volumes:
114+
- name: config-volume
115+
configMap:
116+
name: mongodb-configmap
117+
118+
```
119+
120+
In this example, the `MONGODB_CONFIG_FILE` environment variable is set to the path of the file containing the entire ConfigMap. This file will be mounted into the container. A volume is defined with the name `config-volume` and is associated with the ConfigMap `mongodb-configmap`. This volume is mounted into the container at the path `/etc/mongodb-config`. This way, there will be no repetition and all of the environment variables would still be accessible.
121+
122+
You could also safely remove the `env` key and still have all the data in the ConfigMap accessible:
123+
124+
```
125+
containers:
126+
- name: mongodb
127+
image: mongo:latest
128+
ports:
129+
- containerPort: 27017
130+
volumeMounts:
131+
- name: mongodb-config-volume
132+
mountPath: /etc/mongod
133+
volumes:
134+
- name: mongodb-config-volume
135+
configMap:
136+
name: mongodb-config
137+
```
138+
139+
The above method will make the ConfigMap be considered as a volume instead of having it entered as an environment variable. This means that if you were to update the ConfigMap while the container was running, the container would take the new values immediately. On the other hand, if you had loaded them up as environment variables, you would have to restart the container since the variables are assigned during pod startup. Or you could directly inject the values from the ConfigMap into your container environment using the `envFrom` key:
140+
141+
```
142+
containers:
143+
- name: mongodb
144+
image: mongo:latest
145+
ports:
146+
- containerPort: 27017
147+
envFrom:
148+
- configMapRef:
149+
name: mongodb-config
150+
```
151+
152+
In this version, the envFrom field is used to directly reference the ConfigMap. This will inject all the key-value pairs from the ConfigMap as environment variables into the container.
153+
154+
You can also load the ConfigMap as a command line argument in a deployment yaml. You do this using the `command` key. For example:
155+
156+
```
157+
containers:
158+
- name: mongodb
159+
command: ["mongo", "--database-host", "$(DATABASE_URL)"]
160+
image: mongo:latest
161+
env:
162+
- name: DATABASE_URL
163+
valueFrom:
164+
configMapKeyRef:
165+
name: example-configmap
166+
key: DATABASE_URL
167+
```
168+
169+
This command runs when the pod starts, meaning that the value will be extracted from the ConfigMap at this point.
170+
171+
Now that we have looked at various ways we can reference an existing ConfigMap, let's look at all the ways we can create a ConfigMap. The first method is to declare it in a yaml file, which is the example that has been used so far. However, there is also a way to define it in line with a `kubectl create configmap` command:
172+
173+
```
174+
kubectl create configmap example-configmap –from-literal=DATABASE_URL="mongodb://mongo-server:27017/mydatabase" –from-literal=API_KEY"your_api_key_here" –from-literal=DEBUG_MODE="true"
175+
```
176+
177+
This would create the same ConfigMap as the one we had defined before. As you can see, the longer the ConfigMap, the longer the command will be. And this ConfigMap with 3 values is itself a pretty messy command, which is why defining it as a yaml is always better. However, there are some use cases where the above method would be preferred. For example, if you wanted to auto-generate a bunch of ConfigMaps and create them in the cluster with a script, or you have a dynamic ConfigMap that changes during deployment time.
178+
179+
You have already seen how you can define a ConfigMap using a yaml file. However, you can also create a ConfigMap from any other file type as well, such as a text file. You do this using a command similar to the above one, and it automatically creates a resource of kind ConfigMap that has the contents of the file you specified as its data:
180+
181+
```
182+
kubectl create configmap example-configmap –from-file=key1=mongodb.txt
183+
```
184+
185+
List the ConfigMaps:
186+
187+
```
188+
kubectl get configmaps
189+
```
190+
191+
You can then describe the ConfigMap to see its full resource definition:
192+
193+
```
194+
kubectl describe configmap example-configmap
195+
```
196+
197+
Next, let's quickly look at immutable ConfigMaps. If you don't want the contents of a ConfigMap to be changed after you deploy it, you can add the key `immutable` at the root level of the ConfigMap yaml, and it will throw a forbidden error if you try to change the existing ConfigMap. If you want to change the resource from this point forward, you will have to delete the old resource and create a new one.
198+
199+
So, as you can see, there is a lot of flexibility when it comes to what you can define inside a ConfigMap, as well as in the ways you can refer to the ConfigMap. It's a very simple, yet very useful resource. As you progress along Kubernetes, you will constantly come across this particular resource, so make sure you understand it well before moving ahead to more complex resources.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ A Curated List of Kubernetes Labs and Tutorials
118118
- [Rollback updates to application deployment](./Deployment101/README.md#step-4-rollback-updates-to-application-deployment)
119119
- [Cleaning Up](./Deployment101/README.md#step-5-cleanup)
120120

121+
## ConfigMaps101
122+
- [What are ConfigMaps?](./ConfigMaps101/what-are-configmaps.md)
121123

122124
## Scheduler101
123125

0 commit comments

Comments
 (0)