K8s 运维系列 | 第 11 天:权限安全——RBAC 与 ServiceAccount

引言

在 Kubernetes 集群中,随着业务规模不断扩大,越来越多的人和程序需要访问集群资源。有人需要部署应用、有人需要查看日志、有人只需要读取监控指标,而自动化流水线(CI/CD)也需要调用 API 完成镜像发布。如果所有人都使用同一个高权限账号,一旦凭证泄露,整个集群都可能被攻破。因此,一套细粒度、可管理、可审计的权限体系是生产集群的必备能力。

Kubernetes 的权限安全体系由「认证(Authentication)」「授权(Authorization)」和「准入控制(Admission Control)」三部分组成。认证回答”你是谁”,授权回答”你能做什么”,准入控制则在你动手之前做最后一道校验。今天我们要深入讲解其中最核心的一环:基于角色的访问控制(RBAC,Role-Based Access Control)以及承载 Pod 身份的服务账号(ServiceAccount)。

K8s 运维 第11天

核心概念

1. 认证与授权的关系

Kubernetes 并不管理用户本身,普通用户(自然人)通常由外部系统(如证书、OpenID Connect、LDAP)提供身份。集群内真正原生的”身份”是 ServiceAccount,它是给 Pod 里运行的程序使用的账号。认证通过后,授权阶段由 RBAC 决定这个身份对哪些资源拥有哪些操作权限。

2. RBAC 四大对象

RBAC 通过四个 API 对象来描述权限:

  • Role:定义某个命名空间内的一组权限规则(能对哪些资源做哪些操作)。
  • ClusterRole:与 Role 类似,但作用域是整个集群,也可以授权给非命名空间级资源(如 Node、Namespace、PersistentVolume)。
  • RoleBinding:把 Role 授予某个命名空间内的主体(用户、组、ServiceAccount)。
  • ClusterRoleBinding:把 ClusterRole 授予集群范围内的主体。

3. ServiceAccount

每个命名空间默认会有一个名为 default 的 ServiceAccount。Pod 若未显式指定,就使用 default。ServiceAccount 关联一个 Token(令牌),程序挂载该 Token 即可调用 Kubernetes API。从 1.24 起,默认不再自动挂载长期 Token,推荐使用绑定的临时 Token。

实战步骤

步骤 1:创建命名空间与 ServiceAccount

先创建一个专用命名空间,并为部署团队创建专属服务账号。

kubectl create namespace dev
kubectl create serviceaccount deploy-sa -n dev

查看刚创建的 ServiceAccount:

kubectl get serviceaccount deploy-sa -n dev

步骤 2:编写 Role 定义权限

下面这个 Role 允许在 dev 命名空间内对 Deployment、Service、Pod 进行增删改查,但禁止访问 Secret 和 ConfigMap。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: deploy-role
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
  resources: ["pods", "services"]
  verbs: ["get", "list", "watch", "create", "update", "delete"]

步骤 3:使用 RoleBinding 绑定账号

通过 RoleBinding 把 deploy-role 授予 deploy-sa

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: dev
  name: deploy-binding
subjects:
- kind: ServiceAccount
  name: deploy-sa
  namespace: dev
roleRef:
  kind: Role
  name: deploy-role
  apiGroup: rbac.authorization.k8s.io

应用并验证:

kubectl apply -f role.yaml
kubectl apply -f rolebinding.yaml
kubectl auth can-i create deployments -n dev --as=system:serviceaccount:dev:deploy-sa

步骤 4:验证越权操作被拒绝

用该账号尝试访问 Secret,应当被拒绝:

kubectl auth can-i get secrets -n dev --as=system:serviceaccount:dev:deploy-sa
# 输出 no

步骤 5:让 Pod 使用 ServiceAccount

在 Deployment 的 Pod 模板中指定 serviceAccountName,并显式声明不自动挂载默认 Token:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: dev
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      serviceAccountName: deploy-sa
      automountServiceAccountToken: false
      containers:
      - name: app
        image: nginx:1.25
        ports:
        - containerPort: 80

常见问题

问题 1:明明绑定了 Role,Pod 却报 forbidden。

先确认 ServiceAccount 名称与命名空间是否完全一致,再检查 Role 的 apiGroups 是否写对。核心资源组(Pod、Service)的 apiGroups 是空字符串 "",而 Deployment 属于 apps 组,写错会导致授权不生效。

问题 2:想给用户只读权限,如何快速实现?

集群内置了若干聚合 ClusterRole,例如 vieweditadmin。只读用户直接绑定 view 即可,无需手写 Role。

kubectl create rolebinding viewer --clusterrole=view --user=alice -n dev

问题 3:ServiceAccount 的 Token 泄露了怎么办?

立即删除并重建该 ServiceAccount,Token 会随之失效。生产环境建议缩短 Token 有效期、使用准入控制限制 Secret 访问,并定期轮换凭证。

问题 4:权限改动后为何有时要等几秒才生效?

RBAC 授权结果会被缓存,默认最多延迟约 10 秒。若验证时未立即生效,稍等片刻再试即可。

总结

RBAC 是 Kubernetes 权限管理的基石,它用「角色 + 绑定」的解耦方式,把”能做什么”与”谁来做”分开管理,配合 ServiceAccount 为 Pod 内的程序提供受控身份。掌握 Role/ClusterRole 与 RoleBinding/ClusterRoleBinding 的区别,理解最小权限原则,是构建安全集群的第一步。建议在生产中坚持”按需授权、定期审计、凭证轮换”三原则,避免宽泛的 cluster-admin 权限被滥用。

下期预告

下一期《第 12 天:证书与多集群——kubeconfig 与集群切换》,我们将讲解如何通过 kubeconfig 管理多个集群的访问凭证,实现本地与多套集群之间的无缝切换,敬请期待。

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容