kubernetes RBAC

操作系统:
centos7.3
软件版本:

  • kubernetes 1.8
  • docker-ce 17.03.02

概念:

权限管理
是指控制用户对某些特定资源的访问权限。
设计理念
ACL(访问控制列表):对资源进行权限控制,每个资源都有一个权限列表记录着哪些用户对这个资源能进行哪些操作,优点:实现非常简单,只需要将用户和资源连接起来就可以。缺点是:当用户和资源增多时会产生大量访问控制列表,管理起来非常麻烦。
ABAC(基于属性的访问控制):ABAC控制权限的粒度非常细,非常灵活;属性通常来说分为四类:用户属性、环境属性、操作属性、对象属性;ABAC通过动态的控制一组属性是否满足条件来进行授权判断。优点:权限控制的粒度非常细,非常灵活。缺点:太过于复杂。
例如规则:“禁止所有学生在上课时间进出校门”这条规则,其中,“学生”是用户的角色属性,“上课时间”是环境属性,“进出”是操作属性,而“校门”就是对象属性了。
RBAC(基于角色的访问控制):引入角色概念,通过将权限和角色关联,来实现用户根权限的解耦,角色可以看做是权限的一个集合。通过权限与角色关联,角色与用户的关联可以实现用户和角色多对多的对应关系。优点 ;将权限与角色关联,用户关联角色,这样权限控制更加灵活 。缺点:相比ABAC控制的粒度没有那么细。
RBAC的模型
Who是否可以对What进行How的访问操作(Operator)

kubernetes之前的版本都是使用ABAC做为权限管理控制,在kubernetes1.3发布alpha版本RBAC,在kubernetes1.6版本RBAC提升为Beta版,kubernetes1.8版本正式提升为GA版,为什么用RBAC取代ABAC是因为在kubernetes中ABAC过于复杂,不好管理,难以理解,RBAC相对功能和可管理性来说更加合适kubernetes。所以说没有更好,只有更合适。

在kubernetes中的RBAC定义了四类API资源分别为:
Role:role是一组权限的集合,namespace范围的Role,role权限的有效范围为指定的单一namespace。
ClusterRole:clusterrole根role一样也是一组权限的集合,cluster范围的Role,但clusterrole的有效范围是整个集群的权限和一些集群级别的资源如:集群的node节点、非资源类型endpoint、跨所有命名空间的命名空间范围资源(例如pod,需要运行命令kubectl get pods –all-namespaces来查询集群中所有的pod)。
RoleBinding:将角色根用户或组或ServiceAccount绑定,授予它们对该命名空间资源的权限。
ClusterRoleBinding:将ClusterRole与用户绑定,授予它们对cluster的资源访问权限。

例子
首先我们创建个wanshaoyuan的普通用户
确认kubernetes证书目录是否有以下文件

若没有ca-config.json
创建一个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
EOF

ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
1、创建证书签名请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
cat > wanshaoyuan-csr.json <<EOF
{
"CN": "wanshaoyuan",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

生成证书和公钥

1
cfssl gencert -ca=ca.crt -ca-key=ca.key -config=ca-config.json -profile=kubernetes wanshaoyuan-csr.json | cfssljson -bare wanshaoyuan

创建kubeconfig文件

1
export KUBE_APISERVER="https://192.168.1.10:6443"
1
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=wanshaoyuan.kubeconfig
1
kubectl config set-credentials wanshaoyuan --client-certificate=/etc/kubernetes/pki/wanshaoyuan.pem --client-key=/etc/kubernetes/pki/wanshaoyuan-key.pem --embed-certs=true --kubeconfig=wanshaoyuan.kubeconfig

设置context

1
kubectl config set-context kubernetes --cluster=kubernetes --user=wanshaoyuan  --kubeconfig=wanshaoyuan.kubeconfig

设置默认context,将集群参数和用户参数关联起来,如果配置了多个集群,可以通过集群名来切换不同的环境

1
kubectl config use-context kubernetes --kubeconfig=wanshaoyuan.kubeconfig

查看kubectl的context

用户目前还是kubernetes-admin,切换到wanshaoyuan

1
KUBECONFIG=/etc/kubernetes/pki/wanshaoyuan.kubeconfig

1
cp /etc/kubernetes/pki/wanshaoyuan.kubeconfig  /root/.kube/config

再次查看

用户目前还是kubernetes-admin,切换到wanshaoyuan

1
KUBECONFIG=/etc/kubernetes/pki/wanshaoyuan.kubeconfig

1
cp /etc/kubernetes/pki/wanshaoyuan.kubeconfig  /root/.kube/config

再次查看

创建角色
定义这个角色只能对default这个namespace 执行get、watch、list权限
定义角色

1
2
3
4
5
6
7
8
9
10
11
12
cat role.yaml

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]

角色绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

cat role_bind.yaml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: wanshaoyuan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io


应用

1
kubectl apply -f role.yaml
1
kubectl apply -f role_bind.yaml

check一下

切到wanshaoyuan这个用户
root用户将KUBECONFIG这个变量指向刚刚创建用户出来的kubeconfig

1
KUBECONFIG=/root/RBAC/wanshaoyuan.kubeconfig

非root用户替换默认的config文件

1
cp wanshaoyuan.kubeconfig  /root/.kube/config

检查是否切换成功

验证

可以看见wanshaoyuan这个用户只能访问default这个namespace的pod资源,其他的如namespace都访问不了,同样namespace的其他资源也访问不了
clusterrole定义的是集群级别的权限,也可以把它授予一些集群级别的资源

例如
集群的node节点
非资源类型endpoint
跨所有命名空间的命名空间范围资源(例如pod,需要运行命令kubectl get pods –all-namespaces来查询集群中所有的pod)

例如
定义一个clusterrole限制只能访问集群中的node节点,不能修改,其他资源都不能访问。
cat cluster_role.yaml

1
2
3
4
5
6
7
8
9
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "watch", "list"]

再定义一个ClusterRoleBinding,将上面的clusterrole和用户wanshaoyuan绑定起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat cluster_role_bind.yaml

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets-global
subjects:
- kind: User
name: wanshaoyuan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

应用

1
kubectl apply -f cluster_role.yaml
1
kubectl apply -f cluster_role_bind.yaml

切换用户

1
KUBECONFIG=/root/RBAC/wanshaoyuan.kubeconfig

测试

只能访问node,不能做其他编辑操作,集群内其他资源也访问不了。
例如
定义一个clusterrole限制只能访问集群所有namespace的cesecret,其他资源都不能访问
先定义一个clusterRole

1
2
3
4
5
6
7
8
9
10
cat /root/RBAC/cluster_role.yaml  
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]

再定义一个ClusterRoleBinding,将上面的clusterrole和用户wanshaoyuan绑定起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
cat /root/RBAC/cluster_role_bind.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-secrets-global
subjects:
- kind: User
name: wanshaoyuan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io

应用

1
kubectl apply -f cluster_role.yaml
1
kubectl apply -f cluster_role_bind.yaml

切换用户

1
KUBECONFIG=/root/RBAC/wanshaoyuan.kubeconfig

验证

可以看到,wanshaoyuan这个用户,可以get集群中任意namespace的secret,但其他资源,如pod,之类的都无法查看
修改下,让wanshaoyuan这个帐户可以同时查看pod、secret、deployment

1
KUBECONFIG=/root/RBAC/wanshaoyuan.kubeconfig
1
KUBECONFIG=/etc/kubernetes/admin.conf

修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/root/RBAC/cluster_role.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]

- apiGroups: [""]
resources: ["pod"]
verbs: ["get", "watch", "list"]

- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "watch", "list"]

用kubectl apply去实时更新

1
kubectl apply -f cluster_role.yaml
1
kubectl apply -f cluster_role.yaml

切换用户测试

pod、secret、deployment都能正常获取

角色绑定包含一组相关主体即subject,subject可以是User(用户)也可以是Group(组)还可以是Service Account。
这里要强调下
Kubernetes 集群中包含两类用户:一类是由 Kubernetes 管理的 service account,另一类是普通用户。

普通用户被假定为由外部独立服务管理。管理员分发私钥,用户存储(如 Keystone 或 Google 帐户),甚至包含用户名和密码列表的文件。在这方面,Kubernetes 没有代表普通用户帐户的对象。无法通过 API 调用的方式向集群中添加普通用户。

相对的,service account 是由 Kubernetes API 管理的帐户。它们都绑定到了特定的 namespace,并由 API server 自动创建,或者通过 API 调用手动创建。Service account 关联了一套凭证,存储在 Secret,这些凭证同时被挂载到 pod 中,从而允许 pod 与 kubernetes API 之间的调用。

API 请求被绑定到普通用户或 serivce account 上,或者作为匿名请求对待。这意味着集群内部或外部的每个进程,输入 kubectl ,都必须在向 API Server 发出请求时进行身份验证,否则被视为匿名用户。
来源:https://jimmysong.io/posts/user-authentication-in-kubernetes/

kubernetes在每个namespace内都有一个默认的service account,当在创建pod或其他资源时,没有手工指定Service account时会默认使用namespace里面这个default这个Service account

一般来说为了安全起见,建议一个应用使用一个独立的Service account运行,这样RoleBindings就不会无意中授予其他应用程序的权限,如果需要这样使用的话在部署yaml文件中添加


可以通过以下命令对namespace中的Service account进行默认权限配置
授予my-namespace命名空间内的default这个Service account帐户只读权限(view是集群中的一组通用角色,它的默认权限的是只读,它归属于clusterrole

1
2
3
4
kubectl create rolebinding default-view \
--clusterrole=view \
--serviceaccount=my-namespace:default \
--namespace=my-namespace

授予my-namespace命名空间内的my-sa这个Service account帐户只读权限

1
2
3
4
kubectl create rolebinding my-sa-view \
--clusterrole=view \
--serviceaccount=my-namespace:my-sa \
--namespace=my-namespace

授予my-namespace命名空间内所有的Service account帐户只读权限

1
2
3
4
kubectl create rolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts:my-namespace \
--namespace=my-namespace

默认的Role和ClusteRrole
api-service会默认创建一些role和rolebinding 和clusterrole和clusterrolebind,他们默认都是以system开头的,以system开头的都是为kubernetes系统使用而保留的

这里不多介绍主要讲讲clusterrole里面cluster-admin、admin、edit、view这几个clusterrole,直接参考https://v1-8.docs.kubernetes.io/docs/admin/authorization/rbac/
cluster-admin、admin、edit、view这几个角色是不包含system前缀的,他们是面向用户的角色,可以直接使用rolebind直接使用
具体权限参考下图

比如我们需要访问kubernetes-dashboard时,需要一个能够访问获取所有集群资源的用户此时就可以创建一个帐户关联cluster-admin这个角色。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile

上面创建一个ServiceAccount帐户admin并将它与cluster-admin角色绑定,然后我们可以通过获取admin的token去访问dashboard。
kubectl -n kube-system describe secret admin-token-nwphb

apiGroup解释
上面各类角色转换中的apiGroup的解释
来源:https://segmentfault.com/a/1190000008700595

k8s里面有各种资源,如Pod、Service、RC、namespaces等资源,用户操作的其实也就是这一大堆资源。但这些资源并不是杂乱无章的,使用了GroupVersion的方式组织在一起。每一种资源都属于一个Group,而资源还有版本之分,如v1、v1beta1等。
k8s目前正在使用的API groups:

  • “core” group:它的REST path是api/v1
  • “extensions” group:它的REST path是/apis/extensions/v1beta1
  • “autoscaling”, “abac” …

k8s现阶段,API一共分为13个Group:Core、apps、authentication、authorization、autoscaling、batch、certificates、componentconfig、extensions、imagepolicy、policy、rbac、storage。其中Core的Group Name为空,它包含的API是最核心的API,如Pod、Service等。

参考链接:
http://blog.csdn.net/wangjingna/article/details/49226727
http://blog.csdn.net/jettery/article/details/70138003
http://blog.csdn.net/yan234280533/article/details/75808048
http://blog.csdn.net/yan234280533/article/details/76359199
http://blog.csdn.net/qqhappy8/article/details/78891200
http://www.bijishequ.com/detail/570501
http://www.sohu.com/a/205750642_610730
https://v1-8.docs.kubernetes.io/docs/admin/authorization/rbac/
https://jimmysong.io/kubernetes-handbook/
https://www.cnblogs.com/charlieroro/p/8489515.html