<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Gabriel</title>
    <description>The latest articles on DEV Community by Gabriel (@kainlite).</description>
    <link>https://dev.to/kainlite</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1349917%2F6419171e-8027-4a0f-b2d9-faa43dc699cc.jpeg</url>
      <title>DEV Community: Gabriel</title>
      <link>https://dev.to/kainlite</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kainlite"/>
    <language>en</language>
    <item>
      <title>How to mount secrets as files or environment variables in kubernetes</title>
      <dc:creator>Gabriel</dc:creator>
      <pubDate>Sat, 22 Mar 2025 16:25:56 +0000</pubDate>
      <link>https://dev.to/kainlite/how-to-mount-secrets-as-files-or-environment-variables-in-kubernetes-1m4a</link>
      <guid>https://dev.to/kainlite/how-to-mount-secrets-as-files-or-environment-variables-in-kubernetes-1m4a</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This will be a short article exploring the different ways you can mount secrets in kubernetes and also understand when to use each method, mount means load or expose basically in your Pod either as an env var or as a file, or multiple files even, the decision is up to you and how your app uses or consumes those secrets.&lt;/p&gt;

&lt;p&gt;First we will explore how to create and expose secrets as environment variables, this is probably the most used way and is really useful as the format is really easy to follow and maintain, lets see an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ kubectl create secret generic supersecret &lt;span class="nt"&gt;-n&lt;/span&gt; example &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;MY_SUPER_ENVVAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a_secret &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;ANOTHER_ENVVAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;just_another_secret
secret/supersecret created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Lets check the contents of the secret, it maintains a similar shape as we defined, be sure to check the help of &lt;code&gt;kubectl&lt;/code&gt; as it contains many examples of how to pass data into the actual secret.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ kubectl get secret supersecret &lt;span class="nt"&gt;-o&lt;/span&gt; yaml
apiVersion: v1
data:
  ANOTHER_ENVVAR: &lt;span class="nv"&gt;anVzdF9hbm90aGVyX3NlY3JldA&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;
  MY_SUPER_ENVVAR: &lt;span class="nv"&gt;YV9zZWNyZXQ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
kind: Secret
metadata:
  name: supersecret
  namespace: example
&lt;span class="nb"&gt;type&lt;/span&gt;: Opaque
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All good so far, but how do we actually use that secret? Lets create a spec for it, then we will explore a few options there...&lt;/p&gt;



&lt;h3&gt;
  
  
  First scenario: single key from a secret
&lt;/h3&gt;

&lt;p&gt;In this example we have a StatefulSet mounting a secret using a specific key as an environment variable, this is pretty common and useful when you don't need all keys to be mounted in all pods for example or when using shared configurations, pay special attention to the &lt;code&gt;valueFrom&lt;/code&gt; section, the name indicates the name of the secret and the key how it is stored inside the &lt;code&gt;data&lt;/code&gt; block of the same, this also works with ConfigMaps as you might have guessed, instead of &lt;code&gt;secretKeyRef&lt;/code&gt; use &lt;code&gt;configMapKeyRef&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: example
  name: example
  namespace: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example
        image: busybox:1.36
        &lt;span class="nb"&gt;command&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sh"&lt;/span&gt;, &lt;span class="s2"&gt;"-c"&lt;/span&gt;, &lt;span class="s2"&gt;"/bin/sleep 3600"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="nb"&gt;env&lt;/span&gt;:
          - name: MY_SUPER_ENVVAR
            valueFrom: 
              secretKeyRef:
                name: supersecret
                key: MY_SUPER_ENVVAR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;And the result would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; example &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-ti&lt;/span&gt; example-64f956f9c9-fxn28 &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;env&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ENV
&lt;span class="nv"&gt;MY_SUPER_ENVVAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a_secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  Second scenario: env vars from a secret
&lt;/h3&gt;

&lt;p&gt;In this second example, we will mount all values from the secret as environment variables, so it is important to have the right format in the secret, and there is a super-handy keyword for that: &lt;code&gt;envFrom&lt;/code&gt; and it also works with ConfigMaps, instead of using &lt;code&gt;secretRef&lt;/code&gt; you would need to specify: &lt;code&gt;configMapRef&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: example
  name: example
  namespace: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example
        image: busybox:1.36
        &lt;span class="nb"&gt;command&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sh"&lt;/span&gt;, &lt;span class="s2"&gt;"-c"&lt;/span&gt;, &lt;span class="s2"&gt;"/bin/sleep 3600"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        envFrom:
          - secretRef:
              name: supersecret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;And the result would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; example &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-ti&lt;/span&gt; example-584757d47f-gbxgq &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;env&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;ENV
&lt;span class="nv"&gt;ANOTHER_ENVVAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;just_another_secret
&lt;span class="nv"&gt;MY_SUPER_ENVVAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;a_secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  Third scenario: a secret as files
&lt;/h3&gt;

&lt;p&gt;In some cases your application might need a config file mounted in the pod, in those cases you can mount the entire Secret or ConfigMap or specific keys as specific files (Fourth scenario)&lt;/p&gt;

&lt;p&gt;For this case we will use a new secret, with a json file in it stored as the key &lt;code&gt;test.json&lt;/code&gt; which is the actual filename, this is pretty handy, there could be multiple files stored there and we could mount all of them at once, or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ &lt;span class="nb"&gt;cat &lt;/span&gt;test.json
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"key1"&lt;/span&gt;: &lt;span class="s2"&gt;"value1"&lt;/span&gt;,
  &lt;span class="s2"&gt;"key2"&lt;/span&gt;: &lt;span class="s2"&gt;"value2"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

❯ kubectl create secret generic supersecret2 &lt;span class="nt"&gt;-n&lt;/span&gt; example &lt;span class="nt"&gt;--from-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;test.json
secret/supersecret2 created

❯ kubectl get secret supersecret2 &lt;span class="nt"&gt;-o&lt;/span&gt; yaml
apiVersion: v1
data:
  test.json: &lt;span class="nv"&gt;ewogICJrZXkxIjogInZhbHVlMSIsCiAgImtleTIiOiAidmFsdWUyIgp9Cg&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;
kind: Secret
metadata:
  name: supersecret2
  namespace: example
&lt;span class="nb"&gt;type&lt;/span&gt;: Opaque
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Now lets use our new secret:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: example
  name: example
  namespace: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example
        image: busybox:1.36
        &lt;span class="nb"&gt;command&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sh"&lt;/span&gt;, &lt;span class="s2"&gt;"-c"&lt;/span&gt;, &lt;span class="s2"&gt;"/bin/sleep 3600"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        volumeMounts:
          - mountPath: &lt;span class="s2"&gt;"/var/mysecrets"&lt;/span&gt;
            name: test.json
            readOnly: &lt;span class="nb"&gt;true
      &lt;/span&gt;volumes:
        - name: test.json
          secret:
            secretName: supersecret2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;And the result would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; example &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-ti&lt;/span&gt; example-5b9c58b7f9-zv9nr &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; /var/mysecrets/test.json
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"key1"&lt;/span&gt;: &lt;span class="s2"&gt;"value1"&lt;/span&gt;,
  &lt;span class="s2"&gt;"key2"&lt;/span&gt;: &lt;span class="s2"&gt;"value2"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h3&gt;
  
  
  Fourth scenario: a secret key as a single file
&lt;/h3&gt;

&lt;p&gt;Sometimes you just need a specific config as a file in a specific path, imagine some json config or a string that needs to be present in some file for you app to read.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: example
  name: example
  namespace: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      containers:
      - name: example
        image: busybox:1.36
        &lt;span class="nb"&gt;command&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sh"&lt;/span&gt;, &lt;span class="s2"&gt;"-c"&lt;/span&gt;, &lt;span class="s2"&gt;"/bin/sleep 3600"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        volumeMounts:
          - mountPath: &lt;span class="s2"&gt;"/var/myapp/server.config"&lt;/span&gt;
            name: config
            readOnly: &lt;span class="nb"&gt;true
            &lt;/span&gt;subPath: test.json
      volumes:
        - name: config
          secret:
            secretName: supersecret2
            items:
              - key: test.json
                path: test.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;And the result would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; example &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-ti&lt;/span&gt; example-59f565fbbf-cgk5c &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;cat&lt;/span&gt; /var/myapp/server.config
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"key1"&lt;/span&gt;: &lt;span class="s2"&gt;"value1"&lt;/span&gt;,
  &lt;span class="s2"&gt;"key2"&lt;/span&gt;: &lt;span class="s2"&gt;"value2"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Which is incredible useful because you can mount the file as you need as long as you have it properly stored as a Secret or ConfigMap, when debugging issues with your containers and secrets make sure to use &lt;code&gt;kubectl describe pod&lt;/code&gt;, as that is a big ally to understand the spec that our pod or workload must comply and it will point us in the direction of any possible error or mistake.&lt;/p&gt;



&lt;p&gt;Example with the wrong secret name (do note that I cleaned up the output a bit to make it more readable):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; example describe pod example-58bbc5464f-2mcv7
Name:             example-58bbc5464f-2mcv7
Namespace:        example
Priority:         0
Service Account:  default
Containers:
  example:
    Image:         busybox:1.36
    Image ID:
    Port:          &amp;lt;none&amp;gt;
    Host Port:     &amp;lt;none&amp;gt;
      sh
      &lt;span class="nt"&gt;-c&lt;/span&gt;
      /bin/sleep 3600
    State:          Waiting
      Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Mounts:
      /var/mysecrets from config &lt;span class="o"&gt;(&lt;/span&gt;ro&lt;span class="o"&gt;)&lt;/span&gt;
Conditions:
  Type                        Status
  PodReadyToStartContainers   False
  Initialized                 True
  Ready                       False
  ContainersReady             False
  PodScheduled                True
Volumes:
  config:
    Type:        Secret &lt;span class="o"&gt;(&lt;/span&gt;a volume populated by a Secret&lt;span class="o"&gt;)&lt;/span&gt;
    SecretName:  mysupersecret2
    Optional:    &lt;span class="nb"&gt;false
&lt;/span&gt;Events:
  Type     Reason       Age                 From               Message
  &lt;span class="nt"&gt;----&lt;/span&gt;     &lt;span class="nt"&gt;------&lt;/span&gt;       &lt;span class="nt"&gt;----&lt;/span&gt;                &lt;span class="nt"&gt;----&lt;/span&gt;               &lt;span class="nt"&gt;-------&lt;/span&gt;
  Warning  FailedMount  6s &lt;span class="o"&gt;(&lt;/span&gt;x9 over 2m14s&lt;span class="o"&gt;)&lt;/span&gt;  kubelet            MountVolume.SetUp failed &lt;span class="k"&gt;for &lt;/span&gt;volume &lt;span class="s2"&gt;"config"&lt;/span&gt; : secret &lt;span class="s2"&gt;"mysupersecret2"&lt;/span&gt; not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;With this we have just scratched the surface of what is possible with Kubernetes, but hopefully it was helpful for you, do you have any questions? drop a comment 👇&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
