17、Kubernetes授权RBAC策略
ServiceAccount
利用配置清单创建SA
Requests Attributes
Kubernetes内建授权插件
RBAC
Kubernetes支持的操作(Determine the Request Verb)
要点
作用域
查看Kubernetes的API群组
简单示例
Role示例
ClusterRole示例
交叉授权
Kubernetes内建Cluster
总结
Dashborad示例
利用创建是ServiceAccount的token创建一个kubeconfig文件用于dashboard登录
总结
Role join Rolebinding
ClusterRole join ClusterRolebinding
ClusterRole join Rolebinding
利用配置清单创建SA
Requests Attributes
Kubernetes内建授权插件
RBAC
Kubernetes支持的操作(Determine the Request Verb)
要点
作用域
查看Kubernetes的API群组
简单示例
Role示例
ClusterRole示例
交叉授权
Kubernetes内建Cluster
总结
Dashborad示例
利用创建是ServiceAccount的token创建一个kubeconfig文件用于dashboard登录
总结
Role join Rolebinding
ClusterRole join ClusterRolebinding
ClusterRole join Rolebinding
ServiceAccount
Kubernetes之上的认证用户有两种第一种是常规用户UserAccount,第二种是ServiceAccount,对于ServiceAccount指的是将来在Kubernetes之上的某一个Pod,甚至在Kubernetes之外的运行的某一守护进程,如果需要在必要的时候访问Kubernetes接入APIServer也应该进行认证,此时认证用户帐号是什么以及认证信息是什么,通常应该通过ServiceAccount并结合ServiceAccount当中的Security来完成认证信息的提供;
每一个ServiceAccount的定义方式很简单,简称为SA,在创建SA资源的时候我们可以指定metadata.name来指定该SA的名称,metadata.namespace来指定该ServiceAccount所属的namespace,当前的用户的认证信息是什么则需要靠secrets来提供,这个secrets可以不用非得是tls帐号密码,因为我们的证书和私钥在secrets当中,如果要定义为tls类型的,那是用于ssl通信的,而不是用于认证的,因此这里的secrets不能使用secret创建时的tls类型,而应该使用generic类型的证书,不过呢,在我们创建ServiceAccount是完全不必要自己去定义secerts的,因为我们在创建ServiceAccount帐号时,Kubernetes会自动给我们生成一个secerts,这个secrets保存了相应用户的认证信息,认证并不关键,创建secert的目标不是为了认证,认证代表不了这个用户能做什么,因此直接帮我们生成了认证,让客户端拿着这个密钥可以正常认证通过,关键在于授权,也就是管理员为这个ServiceAccount绑定了什么权限,那么以这个用户运行的Pod或守护进程也相应的拥有什么权限,因此secerts我们不用自己创建它能够自动生成的;
[root@node1 ~]# kubectl explain serviceaccount.secrets
利用配置清单创建SA
[root@node1 ~]# cat sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: cce
namespace: default
[root@node1 ~]# kubectl apply -f sa.yaml
[root@node1 ~]# kubectl get sa
NAME SECRETS AGE
cce 1 17s
default 1 29d
[root@node1 ~]# kubectl describe sa cce
Name: cce
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"cce","namespace":"default"}}
Image pull secrets: <none>
Mountable secrets: cce-token-4sj5m
Tokens: cce-token-4sj5m # 可以看出,当我们创建了一个ServiceAccount之后Kubernetes会自动为我们创建一个Token,无需去自建一个secrets
Events: <none>
Requests Attributes
Kubernetes是基于http或https协议工作的,因此其对应的操作请求,无非就是增删改查,这些增删改查都被直接映射成了http协议的get、put、delete等操作,因此在每一个Kubernetes的相关请求当中,通常这个请求会包含类似以下的信息;
user:这个请求者的身份;
group:这个请求者所属的组;
extra:额外的属性信息;
Resource:指定使用哪个Kind资源;
Subresource:有些资源还有子资源;
API:也就是我们的Kubernetes标准资源属于哪一个API群组下面的那个API;
API:api群组;
Namespace:指定名称空间;
Request path:相对于我们API来讲,就是请求的URL路径,这个URL其实就是Resource的标识方式;
HTTP request verb:HTTP请求方法,GET、DELETE...;
API request verb:向Kubernetes API的请求方法,比如get、list、create、update、patch、watch、proxy、redirect、delete以及deletecollection;
Kubernetes内建授权插件
Node:专用的授权插件,根据Pod对象调度的结果为Nde进行授权,Node是不具有管理和操作Pod权限的,一旦调度器调度到这个Pod跑在某一Pod,那么这个时候就必须为这个Node授权能够访问Pod的相关定义,这是自动完成的;
ABAC:基于属性的访问控制,我们授权就是指一个用户能操作哪个资源的哪个字段,因为属性就是指字段之意,在字段级别做控制,1.6之前的版本使用;
RBAC:基于角色的访问控制,事先定义好角色,直接将权限赋予给角色,只要用户属于这个角色也就有该赋予的权限;
Webhook:web钩子,其实也就是一个http的回调函数,一般而言就是某一个http上的资源发生变化时,能够发起触发,然后做出相应的操作;
RBAC
对于用户授权来讲,对于Kubernetes1.8版本之后强制生效RBAC,任何人的操作必须在RBAC中有明确定义,如果没有定义,就没有权限,而匿名用户默认在RBAC中没有权限,包括认证进来的用户也只有极少数的权限,使用rbac.authorization.k8s.io API驱动授权决策,并支持动态配置,在使用kubadm部署的集群里面查看/etc/kubernetes/manifests/kube-apiserver.yaml该文件就可以查看到默认启用的授权插件;
说白了,RABC出现的原因是serviceaccount只管认证,不管权限,也就是说默认情况下什么都有;
Kubernetes支持的操作(Determine the Request Verb)
为了实现RBAC,需要有用户,这个用户账号有两种,我们称之为Subjects主语,第一种是UserAccount,第二种是ServiceAccount,这就是我们RBAC当中可以拿来当主语的东西;
第二个我们称之为Objects宾语,叫资源,在Kubernetes上能够被操作的资源有三类,第一类,我们叫做Resources,比如Pod,Deployment这都是资源,第二类叫做子资源SubResouces,比如Pod的logs或者status或者URL类型的非对象型资源;
第三种我们称之为Role和RoleBinding,在Role当中我们定义能够对哪个或哪些资源定义哪些操作,比如允许用户get、put在集群上的deployment资源,如果需要某个用户来扮演这个角色,那我们就需要使用RoleBinding,从而使得让Subjects拥有Role的权限,Role还分为Role和ClusterRole,集群级别和namespace级别,RoleBinding还分为RoleBinding和ClusterRoleBinding,将Role绑定集群级别和namespace;
要点
在Kubernetes之上分两种资源,集群级别,名称空间级别,所以Role还分为Role和ClusterRole,分别赋予不同级别的操作权限,如果定义集群级别的资源,比如pv,namespace或者node等,名称空间级别的Pod,Controller,Service等,他们分别用于完成不同级别的资源;
还有一种情况ClusterRole本应该包含ClusterRole,但是它也可以包含Role,首先集群级别的角色并不是只能操作集群级别在资源,而是能够操作集群范围的资源,集群范围包含namespace,当然有一点是确定的名称空间级别资源不能包含集群级别的资源,所以ClusterRole角色的权限可以施加于namespacce级别的资源也可以施加于集群级别的资源,因此RoleBinding还能够把Role绑定到ClusterRole,因为如果有一个ClusterRole需要去创建Pod,那么就需要赋予ClusterRole有namespace级别的权限,因为集群级别的namespace就是所有的namespace,也就是说允许在所有的namespace创建资源,那么此时如果使用RoleBinding绑定到一个ClusterRole,那也就是说把一个用户在一个名称空间上绑定到了ClusterRole,那么又因为Role是namespace级别的资源,虽然Role有了指定的ClusterRole的权限,但是Role是namespace级别的资源所以即使它的权限最大也之能在这个namespace内部,主要作用还是为了实现权限统一定义,在全局模式下定义一个组,让用户加入进来,那么就有了相应的权限了,无需每次都重新定义一个Role;
所谓的授权就是让Subjects可以操作Objects而已,但是他们不能直接产生关联关系,我们需要一个Role这个中间桥建立关联,这样的好处是,将来我们做权限变更只需要修改Role即可,不用动用户的信息,就能完成权限的变动,实现动态授权并实时生效;
作用域
Role:Role对象只能用于授予对某一namespace中资源的访问权限,以下示例表示在“default” namespace中定义一个Role对象,用于授予对资源pods的读访问权限,绑定到该Role的用户则具有get/watch/list pod资源的权限;
ClusterRole:ClusterRole对象可以授予整个集群范围内资源访问权限, 也可以对以下几种资源的授予访问权限;
查看Kubernetes的API群组
为了更容易对API进行扩展,Kubemetes 使用API Groups (API组)进行标识。APIGroups 以及REST URL中的路径进行定义。当前支持两类API groups;
1、Core Groups (核心组),也可以称为Legacy Groups,该组的REST路径位于/api/v1, 作为 Kubernetes 最核心的 API,它是没有“组”的概念,例如 ”vl“,在资源对象的定义中表示为”apiVersion: v1“;
2、具有分组信息的API,以/apis/$GROUP_NAME/$VERSIONURL路径进行标识,在资源对象的定义中表示为apiVersion: $GROUP_NAME/$VERSION(例如,apiVersion: batch/v1);
当API群组为空时,说明就是核心API群组,此时我们在创建Role或者Cluster的时候只需要给定一个空字符串即可;
简单示例
apiVersion: v1
kind: Namespace
metadata:
name: auth
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cce
namespace: auth # 表示允许操作的namespace
rules:
- apiGroups: [""] # ""表示core API group
resources: ["pods","pods/log"] # 允许对API群组里面哪些资源进行操作
verbs: ["get","list","watch"] # 可以通过get查看指定资源,list表示可以列出同一类型的所有资源,watch表示可以使用-w去监控资源变动
Role示例
这里的role不是一个user,user在证书的CN里面,role键名之意角色,创建一个role,给定部分权限,允许读取default名称空间的资源;
# 创建一个role
[root@node1 ~]# cat role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: resource-reader
namespace: default
rules:
- apiGroups: [""] # ""表示core API group
resources: ["pods","pods/log","services"] # 表示允许操作的资源
verbs: ["get","list","watch"] # 表示允许执行的操作,get单个,list所有
[root@node1 ~]# kubectl apply -f role.yaml
[root@node1 ~]# kubectl get role
NAME AGE
resource-reader 8m30s
# 创建rolebinding将指定用户绑定到上面的角色
[root@node1 ~]# cat rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cce-resource-reader
namespace: default
subjects:
- kind: User # User或者Group或者ServiceAccount,如果是ServiceAccount还需要定义一个namespace字段
name: cce # 用户名或者组名或者服务名
apiGroup: rbac.authorization.k8s.io # 对于ServiceAccount可以是空,对于普通用户和组默认是rbac.authorization.k8s.io
roleRef:
kind: Role # Role或者ClusterRole
name: resource-reader # 引用role资源的子资源名称
apiGroup: rbac.authorization.k8s.io # 我们创建Role的时候使用的apigroup,也就是上面的role资源数据哪个API群组
[root@node1 ~]# kubectl apply -f rolebinding.yaml
[root@node1 ~]# kubectl get rolebindings
NAME AGE
cce-resource-reader 44s
# 创建用户,新建一个私钥
[root@node1 ~]# openssl genrsa -out cce.key 2048
# 为证书生成一个证书签署请求,并且使用kubernetes的CA来签署
[root@node1 ~]# openssl req -new -key cce.key -out cce.csr -subj "/CN=cce/O=kubernetes"
# 利用kubernetes的CA来签署我们的证书
[root@node1 ~]# openssl x509 -req -in cce.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out cce.crt -days 36500
[root@node1 ~]# mkdir /etc/kubernetes/cce
[root@node1 ~]# mv cce.crt cce.csr cce.key /etc/kubernetes/cce/
# 创建一个新的kubeconfig文件
[root@node1 ~]# kubectl config set-cluster cce-cluster --server=https://172.16.1.2:6443 --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/etc/kubernetes/cce.conf
# 设定用户配置信息
[root@node1 ~]# kubectl config set-credentials cce --client-certificate=/etc/kubernetes/cce/cce.crt --client-key=/etc/kubernetes/cce/cce.key --username=cce --kubeconfig=/etc/kubernetes/cce.conf --embed-certs=true
# 将user和cluster组合起来形成一个context
[root@node1 ~]# kubectl config set-context context-cce --cluster=cce-cluster --user=cce --kubeconfig=/etc/kubernetes/cce.conf
# 指定默认使用的context
[root@node1 ~]# kubectl config use-context --kubeconfig=/etc/kubernetes/cce.conf context-cce
# 测试是否能够读取service
[root@node1 ~]# kubectl get service --kubeconfig=/etc/kubernetes/cce.conf
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 30d
# 测试是否能读取deployment
[root@node1 ~]# kubectl get deployments.apps --kubeconfig=/etc/kubernetes/cce.conf
Error from server (Forbidden): deployments.apps is forbidden: User "cce" cannot list resource "deployments" in API group "apps" in the namespace "default" # 提示权限被拒绝
# 增加deployments权限
[root@node1 ~]# cat role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: resource-reader
namespace: default
rules:
- apiGroups: ["*"] # * 表示所有api群组
resources: ["pods","pods/log","services","namespaces","deployments"] # 只允许操作哪些资源
verbs: ["get","list","watch"] # 只运行对资源进行何种操作
[root@node1 ~]# kubectl apply -f role.yaml
# 测试权限
[root@node1 ~]# kubectl get deployments.apps --kubeconfig=/etc/kubernetes/cce.conf
No resources found in default namespace.
ClusterRole示例
创建一个ClusterRole允许访问集群级别的资源,集群级别权限也就是最大的,不局限于namespace,也就是说权限再不受namespace的控制,比如授予了一个list权限,那也就可以查看整个集群所有的namespace,不局限于namespace,它和Role的区别也仅仅是namespace;
# 创建一个ClusterRole
[root@node1 ~]# cat clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-resource-reader
# namespace: default 集群级别的角色不需要namespace
rules:
- apiGroups: ["*"] # ""表示core API group
resources: ["pods","pods/log","services","namespaces","deployments"]
verbs: ["get","list","watch"]
[root@node1 ~]# kubectl get clusterrole cluster-resource-reader
NAME AGE
cluster-resource-reader 3m2s
# 创建一个ClusterRoleBinding
[root@node1 ~]# cat clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cce-cluster-resource-reader
# namespace: default 集群级别的角色不需要namespace
subjects:
- kind: User
name: cce
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole # 这里绑定的也不再是Role而是ClusterRole
name: cluster-resource-reader
apiGroup: rbac.authorization.k8s.io
[root@node1 ~]# kubectl get clusterrolebindings.rbac.authorization.k8s.io cce-cluster-resource-reader
NAME AGE
cce-cluster-resource-reader 3m24s
# 测试权限
[root@node1 ~]# kubectl get pods -n kube-system --kubeconfig=/etc/kubernetes/cce.conf
NAME READY STATUS RESTARTS AGE
coredns-5644d7b6d9-ngnpl 1/1 Running 1 30d
coredns-5644d7b6d9-tg25q 1/1 Running 1 30d
交叉授权
让一个Role绑定ClusterRolebinding,因为创建Role的时候需要指定namespace,所以虽然绑定的是ClusterRoleBinding,但是它只能操作特定名称空间集群级别的资源;
# ClusterRole不变
[root@node1 ~]# cat clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-resource-reader
# namespace: default 集群级别的角色不需要namespace
rules:
- apiGroups: ["*"] # ""表示core API group
resources: ["pods","pods/log","services","namespaces","deployments"]
verbs: ["get","list","watch"]
[root@node1 ~]# kubectl get clusterrole cluster-resource-reader
NAME AGE
cluster-resource-reader 3m2s
# 创建一个RoleBinding,将用户绑定到ClusterRole,Role是名称空间级别,所以即使绑定了ClusterRole那也只能在Role允许的名称空间级别操作
[root@node1 ~]# cat cce-robing.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding # 指定为RoleBinding
metadata:
name: cce-resource-reader
namespace: default # 指定允许的namespace
subjects:
- kind: User
name: cce
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole # 绑定类型为ClusterRole
name: cluster-resource-reader
apiGroup: rbac.authorization.k8s.io
[root@node1 ~]# kubectl get rolebindings.rbac.authorization.k8s.io cce-resource-reader
NAME AGE
cce-resource-reader 3m35s
# 测试权限
[root@node1 ~]# kubectl get pods -n default --kubeconfig=/etc/kubernetes/cce.conf # default空间没问题
No resources found in default namespace.
# 换一个名称空间测试
[root@node1 ~]# kubectl get pods -n kube-system --kubeconfig=/etc/kubernetes/cce.conf # 测试权限不足
Error from server (Forbidden): pods is forbidden: User "cce" cannot list resource "pods" in API group "" in the namespace "kube-system"
Kubernetes内建Cluster
cluster-admin:超级管理员权限,拥有整个集群的所有权限;
admin:假如需要授权一个用户对某个名称空间具有管理员权限,那么就可以使用rolebinding绑定到这个admin的集群角色,自动成为该名称空间的管理员;
edit:假如需要授权一个用户对某个名称空间具有修改权限,那么就可以使用rolebinding绑定到这个edit的集群角色,然后就可以修改该名称空间的资源了;
view:假如需要授权一个用户对某个名称空间具有查看你权限,那么就可以使用rolebinding绑定到这个view的集群角色,然后就可以查看该名称空间的资源了;
总结
如果期望一个用户拥有指定名称空间的管理员权限,那么使用rolebing绑定到内建的admin集群角色即可,如果期望一个用户成为整个集群的管理员权限,那么使用clusterrolebinding绑定到admin集群角色即可;
# 绑定之前先测试是否有权限
[root@node1 ~]# kubectl get pods -n default --kubeconfig=/etc/kubernetes/cce.conf
Error from server (Forbidden): pods is forbidden: User "cce" cannot list resource "pods" in API group "" in the namespace "default" # 测试无权限
# 手动将cce用户使用clusterrolebinding绑定到cluster-admin,这个时候就拥有了整个集群的所有管理权限
[root@node1 ~]# kubectl create clusterrolebinding cluster-role --clusterrole=cluster-admin --user=cce
clusterrolebinding.rbac.authorization.k8s.io/cluster-role created
# 测试权限
[root@node1 ~]# kubectl get pods -n default --kubeconfig=/etc/kubernetes/cce.conf
No resources found in default namespace. # 测试通过
# 绑定之前先测试权限
[root@node1 ~]# kubectl get pods --kubeconfig=/etc/kubernetes/cce.conf
Error from server (Forbidden): pods is forbidden: User "cce" cannot list resource "pods" in API group "" in the namespace "default"
# 手动将cce用户使用rolebinding绑定到cluster-admin,这个时候就拥有了指定集群的所有管理权限
[root@node1 ~]# kubectl create rolebinding role --clusterrole=admin --user=cce
rolebinding.rbac.authorization.k8s.io/role created
# 测试权限
[root@node1 ~]# kubectl get pods --kubeconfig=/etc/kubernetes/cce.conf
No resources found in default namespace. # 权限测试通过
Dashborad示例
基于WEB的用户图形界面,基于这个图形界面可以看到Pod,Pod控制器等相关资源,必要时也可以直接把yaml格式的配置清单贴进配置界面进行应用,这是一个用户访问的接口,所以我们就得静心组织Dashboard的用户权限,Dashboard有一特点,它的多用户的,也就意味着你可以用不同权限的用户来进行不同的资源管理,Dashboard自己不会做任何用户认证,它仅仅将认证请求代理至Kubernetes,也就意味着所有的用户得是Kubernetes的用户,用户权限也是在Kubernetes之上所拥有权限;
这里的用户帐号很独特,输入用户帐号之后不是用户直接访问Kubernetes的,它需要代理给Dashboard,Dashboard自己是一个Pod,任何Pod要访问Kubernetes都需要使用ServiceAccount,因此Dashboard使用的帐号是ServiceAccount,不能是普通用户或者是常规用户帐号;
我们应该把Dashboard利用Service的NodePort类型或者使用ingress开放至集群外部;
dashboard Github:https://github.com/kubernetes/dashboard
因为Kubernetes比较高1.16所以默认的dashboard不兼容查看说明:https://github.com/kubernetes/dashboard/blob/93474e53b9ce5a1de0acba93c5aff6295d91dd19/docs/user/installation.md
# 创建一个私钥,用于dashboard的ssl证书
[root@node1 ~]# openssl genrsa -out dashboard.key 2048
# 创建一个证书签署请求
[root@node1 ~]# openssl req -new -key dashboard.key -out dashboard.csr -subj "/O=cce/CN=dashboard"
# 利用kubernetes的CA来签署我们的证书
[root@node1 ~]# openssl x509 -req -in dashboard.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out dashboard.crt -days 36500
[root@node1 ~]# mkdir /etc/kubernetes/dashboard
[root@node1 ~]# mv dashboard.csr dashboard.crt dashboard.key /etc/kubernetes/dashboard/
# 基于自建证书和私钥创建一个secert,从而被我们的dashboard所加载,用它来作为dashboard的ssl证书
[root@node1 ~]# kubectl create namespace kubernetes-dashboard
[root@node1 ~]# kubectl create secret generic kubernetes-dashboard-certs -n kubernetes-dashboard --from-file=dashboard.crt=/etc/kubernetes/dashboard/dashboard.crt --from-file=dashboard.key=/etc/kubernetes/dashboard/dashboard.key # 因为配置清单默认type为Opaque而不是tls所有要使用generic类型
[root@node1 ~]# kubectl get -n kubernetes-dashboardsecrets kubernetes-dashboard-certs -o yaml
apiVersion: v1
data:
dashboard.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN0VENDQVowQ0NRRENkUER3VjBvb3RUQU5CZ2txaGtpRzl3MEJBUXNGQURBVk1STXdFUVlEVlFRREV3cHIKZFdKbGNtNWxkR1Z6TUNBWERURTVNVEl3TnpBNE1UWXdOMW9ZRHpJeE1Ua3hNVEV6TURneE5qQTNXakFpTVF3dwpDZ1lEVlFRS0RBTmpZMlV4RWpBUUJnTlZCQU1NQ1dSaGMyaGliM0poWkRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCCkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUsyR3p4cGpKTFRSZUhla1dWRm1iRXhLY3ZaMFFpYmxRdFpvR05mNnRlbTcKYzFkK1RSRWk0bGFkZWV0TzNVUXprRVlpNmFYTHNadnRCclFTRUd5SG80Z3hhaWMzTVM0eDFPc1RPOHljOUxubApXdjFodDgwYzFWdHRuUDl1Tmo4dGsrc0F6TnhkNDhJNjJFUUw0VzhvSUpwR2wyWVQxbTU4Z2x6c2ozemkxVHJ3ClZ6VHhOaUNwOUdKdjY3SVNmQUxsQXFzeS9IRWNGSTlXcllIS001b2hIcDhGaEgyOTNBWC9zTGhRZGhEcVR6ekwKc1l5WEUra2dkclZaN1Jic2gyNjYxZDBwR2NzMUpHSVBGclhnVGFFeTNyY2w1YWYydGhXbUY3Mi9pZFFMcmpSagpJQUlxZW52ZWVUYWFhdStpWnpXMG05WngwOHFIeGlIL1FXckRKZ1Fwbm1NQ0F3RUFBVEFOQmdrcWhraUc5dzBCCkFRc0ZBQU9DQVFFQVRoSHpYSHBXMXJIQjJCOTNUdndQcHB0Q1JDTDZVdVVwaHd3bWk2allOVmY2ZFBZMjRuMksKUWxmOUh5RStXM1FSVHcycld1OFB6UnRTNGdOR2k5MlpUbnBZQS95TmdtZVFGY3U1T0NUSHkvb1JFdmNDN2wyNgpMN3J5c0E3VmJjR3llTml4eUlUVmpZNXJjTE02Y21SeHZRZDNCcEZhaEZudG1PaEE2N1c5NnJDenZQYW5EK2NCCkpFTzFyQ1B6Umw3dDlPY21kSUg0SythRndhendDNFRrN291VjExVCtvYWJRYWdPZlcrbnVYNlNrR3JoUVErR0wKdU1DWWt5RWhzc2JpL1Z0QklYMlBtTUw2eHJRT3VTQ0M1eEpuaklHaWJVYStFUEJSa1drc1dYZzJzYjRtZ3VhRgpTQzV4MnRQbjZTSVZUWHd6S2lyOUE1NC9EQklJZlVJb1pRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
dashboard.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBclliUEdtTWt0TkY0ZDZSWlVXWnNURXB5OW5SQ0p1VkMxbWdZMS9xMTZidHpWMzVOCkVTTGlWcDE1NjA3ZFJET1FSaUxwcGN1eG0rMEd0QklRYkllamlERnFKemN4TGpIVTZ4TTd6SnowdWVWYS9XRzMKelJ6VlcyMmMvMjQyUHkyVDZ3RE0zRjNqd2pyWVJBdmhieWdnbWthWFpoUFdibnlDWE95UGZPTFZPdkJYTlBFMgpJS24wWW0vcnNoSjhBdVVDcXpMOGNSd1VqMWF0Z2Nvem1pRWVud1dFZmIzY0JmK3d1RkIyRU9wUFBNdXhqSmNUCjZTQjJ0Vm50RnV5SGJyclYzU2taeXpVa1lnOFd0ZUJOb1RMZXR5WGxwL2EyRmFZWHZiK0oxQXV1TkdNZ0FpcDYKZTk1NU5wcHE3NkpuTmJTYjFuSFR5b2ZHSWY5QmFzTW1CQ21lWXdJREFRQUJBb0lCQVFDVnloVGtka2l0UFZSOApFb1ozV2E2S2ZJbVliT3Jkb0hGOW13WTNDZGdXRnhXTnBSenBlZTlmVFRoOUF1ckZnSzA5bmMyS3JMWjRIcmIyCm9kRkRuaUp2NGhmOEdneCtEODMzemZhRXZjZ1M0QVVYVEU3WTQ5Yll3Vm9RdEJabm12UmdtNlE3WldEQnZRSUsKV3ljU1NOVTcxMHZCZGNaWVFXcFd4RzFvSkhaa0ZMK1NEV3pNcUtxNy9VZ0RoeWthTlBRNHdhWjRUVFFaMDdCdgpnd2h4RnN5MWZKeDBDaWV4NGZCa1JudURVa3JTYVV1Tlduekp2TVBXK2ZjOVJ5ZXByS2VWQXVQZmRReDhkYmN1CnhDa2tlZFFJeERwajZPTTFra2Q1UkZVUVFvNERrS0xQdmtzUENJcy9hMmhIbnFJcmxyb3BzTXg1TFVvNS84T1kKZFQvN1psQ0JBb0dCQU5MdW9yd1p1b3NWcjAxaTVxUDh4Vkp4bWJZazJPY0NhRUN6aWkrQlFPbHRjZ2l6ZnlRSQpqQ1ZnNWJrNmU1ak1YUXVtRWUwWkUxN1J0UStJQ3RFVDdHYURVckRxMkNTdW9JbENXTGVudEdxRmg1a2dOODFSCm5FeG9VVGJxOWtOdEIwbmZRU3lsc0RKZzFMdTFDQzhkMExYTnFJNExNKzlzeHYwcjRPemZpUTV4QW9HQkFOS2EKTXdwL20xWHljb05vWTdNOG9sam1HL2RRcmpUUU5vdnNzclA3ZThhNUYwMllBTjZRRDRibGtWMmpJR1lXSUd6cwoySjk0eDdBSElhM0IzR0xzbTJ2UVVIcEhYdlEzMlBnTGZUSkZ1S0NzaFpPNFhpb1ArNHRRS2h3Q0MrTENjUUR4CmI5RVVhY2dxWmxBRjRTOHlIVUNOL3JKQXZZemNGMk5sYXFFSjlFd1RBb0dCQUxVR2t1bG1GMS9JZzRPaHpwbU0KbFBoMWdGcis4cHdIeDl0SGV0L2NTUTVNbktKMUVqZWxra2wrQ0luWWREeWxuM0VnM0ora2RxaFl4OUNGaStyMQo4MXZqZHJOWlNaanB1ZU15NnBycnRmMzVqVzlRWkRPMHg3UVhqeVBYc1BRYS9UZGNBRDVHRUpxYjJkY2l2ZHhaCjlVWWlNM2Q4aTl6K2VTVE1aS1JHRUFVeEFvR0FhNkh2TUJCamZSdDV0dnNrNlRlMTZTVkJhYlpNTWlXdm12ZVAKcFRpRDI5NUFzS0ZjNEdKVDdTZHFrYWFMS21Gb2xRSysrMUdwREtlNGFLdEpUUzJMaVNCZjRQNlU0cytnRGJVaAplUTMwKy9qd0U3MElNd3NVRGZFY2RFLy9ieGJjMWhTT2h4YWRzWFVwOFAvd1JFU2llcG1YYjlaeWlZajZVd3hECjRLWEx1dzBDZ1lBelR0K2djQ0NncUY1WjdXendvWHNBNWNrZ1JWL0l4K1NwYjNncFhJdUIrVmZFU1FUWVlESHgKQ3dJbjdyeksxMlFLMFgxMjJiR0JUOXovakNJbkhRU3l0eElXcWJ6SGVYMzRVMll6aDA0czB5Tlk3a0lsTnZNbgpPNlhuRjBCSkNucStuQjFPRUQxVFpYSmRKVytnY3RoclpiQmxDaDI5TWhKM0RURGx2d3VtZmc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
kind: Secret
metadata:
creationTimestamp: "2019-12-07T08:23:42Z"
name: kubernetes-dashboard-certs
namespace: kube-system
resourceVersion: "16125"
selfLink: /api/v1/namespaces/kube-system/secrets/kubernetes-dashboard-certs
uid: 6f94a139-c9f0-4697-b9c0-d4233606a5e8
type: Opaque
# 正式应用之前需要下载镜像,因为k8s.gcr.io的镜像默认是访问不了的,在各个节点执行;
[root@node1 ~]# docker pull kubernetesui/dashboard:v2.0.0-beta5
# 需要修改配置清单里面Service为NodePort
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30443
selector:
k8s-app: kubernetes-dashboard
# 应用配置清单
[root@node1 ~]# kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta5/aio/deploy/recommended.yaml
[root@node1 ~]# kubectl get pods -n kubernetes-dashboard kubernetes-dashboard-6b86b44f87-kqwb7
NAME READY STATUS RESTARTS AGE
kubernetes-dashboard-6b86b44f87-kqwb7 1/1 Running 0 65s
[root@node1 ~]# kubectl get pods -n kubernetes-dashboard kubernetes-dashboard-6b86b44f87-kqwb7 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kubernetes-dashboard-6b86b44f87-kqwb7 1/1 Running 0 118s 10.244.1.9 node2.cce.com <none> <none>
# 创建一个集群级别的ServiceAccount超级用户
[root@node1 ~]# kubectl create serviceaccount dashboard -n kubernetes-dashboard
# 将dashboard和cluster-admin的ClusterRole进行绑定
[root@node1 ~]# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard
# 找到它自动生产的secerts
[root@node1 ~]# kubectl get serviceaccounts -n kubernetes-dashboard dashboard -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2019-12-07T10:03:14Z"
name: dashboard
namespace: kubernetes-dashboard
resourceVersion: "25463"
selfLink: /api/v1/namespaces/kubernetes-dashboard/serviceaccounts/dashboard
uid: ad2622c4-e28a-49d6-8cf8-38aab2947fc7
secrets:
- name: dashboard-token-xxqtw # 自动生产的secerts
# 找到tokens
[root@node1 ~]# kubectl get serviceaccounts -n kubernetes-dashboard dashboard -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2019-12-07T10:03:14Z"
name: dashboard
namespace: kubernetes-dashboard
resourceVersion: "25463"
selfLink: /api/v1/namespaces/kubernetes-dashboard/serviceaccounts/dashboard
uid: ad2622c4-e28a-49d6-8cf8-38aab2947fc7
secrets:
- name: dashboard-token-xxqtw
[root@node1 ~]# kubectl describe -n kubernetes-dashboard secrets dashboard-token-xxqtw
Name: dashboard-token-xxqtw
Namespace: kubernetes-dashboard
Labels: <none>
Annotations: kubernetes.io/service-account.name: dashboard
kubernetes.io/service-account.uid: ad2622c4-e28a-49d6-8cf8-38aab2947fc7
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1025 bytes
namespace: 20 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6Ik50UUxrZWFyWF8xR3hLX25lQ1k1QUdsU3dQcEhZdGlGTEZLanpJLXJIS0EifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtdG9rZW4teHhxdHciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYWQyNjIyYzQtZTI4YS00OWQ2LThjZjgtMzhhYWIyOTQ3ZmM3Iiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmVybmV0ZXMtZGFzaGJvYXJkOmRhc2hib2FyZCJ9.iBjqf2htzkq23QzcwkVQD7jr2-TmDLpsgLwfZYQNs_wiWV8mUPwVGZYun_UXsTt-Iv59bgTexI6JYitHwYbIld0gwMrkSzNYHEZUF-shLxchJVnfHYs3HdES_cVRLWHDWyBOxZYQeFSVfCgtPvF2OJlG6KK9s4m_-yVJaXebQrS1S1MARGtt3w5qnahV99wOzcZQoZr4SEWOFh9kbHWU1ihiz6nOTKkoR3J-fCy8xj834TCDFqA4LZlJswmIjeJtAZTwtn53kO9S1E9d6ETFaC0lwB3reeDuJqdUWRJZ6E9NdjFAZdkezyKqbx_xVldyVhxY8mfVeAnfQ-CmP3lB_Q
# 使用配置清单的方式创建
apiVersion: v1
kind: ServiceAccount
metadata:
name: cce
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cce-clusterrolebinding-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: ""
kind: ServiceAccount
name: cce
namespace: kubernetes-dashboard
利用创建是ServiceAccount的token创建一个kubeconfig文件用于dashboard登录
# 创建一个集群
[root@node1 ~]# kubectl config set-cluster mykube --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=https://172.16.1.2:6443 --kubeconfig=/etc/kubernetes/dashboard.conf
# 利用现有ServiceAccount的token创建kubeconfig文件
[root@node1 ~]# kubectl config set-credentials cce --token=eyJhbGciOiJSUzI1NiIsImtpZCI6Ik50UUxrZWFyWF8xR3hLX25lQ1k1QUdsU3dQcEhZdGlGTEZLanpJLXJIS0EifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjY2UtdG9rZW4tZmdkMjgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiY2NlIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiNThmY2MzNTQtOTc0ZC00NDQ4LThjYjUtZjZjNjk4YzZjZDMwIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmVybmV0ZXMtZGFzaGJvYXJkOmNjZSJ9.Uj9O0rHEnN3sfuAMitVBHR3TeT5vHXuBTccuQMIDPxwv_CYiHO9cbz-oDVJZTQiw91s7J7ch5kqTzPKAGWCwMW4IH2GTnJAu2X1hDi_kenWAEj5jIwADA1OKHD5If0-xatxRWU2EER9JDpiAhat0q8-IFFaBV5k27miQ3ISzUzOnS8JzXcPjU7dBUnhZb3509TnWK5tl6Kq0EK29BqR1zSfEP2_N3-x13b5CZsd6OHVAVvKWRKhanVhNhe0Osp29_GaqLc_D_4hdJfnPHJyprAJoIHqtLaeRi6TP6HIvALr54gxXDH0M7eusZ3CRQPlOrIjVU6kUp8ST6O21stGa7w --kubeconfig=/etc/kubernetes/dashboard.conf
# 设定context 将user和cluster建立关联
[root@node1 ~]# kubectl config set-context dashboard --cluster=mykube --user=cce --kubeconfig=/etc/kubernetes/dashboard.conf
# 设定默认使用的context
[root@node1 ~]# kubectl config use-context --kubeconfig=/etc/kubernetes/dashboard.conf dashboard
# 测试登录成功
总结
Role join Rolebinding
这种搭配主要是为了将一个用户限制在一个namespace级别,最大权限也就只能控制这个namespace级别内部的属于namespace级别的资源,具体是否是namespace级别的资源使用api-resources查看;
ClusterRole join ClusterRolebinding
这种搭配主要是为了控制一个用户在集群级别的资源权限,最大权限也就是最高管理员权限,具体是否是Cluster级别的资源使用api-resources查看;
ClusterRole join Rolebinding
主要作用还是为了实现权限统一定义,在全局模式下定义一个组,让用户加入进来,那么就有了相应的权限了,无需每次都重新定义一个Role;