Kubernetes v1.35:将 Service Account Tokens 传递给 CSI Drivers 的更好方式

发布: (2026年1月8日 GMT+8 02:30)
7 min read

Source: Kubernetes Blog

理解现有方法

当 CSI 驱动使用 TokenRequests 功能时,它们可以通过在 CSIDriver 规范中配置 tokenRequests 字段来请求工作负载身份的服务账号令牌。这些令牌目前通过 volume attributes map 传递给驱动,使用的键为:

csi.storage.k8s.io/serviceAccount.tokens

为什么 volume_context 有问题

  • 日志风险 – 许多 CSI 驱动使用的 protostanitizer 工具 不会volume_context 视为敏感信息,因此在记录 gRPC 请求时,令牌可能会出现在日志中。

    • 示例:Secrets Store CSI Driver 中的 CVE‑2023‑2878。
    • 示例:Azure File CSI Driver 中的 CVE‑2024‑3744。
  • 消毒不一致 – 每个想要避免此问题的驱动都必须自行实现消毒逻辑,导致不同驱动之间的实现不统一。

CSI 规范已经在 NodePublishVolumeRequest 中定义了 secrets 字段,专门用于此类敏感信息。然而,直接将令牌移动到该字段会导致期望在 volume_context 中获取令牌的现有驱动出现兼容性问题。

Opt‑in 机制工作原理

Kubernetes v1.35 引入了一个 opt‑in 机制,使 CSI 驱动程序可以选择获取服务账户令牌的方式。现有驱动保持不变,而驱动在准备好后可以迁移到更合适的 secrets 字段。

CSIDriver 规范中的新字段

# CAUTION: this is an example configuration.
# Do not use this for your own cluster!
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
  name: example-csi-driver
spec:
  # ... existing fields ...
  tokenRequests:
    - audience: "example.com"
      expirationSeconds: 3600
  # New field for opting into secrets delivery
  serviceAccountTokenInSecrets: true   # defaults to false
  • serviceAccountTokenInSecrets: false(默认)——令牌会放在 volumeContext 中,键为 csi.storage.k8s.io/serviceAccount.tokens(当前行为)。
  • serviceAccountTokenInSecrets: true ——令牌仅会放在 secrets 字段中,使用相同的键。

关于 Beta 发行

  • CSIServiceAccountTokenSecrets 功能门在 kubeletkube‑apiserver 上默认启用。
  • 由于 serviceAccountTokenInSecrets 默认值为 false,启用该功能门 不会 改变任何现有行为。
  • 所有驱动程序仍通过 volume_context 接收令牌,除非它们明确选择加入。
  • 这种向后兼容的做法使该功能能够从 beta 而不是 alpha 开始。

Source:

CSI 驱动作者指南

如果您维护使用 service‑account token 的 CSI 驱动,请按照以下步骤安全地采用新机制。

1. 添加回退逻辑

更新驱动,使其同时检查 两个 位置的 token。这样驱动即可兼容旧方式和新方式。

const serviceAccountTokenKey = "csi.storage.k8s.io/serviceAccount.tokens"

func getServiceAccountTokens(req *csi.NodePublishVolumeRequest) (string, error) {
    // 新行为 – 首先检查 secrets 字段
    if tokens, ok := req.Secrets[serviceAccountTokenKey]; ok {
        return tokens, nil
    }

    // 旧行为 – 回退到 volume context
    if tokens, ok := req.VolumeContext[serviceAccountTokenKey]; ok {
        return tokens, nil
    }

    return "", fmt.Errorf("service account tokens not found")
}

此回退逻辑向后兼容,且可以在任何驱动版本中安全发布,即使集群尚未升级到 v1.35。

2. 推出顺序

驱动准备(可随时进行)

  • 添加回退逻辑。
  • 发布新驱动版本(或回移植到维护分支)。

集群升级与功能启用

  1. kube‑apiserver 升级到 v1.35 或更高版本。
  2. kubelet所有 节点上升级到 v1.35 或更高版本。
  3. 确保已部署包含回退逻辑的 CSI 驱动版本(如果尚未完成)。
  4. 完成 CSI 驱动 DaemonSet 在所有节点上的 rollout。
  5. 更新 CSIDriver 清单,将 serviceAccountTokenInSecrets: true 设置为启用。

3. 重要约束

  • 时机至关重要。 如果您的 CSI 驱动 DaemonSet 与 CSIDriver 对象位于同一清单或 Helm chart 中,需要 两次独立更新

    1. 部署新驱动版本并等待 DaemonSet rollout 完成。
    2. 然后再更新 CSIDriver 规范以启用 serviceAccountTokenInSecrets
  • 不要在所有驱动 Pod 完全 rollout 之前更新 CSIDriver
    如果提前更新,仍在运行旧驱动版本的节点上的 volume mount 将会失败,因为这些旧版 Pod 只会读取 volume_context

为什么这很重要

采用此功能有以下几方面的好处:

  • 消除在驱动日志中意外记录服务账户令牌的风险
  • 将令牌交付对齐到 CSI 规范中敏感数据的预期位置。
  • 减少对驱动特定清理逻辑的需求,促进整个生态系统的一致性。

通过选择加入,您可以使驱动更安全、更具前瞻性,同时保持与现有集群的兼容性。

将账户令牌作为 gRPC 请求中的卷上下文的一部分

  • 它使用 CSI 规范中专门用于敏感数据的字段,这样做很合适。
  • protosanitizer 工具会自动正确处理 secrets 字段,因此无需针对驱动的特定变通方案。
  • 该功能是 可选加入 的,你可以按自己的节奏迁移,而不会破坏现有部署。

行动号召

我们(Kubernetes SIG Storage)鼓励 CSI 驱动作者采用此功能,并就迁移体验提供反馈。

  • 如果你对 API 设计有想法或在采用过程中遇到任何问题,请在 Kubernetes Slack 的 #csi 频道与我们联系(获取邀请,请访问 。

你可以在 KEP‑5538 上关注进展,了解即将发布的 Kubernetes 版本的情况。

Back to Blog

相关文章

阅读更多 »