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?
Objectives
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?
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.
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.
See an exmample ConfigMap:
123456789101112131415161718apiVersion: 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:
1234567891011121314151617181920212223242526apiVersion: 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-keyThere are far more ways to use ConfigMaps in your application. See Configure a Pod to Use a ConfigMap for more information.
See an example Secret:
12345678apiVersion: 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:
12345678910111213141516171819202122232425apiVersion: 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: passwordConfigMaps 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:
123456789101112131415apiVersion: 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-configThen, 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:
1234567891011121314apiVersion: 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.txtYou 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.
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.

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.

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

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.