Kubernetes Series – 4.5: Kubernetes Configuration Objects

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

Kubernetes ConfigMaps

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

kubectl create configmap

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

or

kubectl get cm

kubernetes configurations objects

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.

Kubernetes Secrets

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.

Opaque Secrets

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

kubectl create secret

And if we describe it:

kubectl describe secret asecret

kubernetes configuration objects

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 \ --docker-username=yourusername \ --docker-password=yourpassword \ [email protected]

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

TLS Secrets

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:

echo $SECRET_USERNAME

and/or

echo $SECRET_PASSWORD

Kubernetes Series

Thanks for reading,
Ege Aksoz

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.