As the pods might need the same configuration variables or credentials, you can store them in a single location by using a ConfigMap or a SecretMap.
This mechanism is called “configuration injection”.
You can create a config map the imperative way and specify the source, that can be:
- from literal
- from file
- from env-file
For example:
$ kubectl create configmap cm-db --from-literal=DB_NAME=mydb --from-literal=DBHOST=mydbsite.net
You can generate if from a file, like:
$ kubectl create configmap game-config --from-file=/opt/config-maps/my-map.txt
The file “my-map.txt” might look like:
# Environment files use a new line for each variable.
KIAMOL_CHAPTER=ch04
KIAMOL_SECTION=ch04-4.1
KIAMOL_EXERCISE=try it now
You can as well define a map directly in a yaml file, in the declarative way. For example, to use the file “nginx.conf”:
apiVersion: v1
kind: ConfigMap
metadata:
name: config
data:
nginx.conf: |
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
Or simply key-value entries like:
apiVersion: v1
kind: ConfigMap
metadata:
name: random-generator-config
data:
PATTERN: "logging"
EXTRA_OPTIONS: "high-secure,native"
SEED: "432576345"
You can use the alias “cm” as well. For example, to get the details:
$ kubectl get cm my-cf-map
The config map needs to exist before you deploy the pod.
You can add an environment variable from a config map for a specific container, like:
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
env:
- name: PATTERN
valueFrom:
configMapKeyRef:
name: random-generator-config
key: pattern
Or even add all the variables by a prefix for all the containers with “envFrom”:
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
envFrom:
- configMapRef:
name: random-generator-config
prefix: CONFIG_
You can also mount a config map as a volume:
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
volumeMounts:
- name: config-volume
mountPath: /config
volumes:
- name: config-volume
configMap:
name: random-generator-config
This ways the volume will map each entry with a file.
SECRETS
Secrets have a similar API to config maps, but they are managed by Kubernetes in a different way: they are stored in memory rather than disk and encrypted both when in transit and at rest.
There are three types of secret:
- docker-registry
- TLS
- generic
Assuming you want to put your username and password in two different text files, called “username.txt” and “password.txt” respectively, you can create a secret like the folliwng:
$ kubectl create secret generic database-creds --from-file=username.txt --from-file=password.txt
$ kubectl create secret generic passwords --from-literal=password=foobar
Notice that you need to include “generic” in the command.
You create tls and docker-registry entries in the same way:
$ kubectl create secret tls demo-tls --key "auth.key" --cert "auth.cer" -n foo
$
kubectl create secret docker-registry gcr-pull-key --docker-server=gcr.io --docker-username=_json_key --docker-password="$(cat gke_key.json)" --docker-email=xyz@slb.com
In the manifest file, you can reference secrets:
apiVersion: v1
kind: Pod
metadata:
name: random-generator
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
env:
- name: LOG_FILE
value: /tmp/random.log
- name: PATTERN
valueFrom:
configMapKeyRef:
name: random-generator-config
key: pattern
- name: SEED
valueFrom:
secretKeyRef:
name: random-generator-secret
key: seed
Just like for the config mpa, you can import all the keys an env variables at once, like:
containers:
- name: secret-handler
...
envFrom:
- secretRef:
name: secret1
Besides using the “secretKeyRef” parameter, you can reference a file in a volume and then specify the secret name in the “volumes” section.
For example,:
spec:
containers:
- name: db
image: postgres:11.6-alpine
env:
- name: POSTGRES_PASSWORD_FILE # Sets the path to the file
value: /secrets/postgres_password
volumeMounts: # Mounts a Secret volume
- name: secret # Names the volume
mountPath: "/secrets"
volumes:
- name: secret
secret: # Volume loaded from a Secret
secretName: todo-db-secret-test # Secret name
defaultMode: 0400 # Permissions to set for files
items: # Optionally names the data items
- key: POSTGRES_PASSWORD
path: postgres_password
Credentials get encoded in base64. So you can basically read them in clear text, by running:
$ echo <secret-string> | base64 -d
This means that it´s better to use a specific tools if you want to achieve more security!
As secrets can be accessed by whoever has access to the cluster and decoded (i.e. read in clear text!), they cannot be considered a good productive solution. In other words, you should better look around for a specific commercial tool like Hashicorp Vault.