投影卷

本文档描述了 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 挂载点的路径。

clusterTrustBundle projected volumes

特性状态: `Kubernetes v1.33 [beta]` (默认启用:false)

`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`。

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`)将拥有读、写和执行权限,而非管理员用户将拥有读和执行权限。

最后修改于 2025 年 4 月 7 日 太平洋标准时间下午 2:37:projected volumes: clustertrustbundle API 在 1.33+ 版本中为 Beta (79763df5a5)