概述 RBAC(Role-Based Access Control )基于角色的访问控制,这个基础概念不多赘述
在k8s中有四种对象用于支持该鉴权方式,Role,ClusterRole,RoleBinding,ClusterRoleBinding
分别对应为角色,集群角色,角色绑定关系,集群角色绑定关系
以上四种总体来说分为两类,角色定义,角色绑定
角色定义描述了角色具体的权限信息,而角色绑定则描述了角色和subject(如用户,用户组)的绑定关系
角色定义 Role k8s中角色是和命名空间绑定的,该对象定义用户对于命名空间内的资源的权限,如pod,该命名空间下的serviceAccount等
1 2 3 4 5 6 7 8 9 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-reader rules: - apiGroups: ["" ] resources: ["pods" ] verbs: ["get" , "watch" , "list" ]
ClusterRole 该对象定义的是集群作用域内的资源的权限,比如node,serviceAccount等
1 2 3 4 5 6 7 8 9 10 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: secret-reader rules: - apiGroups: ["" ] resources: ["secrets" ] verbs: ["get" , "watch" , "list" ]
参数说明
apiGroups: 标识api组
resources:标识可以操作的资源
verbs:标识对资源的操作
apiGroups常用的""
,"extensions"
,"apps"
常用的资源诸如:pods
,nodes
等等
在 Kubernetes API 中,大多数资源都是使用对象名称的字符串表示来呈现与访问的。 例如,对于 Pod 应使用 “pods”。 RBAC 使用对应 API 端点的 URL 中呈现的名字来引用资源。 有一些 Kubernetes API 涉及 子资源(subresource) ,例如 Pod 的日志。 对 Pod 日志的请求看起来像这样:
1 GET /api/v1/namespaces/{namespace}/pods/{name}/log
在这里,pods
对应名字空间作用域的 Pod 资源,而 log
是 pods
的子资源。 在 RBAC 角色表达子资源时,使用斜线(/
)来分隔资源和子资源。 要允许某主体读取 pods
同时访问这些 Pod 的 log
子资源,你可以这么写
1 2 3 4 5 6 7 8 9 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: pod-and-pod-logs-reader rules: - apiGroups: ["" ] resources: ["pods" , "pods/log" ] verbs: ["get" , "list" ]
需要指定某个具体的资源可以这样写
1 2 3 4 5 6 7 8 9 10 11 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: default name: configmap-updater rules: - apiGroups: ["" ] resources: ["configmaps" ] resourceNames: ["my-configmap" ] verbs: ["update" , "get" ]
表示可以对名称为my-configmap的ConfigMap进行修改和获取的操作
verbs可能的值有
create
get
delete
list
update
edit
watch
exec
角色绑定 RoleBinding
角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干 主体 (用户、组或服务账户)的列表和对这些主体所获得的角色的引用。 RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。
一个 RoleBinding 可以引用同一的名字空间中的任何 Role。 或者,一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。 如果你希望将某 ClusterRole 绑定到集群中所有名字空间,你要使用 ClusterRoleBinding。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: default subjects: - kind: User name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding 1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: read-secrets-global subjects: - kind: Group name: manager apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
参数说明 这里的subjects指的就是绑定的主体,kind可以是User,Group,ServiceAccount。name表示该对象的名称,apiGroup表示api组,一个角色定义可以绑定多个主体
一个比较完整的例子 创建ServiceAccount 1 2 3 4 5 6 --- apiVersion: v1 kind: ServiceAccount metadata: name: test-server-account namespace: test
赋予权限 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 --- kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: test-role namespace: test rules: - apiGroups: ["" , "extensions" , "apps" ] resources: ["*" ] verbs: ["*" ] - apiGroups: ["batch" ] resources: - jobs - cronjobs verbs: ["*" ] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: test-rolebinding namespace: test subjects: - kind: ServiceAccount name: test-server-account namespace: test roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: test-role --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: test-clusterrole namespace: test rules: - apiGroups: ["" ] resources: ["nodes" ,"pods" ] verbs: ["list" ] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: test-clusterrolebinding namespace: test subjects: - kind: ServiceAccount name: test-server-account namespace: test roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: test-clusterrole
在这个例子中我创建了一个Role名为test-role,具有对test命名空间的所有权限,一个ClusterRole名为test-clusterrole,对于集群里的nodes和pods只有查看的权限,然后把这两个权限都和ServiceAccount名称为test-server-account的用户进行绑定,所以test-server-account这个用户便有了上面两个角色所具有的权限,可以生成一下kubeconfig来测试一下权限
生成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 27 28 29 30 31 32 33 34 35 server=$1 account=test-server-account namespace=test user=test-server-account context_name=test-context cluster_name=test-cluster name=$(kubectl get sa/$account -n $namespace -o jsonpath='{.secrets[0].name}' ) ca=$(kubectl get secret/$name -n $namespace -o jsonpath='{.data.ca\.crt}' ) token=$(kubectl get secret/$name -n $namespace -o jsonpath='{.data.token}' | base64 --decode) if [ ! -d "config" ];then mkdir config fi echo "apiVersion: v1 kind: Config clusters: - name: $cluster_name cluster: certificate-authority-data: ${ca} server: ${server} contexts: - name: $context_name context: cluster: $cluster_name user: $user current-context: $context_name users: - name: $user user: token: ${token} " > config/test.kubeconfig
会在当前目录下创建一个config文件,这里需要传入k8s的master的apiservice的地址,
可以使用kubectl cluster-info
查看,也可以查看~/.kube/config
文件(注:如果使用rancher的rke,使用另外一个context的地址)
这里我脚本保存在generate.sh
中,master的地址为https://172.17.5.6:6443
执行命令
1 sh generate.sh https://172.17.5.6:6443
使用
1 kubectl get sa --kubeconfig config/test.kubeconfig
会提示Error from server (Forbidden): serviceaccounts is forbidden....
1 kubectl get node --kubeconfig config/test.kubeconfig
而执行会返回节点列表
原理 k8s中创建了ServiceAccount之后会生成一个Secret用于鉴权,可以使用
1 kubectl get sa/test-server-account -o yaml
查看该ServiceAccount对应的Secret的名称
根据这个名称去获取对应Secret的访问token和ca信息,然后将这些信息按照kubeconfig文件的格式输出到文件,这种认证方式基于Service Account Tokens
来认证的
参考:
https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/
https://www.cnblogs.com/zjz20/p/13182839.html