投影卷
本文档描述了 Kubernetes 中的 projected volumes。建议熟悉 Volumes 的概念。
简介
`projected` Volume 将多个现有 Volume 源映射到同一个目录中。
目前,以下类型的 Volume 源可以被 Projected:
所有源都必须与 Pod 位于同一命名空间中。有关更多详细信息,请参阅all-in-one volume 设计文档。
包含 Secret、downwardAPI 和 ConfigMap 的示例配置
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox:1.28
command: ["sleep", "3600"]
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/my-username
- downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
- path: "cpu_limit"
resourceFieldRef:
containerName: container-test
resource: limits.cpu
- configMap:
name: myconfigmap
items:
- key: config
path: my-group/my-config
示例配置:设置了非默认权限模式的 Secret
apiVersion: v1
kind: Pod
metadata:
name: volume-test
spec:
containers:
- name: container-test
image: busybox:1.28
command: ["sleep", "3600"]
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/my-username
- secret:
name: mysecret2
items:
- key: password
path: my-group/my-password
mode: 511
每个 projected volume 源都列在 Spec 的 `sources` 下。参数几乎相同,有两个例外:
- 对于 Secret,`secretName` 字段已更改为 `name`,以便与 ConfigMap 的命名保持一致。
- `defaultMode` 只能在 Projected 级别指定,不能为每个 Volume 源指定。但是,如上所示,你可以为每个单独的 Projection 显式设置 `mode`。
serviceAccountToken projected volumes
你可以将当前Service Account 的 Token 注入到 Pod 的指定路径中。例如:
apiVersion: v1
kind: Pod
metadata:
name: sa-token-test
spec:
containers:
- name: container-test
image: busybox:1.28
command: ["sleep", "3600"]
volumeMounts:
- name: token-vol
mountPath: "/service-account"
readOnly: true
serviceAccountName: default
volumes:
- name: token-vol
projected:
sources:
- serviceAccountToken:
audience: api
expirationSeconds: 3600
path: token
示例 Pod 包含一个 Projected Volume,其中包含注入的 Service Account Token。此 Pod 中的容器可以使用该 Token 访问 Kubernetes API Server,并使用该 Pod 的 ServiceAccount 身份进行身份验证。`audience` 字段包含 Token 的预期受众。Token 的接收者必须使用 Token 的 Audience 中指定的标识符来标识自身,否则应拒绝该 Token。此字段是可选的,默认为 API Server 的标识符。
`expirationSeconds` 是 Service Account Token 的预期有效期。它默认为 1 小时,并且必须至少为 10 分钟(600 秒)。管理员还可以通过为 API Server 指定 `--service-account-max-token-expiration` 选项来限制其最大值。`path` 字段指定相对于 Projected Volume 挂载点的路径。
注意
使用 projected volume 源作为`subPath` Volume 挂载的容器不会收到这些 Volume 源的更新。clusterTrustBundle projected volumes
注意
若要在 Kubernetes 1.33 中使用此特性,必须通过 `ClusterTrustBundle` 特性门控和 `--runtime-config=certificates.k8s.io/v1beta1/clustertrustbundles=true` kube-apiserver 标志启用 ClusterTrustBundle 对象的支持,然后启用 `ClusterTrustBundleProjection` 特性门控。`clusterTrustBundle` Projected Volume 源将一个或多个ClusterTrustBundle 对象的内容作为自动更新的文件注入到容器文件系统中。
ClusterTrustBundles 可以通过名称或通过signer name 选择。
要按名称选择,请使用 `name` 字段指定单个 ClusterTrustBundle 对象。
要按 signer name 选择,请使用 `signerName` 字段(以及可选的 `labelSelector` 字段)指定使用给定 signer name 的一组 ClusterTrustBundle 对象。如果不存在 `labelSelector`,则选择该 signer 的所有 ClusterTrustBundle。
kubelet 对选定的 ClusterTrustBundle 对象中的证书进行去重,规范化 PEM 表示形式(丢弃注释和头部),重新排序证书,并将它们写入由 `path` 指定的文件中。随着选定的 ClusterTrustBundles 集或其内容发生变化,kubelet 会保持文件最新。
默认情况下,如果找不到指定的 ClusterTrustBundle,或者 `signerName` / `labelSelector` 不匹配任何 ClusterTrustBundle,则 kubelet 将阻止 Pod 启动。如果你不希望出现此行为,请将 `optional` 字段设置为 `true`,Pod 将在 `path` 处启动时带有一个空文件。
apiVersion: v1
kind: Pod
metadata:
name: sa-ctb-name-test
spec:
containers:
- name: container-test
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: token-vol
mountPath: "/root-certificates"
readOnly: true
serviceAccountName: default
volumes:
- name: token-vol
projected:
sources:
- clusterTrustBundle:
name: example
path: example-roots.pem
- clusterTrustBundle:
signerName: "example.com/mysigner"
labelSelector:
matchLabels:
version: live
path: mysigner-roots.pem
optional: true
SecurityContext 交互
Projected Service Account Volume 增强的提案引入了 Projected 文件具有正确的所有者权限设置。
Linux
在具有 Projected Volume 并在 Pod `SecurityContext` 中设置了 `RunAsUser` 的 Linux Pod 中,Projected 文件具有正确的所有权设置,包括容器用户所有权。
当 Pod 中的所有容器在其`PodSecurityContext` 或容器`SecurityContext` 中设置了相同的 `runAsUser` 时,kubelet 会确保 `serviceAccountToken` Volume 的内容归该用户所有,并且 Token 文件具有权限模式 `0600`。
注意
创建后添加到 Pod 的临时容器不会改变 Pod 创建时设置的 Volume 权限。
如果 Pod 的 `serviceAccountToken` Volume 权限设置为 `0600` 是因为 Pod 中的所有其他容器都使用相同的 `runAsUser`,则临时容器必须使用相同的 `runAsUser` 才能读取 Token。
Windows
在具有 Projected Volume 并在 Pod `SecurityContext` 中设置了 `RunAsUsername` 的 Windows Pod 中,所有权不会被强制执行,这是由于 Windows 中用户帐户的管理方式所致。Windows 将本地用户和组帐户存储在名为 Security Account Manager (SAM) 的数据库文件中。每个容器都维护自己的 SAM 数据库实例,在容器运行时主机对其不可见。Windows 容器旨在将操作系统的用户模式部分与主机隔离运行,因此维护了一个虚拟 SAM 数据库。结果是,在主机上运行的 kubelet 无法为虚拟化容器帐户动态配置主机文件所有权。建议如果主机上的文件要与容器共享,则应将它们放置在 `C:\` 之外的独立 Volume 挂载中。
默认情况下,Projected 文件将具有以下所有权,如下面的 Projected Volume 文件示例所示:
PS C:\> Get-Acl C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt | Format-List
Path : Microsoft.PowerShell.Core\FileSystem::C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt
Owner : BUILTIN\Administrators
Group : NT AUTHORITY\SYSTEM
Access : NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
BUILTIN\Users Allow ReadAndExecute, Synchronize
Audit :
Sddl : O:BAG:SYD:AI(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200a9;;;BU)
这意味着所有管理员用户(如 `ContainerAdministrator`)将拥有读、写和执行权限,而非管理员用户将拥有读和执行权限。
注意
通常不建议授予容器访问主机的权限,因为这可能会带来潜在的安全漏洞。
在 Windows Pod 中创建带有 `SecurityContext` 中设置 `RunAsUser` 的 Pod 将导致 Pod 永远停留在 `ContainerCreating` 状态。因此,建议不要在 Windows Pod 中使用仅限 Linux 的 `RunAsUser` 选项。