Best Practice for Operators for how to get Deployment's configuration
Using enviroment variables
It can be convenient that your app gets your data as environment variables.
Environment variables from ConfigMap
For non-sensitive data, you can store your variables in a ConfigMap
and then define container environment variables using the ConfigMap
data.
Create the ConfigMap
first. File configmaps.yaml
:
apiVersion: v1kind: ConfigMapmetadata: name: special-config namespace: defaultdata: special.how: very---apiVersion: v1kind: ConfigMapmetadata: name: env-config namespace: defaultdata: log_level: INFO
Create the ConfigMap:
kubectl create -f ./configmaps.yaml
Then define the environment variables in the Pod
specification, pod-multiple-configmap-env-variable.yaml
:
apiVersion: v1kind: Podmetadata: name: dapi-test-podspec: containers: - name: test-container image: k8s.gcr.io/busybox command: [ "/bin/sh", "-c", "env" ] env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name: LOG_LEVEL valueFrom: configMapKeyRef: name: env-config key: log_level restartPolicy: Never
Create the Pod
:
kubectl create -f ./pod-multiple-configmap-env-variable.yaml
Now in your controller you can read these environment variables SPECIAL_LEVEL_KEY
(which will give you special.how
value from special-config
ConfigMap
) and LOG_LEVEL
(which will give you log_level
value from env-config
ConfigMap
):
For example:
specialLevelKey := os.Getenv("SPECIAL_LEVEL_KEY")logLevel := os.Getenv("LOG_LEVEL")fmt.Println("SPECIAL_LEVEL_KEY:", specialLevelKey)fmt.Println("LOG_LEVEL:", logLevel)
Environment variables from Secret
If your data is sensitive, you can store it in a Secret
and then use the Secret
as environment variables.
You'll first need to encode your strings using base64
.
# encode username$ echo -n 'admin' | base64YWRtaW4=# encode password$ echo -n '1f2d1e2e67df' | base64MWYyZDFlMmU2N2Rm
Then create a Secret
with the above data:
apiVersion: v1kind: Secretmetadata: name: mysecrettype: Opaquedata: username: YWRtaW4= password: MWYyZDFlMmU2N2Rm
Create a Secret
with kubectl apply
:
$ kubectl apply -f ./secret.yaml
Please notice that there are other ways to create a secret, pick one that works best for you:
- Creating a
Secret
usingkubectl
- Creating a
Secret
from a generator - Creating a
Secret
from files - Creating a
Secret
from string literals
Now you can use this created Secret
for environment variables.
To use a secret in an environment variable in a Pod:
- Create a secret or use an existing one. Multiple Pods can reference the same secret.
- Modify your Pod definition in each container that you wish to consume the value of a secret key to add an environment variable for each secret key you wish to consume. The environment variable that consumes the secret key should populate the secret's name and key in
env[].valueFrom.secretKeyRef
.- Modify your image and/or command line so that the program looks for values in the specified environment variables.
Here is a Pod
example from Kubernetes docs that shows how to use a Secret
for environment variables:
apiVersion: v1kind: Podmetadata: name: secret-env-podspec: containers: - name: mycontainer image: redis env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: mysecret key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password restartPolicy: Never
Finally, as stated in the docs:
Inside a container that consumes a secret in an environment variables, the secret keys appear as normal environment variables containing the base64 decoded values of the secret data.
Now in your controller you can read these environment variables SECRET_USERNAME
(which will give you username
value from mysecret
Secret
) and SECRET_PASSWORD
(which will give you password
value from mysecret
Secret
):
For example:
username := os.Getenv("SECRET_USERNAME")password := os.Getenv("SECRET_PASSWORD")
Using volumes
You can also mount both ConfigMap
and Secret
as a volume to you pods.
Populate a Volume with data stored in a ConfigMap:
apiVersion: v1kind: Podmetadata: name: dapi-test-podspec: containers: - name: test-container image: k8s.gcr.io/busybox command: [ "/bin/sh", "-c", "ls /etc/config/" ] volumeMounts: - name: config-volume mountPath: /etc/config volumes: - name: config-volume configMap: # Provide the name of the ConfigMap containing the files you want # to add to the container name: special-config restartPolicy: Never
Using Secrets as files from a Pod:
To consume a Secret in a volume in a Pod:
- Create a secret or use an existing one. Multiple Pods can reference the same secret.
- Modify your Pod definition to add a volume under .spec.volumes[]. Name the volume anything, and have a .spec.volumes[].secret.secretName field equal to the name of the Secret object.
- Add a
.spec.containers[].volumeMounts[]
to each container that needs the secret. Specify.spec.containers[].volumeMounts[].readOnly = true
and.spec.containers[].volumeMounts[].mountPath
to an unused directory name where you would like the secrets to appear.Modify your image or command line so that the program looks for files in that directory. Each key in the secretdata
map becomes the filename undermountPath
.
An example of a Pod
that mounts a Secret
in a volume:
apiVersion: v1kind: Podmetadata: name: mypodspec: containers: - name: mypod image: redis volumeMounts: - name: foo mountPath: "/etc/foo" readOnly: true volumes: - name: foo secret: secretName: mysecret