×

投影卷将多个现有卷源映射到同一个目录。

可以投影以下类型的卷源

  • 密钥

  • 配置Map

  • 下行API

所有源都必须与Pod位于相同的命名空间。

理解投影卷

投影卷可以将这些卷源的任何组合映射到单个目录,允许用户

  • 自动填充包含来自多个密钥、配置映射和下行API信息的单个卷,以便我可以合成包含各种信息源的单个目录;

  • 填充包含来自多个密钥、配置映射和下行API信息的单个卷,并显式指定每个项目的路径,以便我可以完全控制该卷的内容。

当在基于Linux的Pod的安全上下文中设置RunAsUser权限时,投影文件将设置正确的权限,包括容器用户所有权。但是,当在Windows Pod中设置Windows等效权限RunAsUsername时,kubelet无法正确设置投影卷中文件的属主。

因此,在AWS上的Red Hat OpenShift Service中运行的Windows投影卷不会遵守在Windows Pod的安全上下文中设置的RunAsUsername权限。

以下一般场景显示了如何使用投影卷。

配置映射、密钥、下行API。

投影卷允许您部署包含配置数据的容器,其中包括密码。使用这些资源的应用程序可以部署在Kubernetes上的Red Hat OpenStack Platform (RHOSP)。根据服务将用于生产还是测试,配置数据可能需要以不同的方式进行组装。如果Pod用生产或测试标记,则可以使用下行API选择器metadata.labels生成正确的RHOSP配置。

配置映射 + 密钥。

投影卷允许您部署涉及配置数据和密码的容器。例如,您可以使用包含一些使用保管库密码文件解密的敏感加密任务的配置映射。

配置映射 + 下行API。

投影卷允许您生成包含Pod名称(通过metadata.name选择器可用)的配置。然后,此应用程序可以将Pod名称与请求一起传递,以便轻松确定源,而无需使用IP跟踪。

密钥 + 下行API。

投影卷允许您使用密钥作为公钥来加密Pod的命名空间(通过metadata.namespace选择器可用)。此示例允许操作员使用应用程序安全地传递命名空间信息,而无需使用加密传输。

Pod规范示例

以下是创建投影卷的Pod规范示例。

包含密钥、下行API和配置映射的Pod
apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: container-test
    image: busybox
    volumeMounts: (1)
    - name: all-in-one
      mountPath: "/projected-volume"(2)
      readOnly: true (3)
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
  volumes: (4)
  - name: all-in-one (5)
    projected:
      defaultMode: 0400 (6)
      sources:
      - secret:
          name: mysecret (7)
          items:
            - key: username
              path: my-group/my-username (8)
      - downwardAPI: (9)
          items:
            - path: "labels"
              fieldRef:
                fieldPath: metadata.labels
            - path: "cpu_limit"
              resourceFieldRef:
                containerName: container-test
                resource: limits.cpu
      - configMap: (10)
          name: myconfigmap
          items:
            - key: config
              path: my-group/my-config
              mode: 0777 (11)
1 为需要密钥的每个容器添加volumeMounts部分。
2 指定密钥将出现的未使用目录的路径。
3 readOnly设置为true
4 添加volumes块以列出每个投影卷源。
5 为卷指定任何名称。
6 设置文件的执行权限。
7 添加密钥。输入密钥对象的名称。您要使用的每个密钥都必须列出。
8 指定mountPath下密钥文件的路径。在此处,密钥文件位于/projected-volume/my-group/my-username
9 添加下行API源。
10 添加ConfigMap源。
11 设置特定投影的模式

如果Pod中有多个容器,则每个容器都需要一个volumeMounts部分,但只需要一个volumes部分。

设置非默认权限模式的多个密钥的Pod
apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
  volumes:
  - name: all-in-one
    projected:
      defaultMode: 0755
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - secret:
          name: mysecret2
          items:
            - key: password
              path: my-group/my-password
              mode: 511

只能在投影级别指定defaultMode,而不能为每个卷源指定。但是,如上所示,您可以为每个单独的投影显式设置mode

路径规划注意事项

配置路径相同时密钥之间的冲突

如果将任何密钥配置为具有相同的路径,则Pod规范将不被接受为有效规范。在以下示例中,mysecretmyconfigmap的指定路径相同

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/data
      - configMap:
          name: myconfigmap
          items:
            - key: config
              path: my-group/data

考虑以下与卷文件路径相关的场景。

密钥之间的冲突(未配置路径)

唯一可以发生的运行时验证是在创建Pod时所有路径都已知的情况下,类似于上述场景。否则,当发生冲突时,最近指定的资源将覆盖其之前的任何资源(这对于在创建Pod后更新的资源也是如此)。

一个路径显式指定而另一个路径自动投影时的冲突

如果由于用户指定的路径与自动投影的数据匹配而发生冲突,则后者资源将像以前一样覆盖其之前的任何资源

为Pod配置投影卷

创建投影卷时,请考虑“理解投影卷”中描述的卷文件路径情况。

以下示例显示如何使用投影卷来挂载现有的密钥卷源。这些步骤可用于从本地文件创建用户名和密码密钥。然后,您创建一个运行一个容器的Pod,使用投影卷将密钥挂载到同一个共享目录中。

用户名和密码值可以是任何有效的经过**base64**编码的字符串。

以下示例显示base64编码的admin

$ echo -n "admin" | base64
示例输出
YWRtaW4=

以下示例显示base64编码的密码1f2d1e2e67df

$ echo -n "1f2d1e2e67df" | base64
示例输出
MWYyZDFlMmU2N2Rm
步骤

要使用投影卷来挂载现有的密钥卷源。

  1. 创建密钥

    1. 创建一个类似于以下内容的YAML文件,根据需要替换密码和用户信息

      apiVersion: v1
      kind: Secret
      metadata:
        name: mysecret
      type: Opaque
      data:
        pass: MWYyZDFlMmU2N2Rm
        user: YWRtaW4=
    2. 使用以下命令创建密钥

      $ oc create -f <secrets-filename>

      例如

      $ oc create -f secret.yaml
      示例输出
      secret "mysecret" created
    3. 您可以使用以下命令检查密钥是否已创建

      $ oc get secret <secret-name>

      例如

      $ oc get secret mysecret
      示例输出
      NAME       TYPE      DATA      AGE
      mysecret   Opaque    2         17h
      $ oc get secret <secret-name> -o yaml

      例如

      $ oc get secret mysecret -o yaml
      apiVersion: v1
      data:
        pass: MWYyZDFlMmU2N2Rm
        user: YWRtaW4=
      kind: Secret
      metadata:
        creationTimestamp: 2017-05-30T20:21:38Z
        name: mysecret
        namespace: default
        resourceVersion: "2107"
        selfLink: /api/v1/namespaces/default/secrets/mysecret
        uid: 959e0424-4575-11e7-9f97-fa163e4bd54c
      type: Opaque
  2. 创建具有投影卷的Pod。

    1. 创建一个类似于以下内容的YAML文件,包括volumes部分

      kind: Pod
      metadata:
        name: test-projected-volume
      spec:
        securityContext:
          runAsNonRoot: true
          seccompProfile:
            type: RuntimeDefault
        containers:
        - name: test-projected-volume
          image: busybox
          args:
          - sleep
          - "86400"
          volumeMounts:
          - name: all-in-one
            mountPath: "/projected-volume"
            readOnly: true
          securityContext:
            allowPrivilegeEscalation: false
            capabilities:
              drop: [ALL]
        volumes:
        - name: all-in-one
          projected:
            sources:
            - secret:
                name: mysecret (1)
      1 您创建的密钥的名称。
    2. 从配置文件创建Pod

      $ oc create -f <your_yaml_file>.yaml

      例如

      $ oc create -f secret-pod.yaml
      示例输出
      pod "test-projected-volume" created
  3. 验证Pod容器是否正在运行,然后观察Pod的变化

    $ oc get pod <name>

    例如

    $ oc get pod test-projected-volume

    输出应类似于以下内容

    示例输出
    NAME                    READY     STATUS    RESTARTS   AGE
    test-projected-volume   1/1       Running   0          14s
  4. 在另一个终端中,使用oc exec命令打开到正在运行的容器的shell。

    $ oc exec -it <pod> <command>

    例如

    $ oc exec -it test-projected-volume -- /bin/sh
  5. 在您的shell中,验证projected-volumes目录是否包含您的投影源

    / # ls
    示例输出
    bin               home              root              tmp
    dev               proc              run               usr
    etc               projected-volume  sys               var