Search code examples
kubernetesvolumeskubernetes-secrets

kubernetes deployment mounts secret as a folder instead of a file


I am having a config file as a secret in kubernetes and I want to mount it into a specific location inside the container. The problem is that the volume that is created inside the container is a folder instead of a file with the content of the secrets in it. Any way to fix it? My deployment looks like this:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: jetty
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jetty
  template:
    metadata:
      labels:
        app: jetty
    spec:
      containers:
        - name: jetty
          image: quay.io/user/jetty
          ports:
            - containerPort: 8080
          volumeMounts:
          - name: config-properties
            mountPath: "/opt/jetty/config.properties"
            subPath: config.properties
          - name: secrets-properties
            mountPath: "/opt/jetty/secrets.properties"
          - name: doc-path
            mountPath: /mnt/storage/
          resources:
            limits:
              cpu: '1000m'
              memory: '3000Mi'
            requests:
              cpu: '750m'
              memory: '2500Mi'
      volumes:
      - name: config-properties
        configMap:
          name: jetty-config-properties
      - name: secrets-properties
        secret: 
          secretName: jetty-secrets
      - name: doc-path
        persistentVolumeClaim:
          claimName: jetty-docs-pvc
      imagePullSecrets:
      - name: rcc-quay

Solution

  • Secrets vs ConfigMaps

    Secrets let you store and manage sensitive information (e.g. passwords, private keys) and ConfigMaps are used for non-sensitive configuration data.
    As you can see in the Secrets and ConfigMaps documentation:

    A Secret is an object that contains a small amount of sensitive data such as a password, a token, or a key.

    A ConfigMap allows you to decouple environment-specific configuration from your container images, so that your applications are easily portable.

    Mounting Secret as a file

    It is possible to create Secret and pass it as a file or multiple files to Pods.
    I've create simple example for you to illustrate how it works. Below you can see sample Secret manifest file and Deployment that uses this Secret:
    NOTE: I used subPath with Secrets and it works as expected.

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: my-secret
    data:
      secret.file1: |
        c2VjcmV0RmlsZTEK
      secret.file2: |
        c2VjcmV0RmlsZTIK
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    ...
        spec:
          containers:
          - image: nginx
            name: nginx
            volumeMounts:
            - name: secrets-files
              mountPath: "/mnt/secret.file1"  # "secret.file1" file will be created in "/mnt" directory
              subPath: secret.file1
            - name: secrets-files
              mountPath: "/mnt/secret.file2"  # "secret.file2" file will be created in "/mnt" directory
              subPath: secret.file2
          volumes:
            - name: secrets-files
              secret:
                secretName: my-secret # name of the Secret
                
    

    Note: Secret should be created before Deployment.

    After creating Secret and Deployment, we can see how it works:

    $ kubectl get secret,deploy,pod
    NAME                         TYPE                                  DATA   AGE
    secret/my-secret             Opaque                                2      76s
    
    NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/nginx   1/1     1            1           76s
    
    NAME                         READY   STATUS    RESTARTS   AGE
    pod/nginx-7c67965687-ph7b8   1/1     Running   0          76s
    
    $ kubectl exec nginx-7c67965687-ph7b8 -- ls /mnt
    secret.file1
    secret.file2
    $ kubectl exec nginx-7c67965687-ph7b8 -- cat /mnt/secret.file1
    secretFile1
    $ kubectl exec nginx-7c67965687-ph7b8 -- cat /mnt/secret.file2
    secretFile2
    

    Projected Volume

    I think a better way to achieve your goal is to use projected volume.

    A projected volume maps several existing volume sources into the same directory.

    In the Projected Volume documentation you can find detailed explanation but additionally I created an example that might help you understand how it works. Using projected volume I mounted secret.file1, secret.file2 from Secret and config.file1 from ConfigMap as files into the Pod.

    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: my-secret
    data:
      secret.file1: |
        c2VjcmV0RmlsZTEK
      secret.file2: |
        c2VjcmV0RmlsZTIK
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: my-config
    data:
      config.file1: |
        configFile1  
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: all-in-one
          mountPath: "/config-volume"
          readOnly: true
      volumes:
      - name: all-in-one
        projected:
          sources:
          - secret:
              name: my-secret
              items:
                - key: secret.file1
                  path: secret-dir1/secret.file1
                - key: secret.file2
                  path: secret-dir2/secret.file2
          - configMap:
              name: my-config
              items:
                - key: config.file1
                  path: config-dir1/config.file1
    

    We can check how it works:

    $ kubectl exec nginx -- ls /config-volume
    config-dir1
    secret-dir1
    secret-dir2    
    $ kubectl exec nginx -- cat /config-volume/config-dir1/config.file1
    configFile1
    $ kubectl exec nginx -- cat /config-volume/secret-dir1/secret.file1
    secretFile1
    $ kubectl exec nginx -- cat /config-volume/secret-dir2/secret.file2
    secretFile2
    

    If this response doesn't answer your question, please provide more details about your Secret and what exactly you want to achieve.