news 2026/9/17 7:52:21

Feast Kubernetes 认证与 RBAC 授权配置完全指南:基于 Token Access Review 的组/命名空间/角色鉴权

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Feast Kubernetes 认证与 RBAC 授权配置完全指南:基于 Token Access Review 的组/命名空间/角色鉴权

Feast Kubernetes 认证与 RBAC 授权配置完全指南:基于 Token Access Review 的组/命名空间/角色鉴权

【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feast

导读

本文基于 Feast 官方文档 docs/reference/auth/kubernetes_auth_setup.md 展开,系统讲解 Feast 如何从 Kubernetes 认证令牌(Token)中提取用户组(Groups)、命名空间(Namespaces)与角色(Roles),并借助Permission框架实现细粒度访问控制。你将掌握:Feast Operator 默认的"认证默认开启"行为、如何在FeatureStoreCR 中切换认证模式、如何设计角色/组/命名空间四类授权策略,以及如何在 SDK、CLI、REST/gRPC 中注入 Kubernetes 用户令牌。读完即可在自己的集群环境中完成从认证到授权的完整落地。

一、整体架构:Feast 如何从 Kubernetes Token 提取身份信息

Feast 的 Kubernetes 认证建立在"客户端持有有效 Kubernetes Bearer Token,服务端负责验证并提取身份"的模型之上。服务端通过Token Access Review APIRBAC 资源完成三方面信息提取:

  • Groups(用户组):与 User/ServiceAccount 直接关联的组,以及从关联命名空间中推导出的组;
  • Namespaces(命名空间):与 User/ServiceAccount 关联的 Kubernetes 命名空间;
  • Roles(角色):与 User/ServiceAccount 关联的 Kubernetes 角色。

这套逻辑的核心实现位于 sdk/python/feast/permissions/auth/kubernetes_token_parser.py 中的KubernetesTokenParser类。从源码结构看,它的工作流程分为两条路径:

  1. ServiceAccount 路径:尝试把令牌当作 JWT 解码(jwt.decode且不校验签名),从sub声明中解析出system:serviceaccount:NAMESPACE:SA_NAME格式的服务账号身份,再通过查询当前命名空间下的RoleBinding得到其绑定的Role列表;
  2. 普通用户路径:当 JWT 解码失败(说明是用户令牌),回退到TokenReview结果中的username,并通过全局RoleBindingClusterRoleBinding同时解析"直接绑定给用户"和"绑定给用户所属组"的角色。

在提取组与命名空间时,KubernetesTokenParser调用AuthenticationV1Api().create_token_review(...)发起 Token Access Review,从响应status.user.groups中取组;命名空间则分两种情况推导:

  • 对 ServiceAccount,从system:serviceaccount:<namespace>:<name>形式的用户名中截取命名空间,并进一步查询该命名空间下RoleBinding中绑定到Group的组名,一并并入 groups;
  • 对普通用户,通过扫描dashboard-permissions-*(带opendatahub.io/dashboard=true标签)与admin类型的RoleBinding,推导出用户被授予数据科学项目(Data Science Project)访问权的命名空间集合。

需要强调:Feast 本身不负责颁发令牌(参见 docs/getting-started/components/authz_manager.md 中的说明),客户端负责管理认证令牌并将其随请求传入,服务端只负责校验令牌并提取用户详情。

二、Operator 默认行为:认证默认开启,授权逐步收紧

当使用 Feast Operator 部署时,Kubernetes 认证默认开启。即使在FeatureStoreCR 中没有显式配置authz,Operator 也会自动为所有部署的服务应用kubernetes认证。这意味着:

  • 所有发往 Feast 服务的 HTTP/gRPC 请求必须携带合法的 Kubernetes Bearer Token(放在Authorization请求头中);
  • 服务端通过 Kubernetes Token Access Review API 校验令牌,并提取用户名、组、命名空间与角色;
  • 如果没有任何Permission对象被定义,通过认证的用户将获得全部访问权限(同时在日志中输出一条警告,提示管理员尽快定义细粒度权限);
  • 未认证的请求会收到401 Unauthorized响应。

该设计遵循"Authenticated by Default, Authorized Gradually"(默认认证、逐步授权)的安全模型,确保 Feast 部署不会在未认证状态下被意外暴露,同时允许团队渐进式引入细粒度 RBAC。

2.1 关闭认证:noAuth: true

如果需要在本地开发或测试环境中以无认证方式运行,可以在FeatureStoreCR 中显式设置noAuth: true

apiVersion: feast.dev/v1 kind: FeatureStore metadata: name: my-feature-store spec: feastProject: my_project authz: noAuth: true

⚠️警告noAuth: true会关闭所有认证与授权校验,所有端点将变为公开可访问。仅限本地开发或测试环境使用,生产环境请使用kubernetesoidc认证。

2.2 认证模式选择速查表

spec.authz设置行为
(未指定)Kubernetes 认证开启(默认)
kubernetes: {}Kubernetes 认证开启(显式声明)
oidc: { ... }OIDC 认证开启
noAuth: true关闭所有认证

需要说明的是,Feast 还内置了基于 OIDC 的认证(OidcAuthConfig,见 sdk/python/feast/permissions/auth_model.py),当客户端auth_configtypeoidc时走 OIDC 客户端管理器获取令牌;本文聚焦 Kubernetes 认证路径。

三、Kubernetes RBAC 环境与 Feast 权限的对应关系

要让 Kubernetes RBAC 环境与 Feast 的 RBAC 配置对齐,需要遵循以下规则。

3.1 基于角色的认证设置(Role-based)

  • FeastPermission实例中定义的角色名,必须与 Kubernetes RBACRole的名称一一对应
  • Kubernetes RBACRole必须与 Feast 服务位于同一命名空间
  • 客户端应用可以运行在不同命名空间,使用自己的专用ServiceAccount
  • 将客户端ServiceAccount关联到该 RBACRoleRoleBinding必须定义在 Feast 服务所在的命名空间中

从源码实现看,这一点与KubernetesTokenParser.get_roles()的行为完全吻合:它只查询list_namespaced_role_binding(current_namespace)(Feast 服务所在命名空间),匹配subject.kind == "ServiceAccount"subject.name == service_account_namesubject.namespace == service_account_namespace的绑定,取其role_ref.name作为用户角色。

3.2 基于组与命名空间的认证设置(Group/Namespace-based)

  • FeastPermission实例中定义的组名与命名空间名,必须与 Kubernetes 中实际的GroupNamespace名称对应
  • 用户或服务账号必须位于 FeastPermission实例定义的组或命名空间中;
  • 客户端应用可以运行在不同命名空间,使用自己的专用ServiceAccount或用户;
  • Feast 服务根据Permission实例中定义的组与命名空间关联关系来授予访问权限。

四、策略类型(Policy Types):四类鉴权策略详解

Feast 的权限框架通过策略(Policy)类描述"谁能做什么"。四类策略的实现均位于 sdk/python/feast/permissions/policy.py,全部继承自抽象基类Policy,核心方法是validate_user(user) -> (bool, str),返回"是否匹配"以及不匹配时的原因说明。

4.1 RoleBasedPolicy(基于角色)

按用户角色成员关系授权,用户至少拥有配置角色中的一个即可通过。

from feast.permissions.policy import RoleBasedPolicy policy = RoleBasedPolicy(roles=["data-team", "ml-engineers"])

实现上,validate_user调用user.has_matching_role(self.roles);若用户命中了角色绑定(含直接绑定与组绑定,见get_user_roles()),即可通过校验。

4.2 GroupBasedPolicy(基于用户组)

按用户组归属授权,用户至少加入其中一个组即可通过。

from feast.permissions.policy import GroupBasedPolicy policy = GroupBasedPolicy(groups=["data-team", "ml-engineers"])

4.3 NamespaceBasedPolicy(基于命名空间)

按用户关联的命名空间授权,用户至少位于其中一个被允许的命名空间即可通过。

from feast.permissions.policy import NamespaceBasedPolicy policy = NamespaceBasedPolicy(namespaces=["production", "staging"])

4.4 CombinedGroupNamespacePolicy(组与命名空间组合)

当用户被加入允许的组 OR 允许的命名空间(二者满足其一)时授权通过。

from feast.permissions.policy import CombinedGroupNamespacePolicy policy = CombinedGroupNamespacePolicy( groups=["data-team"], namespaces=["production"] )

源码中该策略的判定逻辑为has_matching_group(groups) or has_matching_namespace(namespaces),不满足时返回原因 "User must be in at least one of the permitted groups or namespaces"。

此外,sdk/python/feast/permissions/policy.py 中还提供了一个AllowAll策略实例,任何用户都能通过校验,作为未定义权限时的默认兜底行为。

五、服务端与客户端配置

5.1 服务端配置

使用 Kubernetes 认证时,服务端会自动提取组、命名空间与角色,无需在既有 Kubernetes 认证配置之外追加任何额外配置。认证模式的切换(kubernetes / oidc / no_auth)通过服务端feature_store.yaml中的auth段完成,AuthConfig基类定义了type: Literal["oidc", "kubernetes", "no_auth"] = "no_auth"字段。

5.2 客户端配置

对于非 ServiceAccount 的外部用户,需要在客户端配置中提供用户令牌。令牌的提供方式详见下一节,也可直接阅读官方文档 docs/reference/auth/user_token_provisioning.md。

六、用户令牌的多种提供方式(客户端视角)

Feast 客户端支持从 CLI、API 与 SDK 三种途径注入 Kubernetes 用户令牌。

6.1 SDK 配置(Python)

方法一:在FeatureStore中直接配置

from feast import FeatureStore from feast.permissions.auth_model import KubernetesAuthConfig # Create auth config with user token auth_config = KubernetesAuthConfig( type="kubernetes", user_token="your-kubernetes-user-token-here" ) # Initialize FeatureStore with auth config fs = FeatureStore( repo_path="path/to/feature_repo", auth_config=auth_config )

方法二:环境变量

import os from feast import FeatureStore # Set environment variable os.environ["LOCAL_K8S_TOKEN"] = "your-kubernetes-user-token-here" # FeatureStore will automatically use the token fs = FeatureStore("path/to/feature_repo")

方法三:配置文件

feature_store.yaml中声明auth段:

project: my-project auth: type: kubernetes user_token: "your-kubernetes-user-token-here"

随后FeatureStore会自动从 YAML 读取认证配置:

from feast import FeatureStore # FeatureStore will read auth config from feature_store.yaml fs = FeatureStore("path/to/feature_repo")

注意KubernetesAuthConfig类通过ConfigDict(arbitrary_types_allowed=True, extra="allow")允许额外字段(见 sdk/python/feast/permissions/auth_model.py),因此user_token字段从 YAML 加载时会被正确识别。

6.2 CLI 使用

方法一:环境变量

# Set the token as environment variable export LOCAL_K8S_TOKEN="your-kubernetes-user-token-here" # Use Feast CLI commands feast apply feast materialize feast get-online-features \ --features feature1,feature2 \ --entity-rows '{"entity_id": "123"}'

方法二:配置文件

feature_store.yaml中配置auth段(同上),然后直接执行 CLI 命令即可:

feast apply feast materialize feast get-online-features \ --features feature1,feature2 \ --entity-rows '{"entity_id": "123"}'

6.3 API 使用(REST/gRPC)

REST API —— 方法一:Authorization 请求头

import requests # For REST API headers = { "Authorization": "Bearer your-kubernetes-user-token-here", "Content-Type": "application/json" } # Get features response = requests.get( "http://feast-server/features", headers=headers ) # Get online features response = requests.post( "http://feast-server/get-online-features", headers=headers, json={ "features": ["feature1", "feature2"], "entity_rows": [{"entity_id": "123"}] } )

REST API —— 方法二:requests Session

import requests from requests.auth import HTTPBearerAuth # Create session with auth session = requests.Session() session.auth = HTTPBearerAuth("your-kubernetes-user-token-here") # Make requests response = session.get("http://feast-server/features")

gRPC API —— 方法一:gRPC Metadata

import grpc from feast.protos.feast.serving.ServingService_pb2_grpc import ServingServiceStub from feast.protos.feast.serving.ServingService_pb2 import GetOnlineFeaturesRequest # Create gRPC channel channel = grpc.insecure_channel('feast-server:6565') stub = ServingServiceStub(channel) # Create metadata with auth token metadata = [('authorization', 'Bearer your-kubernetes-user-token-here')] # Create request request = GetOnlineFeaturesRequest( features=["feature1", "feature2"], entity_rows=[{"entity_id": "123"}] ) # Make gRPC call response = stub.GetOnlineFeatures(request, metadata=metadata)

gRPC API —— 方法二:gRPC Interceptor(统一注入)

import grpc from feast.protos.feast.serving.ServingService_pb2_grpc import ServingServiceStub class AuthInterceptor(grpc.UnaryUnaryClientInterceptor): def __init__(self, token): self.token = token def intercept_unary_unary(self, continuation, client_call_details, request): # Add auth metadata metadata = list(client_call_details.metadata or []) metadata.append(('authorization', f'Bearer {self.token}')) # Update call details client_call_details = client_call_details._replace(metadata=metadata) return continuation(client_call_details, request) # Create channel with interceptor channel = grpc.insecure_channel('feast-server:6565') interceptor = AuthInterceptor("your-kubernetes-user-token-here") channel = grpc.intercept_channel(channel, interceptor) # Use the channel stub = ServingServiceStub(channel)

6.4 编程式 SDK 用法:从 Kubernetes 配置获取令牌

对于运行在集群内、需要动态获取令牌的客户端,可以结合 Kubernetes Python SDK 从 Secret 等安全存储读取令牌:

from feast import FeatureStore from feast.permissions.auth_model import KubernetesAuthConfig from kubernetes import client, config # Load kubeconfig and get token config.load_kube_config() v1 = client.CoreV1Api() # Get token from Kubernetes API or secure storage def get_token_from_k8s(): # Example: Get token from secret secret = v1.read_namespaced_secret( name="user-token", namespace="default" ) return secret.data["token"].decode("utf-8") user_token = get_token_from_k8s() auth_config = KubernetesAuthConfig( type="kubernetes", user_token=user_token ) fs = FeatureStore( repo_path="path/to/feature_repo", auth_config=auth_config )

6.5 令牌解析优先级

客户端获取令牌的完整顺序由KubernetesAuthClientManager.get_token()决定(见 sdk/python/feast/permissions/client/kubernetes_auth_client_manager.py),与官方文档一致:

  1. 服务间通信INTRA_COMMUNICATION_BASE64环境变量(服务到服务调用,此时会生成一个alg: none的占位 JWT);
  2. 直接配置KubernetesAuthConfig中的user_token字段,或feature_store.yaml中的auth.user_token
  3. 服务账号令牌文件/var/run/secrets/kubernetes.io/serviceaccount/token(适用于 Pod 内运行);
  4. 环境变量LOCAL_K8S_TOKEN

同时,客户端管理器工厂AuthenticationClientManagerFactory(见 sdk/python/feast/permissions/client/auth_client_manager.py)会依据auth_config.typekubernetes/oidc)选择对应的客户端管理器;若检测到INTRA_COMMUNICATION_BASE64,则优先走内部通信专用管理器。

七、完整实战:权限定义与下发

7.1 基础权限示例

permissions.py中组合使用全部四类策略定义权限:

from feast.feast_object import ALL_RESOURCE_TYPES from feast.permissions.action import READ, AuthzedAction, ALL_ACTIONS from feast.permissions.permission import Permission from feast.permissions.policy import ( RoleBasedPolicy, GroupBasedPolicy, NamespaceBasedPolicy, CombinedGroupNamespacePolicy ) # Role-based permission role_perm = Permission( name="role_permission", types=ALL_RESOURCE_TYPES, policy=RoleBasedPolicy(roles=["reader-role"]), actions=[AuthzedAction.DESCRIBE] + READ ) # Group-based permission (new) data_team_perm = Permission( name="data_team_permission", types=ALL_RESOURCE_TYPES, policy=GroupBasedPolicy(groups=["data-team", "ml-engineers"]), actions=[AuthzedAction.DESCRIBE] + READ ) # Namespace-based permission (new) prod_perm = Permission( name="production_permission", types=ALL_RESOURCE_TYPES, policy=NamespaceBasedPolicy(namespaces=["production"]), actions=[AuthzedAction.DESCRIBE] + READ ) # Combined permission (new) dev_staging_perm = Permission( name="dev_staging_permission", types=ALL_RESOURCE_TYPES, policy=CombinedGroupNamespacePolicy( groups=["dev-team"], namespaces=["staging"] ), actions=ALL_ACTIONS )

补充说明代码中用到的动作枚举(定义于 sdk/python/feast/permissions/action.py):

动作含义
CREATE创建实例
DESCRIBE访问实例状态
UPDATE更新实例状态
DELETE删除实例
READ_ONLINE/READ_OFFLINE仅读取在线/离线存储
WRITE_ONLINE/WRITE_OFFLINE仅写入在线/离线存储
  • READ = [READ_OFFLINE, READ_ONLINE]WRITE = [WRITE_OFFLINE, WRITE_ONLINE]CRUD = [CREATE, DESCRIBE, UPDATE, DELETE]ALL_ACTIONS覆盖全部 8 个动作。

7.2 下发权限

在服务端(或在具备权限的客户端)通过 CLI/API/SDK 执行:

feast apply

feast apply会将permissions.py中定义的Permission对象写入注册表,之后服务端便会对每个请求按"资源类型 + 动作 + 策略"进行鉴权。未定义任何Permission时,认证通过的用户默认拥有全部权限,但服务端会记录一条 "No permissions defined" 警告日志。

八、故障排查(Troubleshooting)

常见问题

  1. 升级后出现 401 Unauthorized

    • Feast Operator 现在默认启用 Kubernetes 认证;如果既有FeatureStoreCR 未指定authz,升级会自动开启认证。
    • 快速修复(仅测试用):在FeatureStoreCR 中追加authz.noAuth: true以恢复此前的无认证行为。
    • 推荐做法:更新客户端应用,让所有请求携带有效的 Kubernetes Bearer Token。
  2. Token Access Review 失败

    • 检查 Feast 服务是否具备所需的 RBAC 权限(其运行 Deployment 必须被授予查询RoleBinding、执行 TokenReview 等资源的权限,见 sdk/python/feast/permissions/auth/kubernetes_token_parser.py 中get_roles的注释说明);
    • 确认令牌有效且未过期;
    • 以 debug 模式查看服务端日志中的详细错误信息。
  3. 未提取到组/命名空间

    • 确认令牌包含预期的 claims;
    • 检查用户是否已在 Kubernetes/ODH/RHOAI 中正确配置(普通用户的命名空间推导依赖dashboard-permissions-*admin类型的RoleBinding)。
  4. 权限被拒绝(Permission Denied)

    • 确认用户已被加入所需组/命名空间,或已分配所需角色;
    • 检查策略配置是否正确;
    • 查看权限评估日志。
  5. 日志中出现 "No permissions defined" 警告

    • 这是 Kubernetes 认证开启但尚未应用任何Permission对象时的预期行为;
    • 默认情况下认证用户拥有全部访问权限;如需强制细粒度授权,请通过permissions.py+feast apply定义权限。

客户端常见错误

错误信息解决方案
Missing authentication token通过上述任一受支持方式提供令牌(配置项、文件或环境变量)
Invalid or expired access token确认令牌有效且未过期
User is not added into the permitted groups / Namespaces检查用户是否具备所需组/命名空间访问权限

九、迁移指南:从基于角色到基于组/命名空间

如果团队希望从单一的角色模型迁移到更灵活的组/命名空间模型,官方建议按以下步骤渐进推进:

  1. 识别用户组:确定用户归属的组;
  2. 映射命名空间:确定用户应访问的命名空间;
  3. 创建新策略:定义基于组与基于命名空间的策略(对应GroupBasedPolicy/NamespaceBasedPolicy/CombinedGroupNamespacePolicy);
  4. 渐进测试:先从只读权限开始,逐步扩大范围;
  5. 监控:持续观察日志,确保认证与授权行为符合预期。

十、最佳实践

  1. 最小权限原则(Principle of Least Privilege):只授予完成任务所需的最小权限;
  2. 合理组织用户组:按照职责把用户组织进逻辑组;
  3. 命名空间隔离:使用命名空间隔离不同环境或团队;
  4. 定期审计:周期性复查与审计权限配置。

相关文档

  • Authorization Manager(授权管理器组件说明)
  • Permission Model(权限模型概念)
  • RBAC Architecture(RBAC 架构说明)
  • User Token Provisioning(用户令牌提供指南)
  • 权限概念文档

【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feast

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 7:52:01

企业级WLAN高可用设计:VRRP热备+802.1X+RADIUS实战指南

简介&#xff1a;本资源是一份面向通信工程、网络工程专业本科生的毕业设计论文及配套方案&#xff0c;聚焦企业级办公场景下的WLAN覆盖系统设计与落地实施&#xff0c;解决信号覆盖盲区、用户漫游中断、网关单点故障及802.1X安全接入等典型工程问题。压缩包含1个1.01MB的Word文…

作者头像 李华
网站建设 2026/9/17 7:51:48

飞书云OpenCLAW:Serverless API托管的轻量级解决方案

1. 项目背景与核心价值最近在技术社区看到不少开发者讨论飞书云OpenCLAW的限免活动&#xff0c;每天放出10万个免费名额&#xff0c;而且不需要自己准备服务器资源。作为一个常年和云服务打交道的开发者&#xff0c;我第一时间就申请了测试资格&#xff0c;经过一周的深度使用&…

作者头像 李华
网站建设 2026/9/17 7:50:36

学术论文原创性提升与检测系统解析

1. 学术写作中的原创性挑战在当今学术环境中&#xff0c;保持论文原创性始终是研究者面临的核心挑战。随着各类辅助工具的出现&#xff0c;学术界也相应发展出多种检测技术来评估论文的原创程度。对于许多研究者而言&#xff0c;如何在合理使用现代工具的同时确保论文通过原创性…

作者头像 李华
网站建设 2026/9/17 7:49:06

MATLAB实现多智能体拍卖算法优化任务分配

1. 项目背景与核心价值多智能体系统的任务分配问题一直是分布式人工智能领域的核心挑战。传统集中式分配方法存在单点故障风险&#xff0c;而完全分布式方案又难以保证全局效率。拍卖机制作为一种经济学启发的解决方案&#xff0c;通过模拟市场竞争实现资源优化配置&#xff0c…

作者头像 李华
网站建设 2026/9/17 7:49:04

通达信主力监控指标源码:逐笔数据建模与三层逻辑验证

简介&#xff1a;本资源是一份面向股票、期货等金融领域技术分析初学者与进阶交易者的通达信主力监控指标公式详解文档&#xff0c;聚焦主力资金行为识别与买卖信号判别。文档完整呈现主力轨迹、主力进场、洗盘、主力拉高、出货五大核心模块的源码逻辑、参数含义&#xff08;如…

作者头像 李华
网站建设 2026/9/17 7:47:32

STM32 迁移 VS Code:Keil 到 AI 编程调试环境配置实战

我记得很清楚&#xff0c;第一次认真考虑把 STM32 的工程从 Keil 里搬出来&#xff0c;是因为一个很具体的场景&#xff1a;晚上十一点多&#xff0c;我在追一个串口接收丢包的问题&#xff0c;想让 AI 编程助手帮我从 HAL 库里翻一下 UART 中断标志位的清除顺序&#xff0c;结…

作者头像 李华