使用 Node 鉴权

使用 Node 鉴权

节点鉴权是一种特殊用途的鉴权模式,专门对 kubelet 发出的 API 请求进行授权。

概述

节点鉴权器允许 kubelet 执行 API 操作。包括:

读取操作:

  • services
  • endpoints
  • nodes
  • pods
  • 与绑定到 kubelet 节点的 Pod 相关的 Secret、ConfigMap、PersistentVolumeClaim 和持久卷
特性状态: Kubernetes v1.34 [stable](默认启用)

kubelet 仅限于读取自己的节点对象,以及与节点绑定的 Pod。

写入操作:

  • 节点和节点状态(启用 NodeRestriction 准入插件以限制 kubelet 只能修改自己的节点)
  • Pod 和 Pod 状态(启用 NodeRestriction 准入插件以限制 kubelet 只能修改绑定到自身的 Pod)
  • 事件

身份认证与鉴权相关的操作:

  • 对于基于 TLS 的启动引导过程时使用的 certificationsigningrequests API 的读/写权限
  • 为委派的身份验证/鉴权检查创建 TokenReview 和 SubjectAccessReview 的能力

在将来的版本中,节点鉴权器可能会添加或删除权限,以确保 kubelet 具有正确操作所需的最小权限集。

为了获得节点鉴权器的授权,kubelet 必须使用一个凭据以表示它在 system:nodes 组中,用户名为 system:node:<nodeName>。上述的组名和用户名格式要与 kubelet TLS 启动引导 过程中为每个 kubelet 创建的标识相匹配。

<nodeName> 的值必须与 kubelet 注册的节点名称精确匹配。默认情况下,节点名称是由 hostname 提供的主机名,或者通过 kubelet --hostname-override 选项覆盖。 但是,当使用 --cloud-provider kubelet 选项时,具体的主机名可能由云提供商确定, 忽略本地的 hostname--hostname-override 选项。有关 kubelet 如何确定主机名的详细信息,请参阅 kubelet 选项参考

要启用 Node 鉴权器,启动 API 服务器时将 --authorization-config 参数设置为包含 Node 鉴权器的某个文件;例如:

apiVersion: apiserver.config.k8s.io/v1
kind: AuthorizationConfiguration
authorizers:
  ...
  - type: Node
  ...

或者,在启动 API 服务器时将 --authorization-mode 参数设置为一个包含 Node 的逗号分隔的列表;例如:

kube-apiserver --authorization-mode=...,Node --other-options --more-options

要限制 kubelet 可以写入的 API 对象,请使用 --enable-admission-plugins=...,NodeRestriction,... 启动 API 服务器,从而启用 NodeRestriction 准入插件。

服务帐户令牌受众限制

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

当启用了 ServiceAccountNodeAudienceRestriction 特性门控, 并且 NodeRestriction 准入插件处于活动状态时,kubelet 只能请求为那些已经在该节点上运行的 Pod 引用的受众的服务账户令牌。这防止了被攻破的节点获取任意受众的令牌。

允许的受众从 Pod 规约中确定:

  • 默认 API 服务器受众(空或 API 服务器配置的受众)。
  • 在投射服务账户令牌卷源中设置的受众。
  • 在 CSI 驱动 spec.tokenRequests 中配置的受众,适用于 Pod 使用的任何 CSI 驱动, 无论是通过内联 CSI 卷、由 PersistentVolumeClaim 支持的卷,或是临时卷。

这在使用服务账户令牌为镜像凭据提供者时特别相关, 此时 kubelet 代表 Pod 向特定注册表受众请求令牌。

使用 RBAC 允许额外的受众

你可以授予 kubelet 权限,以请求超出 Pod 规约引用的受众的令牌。 当 kubelet 请求带有未在 Pod 规约中找到的受众的令牌时, NodeRestriction 准入插件通过执行带有以下属性的授权检查来验证 kubelet 是否有权限:

属性
动词(Verb)request-serviceaccounts-token-audience
API 组(API Group)(空字符串,意味着核心 API 组)
资源(Resource)请求的受众值
名称(Name)服务账号名称
命名空间(Namespace)服务账号命名空间

你可以使用标准的 RBAC 规则来授权这些检查。 resources 字段控制允许哪些受众,resourceNames 字段控制规则适用的服务账号。

例如,要允许 kubelet 为特定服务账号请求受众 my-registry-audience

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-audience-my-registry
rules:
- verbs: ["request-serviceaccounts-token-audience"]
  apiGroups: [""]
  resources: ["my-registry-audience"]
  resourceNames: ["my-service-account"]

省略 resourceNames 时,允许为任意服务账号请求该受众。 resources 使用通配符("*")时,允许请求任意受众:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-audience-unrestricted
rules:
- verbs: ["request-serviceaccounts-token-audience"]
  apiGroups: [""]
  resources: ["*"]  # 任意受众
  # 无资源名称:任何服务帐户

将 ClusterRole 绑定到 system:nodes 组,使其应用于所有 kubelet:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: node-audience-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: node-audience-my-registry
subjects:
- kind: Group
  name: system:nodes
  apiGroup: rbac.authorization.k8s.io

说明:

此限制是 NodeRestriction 准入插件的一部分, 且仅适用于节点身份(kubelet)。它并不限制其他调用者可以请求的受众。 如果你需要限制其他调用者,请考虑使用 ValidatingAdmissionPolicy

迁移考虑因素

system:nodes 组之外的 kubelet

system:nodes 组之外的 kubelet 不会被 Node 鉴权模式授权,并且需要继续通过当前授权它们的机制来授权。 节点准入插件不会限制来自这些 kubelet 的请求。

具有无差别用户名的 kubelet

在一些部署中,kubelet 具有 system:nodes 组的凭据, 但是无法给出它们所关联的节点的标识,因为它们没有 system:node:... 格式的用户名。 这些 kubelet 不会被 Node 鉴权模式授权,并且需要继续通过当前授权它们的任何机制来授权。

因为默认的节点标识符实现不会把它当作节点身份标识,NodeRestriction 准入插件会忽略来自这些 kubelet 的请求。

最后修改 May 21, 2026 at 4:28 PM PST: [zh-cn]sync access-authn-authz/node (34da774500)