投影卷
本文档描述了 Kubernetes 中的投影卷。建议熟悉卷。
引言
一个projected卷将多个现有的卷源映射到相同的目录。
目前,可以投影以下类型的卷源
所有源都需要位于与 Pod 相同的命名空间中。有关更多详细信息,请参阅all-in-one 卷设计文档。
包含 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
每个投影卷源都在 sources 下的 spec 中列出。参数几乎相同,但有两个例外
- 对于 secret,
secretName字段已更改为name,以与 ConfigMap 命名保持一致。 defaultMode只能在投影级别指定,而不能为每个卷源指定。但是,如上所示,您可以显式为每个单独的投影设置mode。
serviceAccountToken 投影卷
您可以将当前 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 具有一个投影卷,其中包含注入的服务帐户 token。此 Pod 中的容器可以使用该 token 访问 Kubernetes API 服务器,并使用 pod 的 ServiceAccount 的身份进行身份验证。audience 字段包含 token 的预期受众。token 的接收者必须使用 token 的受众中指定的标识符来标识自身,否则应拒绝该 token。此字段是可选的,默认值为 API 服务器的标识符。
expirationSeconds 是服务帐户 token 的预期有效期限。默认值为 1 小时,必须至少为 10 分钟(600 秒)。管理员还可以通过为 API 服务器指定 --service-account-max-token-expiration 选项来限制其最大值。path 字段指定投影卷挂载点的相对路径。
说明
将投影卷源作为subPath 卷挂载的容器将不会收到这些卷源的更新。clusterTrustBundle 投影卷
Kubernetes v1.33 [beta](默认禁用)说明
要在 Kubernetes 1.35 中使用此功能,必须使用ClusterTrustBundle 功能门和 --runtime-config=certificates.k8s.io/v1beta1/clustertrustbundles=true kube-apiserver 标志启用对 ClusterTrustBundle 对象的支持,然后启用 ClusterTrustBundleProjection 功能门。clusterTrustBundle 投影卷源会将一个或多个 ClusterTrustBundle 对象的内容作为自动更新的文件注入到容器文件系统中。
可以通过 名称 或通过 signer 名称 选择 ClusterTrustBundles。
要按名称选择,请使用 name 字段指定单个 ClusterTrustBundle 对象。
要按 signer 名称选择,请使用 signerName 字段(以及可选的 labelSelector 字段)指定使用给定 signer 名称的一组 ClusterTrustBundle 对象。如果未提供 labelSelector,则选择该 signer 的所有 ClusterTrustBundles。
kubelet 会对所选 ClusterTrustBundle 对象中的证书进行去重,规范化 PEM 表示形式(删除注释和标题),重新排序证书,并将它们写入由 path 指定的文件中。当所选 ClusterTrustBundles 或其内容发生更改时,kubelet 会保持文件最新。
默认情况下,如果找不到指定的 ClusterTrustBundle,或者 signerName / labelSelector 与任何 ClusterTrustBundles 不匹配,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
podCertificate 投影卷
Kubernetes v1.35 [beta](默认禁用)说明
在 Kubernetes 1.35 中,必须使用PodCertificateRequest 功能门和 --runtime-config=certificates.k8s.io/v1beta1/podcertificaterequests=true kube-apiserver 标志启用 Pod 证书支持。podCertificate 投影卷源安全地为 pod 配置私钥和 X.509 证书链,以用作客户端或服务器凭据。Kubelet 随后会在它们接近到期时处理刷新私钥和证书链。应用程序只需要确保在文件发生更改时使用像 inotify 或轮询之类的机制及时重新加载文件。
每个 podCertificate 投影支持以下配置字段
signerName:您希望颁发证书的 signer。请注意,signer 可能会有自己的访问要求,并且可能会拒绝向您的 pod 颁发证书。keyType:应生成私钥的类型。有效值包括ED25519、ECDSAP256、ECDSAP384、ECDSAP521、RSA3072和RSA4096。maxExpirationSeconds:您将接受颁发给 pod 的证书的最长有效期。如果未设置,将默认设置为86400(24 小时)。必须至少为3600(1 小时),最多为7862400(91 天)。Kubernetes 内置 signer 限制为最大有效期为86400(1 天)。signer 允许颁发有效期短于您指定的值的证书。credentialBundlePath:在投影中写入凭据包的相对路径。凭据包是 PEM 格式的文件,第一个块是包含 PKCS#8 序列化私钥的“PRIVATE KEY”块,其余块是构成证书链(叶证书和任何中间证书)的“CERTIFICATE”块。keyPath和certificateChainPath:Kubelet 应写入仅私钥或证书链的单独路径。userAnnotations: 一个允许您将额外信息传递给签名者实现的映射。它会逐字复制到 Kubelet 创建的 PodCertificateRequest 对象的spec.unverifiedUserAnnotations字段中。条目受与对象元数据注释相同的验证约束,此外所有键必须具有域名作为前缀。除了整个字段的整体大小限制之外,对值没有其他限制。除了这些基本验证之外,API 服务器不会进行任何额外的验证。签名者实现在使用此数据时应格外小心。签名者在执行适当的验证步骤之前,不得固有地信任此数据。签名者应记录他们支持的键和值。签名者应拒绝包含他们不识别的键的请求。
说明
大多数应用程序应优先使用credentialBundlePath,除非它们需要将密钥和证书保存在单独的文件中以实现兼容性。Kubelet 使用基于符号链接的原子写入策略,以确保在您打开它投影的文件时,您读取的是旧内容或新内容。但是,如果您从单独的文件读取密钥和证书链,Kubelet 可能会在您第一次读取之后和第二次读取之前旋转凭据,从而导致您的应用程序加载不匹配的密钥和证书。# Sample Pod spec that uses a podCertificate projection to request an ED25519
# private key, a certificate from the `coolcert.example.com/foo` signer, and
# write the results to `/var/run/my-x509-credentials/credentialbundle.pem`.
apiVersion: v1
kind: Pod
metadata:
namespace: default
name: podcertificate-pod
spec:
serviceAccountName: default
containers:
- image: debian
name: main
command: ["sleep", "infinity"]
volumeMounts:
- name: my-x509-credentials
mountPath: /var/run/my-x509-credentials
volumes:
- name: my-x509-credentials
projected:
defaultMode: 420
sources:
- podCertificate:
keyType: ED25519
signerName: coolcert.example.com/foo
credentialBundlePath: credentialbundle.pem
userAnnotations:
example.com/annotation1: "value1"
example.com/annotation2: "value2"
SecurityContext 交互
为增强投影服务帐户卷,提案 引入了投影文件具有正确的拥有者权限设置。
Linux
在具有投影卷且 Pod SecurityContext 中设置了 RunAsUser 的 Linux Pod 中,投影文件将具有正确的拥有权设置,包括容器用户拥有权。
当 Pod 中的所有容器在各自的 PodSecurityContext 或容器 SecurityContext 中设置了相同的 runAsUser 时,kubelet 确保 serviceAccountToken 卷的内容由该用户拥有,并且令牌文件的权限模式设置为 0600。
说明
添加到 Pod 的不是更改 Pod 创建时设置的卷权限的 Ephemeral containers。
如果 Pod 的 serviceAccountToken 卷权限设置为 0600,因为 Pod 中的所有其他容器具有相同的 runAsUser,则临时容器必须使用相同的 runAsUser 才能读取令牌。
Windows
在具有投影卷且 Pod SecurityContext 中设置了 RunAsUsername 的 Windows Pod 中,由于 Windows 中用户帐户的管理方式,所有权不强制执行。Windows 将本地用户和组帐户存储和管理在一个名为安全帐户管理器 (SAM) 的数据库文件中。每个容器维护其自己的 SAM 数据库实例,而主机在容器运行时无法访问该数据库。Windows 容器旨在将操作系统的用户模式部分与主机隔离,因此维护虚拟 SAM 数据库。因此,在主机上运行的 kubelet 无法动态配置虚拟化容器帐户的主机文件所有权。建议如果要在容器与主机之间共享主机上的文件,则应将它们放置在 C:\ 之外的自己的卷挂载中。
默认情况下,投影文件将具有以下所有权,如示例投影卷文件所示
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)都将具有读、写和执行权限,而非管理员用户将具有读和执行权限。
说明
通常,不建议授予容器访问主机的权限,因为它可能会为潜在的安全漏洞敞开大门。
在 SecurityContext 中使用 RunAsUser 创建 Windows Pod 将导致 Pod 永远停留在 ContainerCreating 状态。因此,不建议在 Windows Pod 中使用仅适用于 Linux 的 RunAsUser 选项。