投射卷
本文档描述了 Kubernetes 中的**投射卷(projected volumes)**。建议熟悉卷(volumes)。
介绍
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
每个投射卷源都在规范的 sources
下列出。参数几乎相同,但有两个例外:
- 对于 Secret,
secretName
字段已更改为name
,以与 ConfigMap 的命名保持一致。 defaultMode
只能在投射级别指定,而不能为每个卷源指定。然而,如上所示,你可以为每个单独的投射显式设置mode
。
serviceAccountToken 投射卷
你可以将当前服务账号的令牌注入到 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 包含一个投射卷,其中注入了服务账号令牌。此 Pod 中的容器可以使用该令牌访问 Kubernetes API 服务器,并以Pod 的 ServiceAccount 身份进行身份验证。audience
字段包含令牌的预期受众。令牌的接收者必须使用令牌受众中指定的标识符来识别自己,否则应拒绝该令牌。此字段是可选的,默认为 API 服务器的标识符。
expirationSeconds
是服务账号令牌的预期有效期。它默认为 1 小时,并且必须至少为 10 分钟(600 秒)。管理员还可以通过为 API 服务器指定 --service-account-max-token-expiration
选项来限制其最大值。path
字段指定投射卷挂载点的相对路径。
注意
使用投射卷源作为subPath
卷挂载的容器将不会收到这些卷源的更新。clusterTrustBundle 投射卷
Kubernetes v1.33 [beta]
(默认禁用)注意
要在 Kubernetes 1.34 中使用此特性,你必须通过ClusterTrustBundle
特性门控和 --runtime-config=certificates.k8s.io/v1beta1/clustertrustbundles=true
kube-apiserver 标志启用对 ClusterTrustBundle 对象的支持,然后启用 ClusterTrustBundleProjection
特性门控。clusterTrustBundle
投射卷源将一个或多个 ClusterTrustBundle 对象的内容注入为容器文件系统中的自动更新文件。
ClusterTrustBundle 可以通过名称或签名者名称进行选择。
要通过名称选择,请使用 name
字段指定单个 ClusterTrustBundle 对象。
要通过签名者名称选择,请使用 signerName
字段(以及可选的 labelSelector
字段)指定一组使用给定签名者名称的 ClusterTrustBundle 对象。如果 labelSelector
不存在,则选择该签名者的所有 ClusterTrustBundle。
Kubelet 会对选定的 ClusterTrustBundle 对象中的证书进行去重,规范化 PEM 表示(丢弃注释和头),重新排序证书,并将它们写入由 path
命名的文件。当选定的 ClusterTrustBundle 集合或其内容发生变化时,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
podCertificate 投射卷
Kubernetes v1.34 [alpha]
(默认禁用)注意
在 Kubernetes 1.34 中,你必须使用PodCertificateRequest
特性门控和 --runtime-config=certificates.k8s.io/v1alpha1/podcertificaterequests=true
kube-apiserver 标志启用对 Pod 证书的支持。podCertificate
投射卷源安全地为 Pod 提供了私钥和 X.509 证书链,作为客户端或服务器凭据使用。Kubelet 将在私钥和证书链接近过期时处理它们的刷新。应用程序只需确保在文件更改时及时重新加载文件,例如使用 inotify
或轮询机制。
每个 podCertificate
投射支持以下配置字段:
signerName
:你希望颁发证书的签名者。请注意,签名者可能有自己的访问要求,并可能拒绝向你的 Pod 颁发证书。keyType
:应生成的私钥类型。有效值为ED25519
、ECDSAP256
、ECDSAP384
、ECDSAP521
、RSA3072
和RSA4096
。maxExpirationSeconds
:你接受的颁发给 Pod 证书的最长有效期。如果未设置,则默认为86400
(24 小时)。必须至少为3600
(1 小时),最多为7862400
(91 天)。Kubernetes 内置签名者限制为最长有效期86400
(1 天)。签名者可以颁发比你指定有效期短的证书。credentialBundlePath
:凭证包应写入的投射中的相对路径。凭证包是一个 PEM 格式的文件,其中第一个块是包含 PKCS#8 序列化私钥的“PRIVATE KEY”块,其余块是构成证书链(叶证书和任何中间证书)的“CERTIFICATE”块。keyPath
和certificateChainPath
:Kubelet 应该**只**写入私钥或证书链的单独路径。
注意
大多数应用程序应优先使用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
SecurityContext 交互
关于投射服务账号卷增强中文件权限处理的提案引入了投射文件设置正确所有者权限的机制。
Linux
在具有投射卷并在 Pod SecurityContext
中设置 RunAsUser
的 Linux Pod 中,投射文件具有正确的所有权设置,包括容器用户所有权。
当 Pod 中的所有容器在其 PodSecurityContext
或容器 SecurityContext
中设置相同的 runAsUser
时,kubelet 确保 serviceAccountToken
卷的内容由该用户拥有,并且令牌文件的权限模式设置为 0600
。
注意
在 Pod 创建后添加的 临时容器 不会改变 Pod 创建时设置的卷权限。
如果 Pod 的 serviceAccountToken
卷权限由于 Pod 中所有其他容器具有相同的 runAsUser
而设置为 0600
,则临时容器必须使用相同的 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
)将拥有读、写和执行权限,而非管理员用户将拥有读和执行权限。
注意
通常,不鼓励授予容器访问主机的权限,因为这可能会导致潜在的安全漏洞。
在 Windows Pod 中使用 RunAsUser
创建 Pod 将导致 Pod 永远停留在 ContainerCreating
状态。因此,建议不要在 Windows Pod 中使用仅适用于 Linux 的 RunAsUser
选项。