Skip to content

Instantly share code, notes, and snippets.

@mansam
Last active January 16, 2020 20:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mansam/54b2b60a73c0b68e54e4bd4303d8acfe to your computer and use it in GitHub Desktop.
Save mansam/54b2b60a73c0b68e54e4bd4303d8acfe to your computer and use it in GitHub Desktop.
Mounting a Secret into a Directory that Already Contains Files on an Image You Don't Control

Mounting a Secret into a Directory that Already Contains Files on an Image You Don't Control

In some situations you may want to mount a value from a Secret or ConfigMap as a file in a directory which contains files you'd rather not overwrite. For this, you can use a subPath when defining the volume mount. Lets assume we have a secret my-secret which contains a key ca_bundle.pem.

volumes:
- name: my-secret-volume
  secret:
    secretName: my-secret

volumeMounts:
- name: my-secret-volume
  mountPath: /etc/ssl/certs/ca_bundle.pem
  subPath: ca_bundle.pem

The above volume mount will extract the key named in subpath from the secret, and mount it at mountPath without destroying the rest of the contents of that directory. In this case, ca_bundle.pem from my-secret gets mounted at /etc/ssl/certs/ca_bundle.pem.

Normally, when a Secret or ConfigMap is mounted as a volume, the files inside will be updated whenever the Secret or ConfigMap is updated. However, files mounted as subpaths will not receive updates due to some of the specifics of how that mounting works. It would be nice to be able to mount the Secret as a volume normally, and then create a symlink to that file so that we receive updates. One approach would be to adjust the image itself to put a symlink where we want, but that's only possible if we control the image. Instead, we can use an Init Container to create the symlink for us when the Pod starts up.

containers:
  - image: my-container-image:1.1
    <snip>
    volumeMounts:
      - name: certs
        mountPath: /etc/ssl/certs
      - name: credentials
        mountPath: /credentials
initContainers:
  - image: my-container-image:1.1 (important to use the same image rather than a busybox or etc)
    name: setup-secret-symlink
    command:
      - sh
      - '-ec'
      - >-
        cp /etc/ssl/certs/* /certs/;
        ln -sf /credentials/ca_bundle.pem /certs/ca_bundle.pem;
    volumeMounts:
      - name: certs
        mountPath: /certs
      - name: credentials
        mountPath: /credentials
volumes:
  - name: certs
    emptyDir: {}
  - name: credentials
    secret:
      secretName: credentials

It would make sense to create an emptyDir mount, use the init container to write a symlink to our secret volume in the emptyDir, and then mount that symlink as a subpath where we want it on the container. However, for security reasons Kubernetes won't let us mount a symlink to a subpath-- we would still have to clobber the files that were originally in /etc/ssl/certs, which we are trying to avoid. Instead, we can copy the contents of /etc/ssl/certs on the init container to the emptyDir, write the symlink where we want it, and then mount that entire volume over top of /etc/ssl/certs on the main container. This effectively replaces the version of /etc/ssl/certs with the one from the init container, plus our symlink.

(Note: The security issue being worked around is specific to the way symlinks are resolved as part of mounting subpaths and doesn't impact normal mounts, so we're not sidestepping a security measure with this work around.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment