Kubernetes授权机制之RBAC


在 Kubernetes 中,所有资源对象都是通过 API 进行操作,他们保存在 etcd 里。而对 etcd 的操作我们需要通过访问 kube-apiserver 来实现,上面的 Service Account 其实就是 APIServer 的认证过程,而授权的机制是通过 RBAC:基于角色的访问控制实现。

在Kubernetes(K8s)集群中,API Server就像“中央大门”,所有操作(比如查看Pod、部署应用、删除资源)都必须经过它。而RBAC(基于角色的访问控制)就是这扇大门的“智能门卫”——它不仅能识别“来访者”身份,还能精准管控“能进哪个区域”“能做什么事”,核心原则是“最小权限”:只给完成工作必需的权限,多余权限一概不给,从根源上降低集群安全风险。

对于新手来说,RBAC看似复杂,但只要抓住“定义权限→分配权限”的核心逻辑,再结合实际场景实操,就能快速掌握。本文将从基础概念、核心组件、实操技巧、高级用法到问题排查,全方位拆解RBAC,让你看完就能用。

一、先搞懂3个基础问题:为什么需要RBAC?

在没有RBAC的情况下,K8s集群可能面临“谁都能操作资源”的混乱局面——开发人员误删生产环境Pod、第三方应用非法访问集群资源等问题时有发生。RBAC的出现就是为了解决这些问题,它的核心价值体现在3点:

  • 身份与权限分离:先定义“能做什么”(角色),再分配“谁能做”(绑定),逻辑清晰,便于管理;
  • 细粒度控制:可按“命名空间+资源类型+操作动作”精准授权,比如“只允许开发人员在dev命名空间查看Pod,不能删除”;
  • 可复用与可扩展:定义好的角色(尤其是ClusterRole)可多次绑定给不同对象,后续修改权限只需调整角色,无需逐个修改分配关系。

简单说,RBAC让K8s集群的权限管理从“粗放式”变成“精细化”,是保障集群安全的核心机制。

二、RBAC四大核心组件:通俗解释+实操示例

RBAC的权限控制靠4个核心API资源实现,分为“定义权限”和“分配权限”两大类。用生活化的比喻理解:Role/ClusterRole是“权限说明书”,明确能做什么;RoleBinding/ClusterRoleBinding是“权限分配单”,明确把说明书发给谁。

(一)核心组件速览表

组件类型 资源名称 作用范围 通俗作用 适用场景
定义权限 Role 单个命名空间 制定“局部权限说明书”:仅在当前命名空间生效 给特定命名空间内的资源授权(如dev命名空间的Pod查看权限)
定义权限 ClusterRole 整个集群 制定“全局权限说明书”:可作用于所有命名空间或集群级资源 1. 管理集群级资源(如节点、命名空间);2. 跨命名空间授权(如查看所有命名空间的Pod);3. 复用权限(多个命名空间共用同一套权限规则)
分配权限 RoleBinding 单个命名空间 发放“局部权限分配单”:把Role或ClusterRole的权限,限定在当前命名空间分配给对象 1. 给命名空间内的用户/服务账户分配Role权限;2. 让ClusterRole的权限仅在单个命名空间生效(如让用户仅在test命名空间使用全局只读权限)
分配权限 ClusterRoleBinding 整个集群 发放“全局权限分配单”:把ClusterRole的权限分配给对象,全集群生效 给用户/用户组分配集群级权限(如运维人员的集群管理权限)

(二)权限三要素:定义权限的“必填项”

不管是Role还是ClusterRole,制定“权限说明书”时必须明确3个要素,少一个都无法生效,就像写说明书要明确“操作对象+操作动作+限定条件”:

  • 资源(Resources):要操作的K8s对象,比如Pod、Deployment、Service、Node(节点)、Namespace(命名空间)等;
  • 操作(Verbs):对资源的具体动作,常用动作包括:
  • 只读类:get(查询单个资源)、list(列出资源清单)、watch(实时监听资源变化);
  • 写操作类:create(创建)、update(更新)、patch(部分更新);
  • 删除类:delete(删除单个资源)、deletecollection(删除资源集合,如所有Pod);

  • 资源名称(ResourceNames,可选):限定权限仅作用于“特定名称的资源”,比如只允许修改名为“prod-app”的Deployment,相当于“说明书的附加条件”。

(三)逐个拆解组件:附完整实操示例(可直接复制)

1. Role:命名空间内的“局部权限说明书”

特点:仅作用于所在的命名空间,无法操作Node等集群级资源,适合“局部资源管控”。

实操示例:在default命名空间创建一个名为pod-ops的Role,允许“查看、创建、更新Pod”,但仅允许删除名为test-pod的Pod(通过ResourceNames限定)。

# 保存为 role-pod-ops.yaml
apiVersion: rbac.authorization.k8s.io/v1  # RBAC固定API版本,直接照抄
kind: Role  # 资源类型为Role
metadata:
  name: pod-ops  # Role名称,自定义
  namespace: default  # 必须指定命名空间(作用范围)
rules:  # 权限规则(可配置多个规则)
- apiGroups: [""]  # 核心资源(Pod、Service等)的API组,固定填""
  resources: ["pods"]  # 操作的资源:Pod
  verbs: ["get", "list", "watch", "create", "update", "delete"]  # 允许的操作
  resourceNames: ["test-pod"]  # 仅允许操作名为test-pod的Pod(可选配置)
- apiGroups: [""]  # 第二个规则:允许查看所有Pod的日志(不受资源名称限制)
  resources: ["pods/log"]  # 操作的子资源:Pod日志
  verbs: ["get", "list"]

创建命令:执行后Role立即生效

kubectl apply -f role-pod-ops.yaml

验证创建结果:查看default命名空间的Role

kubectl get role -n default
# 输出结果中会显示pod-ops,说明创建成功

2. ClusterRole:集群级的“全局权限说明书”

特点:无命名空间限制,可操作集群级资源(如Node),也可作用于所有命名空间的资源,适合“全局权限复用”。

实操示例:创建一个名为cluster-resource-ops的ClusterRole,允许:1. 查看所有命名空间的Pod、Deployment;2. 查看和创建命名空间;3. 查看节点信息。

# 保存为 clusterrole-resource-ops.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole  # 资源类型为ClusterRole
metadata:
  name: cluster-resource-ops  # 自定义名称,无需指定命名空间
rules:
# 规则1:查看所有命名空间的Pod和Deployment
- apiGroups: ["", "apps"]  # ""=核心组(Pod),apps=Deployment所属组
  resources: ["pods", "deployments"]
  verbs: ["get", "list", "watch"]
# 规则2:查看和创建命名空间(集群级资源)
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "list", "create"]
# 规则3:查看节点信息(集群级资源)
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list"]

创建命令

kubectl apply -f clusterrole-resource-ops.yaml

验证创建结果:查看集群内所有ClusterRole

kubectl get clusterrole
# 输出结果中会显示cluster-resource-ops

3. RoleBinding:给“局部对象”分配权限

核心作用:把Role或ClusterRole的权限,分给“主体”(权限接收者),且仅在当前命名空间生效。

主体(Subject)类型:权限的接收者有3种,覆盖“外部用户”“内部服务”“用户组”所有场景:

  • User:外部用户(如运维人员、开发人员),由K8s外的认证系统管理(如CA证书、LDAP);
  • Group:用户组(如“dev-team”组,包含所有开发人员),方便批量授权;
  • ServiceAccount:K8s内部的“服务账户”,专门给Pod内的应用使用(比如Pod里的Java程序要调用K8s API,就用这个账户授权)。

实操示例1:绑定Role到ServiceAccount(最常用场景) 把前面创建的pod-ops Role(default命名空间),绑定到default命名空间的my-app-sa服务账户,让Pod内应用拥有对应的Pod操作权限。

# 保存为 rolebinding-pod-ops.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-ops-binding  # 自定义名称
  namespace: default  # 必须和Role在同一个命名空间
subjects:  # 权限接收者(主体)
- kind: ServiceAccount  # 主体类型:服务账户
  name: my-app-sa  # 服务账户名称(需提前创建:kubectl create sa my-app-sa -n default)
  namespace: default  # 服务账户所在命名空间
roleRef:  # 引用要分配的Role(固定格式,不能改)
  apiGroup: rbac.authorization.k8s.io
  kind: Role  # 引用的是Role类型
  name: pod-ops  # 引用的Role名称

创建命令

kubectl apply -f rolebinding-pod-ops.yaml

实操示例2:绑定ClusterRole到User(限定命名空间) 让外部用户dev-user仅在dev命名空间,拥有cluster-resource-ops ClusterRole的权限(相当于“全局权限局部使用”)。

# 保存为 rolebinding-cluster-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-user-resource-ops
  namespace: dev  # 限定在dev命名空间生效(需提前创建dev命名空间:kubectl create ns dev)
subjects:
- kind: User  # 主体类型:外部用户
  name: dev-user  # 用户名(需提前通过认证系统创建)
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole  # 引用ClusterRole
  name: cluster-resource-ops  # 引用的ClusterRole名称

创建命令

kubectl apply -f rolebinding-cluster-role.yaml

4. ClusterRoleBinding:给“全局对象”分配权限

核心作用:把ClusterRole的权限分给主体,作用于整个集群(所有命名空间+集群级资源),适合“批量授权全局权限”。

实操示例:给用户组ops-team(运维团队)分配K8s默认的cluster-admin权限(拥有集群内所有操作权限,谨慎使用!),让运维人员能管理整个集群。

# 保存为 clusterrolebinding-ops-admin.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ops-team-admin-binding  # 自定义名称
subjects:
- kind: Group  # 主体类型:用户组
  name: ops-team  # 用户组名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin  # K8s默认ClusterRole,拥有所有权限

创建命令

kubectl apply -f clusterrolebinding-ops-admin-binding.yaml

三、关键实操:如何验证权限是否生效?(必学)

创建完Role和Binding后,不能凭感觉判断权限是否生效,用kubectl auth can-i命令就能“一键核查”,简单又精准,新手必须掌握!

(一)常用命令格式(直接套用)

核查场景 命令格式 示例
核查当前用户的权限 kubectl auth can-i <操作> <资源> -n <命名空间> 核查自己能否在default命名空间创建Pod:kubectl auth can-i create pods -n default
核查指定ServiceAccount的权限 kubectl auth can-i <操作> <资源> -n <命名空间> --as=system:serviceaccount:<命名空间>:<服务账户名> 核查default命名空间的my-app-sa能否删除test-pod:kubectl auth can-i delete pods -n default --as=system:serviceaccount:default:my-app-sa
核查跨命名空间权限 kubectl auth can-i <操作> <资源> --all-namespaces 核查能否查看所有命名空间的Deployment:kubectl auth can-i list deployments --all-namespaces
核查集群级资源权限 kubectl auth can-i <操作> <集群资源> 核查能否查看节点信息:kubectl auth can-i list nodes

(二)结果说明

  • 输出yes:权限生效,允许执行该操作;
  • 输出no:权限未生效,不允许执行;
  • 输出unknown:权限配置有误(如主体不存在、API组填错),需排查配置。

(三)进阶核查:查看权限来源

如果想知道“某个权限来自哪个Role/Binding”,可以在命令后加--verbose参数,示例:

kubectl auth can-i get pods -n default --as=system:serviceaccount:default:my-app-sa --verbose

输出结果中会显示权限对应的Role和RoleBinding名称,方便排查权限来源。

四、5个高频实战场景:直接套用,覆盖80%需求

RBAC的核心价值在于“落地到实际场景”,以下5个场景是工作中最常用的,新手可以直接复制配置文件,修改参数即可使用。

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

Pod内的应用(如Java、Python程序)要调用K8s API(比如获取Pod列表、查看命名空间),必须通过ServiceAccount授权,步骤如下:

1.创建ServiceAccount(在prod命名空间):

kubectl create sa app-api-sa -n prod

2.创建Role(允许在prod命名空间查看Pod和Deployment):

# 保存为 role-app-api.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-api-role
  namespace: prod
rules:
- apiGroups: ["", "apps"]
  resources: ["pods", "deployments"]
  verbs: ["get", "list", "watch"]

创建命令:kubectl apply -f role-app-api.yaml

3.创建RoleBinding(绑定Role到ServiceAccount):

# 保存为 rolebinding-app-api.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-api-binding
  namespace: prod
subjects:
- kind: ServiceAccount
  name: app-api-sa
  namespace: prod
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: app-api-role

创建命令:kubectl apply -f rolebinding-app-api.yaml

4.部署Pod时指定ServiceAccount:

# 保存为 pod-app-api.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app-api-pod
  namespace: prod
spec:
  serviceAccountName: app-api-sa  # 关联前面创建的服务账户
  containers:
  - name: app-api
    image: your-app-image:latest  # 替换为你的应用镜像

创建命令:kubectl apply -f pod-app-api.yaml

场景2:给开发人员分配“命名空间只读权限”

需求:让开发人员dev-user仅能在dev命名空间查看Pod、Deployment、Service,不能创建/删除资源,步骤如下:

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

# 保存为 clusterrole-ns-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: ns-reader
rules:
- apiGroups: ["", "apps", "networking.k8s.io"]  # 包含核心资源、部署资源、网络资源
  resources: ["pods", "deployments", "services", "ingresses"]
  verbs: ["get", "list", "watch"]

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

2.创建RoleBinding(绑定到dev-user,限定dev命名空间):

# 保存为 rolebinding-dev-reader.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

创建命令:kubectl apply -f rolebinding-dev-reader.yaml

场景3:给运维人员分配“集群级管理权限”

需求:让运维组ops-team能管理整个集群的资源(包括创建命名空间、管理节点、操作所有命名空间的资源):

直接使用K8s默认的cluster-admin ClusterRole,创建ClusterRoleBinding:

# 保存为 clusterrolebinding-ops-team.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ops-team-admin
subjects:
- kind: Group
  name: ops-team
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin

创建命令:kubectl apply -f clusterrolebinding-ops-team.yaml

场景4:限制用户仅能操作特定资源(资源名称限定)

需求:让用户test-user仅能修改test命名空间中名为test-app的Deployment,不能操作其他资源:

1.创建Role(限定资源名称):

# 保存为 role-specific-deploy.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: specific-deploy-ops
  namespace: test
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "update", "patch"]
  resourceNames: ["test-app"]  # 仅允许操作名为test-app的Deployment

创建命令:kubectl apply -f role-specific-deploy.yaml

2.创建RoleBinding(绑定到test-user):

# 保存为 rolebinding-test-user.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-user-deploy-ops
  namespace: test
subjects:
- kind: User
  name: test-user
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: specific-deploy-ops

创建命令:kubectl apply -f rolebinding-test-user.yaml

场景5:跨命名空间授权(查看所有命名空间的Pod)

需求:让用户audit-user能查看所有命名空间的Pod(跨命名空间权限):

1.创建ClusterRole(允许查看所有Pod):

# 保存为 clusterrole-all-pod-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: all-pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

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

2.创建ClusterRoleBinding(绑定到audit-user):

# 保存为 clusterrolebinding-audit-user.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: audit-user-pod-reader
subjects:
- kind: User
  name: audit-user
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: all-pod-reader

创建命令:kubectl apply -f clusterrolebinding-audit-user.yaml

五、RBAC高级用法:让权限管理更高效

(一)聚合ClusterRole:批量管理相似权限

如果有多个ClusterRole需要统一授权(比如“日志查看”“监控数据读取”等权限),可以用“聚合ClusterRole”把它们整合起来,后续授权只需绑定聚合角色,无需逐个绑定。

示例:创建聚合角色aggregated-monitor,包含log-readermetrics-reader两个ClusterRole的权限:

# 保存为 clusterrole-aggregated-monitor.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: aggregated-monitor
  labels:
    rbac.authorization.k8s.io/aggregate-to-monitor: "true"  # 聚合标签,用于匹配子角色
rules: []  # 无需配置规则,自动继承匹配标签的ClusterRole权限

创建子角色(需包含相同的聚合标签):

# 日志查看角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: log-reader
  labels:
    rbac.authorization.k8s.io/aggregate-to-monitor: "true"  # 匹配聚合标签
rules:
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get", "list"]
# 监控数据读取角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: metrics-reader
  labels:
    rbac.authorization.k8s.io/aggregate-to-monitor: "true"  # 匹配聚合标签
rules:
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list"]

后续授权时,只需绑定aggregated-monitor,就能获得两个子角色的所有权限,管理更高效。

(二)ServiceAccount自动挂载令牌

K8s 1.24+版本中,ServiceAccount的令牌不再自动挂载到Pod,需要手动开启“自动挂载”或创建Secret挂载。

方法1:创建ServiceAccount时开启自动挂载

kubectl create sa my-sa -n dev --automount-token=true

方法2:在Pod YAML中指定自动挂载

spec:
  serviceAccountName: my-sa
  automountServiceAccountToken: true  # 开启自动挂载

六、避坑指南:新手常犯的6个错误及解决方案

1. 命名空间不一致(最常见错误)

  • 错误表现:Role和RoleBinding不在同一个命名空间,导致权限绑定失效;
  • 解决方案:确保Role的metadata.namespace与RoleBinding的metadata.namespace完全一致,ClusterRole无需指定命名空间。

2. API组填写错误

  • 错误表现:权限规则不生效,kubectl auth can-i返回no
  • 原因:不同资源属于不同API组,比如Deployment在apps组,Ingress在networking.k8s.io组,填错API组会导致规则无效;
  • 解决方案:不确定资源所属API组时,用以下命令查询:
kubectl api-resources | grep <资源名称>
# 示例:查询Deployment的API组
kubectl api-resources | grep deployments
# 输出结果中“APIGROUP”列即为所属API组(如apps)

3. 过度授权(安全风险)

  • 错误表现:给普通用户分配cluster-admin权限,或给应用分配delete等高危操作权限;
  • 解决方案:遵循“最小权限原则”,仅分配必需的权限,比如:
  • 开发人员:仅给命名空间只读权限;
  • 应用程序:仅给需要的资源操作权限(如仅查看Pod,不分配删除权限)。

4. 主体(Subject)信息错误

  • 错误表现:权限绑定后,主体无法使用权限;
  • 常见错误:
  • ServiceAccount的命名空间填错;
  • User/Group名称与认证系统中的名称不一致(如LDAP中的用户名拼写错误);
  • 解决方案:
  • 检查ServiceAccount是否存在:kubectl get sa -n <命名空间>
  • 确认User/Group名称与认证系统(如CA证书、LDAP)中的配置一致。

5. 资源名称(ResourceNames)使用不当

  • 错误表现:配置了resourceNames后,无法操作目标资源;
  • 常见错误:资源名称拼写错误,或给list(列清单)操作配置resourceNameslist操作针对资源集合,不能限定单个资源名称);
  • 解决方案:
  • 确认资源名称正确:kubectl get <资源类型> -n <命名空间>
  • resourceNames仅适用于单个资源操作(如getupdatedelete),不适用于listwatch等集合操作。

6. 权限不生效的排查流程(通用步骤)

如果权限绑定后不生效,按以下步骤排查:

1.检查Role/ClusterRole是否创建成功:kubectl get role -n <命名空间>kubectl get clusterrole

2.检查RoleBinding/ClusterRoleBinding是否创建成功:kubectl get rolebinding -n <命名空间>kubectl get clusterrolebinding

3.检查权限规则是否正确:用kubectl describe role <角色名称> -n <命名空间>查看规则(API组、资源、 verbs是否正确);

4.用kubectl auth can-i --verbose命令查看权限来源,确认是否绑定到目标主体;

5.检查是否有其他RBAC规则冲突(如存在更严格的RoleBinding限制了权限)。

七、总结

RBAC的核心逻辑其实很简单:先定义权限(Role/ClusterRole),再分配权限(RoleBinding/ClusterRoleBinding),记住两个核心组合就能应对大部分场景:

  • 命名空间内权限:Role + RoleBinding;
  • 集群级/跨命名空间权限:ClusterRole + ClusterRoleBinding。

对于新手来说,建议先从“给Pod授权”和“只读权限配置”这两个场景入手,熟悉后再尝试高级用法。实操时多使用kubectl auth can-i命令验证权限,遇到问题按“避坑指南”排查,就能快速掌握RBAC的使用。

RBAC是K8s安全的基础,合理配置RBAC能有效防范非法访问和误操作,保护集群资源安全。随着集群规模扩大,还可以结合K8s的认证系统(如OIDC、LDAP)和网络策略,构建更完善的集群安全体系。

# kubeadm部署的k8s可以在/etc/kubernetes/manifests下查看到静态pod的yaml文件
root@k8s-master01:/etc/kubernetes/manifests# grep authorization kube-apiserver.yaml
    - --authorization-mode=Node,RBAC

# Node是专用于向kubelet授权使用。
# RBAC是基于角色的范文控制

常用授权逻辑

  • DAC(自主访问控制)
  • MAC(强制访问控制)
  • RBAC(基于角色的访问控制)
  • ABAC(基于属性的访问控制)

RBAC

RBAC:Role-Based Access Control

RBAC

简单来说,就是通过将权限分配给➡角色,再将角色分配给➡用户,来实现对系统资源的访问控制。

在一个组织内把一个组织内应该具有的权限的集合定义成多个角色,然后设定某个用户可以扮演其中1到多个角色。从而让某个用户拥有在组织内的某个授权。

k8s的RBAC是一种许可授权,只允许用户做什么事情,默认拒绝所有。未显示指定授予的权限,默认都会被拒绝。

  Role --> Verbs  --> Objects
  ClusterRole --> Verbs  --> Objects
  Subject --> RoleBinding --> Roles
  Subject --> ClusterRoleBinding --> ClusterRoles
  Subject --> RoleBinding --> ClusterRoles

k8s 的 API-Server 是 RESTful 风格的 http/https 服务,其权限无非就是基于http协议所能支持的 GET, POST, PUT, DELETE, PATCH, ...等操作,在 API-Server 上 Object 指的是资源对象。

所谓的权限也就是,Action 能施加到哪些对象上;

RBAC四个资源类型

  • Role: 角色,名称空间级别;
  • ClusterRole:集群角色,全局级别;
  • RoleBinding:"角色绑定",指是将用户与角色关联起来,意味着,用户仅得到了特定名称空间下的Role的权限,作用范围也限于该名称空间;
  • ClusterRoleBinding:集群角色绑定,让用户扮演指定的集群角色;意味着,用户得到了是集群级别的权限,作用范围也是集群级别;

User --> Rolebindig --> ClusterRole:权限降级,ClusterRole,用户得到的权限仅是 ClusterRole 的权限在 Rolebinding 所属的名称空间上的一个子集;

系统上默认的ROLE

1.查看系统上默认的role

extension-apiserver-authentication-reader        2024-04-15T06:14:01Z
kube-proxy                                       2024-04-15T06:14:03Z
kubeadm:kubelet-config-1.21                      2024-04-15T06:14:01Z
kubeadm:nodes-kubeadm-config                     2024-04-15T06:14:01Z
system::leader-locking-kube-controller-manager   2024-04-15T06:14:01Z
system::leader-locking-kube-scheduler            2024-04-15T06:14:01Z
system:controller:bootstrap-signer               2024-04-15T06:14:01Z
system:controller:cloud-provider                 2024-04-15T06:14:01Z
system:controller:token-cleaner                  2024-04-15T06:14:01Z

2.查看kube-proxy的role中的内容

root@k8s-master01:~# kubectl get role kube-proxy -n kube-system -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: "2024-04-15T06:14:03Z"
  name: kube-proxy
  namespace: kube-system
  resourceVersion: "299"
  uid: b92871dd-4224-4f31-8fe2-0c4b89ca40ff
rules:
- apiGroups:
  - ""
  resourceNames:
  - kube-proxy
  resources:
  - configmaps
  verbs:
  - get

能接受施加Verb的目标有三类:

  • resources:资源类型,该类型下的所有对象都是目标, pods;
  • resourceNames:特定的对象个体,pods/mypod;
  • nonResourceURLs:非资源型的URL,/status.

能施加的Verb有以下:

  • create、get、list、delete、patch、update

RBAC示例

rbac资源清单创建示例

1.使用资源清单来创建role

root@k8s-master01:~/yaml/chapter09# vim pods-reader-rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pods-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods","services","pods/log"]
  verbs: ["get","list","watch"]

2.将其应用到集群上

root@k8s-master01:~/yaml/chapter09# kubectl apply -f pods-reader-rbac.yaml
role.rbac.authorization.k8s.io/pods-reader created

# 角色已经在default名称空间下生成
root@k8s-master01:~/yaml/chapter09# kubectl get role
NAME          CREATED AT
pods-reader   2021-08-02T06:44:03Z

3.角色需要将其绑定到用户上

root@k8s-master01:~/yaml/chapter09# vim darius-pods-reader.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: darius-pods-reader
  namespace: default
subjects:
- kind: User
  name: darius
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pods-reader
  apiGroup: rbac.authorization.k8s.io

4.应用绑定

root@k8s-master01:~/yaml/chapter09# kubectl apply -f darius-pods-reader.yaml
rolebinding.rbac.authorization.k8s.io/darius-pods-reader created

5.使用darius账号进行测试

root@k8s-master01:~/yaml/chapter09# kubectl get pods --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME                                             READY   STATUS      RESTARTS   AGE
configmaps-env-demo                              1/1     Running     0          17d
configmaps-volume-demo                           1/1     Running     0          17d
configmaps-volume-demo2                          2/2     Running     0          17d
configmaps-volume-demo3                          1/1     Running     0          16d
cronjob-demo-27131450-85h7z                      0/1     Completed   0          5m1s
cronjob-demo-27131452-xqqrk                      0/1     Completed   0          3m1s
cronjob-demo-27131454-fn7fp                      0/1     Completed   0          61s
daemonset-demo-6qqmt                             1/1     Running     0          11d
daemonset-demo-fvkhj                             1/1     Running     0          11d
daemonset-demo-pxmrd                             1/1     Running     0          11d
demodb-0                                         1/1     Running     0          6d5h
demodb-1                                         1/1     Running     0          6d5h
deployment-demo-77d46c4794-5whvx                 1/1     Running     0          11d

# 已经能正常获取pods资源。

集群管理角色

admin集群管理角色

在 k8s 系统上存在一个 admin 的 ClusterRole,其作用的范围为集群范围,其内部定义了核心资源类型当中的非集群级别资源的管理权限。此 admin 拥有除集群级别之外的所有管理权限。

root@k8s-master01:~/yaml/chapter09# kubectl get clusterrole admin
NAME    CREATED AT
admin   2024-04-15T06:13:59Z

如果我们使用 ClusterRolebinding 将某个用户绑定在 admin 这个 ClusterRole 上那么其将拥有除了集群级别管理权限之外的所有管理权限。

cluster-admin集群管理角色

cluster-admin 是集群管理员,其拥有k8s的一切管理权限。

root@k8s-master01:~/yaml/chapter09# kubectl get clusterrole cluster-admin
NAME            CREATED AT
cluster-admin   2024-04-15T06:13:59Z

如果将某个用户以 clusterRoleBinding 绑定在 cluster-admin 那其将拥有集群级别的一切操作管理权限。

rbac命令行创建示例

admin集群管理角色绑定示例:

此处为了不予刚才示例混淆,先将 darius 的 rolerolebinding 删除

root@k8s-master01:~/yaml/chapter09# kubectl delete rolebindings.rbac.authorization.k8s.io darius-pods-reader
rolebinding.rbac.authorization.k8s.io "darius-pods-reader" deleted

root@k8s-master01:~/yaml/chapter09# kubectl delete role pods-reader
role.rbac.authorization.k8s.io "pods-reader" deleted

1.将用户于admin的clusterRole进行绑定

root@k8s-master01:~/yaml/chapter09# kubectl create clusterrolebinding darius-admin --user=darius --clusterrole=admin
clusterrolebinding.rbac.authorization.k8s.io/darius-admin created

2.使用darius账号进行测试

root@k8s-master01:~/yaml/chapter09# kubectl get pods -n kube-system --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME                                   READY   STATUS    RESTARTS   AGE
coredns-6f6b8cc4f6-8wm8v               1/1     Running   0          18d
coredns-6f6b8cc4f6-tzmnm               1/1     Running   0          18d
etcd-k8s-master01                      1/1     Running   1          18d
kube-apiserver-k8s-master01            1/1     Running   1          18d
kube-controller-manager-k8s-master01   1/1     Running   1          18d
kube-flannel-ds-dl2rq                  1/1     Running   0          18d
kube-flannel-ds-fmml6                  1/1     Running   0          18d
kube-flannel-ds-rwh5f                  1/1     Running   0          18d
kube-flannel-ds-tqbbv                  1/1     Running   0          18d
kube-proxy-6qdpb                       1/1     Running   0          18d
kube-proxy-kp5ch                       1/1     Running   0          18d
kube-proxy-ntmzb                       1/1     Running   0          18d
kube-proxy-vwdm8                       1/1     Running   0          18d
kube-scheduler-k8s-master01            1/1     Running   1          18d

此时其能访问到 kube-system 的资源了。但是集群级别的操作依旧不能使用。

# 查看nodes相关资源
root@k8s-master01:~/yaml/chapter09# kubectl get nodes --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
Error from server (Forbidden): nodes is forbidden: User "darius" cannot list resource "nodes" in API group "" at the cluster scope

# 权限被拒绝,因为admin的ClusterRole没有此授权。

cluster-admin集群管理角色绑定示例:

将此前创建的admin相关的 clusterrolebinding 进行删除,以免干扰

root@k8s-master01:~/yaml/chapter09# kubectl delete clusterrolebindings darius-admin
clusterrolebinding.rbac.authorization.k8s.io "darius-admin" deleted

3.将darius用户使用clusterRolebinding绑定到cluster-admin这个roles上

root@k8s-master01:~/yaml/chapter09# kubectl create clusterrolebinding darius-cluster-admin --user=darius --clusterrole=cluster-admin
clusterrolebinding.rbac.authorization.k8s.io/darius-cluster-admin created

4.再次测试其能否进行集群级别的操作

root@k8s-master01:~/yaml/chapter09# kubectl get nodes --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME           STATUS   ROLES                  AGE   VERSION
k8s-master01   Ready    control-plane,master   18d   v1.21.2
k8s-node01     Ready    <none>                 18d   v1.21.2
k8s-node02     Ready    <none>                 18d   v1.21.2
k8s-node03     Ready    <none>                 18d   v1.21.2

授权其他话题

组在k8s中的作用

在k8s中 cluster-admin 是将 system:masters 组绑定在 cluster-admin 之上的。那么组内的所有用户都将拥有此权限。

root@k8s-master01:~/yaml/chapter09# kubectl describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind   Name            Namespace
  ----   ----            ---------
  Group  system:masters

对于证书认证来说组信息在Subj中的O内存放,如果其O内存放的为 system:master 那么所创建的用户自动拥有管理员权限,无需再授权。

验证

# 生成私钥文件
root@k8s-master01:/etc/kubernetes/usercerts# (umask 077;openssl genrsa -out testadm.key 2048)                     
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................................................................................+++++
............+++++
e is 65537 (0x010001)

# 生成证书签署请求,此处subj中的O使用system:masters
root@k8s-master01:/etc/kubernetes/usercerts# openssl req -new -key testadm.key -out testadm.csr -subj "/CN=testadm/O=system:masters"

# 使用k8s集群的证书和私钥对证书签署请求进行签发
root@k8s-master01:/etc/kubernetes/usercerts# openssl x509 -req -days 3655 -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -in testadm.csr -out testadm.crt
Signature ok
subject=CN = testadm, O = system:masters
Getting CA Private Key

# 以下为制作kubeconfig文件
# 在kubeconfig文件中设定集群
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config set-cluster kubernetes --server=https://kube-api:6443 --embed-certs --certificate-authority=/etc/kubernetes/pki/ca.crt --kubeconfig=/tmp/testadmcfg
Cluster "kubernetes" set.

# 在kubeconfig文件中设定用户
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config set-credentials testadm --client-certificate=testadm.crt --client-key=testadm.key --embed-certs=true --kubeconfig=/tmp/testadmcfg
User "testadm" set.

# 在kubeconfig文件中设定用户和集群的关联关系
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config set-context 'testadm@kubernetes' --user=testadm --cluster=kubernetes --kubeconfig=/tmp/testadmcfg
Context "testadm@kubernetes" created.

# 在kubeconfig文件中设定当前使用的账号
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config use-context testadm@kubernetes --kubeconfig=/tmp/testadmcfg
Switched to context "testadm@kubernetes".

# 当前账号没有进行授权,使用该账号获取集群信息。
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get nodes --kubeconfig=/tmp/testadmcfg
NAME           STATUS   ROLES                  AGE   VERSION
k8s-master01   Ready    control-plane,master   18d   v1.21.2
k8s-node01     Ready    <none>                 18d   v1.21.2
k8s-node02     Ready    <none>                 18d   v1.21.2
k8s-node03     Ready    <none>                 18d   v1.21.2

以上结果可以看出证书认证中 O 这一项如果为 system:masters 则无需再进行授权就能对集群进行操作。组这一项对k8s来说至关重要。

rolebinding来绑定ClusterRole

rolebinding 来绑定 ClusterRole 则以为着降级,其会将集群级别的操作限定在名称空间内。

验证

避免干扰先将此前创建的 clusterrolebinding 进行删除

root@k8s-master01:/etc/kubernetes/usercerts# kubectl delete clusterrolebindings darius-cluster-admin
clusterrolebinding.rbac.authorization.k8s.io "darius-cluster-admin" deleted

1.将darius用户使用 rolebinding 绑定到 cluster-admin 这个 ClusterRole

root@k8s-master01:/etc/kubernetes/usercerts# kubectl create rolebinding darius-admin --user=darius --clusterrole=cluster-admin
rolebinding.rbac.authorization.k8s.io/darius-admin created

# 注意此处rolebing时没有指定名称空间表示默认名称空间,darius用户的权限会限定在default名称空间下
# 如果指定了名称空间如"-n dev",darius用户则会被限定在dev名称空间下。

2.验证

# 测试访问默认名称空间内的资源
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get svc --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP    PORT(S)          AGE
demoapp-svc   ClusterIP   10.102.254.190   <none>         80/TCP           11d
demodb        ClusterIP   None             <none>         9907/TCP         7d3h

# 访问其他名称空间内的资源
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get svc -n kube-system --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
Error from server (Forbidden): services is forbidden: User "darius" cannot list resource "services" in API group "" in the namespace "kube-system"
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get svc -n dev --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
Error from server (Forbidden): services is forbidden: User "darius" cannot list resource "services" in API group "" in the namespace "dev"

rolebinding绑定ServiceAccount

创建一个 ServiceAccount,并将其使用 rolebinding 绑定到admin的 ClusterRole

# 创建ServiceAccount
root@k8s-master01:/etc/kubernetes/usercerts# kubectl create serviceaccount dev-admin
serviceaccount/dev-admin created

# 创建rolebinding将dev-admin的sa绑定到admin这个ClusterRole上
root@k8s-master01:~# kubectl create rolebinding dev-admin --clusterrole=admin --serviceaccount=dev:dev-admin -n dev
rolebinding.rbac.authorization.k8s.io/dev-admin created

# dev:dev-admin表示dev名称空间下的dev-admin的ServiceAccount

以上操作后,如果有pod的 ServiceAcountNamedev-admin 那么此pod将拥有该名称空间下的所有操作权限。