5.4. 使用投射卷来映射卷

投射卷会将几个现有的卷源映射到同一个目录中。

可以投射以下类型的卷源:

  • Secret
  • Config Map
  • Downward API
注意

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

5.4.1. 了解投射卷

投射卷可将这些卷源的任何组合映射到一个目录中,让用户能够:

  • 使用来自多个 secret、configmap 的密钥和 downward API 信息自动填充单个卷,以便在一个目录中整合不同来源的信息;
  • 使用来自多个 secret、configmap 的密钥和 downward API 信息填充单个卷,并且明确指定各个项目的路径,以便能够完全掌控卷中的内容。

以下一般情景演示了如何使用投射卷。

ConfigMap、Secret、Downward API。
通过投射卷,使用包含密码的配置数据来部署容器。使用这些资源的应用程序可以在 Kubernetes 上部署 Red Hat OpenStack Platform(RHOSP)。根据服务要用于生产环境还是测试环境,可能需要对配置数据进行不同的编译。如果 pod 标记了生产或测试用途,可以使用 Downward API 选择器 metadata.labels 来生成正确的 RHOSP 配置。
ConfigMap + Secret。
借助投射卷来部署涉及配置数据和密码的容器。例如,您可以执行含有某些敏感加密任务的 configmap,这些任务需要使用保险箱密码文件来解密。
ConfigMap + Downward API。
借助投射卷来生成包含 pod 名称的配置(可通过 metadata.name 选择器使用)。然后,此应用程序可以将 pod 名称与请求一起传递,以在不使用 IP 跟踪的前提下轻松地判断来源。
Secret + Downward API。
借助投射卷,将 secret 用作公钥来加密 pod 的命名空间(可通过 metadata.namespace 选择器使用)。这个示例允许操作员使用应用程序安全地传送命名空间信息,而不必使用加密传输。

5.4.1.1. Pod 规格示例

以下是用于创建投射卷的 pod 规格示例。

带有 secret、downward API 和 configmap 的 Pod

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts: 1
    - name: all-in-one
      mountPath: "/projected-volume"2
      readOnly: true 3
  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
为每个需要 secret 的容器添加 volumeMounts 部分。
2
指定一个到还未使用的目录的路径,secret 将出现在这个目录中。
3
readOnly 设为 true
4
添加一个 volumes 块,以列出每个投射卷源。
5
为卷指定任意名称。
6
设置文件的执行权限。
7
添加 secret。输入 secret 对象的名称。必须列出您要使用的每个 secret。
8
指定 mountPath 下 secret 文件的路径。此处,secret 文件位于 /projected-volume/my-group/my-config
9
添加 Downward API 源。
10
添加 ConfigMap 源。
11
设置具体的投射模式
注意

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

具有设定了非默认权限模式的多个 secret 的 Pod

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  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

5.4.1.2. 路径注意事项

配置路径相同时发生密钥间冲突

如果您使用同一路径配置多个密钥,则 pod 规格会视其为有效。以下示例中为 mysecretmyconfigmap 指定了相同的路径:

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  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 创建后更新的资源也是如此)。
一个路径为显式而另一个路径为自动投射时发生冲突
如果因为用户指定的路径与自动投射的数据匹配,从而发生冲突,则像前文所述一样,后面的资源将覆盖前面的资源

5.4.2. 为 Pod 配置投射卷

在创建投射卷时,请注意了解投射卷中介绍的卷文件路径情况。

以下示例演示了如何使用投射卷挂载现有 Secret 卷源。可以使用这些步骤从本地文件创建用户名和密码 Secret。然后,创建一个只运行一个容器的 pod,使用投射卷将 Secret 挂载到同一个共享目录中。

流程

使用投射卷挂载现有的 Secret 卷源。

  1. 输入以下内容并相应地替换密码和用户信息,创建包含这些 secret 的文件:

    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    type: Opaque
    data:
      pass: MWYyZDFlMmU2N2Rm
      user: YWRtaW4=

    userpass 值可以是采用 base64 编码的任意有效字符串。此处的示例使用了 base64 编码值 user: adminpass:1f2d1e2e67df

    $ echo -n "admin" | base64
    YWRtaW4=
    $ echo -n "1f2d1e2e67df" | base64
    MWYyZDFlMmU2N2Rm
  2. 使用以下命令来创建 secret:

    $ oc create -f <secrets-filename>

    例如:

    $ oc create -f secret.yaml
    secret "mysecret" created
  3. 您可以使用以下命令来检查是否创建了 secret:

    $ oc get secret <secret-name>
    $ oc get secret <secret-name> -o yaml

    例如:

    $ oc get secret mysecret
    NAME       TYPE      DATA      AGE
    mysecret   Opaque    2         17h
    $ 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
  4. 创建类似以下示例的 pod 配置文件,使其包含 volumes 部分:

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-projected-volume
    spec:
      containers:
      - name: test-projected-volume
        image: busybox
        args:
        - sleep
        - "86400"
        volumeMounts:
        - name: all-in-one
          mountPath: "/projected-volume"
          readOnly: true
      volumes:
      - name: all-in-one
        projected:
          sources:
          - secret:      1
              name: user
          - secret:      2
              name: pass
    1 2
    您创建的 secret 的名称。
  5. 从配置文件创建 pod:

    $ oc create -f <your_yaml_file>.yaml

    例如:

    $ oc create -f secret-pod.yaml
    pod "test-projected-volume" created
  6. 验证 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
  7. 在另一个终端中,使用 oc exec 命令来打开连接到运行中容器的 shell:

    $ oc exec -it <pod> <command>

    例如:

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

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