In Kubernetes, we can configure our resources within that resource but sometimes this makes the resource YAML file incredibly difficult to follow and unmaintainable. This is why we need Kubernetes configuration objects.
A ConfigMap is an API object used to store non-confidential data in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or as configuration files in a volume.
Use a ConfigMap for setting configuration data separately from the application code.
Please note that ConfigMap and the resource that will use it ( e.g Pod ) should be in the same namespace
ConfigMap can be created both in an imperative and declarative way.
With the imperative way, we can either read config from file or input the config within the command. For instance, if we have a file called config.txt.
kubectl create configmap my-config --from-file=/path/to/file/config.txt
If it is an env file:
kubectl create configmap my-config --from-env-file=/path/to/file/config.env
We can also create it from literal:
kubectl create configmap my-config --from-literal=foo=bar
For more information on this please take a look at here: https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#-em-configmap-em-
In a declarative way, ConfigMap is slightly different from other resources in Kubernetes as there is no spec but data this time.
apiVersion: v1 kind: ConfigMap metadata: name: my-config data: foo:"bar"
To retrieve the configmap use:
kubectl get configmaps
kubectl get cm
After we create a ConfigMap in any of these ways above, let’s use it in a Kubernetes resource that we have created a lot of times in this tutorial.
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx env: - name: FOO_ENV valueFrom: configMapKeyRef: name: my-config key: foo
And if you describe that pod, you’ll observe the env variable.
What if the configuration parameters that we would like to use are confidential. Then we use Secrets instead of ConfigMaps.
A sample declarative way to create a Secret is as follows:
apiVersion: v1 kind: Secret metadata: name: asecret type: Opaque data: foo:bar
As you can see, it is similar to creating a ConfigMap only difference being you need to specify type here ( Opaque is the default if not specified). There are different types of Secrets for different usage purposes which I would like to talk about a few of them.
This is the default secret type to store data. An opaque secret can be created both in an imperative and declarative way. To create it you need to use a ‘generic’ subcommand.
kubectl create secret generic asecret
Of course, this will create a secret with no data and you may edit it to add data afterward. You can also create a generic secret “from file” or “from literal” in the same way as ConfigMap.
kubectl create secret generic asecret --from-literal=foo=bar
And if we describe it:
kubectl describe secret asecret
We can observe the type is “Opaque” and the data inside is hidden.
Docker Config Secrets
If you are familiar with Docker, you might know that some of the docker images require login to the DockerHub. If that is the case we need to Docker config Secrets in Kubernetes.
Docker config secrets can be created both in an imperative and declarative way.
kubectl create secret docker-registry my-docker-registry-secret \
And you can use this secret in the declaration of the resource that will use the image that requires login.
Basic authentication Secret
Sometimes we just need basic authentication ( i.e username/password ) to access the resource we want to access. For these scenarios, Kubernetes supports the Basic authentication Secrets.
This type of secret can only be created in the declarative approach:
apiVersion: v1 kind: Secret metadata: name: basic-auth type: kubernetes.io/basic-auth stringData: username: admin password: t0p-Secret
For some applications, we need to set up secure communication and we use TLS for this purpose. We can use TLS Secrets to store our TLS keys and certs in an encrypted way.
This type of secret can be created both in imperative and declarative ways.
kubectl create secret tls my-tls-secret --cert=path/to/cert/file --key=path/to/key/file
For all types of secrets, you may refer to the documentation: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types
Configure a Secret With a Pod
We learned about creating different types of secrets but how can we use them with a Pod.
There are multiple ways to use secrets with a Pod.
Mount Secret to Pod(s)
After creating the secret, you can mount that secret to the Pod(s). You can learn more about volumes and mount here ( hyperlink to volume page ).
A sample YAML file for mounting a secret:
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: mysecret
As you can see here, we use the volume approach but this time attach a secret there.
To consume the secret that has been mounted, basically, we need to go to the mountPath ( i.e /etc/foo in this example ). There we will see a key/value pair but the value will be base64 encoded.
Using Secrets as Environment Variables
Another way of using secrets with a Pod is to use them as environment variables. This approach as you can see is similar to using a ConfigMap.
After we have created a secret, basically we put the secret information as an environment variable in the Pod definition, such as:
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password restartPolicy: Never
To consume secret that has been introduced as an environment variable, you need to use shell commands such as:
- Episode 1: Introduction to Kubernetes
- Episode 2: How to Create a Kubernetes Cluster
- Episode 3: Kubectl
- Episode 4.1: Kubernetes Objects
- Episode 4.2: Kubernetes Workloads
- Episode 4.3: Kubernetes Services
- Episode 4.4: Kubernetes Storage
- Episode 4.5: Kubernetes Configuration Objects
- Episode 5: Scheduling in Kubernetes
- Episode 6: Kubernetes Upgrade and Deployment Strategies
- Episode 7: Kubernetes Security
- Episode 8: Deploy a Full Stack Application in Kubernetes
Thanks for reading,
Holding a BSc in Mechatronics, Ege loves to automate. He is now working as a Software Development Engineer In Test at XebiaLabs, Amsterdam. He is also passionate about Artificial Neural Networks.