Kubernetes RBAC 最小权限:给 AI 服务单独建 ServiceAccount
一、default ServiceAccount 是隐患的起点
安全审计的时候发现,团队 40 个微服务全部共用 default ServiceAccount。Pod 里任意一行 kubectl get pods -A 就能看到整个集群所有的 Pod 列表。更糟糕的是,这个 default ServiceAccount 还绑了一个有 cluster-admin 角色的 ClusterRoleBinding——这是早期搭建集群时为了方便随手加的。
这意味着任何一个服务被攻破,攻击者就能拿到整个集群的控制权。AI 模型推理服务通常需要 GPU 调度和镜像拉取权限,但不需要修改 ConfigMap,不需要删除 Deployment,更不需要访问其他 Namespace 的 Secret。
最小权限原则不是"先用着以后再改"。基础设施不需要漂亮话。权限管理的本质是:每个组件只拥有完成工作所必需的最小权限集合,除此之外的一切都默认拒绝。
二、Kubernetes RBAC 的权限模型
Kubernetes RBAC 的核心概念只有四个:ServiceAccount、Role、ClusterRole、RoleBinding。理解它们的组合方式,就能设计出安全的权限体系。
flowchart LR
SA[ServiceAccount] –> RB[RoleBinding]
RB –> R[Role<br/>Namespace 级]
SA –> CRB[ClusterRoleBinding]
CRB –> CR[ClusterRole<br/>集群级]
R –> P1[权限:get/list pods<br/>范围:default namespace]
CR –> P2[权限:get nodes<br/>范围:全集群]
ServiceAccount:Pod 在集群中的身份标识。每个 Pod 必须属于一个 ServiceAccount。
Role:定义在某个 Namespace 内的一组权限规则。Role 只能控制本 Namespace 的资源。
ClusterRole:定义集群级别的一组权限规则。可以控制所有 Namespace 的资源,以及 Nodes、PV 等集群级资源。
RoleBinding / ClusterRoleBinding:将 Role/ClusterRole 绑定到 ServiceAccount。这是授权环节,决定"谁有什么权限"。
权限模型的四个粒度:
三、AI 模型服务最小权限配置
以下是为 AI 模型推理服务配置的专用 ServiceAccount 和 Role:
—
# 1. 为 AI 推理服务创建专用 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: ai-inference-sa
namespace: ai-inference
labels:
app: ai-inference
security-tier: restricted
—
# 2. 定义 AI 推理服务所需的最小权限 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ai-inference-role
namespace: ai-inference
rules:
# GPU 指标采集:读取当前 Pod 信息
– apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
resourceNames: [] # 不限制具体 Pod,因为 Pod 名是动态的
# 读取自身的 ConfigMap 配置
– apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
resourceNames: ["ai-inference-config", "model-registry"]
# 读取模型仓库的 Secret(镜像拉取凭证)
– apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
resourceNames: ["model-registry-pull-secret"]
# 不授予:pods/exec、pods/delete、secrets 列表、deployments 写权限
—
# 3. 将 ServiceAccount 绑定到 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ai-inference-binding
namespace: ai-inference
subjects:
– kind: ServiceAccount
name: ai-inference-sa
namespace: ai-inference
roleRef:
kind: Role
name: ai-inference-role
apiGroup: rbac.authorization.k8s.io
—
# 4. Deployment 中使用专用 ServiceAccount
apiVersion: apps/v1
kind: Deployment
metadata:
name: model-inference
namespace: ai-inference
spec:
replicas: 3
selector:
matchLabels:
app: model-inference
template:
metadata:
labels:
app: model-inference
spec:
# 指定专用 ServiceAccount,而非 default
serviceAccountName: ai-inference-sa
# 禁止自动挂载 default token(如果不需要访问 API Server)
automountServiceAccountToken: true
containers:
– name: inference
image: model-inference:v4.0.0
resources:
limits:
nvidia.com/gpu: 1
env:
– name: MODEL_REGISTRY_SECRET
valueFrom:
secretKeyRef:
name: model-registry-pull-secret
key: .dockerconfigjson
nodeSelector:
accelerator: nvidia-tesla-t4
—
# 5. 每 Namespace 独立授权——模型训练服务的权限配置
apiVersion: v1
kind: ServiceAccount
metadata:
name: ai-training-sa
namespace: ai-training
—
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ai-training-role
namespace: ai-training
rules:
# 训练任务需要创建和管理 Job
– apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "get", "list", "delete"]
# 训练需要读写 PVC 存储模型和数据
– apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list"]
# 训练 Pod 需要读取自己的日志
– apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
# 不授予:secrets、configmaps、deployments 写权限
# 不授予:其他 namespace 的任何资源访问
—
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ai-training-binding
namespace: ai-training
subjects:
– kind: ServiceAccount
name: ai-training-sa
namespace: ai-training
roleRef:
kind: Role
name: ai-training-role
apiGroup: rbac.authorization.k8s.io
关键权限设计决策:
推理服务不授予写权限。推理服务只需要读取配置和 Secrets,不需要创建、更新、删除任何资源。Role 中完全没有 create、update、delete、patch 动词。
Secret 访问限制到具体资源名。推理服务只需要拉取镜像凭证的 Secret,不能列出所有 Secrets。用 resourceNames 精确锁定。
推理与训练使用不同的 ServiceAccount 和 Namespace。训练服务需要写 PVC、创建 Job,风险面更大。隔离在两个 Namespace 中,即使训练 Pod 被攻破,也无法访问推理服务的配置。
禁止使用 cluster-admin 绑定。如果有全局可观测性需求(如统一的指标采集),应该为 DaemonSet 的 node-exporter 创建专用的 ClusterRole,而不是把 cluster-admin 挂给业务服务。
四、权限审计与持续治理
定期权限审计。用工具扫描集群中所有的 RoleBinding 和 ClusterRoleBinding,列出每个 ServiceAccount 的实际权限。重点关注以下几类高风险配置:
- 任何绑定到 cluster-admin 的非系统 ServiceAccount
- 包含 * 通配符的 verbs 或 resources
- 跨 Namespace 的 RoleBinding(虽然 Role 是 Namespace 级的,但绑定可以跨 Namespace)
审计命令示例:
# 检查是否有 cluster-admin 绑定到用户 ServiceAccount
kubectl get clusterrolebindings -o json | \\
jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects[] | select(.kind=="ServiceAccount")'
# 列出所有包含通配符的 Role
kubectl get roles -A -o json | \\
jq '.items[] | select(.rules[].verbs[] | contains("*")) | {name: .metadata.name, namespace: .metadata.namespace}'
Pod Security Admission。从 Kubernetes 1.25 开始,PodSecurityPolicy 被弃用,替代方案是 Pod Security Admission。对于 AI 推理服务,应该使用 restricted 级别的 Pod Security Standard——禁止特权容器、禁止 hostPath 挂载、要求只读根文件系统。
动态准入控制。对于更严格的权限控制,可以引入 OPA Gatekeeper 或 Kyverno。例如编写策略:任何使用 GPU 的 Deployment 必须指定专用的 ServiceAccount,且该 ServiceAccount 不能包含 secrets 的 list 权限。
RBAC 变更的审计日志。确保 API Server 开启了审计日志,监控 RoleBinding 和 ClusterRoleBinding 的创建和修改事件。任何提升权限的操作都应触发告警。
五、总结
Kubernetes RBAC 最小权限的核心是为每个服务创建专用 ServiceAccount 和 Role,只授予该服务完成工作所需的最小权限集合。
关键实践:推理服务只授予 get/list 权限,不授予 create/delete;Secret 访问用 resourceNames 精确限制;推理和训练使用不同的 ServiceAccount 和 Namespace;定期审计所有 RoleBinding 和 ClusterRoleBinding;用 Pod Security Admission 限制容器运行级别;对高风险权限变更设置告警。最小的权限面就是最大的安全面。



