用kubectl和RBAC把AI服务器的K8s运维权限管起来
在AI服务器上做K8sOps配置,最该先做的不是装监控大屏或自动化平台,而是把谁能用kubectl、能操作哪些资源管清楚。
默认的cluster-admin账号一旦被随手共享,后面所有运维动作都缺少边界。
本文按实操顺序讲:确认集群可用、按命名空间拆分权限、创建只读与节点运维两类角色,并用kubectl auth can-i验证授权是否真的生效。
先确认集群和GPU资源能被识别
下面的操作假设你手上有一台已装好kubelet和容器运行时的AI服务器,并且能通过kubeconfig访问集群。
先确认节点状态和GPU资源是否已上报,这是后续给GPU节点单独授权的依据。
kubectl get nodes -o wide
kubectl get nodes -L nvidia.com/gpu.present
kubectl describe node | grep -A5 "Allocatable"
预期结果是节点为Ready,GPU节点的Allocatable里能看到nvidia.com/gpu。
如果看不到,说明设备插件没有正常注册,此时先不要急着配权限,否则运维人员拿到权限也调度不到GPU。
记下你的GPU节点标签,例如nvidia.com/gpu.present=true,后面配置节点运维角色时会用到这个标签做筛选思路。
用命名空间切开不同团队的边界
RBAC的授权范围依赖命名空间。
建议先为推理服务和训练任务分别建命名空间,避免所有人都在default里操作。
kubectl create namespace inference
kubectl create namespace training
命名空间建好后,权限规则才有明确的挂载点。不要把所有账号都绑定到cluster-admin,这是AI服务器集群最常见也最难回收的权限问题。
创建只读角色并绑定给普通运维
只读角色适合值班同学排查Pod状态、看日志、查事件。
下面在inference命名空间内创建Role,只允许get、list、watch:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: inference-readonly
namespace: inference
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "services", "events"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "watch"]
保存为inference-readonly.yaml后执行kubectl apply -f inference-readonly.yaml,
再用RoleBinding把角色绑到一个已存在的用户或ServiceAccount上:
kubectl create rolebinding inference-readonly-binding \
--role=inference-readonly \
--user=ops-readonly \
--namespace=inference
这里的ops-readonly需要是你集群里真实存在的认证主体,例如由外部身份系统签发的用户名。
如果账号不存在,绑定本身不会报错,但登录后仍然没有权限,验证时要注意区分。
给GPU节点运维单独授权
节点级操作(打标签、看节点状态、cordon/drain)属于集群范围资源,不能用命名空间Role覆盖,需要ClusterRole。
但也不应直接给cluster-admin,可以只放开节点相关动词:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gpu-node-operator
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["nodes/status"]
verbs: ["get", "patch", "update"]
应用后用ClusterRoleBinding绑定到节点运维账号:
kubectl apply -f gpu-node-operator.yaml
kubectl create clusterrolebinding gpu-node-operator-binding \
--clusterrole=gpu-node-operator \
--user=node-ops
注意:nodes/status的patch权限会影响节点可调度状态,只给确实需要维护GPU节点的人。
普通应用运维不需要这个角色。
用auth can-i验证授权结果
配置完不要只看YAML是否apply成功,要用kubectl auth can-i模拟判断。
以下命令分别验证只读账号和节点运维账号:
kubectl auth can-i list pods --namespace=inference --as=ops-readonly
kubectl auth can-i delete pods --namespace=inference --as=ops-readonly
kubectl auth can-i patch nodes --as=node-ops
kubectl auth can-i create deployments --namespace=training --as=ops-readonly
预期结果依次是yes、no、yes、no。
如果第一条返回no,优先检查RoleBinding的命名空间和用户名是否写错;
如果节点相关返回no,检查是否误用了Role而不是ClusterRole。
几个容易踩的坑
- 只读角色里漏了
pods/log,值班同学能看Pod列表却打不开日志,排错效率很低。 - 把RoleBinding建在错误的命名空间,现象是“明明配了权限却没有”。
- 给应用团队开放
nodes的update权限,可能误改节点标签,导致GPU调度规则失效。 - 用ServiceAccount做CI发布时,忘记同时授权
deployments和pods,滚动更新会卡在中途。
权限配置完成后,建议把YAML清单纳入版本管理,每次变更都重新跑一遍auth can-i验证。
后续再接监控或发布流水线时,这套命名空间和角色划分就是K8sOps继续扩展的基础。