7.4. 使用投射卷来映射卷
投射卷会将几个现有的卷源映射到同一个目录中。
可以投射以下类型的卷源:
- Secret
- Config Map
- Downward API
所有源都必须位于与 pod 相同的命名空间中。
7.4.1. 了解投射卷
投射卷可将这些卷源的任何组合映射到一个目录中,让用户能够:
- 使用来自多个 secret、配置映射的密钥和 downward API 信息自动填充单个卷,以便在一个目录中整合不同来源的信息;
- 使用来自多个 secret、配置映射的密钥和 downward API 信息填充单个卷,并且明确指定各个项目的路径,以便能够完全掌控卷中的内容。
当在基于 Linux 的 Pod 的安全上下文中设置 RunAsUser
权限时,投射文件具有正确的权限集,包括容器用户所有权。但是,当 Windows pod 中设置了与 Windows 等效的 RunAsUsername
权限时,kubelet 将无法正确设置投射卷中的文件的所有权。
因此,在 Windows pod 的安全上下文中设置的 RunAsUsername
权限不适用于在 Red Hat OpenShift Service on AWS 上运行的 Windows 项目卷。
以下一般情景演示了如何使用投射卷。
- 配置映射、secret、Downward API。
-
通过投射卷,使用包含密码的配置数据来部署容器。使用这些资源的应用程序可以在 Kubernetes 上部署 Red Hat OpenStack Platform(RHOSP)。根据服务要用于生产环境还是测试环境,可能需要对配置数据进行不同的编译。如果 pod 标记了生产或测试用途,可以使用 Downward API 选择器
metadata.labels
来生成正确的 RHOSP 配置。 - 配置映射 + secret。
- 借助投射卷来部署涉及配置数据和密码的容器。例如,您可以执行含有某些敏感加密任务的配置映射,这些任务需要使用保险箱密码文件来解密。
- ConfigMap + Downward API。
-
借助投射卷来生成包含 pod 名称的配置(可通过
metadata.name
选择器使用)。然后,此应用程序可以将 pod 名称与请求一起传递,以在不使用 IP 跟踪的前提下轻松地判断来源。 - Secret + Downward API。
-
借助投射卷,将 secret 用作公钥来加密 pod 的命名空间(可通过
metadata.namespace
选择器使用)。这个示例允许 Operator 使用应用程序安全地传送命名空间信息,而不必使用加密传输。
7.4.1.1. Pod specs 示例
以下是用于创建投射卷的 Pod
spec 示例。
带有 secret、Downward 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
- 为每个需要 secret 的容器添加
volumeMounts
部分。 - 2
- 指定一个到还未使用的目录的路径,secret 将出现在这个目录中。
- 3
- 将
readOnly
设为true
。 - 4
- 添加一个
volumes
块,以列出每个投射卷源。 - 5
- 为卷指定任意名称。
- 6
- 设置文件的执行权限。
- 7
- 添加 secret。输入 secret 对象的名称。必须列出您要使用的每个 secret。
- 8
- 指定
mountPath
下 secret 文件的路径。此处,secret 文件位于 /projected-volume/my-group/my-username。 - 9
- 添加 Downward API 源。
- 10
- 添加 ConfigMap 源。
- 11
- 设置具体的投射模式
如果 pod 中有多个容器,则每个容器都需要一个 volumeMounts
部分,但 volumes
部分只需一个即可。
具有设定了非默认权限模式的多个 secret 的 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
。
7.4.1.2. 路径注意事项
- 配置路径相同时发生密钥间冲突
如果您使用同一路径配置多个密钥,则 pod 规格会视其为有效。以下示例中为
mysecret
和myconfigmap
指定了相同的路径: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 创建后更新的资源也是如此)。
- 一个路径为显式而另一个路径为自动投射时发生冲突
- 如果因为用户指定的路径与自动投射的数据匹配,从而发生冲突,则像前文所述一样,后面的资源将覆盖前面的资源
7.4.2. 为 Pod 配置投射卷
在创建投射卷时,请注意了解投射卷中介绍的卷文件路径情况。
以下示例演示了如何使用投射卷挂载现有的 secret 卷源。可以使用这些步骤从本地文件创建用户名和密码 secret。然后,创建一个只运行一个容器的 pod,使用投射卷将 secret 挂载到同一个共享目录中。
用户名和密码值可以是任何经过 base64 编码的有效字符串。
以下示例显示 admin
(base64 编码):
$ echo -n "admin" | base64
输出示例
YWRtaW4=
以下示例显示了 base64 中的 1f2d1e2e67df
密码:
$ echo -n "1f2d1e2e67df" | base64
输出示例
MWYyZDFlMmU2N2Rm
流程
使用投射卷挂载现有的 secret 卷源。
创建 secret:
创建一个类似如下的 YAML 文件,根据需要替换密码和用户信息:
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: pass: MWYyZDFlMmU2N2Rm user: YWRtaW4=
使用以下命令来创建 secret:
$ oc create -f <secrets-filename>
例如:
$ oc create -f secret.yaml
输出示例
secret "mysecret" created
您可以使用以下命令来检查是否创建了 secret:
$ 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
使用投射卷创建 pod。
创建一个类似如下的 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
- 您创建的 secret 的名称。
从配置文件创建 pod:
$ oc create -f <your_yaml_file>.yaml
例如:
$ oc create -f secret-pod.yaml
输出示例
pod "test-projected-volume" created
验证 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
在另一个终端中,使用
oc exec
命令来打开连接到运行中容器的 shell:$ oc exec -it <pod> <command>
例如:
$ oc exec -it test-projected-volume -- /bin/sh
在 shell 中,验证
projected-volumes
目录是否包含您的投射源:/ # ls
输出示例
bin home root tmp dev proc run usr etc projected-volume sys var