- Discuss configuration management for applications in Kubernetes using ConfigMaps.
- Share sensitive data (such as passwords) using Secrets.
ConfigMaps allow us to decouple the configuration details from the container image. In the form of environment variables, sets of commands and arguments, or volumes, we can pass configuration data, which then are consumed by Pods. We can create ConfigMaps from literal values, from configuration files, from one or more files or directories.
Create from Literal Values
As with other objects we can create and display ConfigMaps by using the
We are going to create the ConfigMap and display the Details
$ kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2 configmap/my-config created $ kubectl get configmaps my-config -o yaml
We can see in the output, in yaml format, our passed values in the data field. The name and other details are part of the metadata field.
Create from Configuration File
We specify the
kind, metadata and
data fields, targeting the v1 endpoint.
apiVersion: v1 kind: COnfigMap metadata: name: customer1 data: TEXT1: Customer1_Company TEXT2: Welcomes You COMPANY: Customer1 Company Technology Ltd.
$ kubectl create -f customer1-configmap.yaml configmap/customer1 created
Create a ConfigMap from a File
We are going to create a file called
permission=read-only allowed="true" resetCount=3
And create the ConfigMap with
$ kubectl create configmap permission-config --from-file=./permission-reset.properties configmap/permission-config created
Use ConfigMaps inside Pods
Inside the container, we retrieve key-value data or values as environment variables.
... containers: - name: myapp-full-container image: myapp envFrom: - configMapRef: name: full-config-map ...
This configuration will give the myapp-full-container the values of full-config-map as environment variables.
It is also possible to specify two seperate ConfigMaps from which the container should receive its environment variables.
... containers: - name: myapp-specific-container image: myapp env: - name: SPECIFIC_ENV_VAR1 valueFrom: configMapKeyRef: name: config-map-1 key: SPECIFIC_DATA - name: SPECIFIC_ENV_VAR2 valueFrom: configMapKeyRef: name: config-map-2 key: SPECIFIC_INFO ...
We will get the SPECIFIC_ENV_VAR1 variable set to SPECIFIC_DATA key of config-map-1, and SPECIFIC_ENV_VAR2 set to SPECIFIC_INFO key from config-map-2.
A Volume can be configured inside a Pod. For each key in the ConfigMap, a file gets created inthe mount path and the content of that file becomes the respective key's value:
... containers: - name: myapp-vol-container image: myapp volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: name: vol-config-map ...
How to configure pod ConfigMaps can be found here. Also some Hands on examples are given.
Secrets are similar to ConfigMaps, but we are able to control how the information in a Secre is used, reducing the risk for accidental exposures. In Deployments or other resources, the Secret object is referenced, wihtout exposing its content.
Kubernetes Secrets are, by default, stored as unencrypted base64-encoded strings. By default they can be retrieved - as plain text - by anyone with API access, or anyone with access to Kubernetes' underlying data store, etcd. In order to safely use Secrets, we recommend you (at a minimum):
Enable Encryption at Rest for Secrets.
Enable RBAC rules that restrict reading and writing the Secret. Be aware that secrets can be obtained implicitly by anyone with the permission to create a Pod.
Create a Secret from literal
We can create secrets by using the
kubectl CLI and view the details, although they will not reveal the content of the Secret.
$ kubectl create secret generic my-password --from-literal=password=mysqlpassword secret/my-password created $ kubectl get secret my-password NAME TYPE DATA AGE my-password Opaque 1 27s $ kubectl describe secret my-password Name: my-password Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password: 13 bytes
Create a Secret Manually
First we encode the password using
base64 and then use it in the configuration file.
echo mysqlpassword |base64 bXlzcWxwYXNzd29yZAo= --- apiVersion: v1 kind: Secret metadata: name: my-password type: Opaque data: password: bXlzcWxwYXNzd29yZAo=
Note that any one can decode our encoded string, base64 doesn't mean encryption.
stringData maps, there is no need to encode the value of each sensitive information field. The value of the sensitive field will be encoded when the password Secret is created. Using mypass.yaml we can use the
kubectl create command.
apiVersion: v1 kind: Secret metadata: name: my-password type: Opaque stringData: password: mysqlpassword
$ kubectl create -f mypass.yaml secret/my-password created
Create a Secret from File and display its details
We are going to encode our sensitive data and then write encoded data to a Text file.
$ echo mysqlpassword | base64 bXlzcWxwYXNzd29yZAo= $ echo -n 'bXlzcWxwYXNzd29yZAo=' > password.txt
Create the secret from the password.txt file,
$ kubectl create secret generic my-file-password --from-file=password.txt secret/my-file-password created $ kubectl get secret my-file-password NAME TYPE DATA AGE my-file-password Opaque 1 77s $ kubectl describe secret my-file-password Name: my-file-password Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== password.txt: 20 bytes
Use Secrets inside pods
Just like ConfigMaps, Secrets are consumed by containers in pods as mounted data volumes or as environment variables.
Using secrets as Environment Variables, we'll assing the password key of the my-password Secret.
... spec: containers: - image: wordpress:4.7.3-apache name: wordpress env: - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: my-password key: password ...
Using secrets as Files from a Pod, where we mount a Secret as a Volume inside a Pod.
.... spec: containers: - image: wordpress:4.7.3-apache name: wordpress volumeMounts: - name: secret-volume mountPath: "/etc/secret-data" readOnly: true volumes: - name: secret-volume secret: secretName: my-password ....
For more details and some examples you can visit Managing Secrets.
We are going to alter the index.html file inside an nginx container by providing a ConfigMap, lets assume following web-config.yaml
apiVersion: v1 kind: ConfigMap metadata: name: web-config namespace: default data: STRING: Welcome to MY-NGINX! PATH: /usr/share/nginx/html/index.html
We'll create the object and display the web-config with two data fields.
$ kubectl create -f web-config.yaml configmap/web-config created $ kubectl describe cm Name: web-config Namespace: default Labels: <none> Annotations: <none> Data ==== PATH: ---- /usr/share/nginx/html/index.html STRING: ---- Welcome to MY-NGINX! Events: <none>
Let's assume a app-config.yaml where we create a Pod with a nginx container, which replaces the content of the given DATA_STRING on the given DATA_PATH.
Both these variables will be passed in as environment Variables via the ConfigMap we just created.
apiVersion: v1 kind: Pod metadata: name: app-config spec: containers: - name: nginx image: nginx command: ["/bin/sh", "-c", "echo $(DATA_STRING) > $(DATA_PATH); sleep 3600" ] env: - name: DATA_STRING valueFrom: configMapKeyRef: name: web-config key: STRING optional: true - name: DATA_PATH valueFrom: configMapKeyRef: name: web-config key: PATH optional: true restartPolicy: Never
$ kubectl create -f app-config.yaml pod/app-config created
This time we will observe the value inside the container by using the
kubectl exec command. And by
cat index.html we will see the content of the file.
$ kubectl exec app-config -- /bin/sh -c 'cat /usr/share/nginx/html/index.html' Welcome to MY-NGINX!
As we expected the content of the file will be the value we have passed in by the ConfigMap.
The Secrets part of this Hands On would be almost the same. This is how we consume ConfigMaps in our Pods containers. A good way to provide different values for the same containers, without creating several similar containers.
That's it for today folks! There is much more to read and to configure out here. We only went through a simple example, we also know how to consume environmental values in our containers. Be it php, nodejs, .net and what not. This way we will give simple values as well as sensitive information in our containers.