Assuming that you have already deployed applications, you may consider securing them. Some of them 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 of them 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. Especially 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 need to be configured with sensitive data like passwords or API keys.
These backing services should be treated as attached resources. There should be no hard-coded configuration in the 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 change the application. Typically, the application is configured via environment variables, which are simple key-value pairs that are passed to the application at startup. So by continuing the example above, the application should be configured with environment variables storing the database connection string, SMTP server address and credentials, and so on. 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 sensitive data is stored in plain text in the version control system. This is not a good practice since the data is not encrypted and can be read by anyone with access to the version control system.
Kubernetes has two native resources to store configuration data decoupled from the application: ConfigMaps and Secrets.
ConfigMaps should be used for non-sensitive data. Secrets should be used for sensitive data like passwords or API keys. Please note that there is also a restriction on the size of the data stored in ConfigMaps and Secretes. 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.
A ConfigMap can be created as follows:
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"
}
So, as you can see, ConfigMaps are a simple but powerful way to store configuration data. But how do you use them in your application?
You can assign a ConfigMap to a container in a Deployment manifest as follows:
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: my-image
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. Please refer to the official documentation for more information.
A Secret can be created as follows:
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 listed manifest creates a Secret with two keys: username and password. Kubernetes also comes with different Secret types that can be used to store different types of sensitive data. For example, you can use the kubernetes.io/dockerconfigjson type to store 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 follows:
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: password
ConfigMaps and Secrets in Kubernetes allow you to inject 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:
1234567891011121314apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
volumeMounts:
- name: my-config-volume
mountPath: /etc/config
volumes:
- name: my-config-volume
configMap:
name: my-config
You can then access the data in config.txt as a file 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:
12345678910111213apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
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 while injecting is useful when you need to pass the data to your application as environment variables or command-line arguments.
In the 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 for the current namespace by clicking on the corresponding menu item in the left 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 in the top right corner.
For secrets by default, the values are base64 encoded. You can click on the "Decode" button 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 you can create and manage them in the Kyma dashboard.
Log in to track your progress & complete quizzes