There are two resources for configuration management. Secrets are for sensitive information that are given to containers on runtime. ConfigMaps are basically secrets but may contain any kinds of configuration. Use cases for ConfigMaps vary: you may have a ConfigMap mapped to a file with some values that the server reads during runtime and changing the ConfigMap will instantly change the behavior of the application. Both can be used to introduce environment variables.
Let's use pixabay to display images on a simple web app. We will need to utilize authentication with an API key. The API docs are good, we just need to log in to get ourselves a key here https://pixabay.com/api/docs/.
Here's the app available. The application requires an API_KEY environment variable.
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes-hy/material-example/master/app4/manifests/deployment.yaml \ -f https://raw.githubusercontent.com/kubernetes-hy/material-example/master/app4/manifests/ingress.yaml \ -f https://raw.githubusercontent.com/kubernetes-hy/material-example/master/app4/manifests/service.yaml
The requirement for an environment variable inside a secret is added to the deployment like so
... containers: - name: imageagain envFrom: - secretRef: name: pixabay-apikey
or if we wanted to remap the field, for example to use the same secret in multiple applications:
... containers: - name: imageagain env: - name: API_KEY # ENV name passed to container valueFrom: secretKeyRef: name: pixabay-apikey key: API_KEY # ENV name in the secret
The application won't run at first and we can see the reason with
kubectl get po and a more detailed with
kubectl describe pod imageapi-dep-....
Let's use a secret to pass the API key environment variable to the application.
Secrets use base64 encoding to avoid having to deal with special characters. We would like to use encryption to avoid printing our API_KEY for the world to see but for the sake of testing create and apply a new file secret.yaml with the following:
apiVersion: v1 kind: Secret metadata: name: pixabay-apikey data: API_KEY: aHR0cDovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PWRRdzR3OVdnWGNR # base64 encoded should look something like this, note that this won't work
As the containers are already instructed to use the environment from the secret using it happens automatically. We can now confirm that the app is working and then delete the old secret.
For encrypted secrets let's use "Sealed Secrets". It seems to be a solution until proven otherwise. We need to install it into our local machine as well as to our cluster. Install instructions are simple: apply the correct version to kube-system namespace.
$ kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.12.1/controller.yaml
It may take a while to start but after that it's ready to convert your secret into a sealed secret and apply it. Before that confirm that we didn't forget to remove the old secret.
$ kubectl get secrets NAME TYPE DATA AGE default-token-jfr7n kubernetes.io/service-account-token 3 36m $ kubeseal -o yaml < secret.yaml > sealedsecret.yaml $ kubectl apply -f sealedsecret.yaml $ kubectl get secrets NAME TYPE DATA AGE default-token-jfr7n kubernetes.io/service-account-token 3 37m pixabay-apikey Opaque 1 2s
To confirm everything is working we can delete the pod and let it restart with the new environment variable
kubectl delete po imageapi-dep-.... Using SealedSecret was our first time using a custom resource. We will be designing our own custom resources in part 5.
ConfigMaps are similar but the data doesn't have to be encoded and is not encrypted. Let's say you have a videogame server that takes a "serverconfig.txt" which looks like this:
The following ConfigMap would contain the values:
apiVersion: v1 kind: ConfigMap metadata: name: example-configmap data: serverconfig.txt: | maxplayers=12 difficulty=2
Now the ConfigMap can be added into the container as a volume. By changing a value, like "maxplayers" in this case, and applying the ConfigMap the changes would be reflected in that volume.