Mapping volumes using projected volumes

    The following types of volume sources can be projected:

    • Secrets

    • Config Maps

    • Downward API

    Projected volumes can map any combination of these volume sources into a single directory, allowing the user to:

    • automatically populate a single volume with the keys from multiple secrets, config maps, and with downward API information, so that I can synthesize a single directory with various sources of information;

    • populate a single volume with the keys from multiple secrets, config maps, and with downward API information, explicitly specifying paths for each item, so that I can have full control over the contents of that volume.

    The following general scenarios show how you can use projected volumes.

    Config map, secrets, Downward API.

    Projected volumes allow you to deploy containers with configuration data that includes passwords. An application using these resources could be deploying Red Hat OpenStack Platform (RHOSP) on Kubernetes. The configuration data might have to be assembled differently depending on if the services are going to be used for production or for testing. If a pod is labeled with production or testing, the downward API selector can be used to produce the correct RHOSP configs.

    Config map + secrets.

    Projected volumes allow you to deploy containers involving configuration data and passwords. For example, you might execute a config map with some sensitive encrypted tasks that are decrypted using a vault password file.

    ConfigMap + Downward API.

    Projected volumes allow you to generate a config including the pod name (available via the metadata.name selector). This application can then pass the pod name along with requests to easily determine the source without using IP tracking.

    Secrets + Downward API.

    Projected volumes allow you to use a secret as a public key to encrypt the namespace of the pod (available via the metadata.namespace selector). This example allows the Operator to use the application to deliver the namespace information securely without using an encrypted transport.

    The following are examples of Pod specs for creating projected volumes.

    Pod with multiple secrets with a non-default permission mode set

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: volume-test
    5. spec:
    6. containers:
    7. - name: container-test
    8. image: busybox
    9. volumeMounts:
    10. - name: all-in-one
    11. mountPath: "/projected-volume"
    12. readOnly: true
    13. volumes:
    14. - name: all-in-one
    15. projected:
    16. defaultMode: 0755
    17. sources:
    18. - secret:
    19. name: mysecret
    20. items:
    21. - key: username
    22. path: my-group/my-username
    23. - secret:
    24. name: mysecret2
    25. items:
    26. - key: password
    27. path: my-group/my-password
    28. mode: 511

    Pathing Considerations

    Collisions Between Keys when Configured Paths are Identical

    If you configure any keys with the same path, the pod spec will not be accepted as valid. In the following example, the specified path for mysecret and myconfigmap are the same:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: volume-test
    5. containers:
    6. - name: container-test
    7. volumeMounts:
    8. - name: all-in-one
    9. mountPath: "/projected-volume"
    10. readOnly: true
    11. volumes:
    12. - name: all-in-one
    13. projected:
    14. sources:
    15. - secret:
    16. name: mysecret
    17. items:
    18. - key: username
    19. path: my-group/data
    20. - configMap:
    21. name: myconfigmap
    22. items:
    23. - key: config
    24. path: my-group/data

    Consider the following situations related to the volume file paths.

    Collisions Between Keys without Configured Paths

    The only run-time validation that can occur is when all the paths are known at pod creation, similar to the above scenario. Otherwise, when a conflict occurs the most recent specified resource will overwrite anything preceding it (this is true for resources that are updated after pod creation as well).

    Collisions when One Path is Explicit and the Other is Automatically Projected

    In the event that there is a collision due to a user specified path matching data that is automatically projected, the latter resource will overwrite anything preceding it as before

    Configuring a Projected Volume for a Pod

    When creating projected volumes, consider the volume file path situations described in Understanding projected volumes.

    The following example shows how to use a projected volume to mount an existing secret volume source. The steps can be used to create a user name and password secrets from local files. You then create a pod that runs one container, using a projected volume to mount the secrets into the same shared directory.

    Procedure

    To use a projected volume to mount an existing secret volume source.

    1. Create files containing the secrets, entering the following, replacing the password and user information as appropriate:

      1. apiVersion: v1
      2. kind: Secret
      3. metadata:
      4. name: mysecret
      5. type: Opaque
      6. data:
      7. pass: MWYyZDFlMmU2N2Rm
      8. user: YWRtaW4=

      The user and pass values can be any valid string that is base64 encoded.

      The following example shows admin in base64:

      1. $ echo -n "admin" | base64

      Example output

      1. YWRtaW4=
      1. $ echo -n "1f2d1e2e67df" | base64

      Example output

      1. MWYyZDFlMmU2N2Rm
    2. Use the following command to create the secrets:

      1. $ oc create -f <secrets-filename>

      For example:

      Example output

      1. secret "mysecret" created
    3. You can check that the secret was created using the following commands:

      1. $ oc get secret <secret-name>

      For example:

      1. $ oc get secret mysecret

      Example output

      1. NAME TYPE DATA AGE
      2. mysecret Opaque 2 17h
      1. $ oc get secret <secret-name> -o yaml

      For example:

      1. $ oc get secret mysecret -o yaml
      1. apiVersion: v1
      2. pass: MWYyZDFlMmU2N2Rm
      3. kind: Secret
      4. metadata:
      5. creationTimestamp: 2017-05-30T20:21:38Z
      6. name: mysecret
      7. namespace: default
      8. resourceVersion: "2107"
      9. selfLink: /api/v1/namespaces/default/secrets/mysecret
      10. uid: 959e0424-4575-11e7-9f97-fa163e4bd54c
      11. type: Opaque
    4. Create a pod configuration file similar to the following that includes a volumes section:

      1. apiVersion: v1
      2. kind: Pod
      3. metadata:
      4. name: test-projected-volume
      5. spec:
      6. containers:
      7. - name: test-projected-volume
      8. image: busybox
      9. args:
      10. - sleep
      11. - "86400"
      12. volumeMounts:
      13. - name: all-in-one
      14. mountPath: "/projected-volume"
      15. readOnly: true
      16. volumes:
      17. - name: all-in-one
      18. projected:
      19. sources:
      20. - secret: (1)
      21. name: user
      22. - secret: (1)
      23. name: pass
    5. Create the pod from the configuration file:

      For example:

      1. $ oc create -f secret-pod.yaml

      Example output

      1. pod "test-projected-volume" created
    6. Verify that the pod container is running, and then watch for changes to the pod:

      1. $ oc get pod <name>

      For example:

      1. $ oc get pod test-projected-volume

      The output should appear similar to the following:

      Example output

      1. NAME READY STATUS RESTARTS AGE
      2. test-projected-volume 1/1 Running 0 14s
    7. In another terminal, use the oc exec command to open a shell to the running container:

      1. $ oc exec -it <pod> <command>

      For example:

      1. $ oc exec -it test-projected-volume -- /bin/sh