<p><strong>Background:</strong></p>

<p>Currently we're using Docker and Docker Compose for our services. We have externalized the configuration for different environments into files that define environment variables read by the application. For example a <code>prod.env</code> file:</p>

<pre><code>ENV_VAR_ONE=Something Prod
ENV_VAR_TWO=Something else Prod
</code></pre>

<p>and a <code>test.env</code> file:</p>

<pre><code>ENV_VAR_ONE=Something Test
ENV_VAR_TWO=Something else Test
</code></pre>

<p>Thus we can simply use the <code>prod.env</code> or <code>test.env</code> file when starting the container:</p>

<pre><code>docker run --env-file prod.env &lt;image&gt;
</code></pre>

<p>Our application then picks up its configuration based on the environment variables defined in <code>prod.env</code>. </p>

<p><strong>Questions:</strong></p>

<ol>
<li>Is there a way to provide environment variables from a file in Kubernetes (for example when defining a pod) instead of hardcoding them like this:</li>
</ol>

<pre>
apiVersion: v1
kind: Pod
metadata: 
  labels: 
    context: docker-k8s-lab
    name: mysql-pod
  name: mysql-pod
spec: 
  containers: 
    - 
      env: 
        - 
          name: MYSQL_USER
          value: mysql
        - 
          name: MYSQL_PASSWORD
          value: mysql
        - 
          name: MYSQL_DATABASE
          value: sample
        - 
          name: MYSQL_ROOT_PASSWORD
          value: supersecret
      image: "mysql:latest"
      name: mysql
      ports: 
        - 
          containerPort: 3306
</pre>

<ol start="2">
<li>If this is not possible, what is the suggested approach?</li>
</ol>

<p>You can populate a container's environment variables through the use of <a href="http://kubernetes.io/docs/user-guide/secrets/" rel="noreferrer">Secrets</a> or <a href="http://kubernetes.io/docs/user-guide/configmap/" rel="noreferrer">ConfigMaps</a>. Use Secrets when the data you are working with is sensitive (e.g. passwords), and ConfigMaps when it is not.</p>

<p>In your Pod definition specify that the container should pull values from a Secret:</p>

<pre><code>apiVersion: v1
kind: Pod
metadata: 
  labels: 
    context: docker-k8s-lab
    name: mysql-pod
  name: mysql-pod
spec: 
  containers:
  - image: "mysql:latest"
    name: mysql
    ports: 
    - containerPort: 3306
    envFrom:
      - secretRef:
         name: mysql-secret
</code></pre>

<p>Note that this syntax is only available in Kubernetes 1.6 or later. On an earlier version of Kubernetes you will have to specify each value manually, e.g.:</p>

<pre><code>env: 
- name: MYSQL_USER
  valueFrom:
    secretKeyRef:
      name: mysql-secret
      key: MYSQL_USER
</code></pre>

<p><strong>(Note that <code>env</code> take an array as value)</strong></p>

<p>And repeating for every value.</p>

<p>Whichever approach you use, you can now define two different Secrets, one for production and one for dev.</p>

<p>dev-secret.yaml:</p>

<pre><code>apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  MYSQL_USER: bXlzcWwK
  MYSQL_PASSWORD: bXlzcWwK
  MYSQL_DATABASE: c2FtcGxlCg==
  MYSQL_ROOT_PASSWORD: c3VwZXJzZWNyZXQK
</code></pre>

<p>prod-secret.yaml:</p>

<pre><code>apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  MYSQL_USER: am9obgo=
  MYSQL_PASSWORD: c2VjdXJlCg==
  MYSQL_DATABASE: cHJvZC1kYgo=
  MYSQL_ROOT_PASSWORD: cm9vdHkK
</code></pre>

<p>And deploy the correct secret to the correct Kubernetes cluster:</p>

<pre><code>kubectl config use-context dev
kubectl create -f dev-secret.yaml

kubectl config use-context prod
kubectl create -f prod-secret.yaml
</code></pre>

<p>Now whenever a Pod starts it will populate its environment variables from the values specified in the Secret.</p>
