Explaining ConfigMaps and Secrets

Objectives

After completing this lesson, you will be able to:
  • Explain how to store Configs and Secrets decoupled from your application
  • Configure your application to use ConfigMaps and Secrets
  • Identify differences between mounting and injecting ConfigMaps and Secrets

Usage Scenario for ConfigMaps and Secrets

Assuming that you have already deployed applications, you may consider securing them. Some applications need configuration with sensitive data like passwords or API keys. So, how to store this data securely and inject it into your application?

Why Use ConfigMaps and Secrets?

Applications typically need some configuration. When it comes to distributed applications, each application likely needs to access a database, a message queue, or an SMTP service to send emails. In addition, applications often must be configured with sensitive data like passwords or API keys.

These backing services should be treated as attached resources. It's not recommended to use hard-coded configuration in an application. Instead, the application should be configured to use the attached resources. This allows for easy change of the backing services without the need to update the application. Typically, the application is configured using environment variables, which are simple key-value pairs that are passed to the application at startup. For example, environment variables might store the database connection string, SMTP server address and credentials, and more. The same also applies to sensitive data like passwords or API keys.

When deploying workloads to Kubernetes, you can define environment variables directly in the Deployment manifest. However, this is not a good practice since these manifests are often stored in version control systems like Git. This means that the version control system stores the sensitive data in plain text. This way, the data is not encrypted and anyone who has access to the version control system can read it.

What are ConfigMaps and Secrets in Kubernetes?

Kubernetes has two native resources to store configuration data decoupled from the application: ConfigMaps and Secrets.

ConfigMaps must be used for non-sensitive data. Secrets should be used for sensitive data like passwords or API keys. Note that there is also a restriction on the size of the data stored in ConfigMaps and Secrets. ConfigMaps and Secrets can both store up to 1 MB of data. Everything that exceeds this limit should be mounted into the application as storage.

Using ConfigMaps

See an exmample ConfigMap:

YAML
123456789101112131415161718
apiVersion: v1 kind: ConfigMap metadata: name: my-config data: my-key: "my-value" my-other-key: "my-other-value" # You can also use file-like key-value pairs my-file-like-key: | # This "file" contains a bash script /bin/bash echo "Hello World" my-other-file-like-key: | # This "file" contains a JSON object { "key": "value" }

ConfigMaps are a simple but powerful way to store configuration data. But how do you use them in your application?

To do this, you can assign a ConfigMap to a container in a Deployment manifest as in the following example:

YAML
1234567891011121314151617181920212223242526
apiVersion: apps/v1 kind: Deployment metadata: name: hello-kyma-config spec: replicas: 1 selector: matchLabels: app: hello-kyma-config template: metadata: labels: app: hello-kyma-config spec: containers: - name: my-container image: bash envFrom: # 1. Use all keys as environment variables - configMapRef: name: my-config env: # 2. Use only specific keys as environment variables - name: MY_KEY valueFrom: configMapKeyRef: name: my-config key: my-key

There are far more ways to use ConfigMaps in your application. See Configure a Pod to Use a ConfigMap for more information.

Using Secrets

See an example Secret:

YAML
12345678
apiVersion: v1 kind: Secret metadata: name: my-secret type: Opaque # default type data: username: "YWRtaW4=" # This is the base64 encoded string "admin" password: "dG9wc2VjcmV0" # This is the base64 encoded string "topsecret"

The above manifest creates a Secret with two keys: username and password. Kubernetes also comes with different Secret types that you can use to store different types of sensitive data. For example, the type kubernetes.io/dockerconfigjson stores a Docker config file. This is useful if you want to pull images from a private Docker registry.

Using Secrets in your application is very similar to using ConfigMaps. You can assign a Secret to a container in a Deployment manifest as in the following example:

YAML
12345678910111213141516171819202122232425
apiVersion: apps/v1 kind: Deployment metadata: name: hello-kyma-secret spec: selector: matchLabels: app: hello-kyma-secret template: metadata: labels: app: hello-kyma-secret spec: containers: - name: my-container image: ghcr.io/sap-samples/kyma-runtime-learning-journey/hello-kyma:1.0.0 envFrom: # 1. Use all keys as environment variables - secretRef: name: my-secret env: # 2. Use only specific keys as environment variables - name: PASSWORD valueFrom: secretKeyRef: name: my-secret key: password

Difference Between Mounting and Injecting ConfigMaps and Secrets

ConfigMaps and Secrets in Kubernetes allow you to provide configuration data into Pods at runtime. There are two ways to do this: mounting and injecting.

Mounting involves creating a volume in the Pod and adding the ConfigMap or Secret as a volume to that Pod. This allows you to access the data in the ConfigMap or Secret as files in the volume.

For example, if you have a ConfigMap named my-config with a key config.txt, you can mount it in your Pod like this:

YAML
123456789101112131415
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: bash volumeMounts: - name: my-config-volume mountPath: /etc/config volumes: - name: my-config-volume configMap: name: my-config

Then, you access the data in the file config.txt at /etc/config/config.txt in your container.

Injecting, on the other hand, involves injecting the data directly into the Pod as environment variables or command-line arguments.

For example, if you have a Secret named my-secret with a key password.txt you can inject it into your Pod like this:

YAML
1234567891011121314
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: bash env: - name: MY_PASSWORD valueFrom: secretKeyRef: name: my-secret key: password.txt

You can then access the value of password.txt as the environment variable MY_PASSWORD in your container.

In general, mounting is useful when you need to access the data as files in your container. Injecting is useful when you need to pass the data to your application as environment variables or command-line arguments.

ConfigMaps and Secrets in Kyma Dashboard

In Kyma dashboard, you can create, view, edit, and delete ConfigMaps and Secrets. You can also use the dashboard to create a new Deployment and assign a ConfigMap or Secret to it.

For both ConfigMaps and Secrets, you can see an overview of all existing resources created in the current namespace by clicking on the corresponding menu item in the navigation.

ConfigMaps Overview

After clicking on a ConfigMap or Secret, you can see the details of the resource. You can also edit the resource by clicking on the Edit button.

ConfigMap Details

For Secrets, the values are base64 encoded by default. You can choose Decode to decode the values to plain text.

Secret Details

Summary

This lesson explained the concept of ConfigMaps and Secrets. You have learned when and how to use them and how to create and manage them in the Kyma dashboard.

Further Reading