k8s中的RBAC
我们在业务开发中经常会遇到权限认证和授权业务。
前面说到的serviceAccount就是k8s的认证过程。而k8s的授权机制是通过RBAC来完成的。
RBAC顾名思义即基于角色的权限控制。
RBAC的授权是通过四种资源来配置的,它们又可以分成两组
- Role(角色) 和 ClusterRole(集群角色),它们指定了在资源上可以执行哪些动词
- RoleBinding(角色绑定) 和 ClusterRoleBinding(集群角色绑定),它们将上述角色绑定到特定的用户、组或ServiceAccounts上。
角色定义了可以做什么操作,而绑定定义了谁可以做这些操作
在k8s中所有的资源信息都在etcd里,要访问etcd必须通过apiserver。而apiserver就是通过role来控制哪些账号能访问哪些资源。
Role和ClusterRole
k8s了有两个和角色相关的资源:Role和ClusterRole
Role 是定义在一个 namespace 中,而 ClusterRole 是集群级别的。
定义一个Role
1 | apiVersion: rbac.authorization.k8s.io/v1 |
这个Role的规则含义是:在名字为 test的namespace 中,对Pods有get,watch,list的权限
注意一点:在指定资源时必须使用复数的形式。
定义一个ClusterRole
1 | apiVersion: rbac.authorization.k8s.io/v1 |
与Role的区别就是matadata中没有namespace的限定。
这个ClusterRole的含义是,对整个集群的service有get,create,list的权限
分别创建
1 | kc apply -f test_role.yaml |
rules的参数说明:
- apiGroups可配置参数
“”(空表示core api组),“apps”, “autoscaling”, “batch”, “extensions”等等
这个apiGroups指的就是kubectl api-resources的APIGROUP

- resources可配置参数
不同的apiGroups对应的resource是不一样的。
比如 “”组有pods,nodes等等resources
apps组才有deployments
就是和代码开发对应的
verbs可配置参数
“get”,“list”,“watch”, “create”,“update”, “patch”, “delete”,“exec”resourcesNames
上面三个是必填的,这个resourcesNames是可选的
他的含义是可以对具体某个资源进行限制。比如对名字是aaa的pod进行授权
RoleBinding 和 ClusterRoleBinding
我们定义了role,但现在role只是被定义出来,并没有实际的作用。因为现在role还是孤零零的存在,需要将role和用户进行绑定,才能真正发挥作用。

role可以和三种对象subjects绑定,一种是User,一个是Group,最重要的一个就是serviceaccount。
和useraccount绑定
1 | apiVersion: rbac.authorization.k8s.io/v1 |
这个绑定的含义是,给用户yys绑定了test-role角色,也就是yys拥有了对名字为 test的namespace 中,对Pods有get,watch,list的权限
实验
用root用户操作
新建用户yys
1
2
3
4[root@paas-m-k8s-master-1 test]# useradd yys
[root@paas-m-k8s-master-1 test]# su - yys
[yys@paas-m-k8s-master-1 ~]$ kubectl -n test get pod
The connection to the server localhost:8080 was refused - did you specify the right host or port?默认肯定是访问不到的,如果想要访问,必须要创建用户的访问证书
创建访问证书
1
2
3
4
5
6
7
8
9## 下载证书生成工具 cfssl
# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
## 给执行权限
# chmod +x *
# mkdir cert
# cd cert创建CA证书签名请求JSON文件 yys-csr.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17{
"CN": "yys", # 用户名称,必须填你的用户名,因为api-server鉴权时就用证书的CN字段作为用户名
"hosts": [], # 主机地址,不填表示所有主机都可使用
"key": {
"algo": "rsa", # 加密算法
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"O": "OKK",
"ST": "BeiJing",
"OU": "System"
}
]
}开始创建访问证书
1
2# cd /etc/kubernetes/pki/
# /home/yys/cfssl_linux-amd64 gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /home/yys/cert/yys-csr.json | /home/yys/cfssljson_linux-amd64 -bare yys
执行成功后多出这三个文件
为yys用户生成集群kubeconfig文件
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## 给用户创建kubeconfig文件
[root@paas-m-k8s-master-1 cert]# pwd
/home/yys/cert
[root@paas-m-k8s-master-1 cert]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=https://你的master的ip:6443 --kubeconfig=yys.kubeconfig
Cluster "kubernetes" set.
[root@paas-m-k8s-master-1 cert]# ll
总用量 8
-rw-rw-r-- 1 yys yys 231 6月 30 15:00 yys-csr.json
-rw------- 1 root root 1570 6月 30 15:07 yys.kubeconfig
## 设置客户端参数,绑定用户信息至kubeconfig中
[root@paas-m-k8s-master-1 cert]# kubectl config set-credentials yys \
--client-certificate=/etc/kubernetes/pki/yys.pem \
--client-key=/etc/kubernetes/pki/yys-key.pem \
--embed-certs=true \
--kubeconfig=yys.kubeconfig
User "yys" set.
## 设置上下文参数
[root@paas-m-k8s-master-1 cert]# kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=yys \
--namespace=test \
--kubeconfig=yys.kubeconfig
Context "kubernetes created.把kubeconfig文件复制到 用户的home目录的.kube下
1
2
3mkdir -p /home/yys/.kube
cp /home/yys/cert/yys.kubeconfig /home/yys/.kube/config
chown -R yys:yys /home/yys/.kube切换用户为yys,绑定kubectl读取config
1
2
3
4[root@paas-m-k8s-master-1 .kube]# su - yys
[yys@paas-m-k8s-master-1 ~]$ kubectl config use-context kubernetes --kubeconfig=/home/yys/.kube/config
Switched to context "kubernetes".测试
1
2[yys@paas-m-k8s-master-1 ~]$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "yys" cannot list resource "pods" in API group "" in the namespace "test"apply 绑定
1
2切回root用户
# kc apply -f test-rolebing.yaml应用rolebinding
再切回yys用户
1
2
3
4
5
6[yys@paas-m-k8s-master-1 .kube]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
jdktest-9302-e2y-1li-f283862d4944-job-9d9l8 0/1 Error 0 638d
nginx-volume-host 1/1 Running 0 217d
...
pcloud-testjjj-latest-7t9-esm-e2487db22694-job-29492 0/1 Completed 0 710d打印的就是test namespace下的pod。因为我们创建这个Context时已经制定了namespace就是test
如果干点别的
1
2[yys@paas-m-k8s-master-1 ~]$ kubectl get ns
Error from server (Forbidden): namespaces is forbidden: User "yys" cannot list resource "namespaces" in API group "" at the cluster scope会报没权限
和serviceaccount绑定
我们已经知道,ServiceAccount的主要作用是pod和apiserver交互。我们编写的程序默认是不能直接调用api-server的,需要对pod进行合适的授权,这个授权就是通过和ServiceAccount绑定来做的。
关于ServiceAccount的介绍,请看这里
说说K8S中的ServiceAccount (qq.com)
在这篇文章里,我们创建了一个命名为mytest的serviceaccount。创建了一个名为test-sa的pod使用这个sa。
我们继续沿用。
实验
进入这个pod
1 | [root@paas-m-k8s-master-1 test]# kc exec -it test-sa -- /bin/sh |
现在访问一下api-server
1 | # export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt |
可以看到现在调用api-server是Forbidden的。
绑定role
新建一个role,并进行roleBinding。
写在一起了
1 | kind: Role |
现在再进到之前的pod里
1 | curl -H "Authorization: Bearer $TOKEN" https://kubernetes/api/v1/namespaces/default/pods |

可以看到已经可以调用了,说明通过roleBinding赋予了pod调用api-server的权限