Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combining multiple k8s secrets into an env variable

My k8s namespace contains a Secret which is created at deployment time (by svcat), so the values are not known in advance.

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: my-database-credentials
data:
  hostname: ...
  port: ...
  database: ...
  username: ...
  password: ...

A Deployment needs to inject these values in a slightly different format:

...

containers:
  env:
  - name: DATABASE_URL
    valueFrom:
      secretKeyRef:
        name: my-database-credentials
        key: jdbc:postgresql:<hostname>:<port>/<database> // ??

  - name: DATABASE_USERNAME
    valueFrom:
      secretKeyRef:
        name: my-database-credentials
        key: username

  - name: DATABASE_PASSWORD
    valueFrom:
      secretKeyRef:
        name: my-database-credentials
        key: password

The DATABASE_URL needs to be composed out of the hostname, port, 'database` from the previously defined secret.

Is there any way to do this composition?

like image 687
metacubed Avatar asked Jan 13 '19 21:01

metacubed


People also ask

How do I use secret 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.

How do you store k8s secrets?

When you create a Secret with kubectl create -f secret. yaml , Kubernetes stores it in etcd. The Secrets are stored in clear in etcd unless you define an encryption provider. When you define the provider, before the Secret is stored in etcd and after the values are submitted to the API, the Secrets are encrypted.

Is it possible to mount secrets to pods?

A secret can be used with a pod in three ways: To populate environment variables for containers. As files in a volume mounted on one or more of its containers. By kubelet when pulling images for the pod.

Can I use both env and envFrom?

As mentioned, both env and envFrom can be used to share ConfigMap key/value pairs with a container as well. However, in the case of the mariadb-config ConfigMap, your entire file is stored as the value to your key, and the file needs to exist in the container's filesystem for MariaDB to be able to use it.


1 Answers

Kubernetes allows you to use previously defined environment variables as part of subsequent environment variables elsewhere in the configuration. From the Kubernetes API reference docs:

Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables.

So, you can first extract the required secret values into environment variables, and then compose the DATABASE_URL with those variables.

...

containers:
  env:
  - name: DB_URL_HOSTNAME               // part 1
    valueFrom:
      secretKeyRef:
        name: my-database-credentials
        key: hostname

  - name: DB_URL_PORT                   // part 2
    valueFrom:
      secretKeyRef:
        name: my-database-credentials
        key: port

  - name: DB_URL_DBNAME                 // part 3
    valueFrom:
      secretKeyRef:
        name: my-database-credentials
        key: database

  - name: DATABASE_URL                  // combine
    value: jdbc:postgresql:$(DB_URL_HOSTNAME):$(DB_URL_PORT)/$(DB_URL_DBNAME)

...

Note the round brackets $(...) used for variable expansion - it's the Kubernetes dependant variable notation.

like image 85
metacubed Avatar answered Sep 30 '22 16:09

metacubed