1 2 |
在Kubernetes中所有的API对象都保存在ETCD里,可是,对这些API对象的操作,却一定是通过访问kube-apiserver实现的。我们需要APIServer来帮助我们授权工作,而在Kubernetes项目中,负责完成授权(Authorization)的工作机制就是RBAC: 基于角色的访问控制 (Role-Based Access Control) RBAC是基于角色的访问控制 (Role-Based Access Control) 在RBAC中,权限与角色相关联。Kubernetes 基于角色的访问控制使用rbac.authorization.k8s.io API组来实现权限控制,RBAC允许管理员通过Kubernetes API动态的配置权限策略。如果需要开启RBAC授权需要在apiserver组件中指定--authorization-mode=Node,RBAC |
首先明确一下RBAC的三个基本概念:

- Role: 角色,它定义了一组规则,定义了一组对Kubernetes API对象的操作权限
- Subject: 被作用者,既可以是”人”,也可以是机器,当然也可以是我们K8s中定义的用户(ServiceAccount主要负责kubernetes内置用户)
- RoleBinding: 定义了”被作用者”和”角色”的绑定关系
角色分为两种 :
一种是Role,负责命名空间(namespace)内的权限
一种是ClusterRole,负责整个Kubernetes集群范围内的权限
使用方式:
1.用户使用:如果是用户需求权限,则将Role/ ClusterRole 与 User(或Group)绑定(这需要创建User/Group)。
2.程序使用:如果是程序需求权限, 将Role / ClusterRole 与 ServiceAccount指定(这需要创建ServiceAccount并且在deployment中指定ServiceAccount)。
RBAC API对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Kubernetes有一个很基本的特性就是它的所有资源都是模型化的API对象,允许执行CRUD(Create、Read、Update、Delete)操作。资源如下 Pods ConfigMaps Deployments Nodes Secrets Namespaces 资源对象可能存在的操作有如下: create get delete list update edit watch exec 这些资源和API Group进行关联,比如Pods属于Core API Group,而Deployment属于apps API Group,要在kubernetes中进行RBAC授权 |
用户使用
1.Role 和 Rolebinding
Role(可以理解为设定权限)它本身就是一个Kubernetes的API对象,定义文件如下:
1 2 3 4 5 6 7 8 9 |
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: mynamespace name: example-role rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] |
解释:
1 2 3 |
首先, Role 对象指定了它能产生作用的Namespace(mynamespace).Namespace是kubernetes项目中的一个逻辑管理单位。不同Namespace的API对象,在通过kubectl命令进行操作的时候,是互相隔离的. namespace并不会提供任何实际的隔离或者多租户能力,如果没有设置namespace默认则是default. rules字段定义它的是权限规则,这条规则的含义就是允许"被作用者",对namespace下面pod (resources中定义)有哪些权限. |
用户的权限对应的API资源对象已经创建了,但是还没有绑定。也就是只有一个规则没有规定哪些用户使用这个权限
这里进行Rolebinding 介绍 :(绑定设定好的权限给某个用户)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-rolebinding namespace: mynamespace subjects: - kind: User name: example-user #绑定给某个用户 apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: example-role #设定好的权限 apiGroup: rbac.authorization.k8s.io |
解析:
1 2 3 4 5 6 7 |
在Rolebinding中定义了一个subject字段,即"被作用者".它的类型是User,即Kubernetes里的用户,被作用的用户名称为:example-user 在kubernetes里的User,也就是用户,只是一个授权系统里的逻辑概念。它需要通过外部认证服务,比如Keystone,来提供。或者直接给APIServer指定一个用户名、密码文件。那么kubernetes的授权系统就能够从这个文件里找到对象的用户 Rolebinding对象通过roleRef字段可以直接通过名字,来引用前面定义的Role(权限)对象(example-role),从而定义了"被作用者(Subject)"和"角色(Role)"之间的绑定关系 Role和RoleBinding 他们的权限限制规则仅仅在他们自己的namespace内有效,roleRef也只能引用当前namespace里的Role对象 |
2.ClusterRole 和 ClusterRoleBinding
1 |
对于某一个role(角色)想要作用于所有namespace的时候,就必须需要使用ClusterRole和ClusterRoleBinding两个组合。这两个API 对象的用法跟Role和Rolebinding完全一样。 |
1 2 3 4 5 6 7 8 |
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-clusterrole rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] |
1 2 3 4 5 6 7 8 9 10 11 12 |
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-clusterrolebinding subjects: - kind: User name: example-user apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: example-clusterrole apiGroup: rbac.authorization.k8s.io |
在上面的例子中,ClusterRole和ClusterRoleBinding的组合,意味着名叫example-user的用户,拥有对所有namespace里的Pod进行Get、Watch、List操作的权限。
类似的,Role对象的rules字段也可以进一步细化,可以只针对某一个具体权限对象进行设置
1 2 3 4 5 |
rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-config"] verbs: ["get"] |
上面的例子表示,这条规则的”被作用者”,只对my-config的configmap对象有权限进行get操作。
前面说过,在Kubernetes中已经内置了很多个位系统保留的ClusterRole,它们的名字都是以system:开头。一般来说,这些内置的ClusterRole,是绑定给Kubernetes系统组件对应的ServiceAccount使用.
通过命令获取: kubectl get clusterroles

此外,Kubernetes还提供了四个预先定义好的ClusterRole来提供用户直接使用
- cluster-admin
- admin
- edit
- view
其中cluster-admin角色,对应的是整个Kubernetes项目中最高权限(verbs=*)
我们可以通过下面的命令查看clusterrole的权限
1 |
kubectl describe clusterrole cluster-admin -n kube-system |

1 |
我们使用的dashboard 需要对所有资源都有权限,所以他的ClusterRoleBinding里绑定的权限就是cluster-admin |
程序使用
ServiceAccount
前面所介绍的大多数时候都不怎么使用,ServiceAccount主要负责kubernetes内置用户,下面简单定义一个ServiceAccount
1 2 3 4 5 |
apiVersion: v1 kind: ServiceAccount metadata: namespace: mynamespace name: example-sa |
我们定义的这个serverAccount对象,只需要name以及namespace最基础字段就可以。然后通过编写rolebinding的yaml文件,来为这个serviceAccount分配权限 。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-rolebinding namespace: mynamespace subjects: - kind: ServiceAccount name: example-sa #被作用的对象ServiceAccount的名称 namespace: mynamespace roleRef: kind: Role name: example-role #最上头定义的那个角色权限 apiGroup: rbac.authorization.k8s.io |
在这个Rolebinding对象里,subject字段的类型(kind),不在是一个User,而是一个名叫example-sa的ServerAccount。而roleRef引用的Role对象,依然是前头定义的名叫example-role的角色权限
创建并演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
创建pod:pod-sa.yaml apiVersion: v1 kind: Pod metadata: namespace: mynamespace name: sa-token-test spec: containers: - name: nginx image: nginx:1.7.9 serviceAccountName: example-sa 创建权限:role.yaml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: mynamespace name: example-role rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] 创建绑定作用规则:role-binding.yaml kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-rolebinding namespace: mynamespace subjects: - kind: ServiceAccount name: example-sa namespace: mynamespace roleRef: kind: Role name: example-role apiGroup: rbac.authorization.k8s.io #接下来我们创建命名空间 kubectl create namespace mynamespace namespace/mynamespace created #应用当前目录下所有yaml kubectl apply -f . rolebinding.rbac.authorization.k8s.io/example-rolebinding created role.rbac.authorization.k8s.io/example-role created serviceaccount/example-sa created #查看SeviceAccount kubectl get sa -n mynamespace NAME SECRETS AGE default 1 26s example-sa 1 22s #查看详细 kubectl get sa -n mynamespace example-sa -o yaml apiVersion: v1 kind: ServiceAccount metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-sa","namespace":"mynamespace"}} creationTimestamp: "2019-11-28T08:01:22Z" name: example-sa namespace: mynamespace resourceVersion: "14579937" selfLink: /api/v1/namespaces/mynamespace/serviceaccounts/example-sa uid: 4481a40f-11b5-11ea-a57e-525400d7b284 secrets: - name: example-sa-token-wms94 |
K8s会为ServiceAccount自动创建一个Secret对象,即ServiceAccount定义最下面的secrets字段。其中,这里的secret就是ServiceAccount对应来跟APIServer进行交互的授权文档,一般为TOken,保存证书和密码等,它以一个Secret对象保存在ETCD中
这时候我们就可以直接在pod中引用这个serviceAccount了
1 2 3 4 5 6 7 8 9 10 11 12 |
apiVersion: v1 kind: Pod metadata: namespace: mynamespace name: sa-token-test spec: containers: - name: nginx image: nginx serviceAccountName: example-sa #在最下面一行我们定义了一个名为example-sa |
接下来我们可以通过describe查看pod状态
1 2 3 4 5 6 7 8 9 |
kubectl describe pod -n mynamespace sa-token-test Name: sa-token-test Namespace: mynamespace ... Mounts: /var/run/secrets/kubernetes.io/serviceaccount from example-sa-token-wms94 (ro) ... 可以看到:ServiceAccount的token也就是secret对象是被Kubernetes自动挂载到了容器/var/run/secrets/kubernetes.io/serviceaccount目录下 |

我们可以到Pod目录进行查看
1 2 3 4 |
kubectl exec -it sa-token-test -n mynamespace -- /bin/bash ls /var/run/secrets/kubernetes.io/serviceaccount ca.crt namespace token |
在Kubernetes集群访问主要是通过ca.crt来访问Apiserver,更重要的是此时它只可以做GET、WATCH和LIST操作。因为example-sa这个ServiceAccount的权限已经被我们绑定了role限制。
如果一个Pod没有声明ServiceAccount,Kubernetes会自动在它的namespace创建一个名称为default的默认ServiceAccount,然后分配给Pod。但是这种情况下默认ServiceAccount没有关联任何Role。也就是说它有APIServer的绝大多数权限 .
用户组概念
User 和 Group
Kubernetes除了有用户(User),还拥有用户组(Group)概念,如果我们Kubernetes配置了外部认证服务的话,这个用户组的概念就由外部认证服务提供
一个ServiceAccount在Kubernetes对应的用户的名字是
1 2 3 |
system:serviceaccount:<ServiceAccount名字> 例如上面的那个sa对应的就是 system:serviceaccount:example-sa |
而对应的用户组则是
1 2 |
system:serviceaccounts:<Namespace名字> 例如上面的那个sa对应的就是 system:serviceaccount:mynamespace |
比如,我们可以在RoleBinding中定义如下subjects
1 2 3 4 |
subjects: - kind: Group name: system:serviceaccounts:mynamespace apiGroup: rbac.authorization.k8s.io |
这就意味着role的规则权限,作用于mynamespace(这个命名空间里 -n mynamespace)里的所有ServiceAccount,这就用到了用户组的概念
1 2 3 4 |
subjects: - kind: Group name: system:serviceaccounts apiGroup: rbac.authorization.k8s.io |
如果这样写,这个role的规则权限,则作用于整个系统里ServiceAccount
1 2 3 4 5 |
在Kubernetes中已经内置了很多歌为系统保留的ClusterRole,它们的名字都以system:开头,可以使用kubectl get clusterroles查找到 现在我们可以理解,所谓的角色(Role),其实就是一组规则权限列表,而我们分配这些权限的方式,就是通过创建RoleBinding对象,将被用者(subject)和权限列表绑定。 而对应的ClusterRole和ClusterRoleBinding,则是Kubernetes集群级别的Role和RoleBinding,它们不受namespace限制 |
实践:
一:创建一个只能访问某个namespace的ServiceAccount
当我们创建一个sa之后,会自动帮我们创建一个secrets
1 |
kubectl create sa shooter-sa -n kube-system |
接下来可以查看一下sa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
kubectl get sa -n kube-system shooter-sa -o yaml [root@k8s-master01 dashboard]# kubectl get sa -n kube-system shooter-sa -o yaml apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: "2020-11-18T08:03:08Z" name: shooter-sa namespace: kube-system resourceVersion: "2509182" selfLink: /api/v1/namespaces/kube-system/serviceaccounts/shooter-sa uid: 691b2a95-c8cb-45a7-8b70-e34ebcfd5b21 secrets: - name: shooter-sa-token-vjwdc [root@k8s-master01 dashboard]# |
也可以通过get secret查看
1 2 3 4 |
kubectl get secrets -n kube-system |grep shooter-sa-token [root@k8s-master01 dashboard]# kubectl get secrets -n kube-system |grep shooter-sa-token shooter-sa-token-vjwdc kubernetes.io/service-account-token 3 97s |
我们需要创建一个role (角色)对象与sa进行关联
yaml文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: sa-role namespace: kube-system rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list"] - apiGroups: ["apps", "extensions"] resources: ["pods", "deployment", "replicasets"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] |
这里我们创建的role设置的权限是对pod有get和list权限,对deployment有下面其他权限
执行文件yaml
1 2 |
[root@k8s-master01 sa]# kubectl apply -f sa-role.yaml role.rbac.authorization.k8s.io/sa-role created |
检查状态
1 |
kubectl get role -n kube-system |

角色创建完成之后我们就需要创建一个RoleBinding
yaml文件如下
1 2 3 4 5 6 7 8 9 10 11 12 13 |
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: sa-rolebinding namespace: kube-system subjects: - kind: ServiceAccount name: shooter-sa #绑定serviceAccount namespace: kube-system roleRef: kind: Role name: sa-role #绑定角色权限 apiGroup: rbac.authorization.k8s.io |
1 2 3 |
#执行 [root@k8s-master01 sa]# kubectl apply -f sa-rolebinding.yaml rolebinding.rbac.authorization.k8s.io/sa-rolebinding created |
查看
1 |
kubectl get rolebinding -n kube-system|grep sa |

这时候我们创建的ServerAccount已经和我们role(角色权限)进行绑定了,通过rolebinding进行绑定。下面可以进行测试
测试:
首先我们复制我们创建sa中secret里面的token
1 2 3 4 |
kubectl -n kube-system get secret | grep shooter-sa #然后查看secret 当中的 token kubectl describe secret shooter-sa-token-vjwdc -n kube-system |

现在token已经创建好了,我们使用dashboard进行演示 (不同权限看到的资源对象不同)
复制token登录dashboard

当我们登陆到dashboard界面上,默认访问的为default命名空间,因为我们授权的是kube-system空间,所以很多地方没有权限。会有下面的403报错

我们将default修改为kube-system即不会再报错

二、创建一个可以访问所有namespace的ServiceAccount
上面创建单个namespace访问权限主要是用了role和rolebinding,接下来我们使用clusterRole和ClusterRoleBinding进行演示。使用role和rolebinding只会绑定特定的namespace下,clusterRole会绑定到集群下
首先创建一个ServiceAccount对象
1 2 3 4 5 |
apiVersion: v1 kind: ServiceAccount metadata: name: root-sa namespace: kube-system |
再创建一个ClusterRoleBinding
1 2 3 4 5 6 7 8 9 10 11 12 |
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: root-clusterrolebinding #clusterrolebinding的名称 subjects: #被作用者 - kind: ServiceAccount #类型 name: root-sa #serviceAccount名称 namespace: kube-system #sa命名空间 roleRef: #角色引用 kind: ClusterRole #类型为clusterRole name: cluster-admin #clust-admin为rbac系统最大权限 apiGroup: rbac.authorization.k8s.io |
接下来开始创建
1 2 3 4 5 |
[root@k8s-master01 sa]# kubectl apply -f sa-root.yaml serviceaccount/root-sa created [root@k8s-master01 sa]# kubectl apply -f root-clusterroleBinding.yaml clusterrolebinding.rbac.authorization.k8s.io/root-clusterrolebinding created [root@k8s-master01 sa]# |
查看secret中root-sa的token
1 2 3 4 |
kubectl -n kube-system get secret | grep root-sa #然后查看secret 当中的 token kubectl describe secret root-sa-token-99tkh -n kube-system |
使用此token再次登录dashboard

访问进来就没有error报错,也就是现在serviceAccount已经绑定到最高权限的root-sa。可以访问所有资源对象,并且增删改查权限都有
(完)
- 本文固定链接: https://www.yoyoask.com/?p=4381
- 转载请注明: shooter 于 SHOOTER 发表