K8s学习笔记(二十一) RBAC

1 RBAC 是什么?为什么需要它?

在 K8s 中,所有操作(比如kubectl get poddelete deployment)最终都会通过API Server 执行。RBAC 是 K8s 默认的授权模式,作用是:

  • 控制 "谁"(用户 / 服务账户)能访问 API Server;
  • 限制 "能做什么"(比如只读、修改、删除);
  • 限定 "作用范围"(比如某个命名空间、整个集群)。

核心原则:最小权限原则(只给完成任务必需的权限,避免过度授权)。

2 RBAC 的 4 个核心组件(必背)

RBAC 通过 4 个 K8s API 资源实现权限控制,分为 "角色(定义权限)" 和 "绑定(分配权限)" 两类:

组件类型 资源名称 作用域 核心作用
角色(权限定义) Role 单个命名空间 定义 "在某个命名空间内,能对哪些资源执行哪些操作"
角色(权限定义) ClusterRole 整个集群(无命名空间) 定义 "集群级资源(如节点、命名空间)" 或 "跨所有命名空间资源" 的操作权限
绑定(权限分配) RoleBinding 单个命名空间 将 Role 的权限分配给 "主体"(用户 / 服务账户 / 用户组)
绑定(权限分配) ClusterRoleBinding 整个集群 将 ClusterRole 的权限分配给 "主体",作用于整个集群或所有命名空间

2.1 先理解 "权限三要素"

无论 Role 还是 ClusterRole,定义权限时都围绕 3 个要素:

  • 资源(Resources) :K8s 中的对象,如podsdeploymentsservicesnamespaces(集群级)、nodes(集群级)等;
  • 操作(Verbs) :对资源的动作,如getlistcreateupdatedeletewatch(实时监听)等;
  • 资源名称(ResourceNames,可选) :限定权限只作用于 "特定名称的资源"(比如只允许修改名为my-pod的 Pod)。

2.2 逐个拆解核心组件

(1)Role:命名空间内的权限

特点:仅作用于它所在的命名空间,无法访问集群级资源(如节点)。

示例 YAML :创建一个名为pod-reader的 Role,允许在default命名空间 "读取 Pod"(get/list/watch):

yaml 复制代码
# role-pod-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1  # RBAC的固定API版本
kind: Role
metadata:
  name: pod-reader          # Role名称
  namespace: default        # 作用的命名空间(必须指定)
rules:                      # 权限规则(可多个)
- apiGroups: [""]           # API组:""表示核心API组(如pods、services)
  resources: ["pods"]       # 允许操作的资源:Pod
  verbs: ["get", "list", "watch"]  # 允许的操作

创建命令:kubectl apply -f role-pod-reader.yaml

(2)ClusterRole:集群级 / 跨命名空间权限

特点

  • 作用于整个集群,无需指定命名空间;
  • 可管理集群级资源 (如nodesnamespaces);
  • 可管理 "跨所有命名空间的资源"(如 "查看所有命名空间的 Pod");
  • 可被 RoleBinding 引用(实现 "在单个命名空间使用集群级权限")。

示例 YAML :创建一个名为cluster-pod-reader的 ClusterRole,允许 "读取所有命名空间的 Pod" 和 "查看节点信息":

yaml 复制代码
# clusterrole-pod-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-pod-reader  # ClusterRole名称(无命名空间)
rules:
# 规则1:读取所有命名空间的Pod
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
# 规则2:查看节点(集群级资源)
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list"]

创建命令:kubectl apply -f clusterrole-pod-reader.yaml

(3)RoleBinding:将 Role/ClusterRole 绑定到主体(命名空间内)

作用:把 "Role 的权限" 或 "ClusterRole 的权限(限定在单个命名空间)" 分配给 "主体"。

主体(Subject):权限的接收者,分 3 类:

  • User:外部用户(如运维人员,由 K8s 外的认证系统管理,如 CA 证书、LDAP);
  • Group:用户组(如 "dev-team" 组,包含多个 User);
  • ServiceAccount:K8s 内部的 "服务账户"(给 Pod 内的应用使用,如 Pod 访问 API Server 时用的账户)。

示例 1:绑定 Role 到 ServiceAccount

创建一个 RoleBinding,将前面的pod-reader Role 绑定到default命名空间的my-sa ServiceAccount:

yaml 复制代码
# rolebinding-pod-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: default  # 必须和Role的命名空间一致
subjects:  # 主体列表
- kind: ServiceAccount
  name: my-sa         # ServiceAccount名称
  namespace: default  # ServiceAccount所在命名空间
roleRef:  # 引用的角色(固定格式)
  apiGroup: rbac.authorization.k8s.io
  kind: Role          # 引用的是Role(也可改为ClusterRole)
  name: pod-reader    # 引用的Role名称

示例 2:绑定 ClusterRole 到 User(限定在单个命名空间)

如果想让用户dev-user仅在dev命名空间拥有cluster-pod-reader的权限(虽然 ClusterRole 是集群级,但 RoleBinding 限定了命名空间):

yaml 复制代码
# rolebinding-cluster-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-user-pod-reader
  namespace: dev  # 限定在dev命名空间
subjects:
- kind: User
  name: dev-user  # 外部用户名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole  # 引用ClusterRole
  name: cluster-pod-reader
(4)ClusterRoleBinding:将 ClusterRole 绑定到主体(集群级)

作用 :把 ClusterRole 的权限分配给主体,作用于整个集群(所有命名空间 + 集群资源)。

示例 :让用户组admin-team拥有 "集群管理员" 权限(K8s 默认有cluster-admin ClusterRole,拥有所有权限):

yaml 复制代码
# clusterrolebinding-admin.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-team-binding
subjects:
- kind: Group
  name: admin-team  # 用户组名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin  # K8s默认ClusterRole(所有权限,谨慎使用)

3 关键实操:如何验证权限?

创建 Role/Binding 后,需要验证权限是否生效,核心命令是 kubectl auth can-i(检查 "某个主体能否执行某个操作")。

语法

bash 复制代码
# 1. 检查当前用户的权限(默认是kubectl配置的用户)
kubectl auth can-i <操作> <资源> -n <命名空间>

# 2. 检查指定ServiceAccount的权限
kubectl auth can-i <操作> <资源> -n <命名空间> --as=system:serviceaccount:<命名空间>:<ServiceAccount名称>

# 3. 检查跨命名空间/集群资源的权限
kubectl auth can-i <操作> <资源> --all-namespaces  # 所有命名空间
kubectl auth can-i <操作> nodes  # 集群资源(无需-n)

示例

  1. 检查default命名空间的my-sa能否读取 Pod:

    bash 复制代码
    kubectl auth can-i get pods -n default --as=system:serviceaccount:default:my-sa
    # 输出:yes(表示有权限)/ no(无权限)
  2. 检查dev-user能否在dev命名空间删除 Pod:

    bash 复制代码
    kubectl auth can-i delete pods -n dev --as=dev-user
  3. 检查admin-team能否查看节点:

    bash 复制代码
    kubectl auth can-i list nodes --as=system:serviceaccount:kube-system:default --as-group=admin-team

4 常见场景:实战案例

场景 1:给 Pod 内应用授权(最常用)

Pod 内的应用(如 Java 程序)要调用 K8s API(比如获取 Pod 列表),需通过ServiceAccount授权:

  1. 创建自定义 ServiceAccount:kubectl create sa my-app-sa -n dev

  2. 创建 Role(允许在dev命名空间读取 Pod):参考前面的pod-reader

  3. 创建 RoleBinding(将 Role 绑定到my-app-sa):参考前面的rolebinding-pod-reader

  4. 部署 Pod 时指定 ServiceAccount:

    yaml 复制代码
    # pod-with-sa.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-app-pod
      namespace: dev
    spec:
      serviceAccountName: my-app-sa  # 指定ServiceAccount
      containers:
      - name: my-app
        image: nginx

场景 2:给开发人员 "命名空间只读权限"

dev-user只能在dev命名空间查看 Pod/Deployment,不能修改:

  1. 创建 ClusterRole(通用只读权限,可复用):

    yaml 复制代码
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: ns-reader
    rules:
    - apiGroups: ["", "apps"]  # ""=核心组(pods),apps=部署组(deployments)
      resources: ["pods", "deployments", "services"]
      verbs: ["get", "list", "watch"]
  2. 创建 RoleBinding(将 ClusterRole 绑定到dev-user,限定在dev命名空间):

    yaml 复制代码
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: dev-user-reader
      namespace: dev
    subjects:
    - kind: User
      name: dev-user
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: ns-reader

5 避坑指南

  1. 命名空间一致性 :Role 和引用它的 RoleBinding 必须在同一个命名空间,ClusterRole 无命名空间限制。

  2. API 组正确:不同资源属于不同 API 组,比如:

    • 核心资源(pods、services):apiGroups: [""]

    • 部署资源(deployments、statefulsets):apiGroups: ["apps"]

    • 网络资源(ingresses):

      复制代码
      apiGroups: ["networking.k8s.io"]

      (不确定时用kubectl api-resources | grep <资源名>查看 API 组)。

  3. 避免过度授权 :除非必要,不要使用cluster-admin(所有权限),也不要给delete/update等高危操作。

  4. 权限不生效?检查三点:

    • Role/Binding 是否创建成功:kubectl get role -n <ns>kubectl get rolebinding -n <ns>
    • 主体(Subject)的名称 / 命名空间是否正确;
    • 规则(rules)的apiGroups/resources/verbs是否正确。

6 总结

RBAC 的核心逻辑是 "先定义权限(Role/ClusterRole),再分配权限(RoleBinding/ClusterRoleBinding) ",记住:

  • 命名空间内的权限:Role + RoleBinding;
  • 集群级 / 跨命名空间权限:ClusterRole + ClusterRoleBinding;
  • 验证权限用kubectl auth can-i,实战优先掌握 "ServiceAccount 给 Pod 授权" 的场景。
相关推荐
递归不收敛11 小时前
大语言模型(LLM)入门笔记:嵌入向量与位置信息
人工智能·笔记·语言模型
冷雨夜中漫步11 小时前
高级系统架构师笔记——数据库设计基础知识(5)Armstrong公理系统、无损连接和有损连接
笔记·系统架构
deng-c-f11 小时前
Linux C/C++ 学习日记(28):KCP协议(四):如何实现更复杂的业务:将连接状态的管理进行封装,用户只需实现发送、接收、断开的处理逻辑。
学习·网络编程·kcp
im_AMBER12 小时前
算法笔记 05
笔记·算法·哈希算法
東雪蓮☆13 小时前
K8s 平滑升级
linux·运维·云原生·kubernetes
Element_南笙13 小时前
吴恩达新课程:Agentic AI(笔记2)
数据库·人工智能·笔记·python·深度学习·ui·自然语言处理
koo36414 小时前
李宏毅机器学习笔记21-26周汇总
人工智能·笔记·机器学习
.小小陈.14 小时前
数据结构2:单链表
c语言·开发语言·数据结构·笔记·学习方法
立志成为大牛的小牛14 小时前
数据结构——二十三、并查集的终极优化(王道408)
开发语言·数据结构·笔记·学习·程序人生·考研
全栈游侠15 小时前
04-优先级与延时链表
笔记