ServiceAccount & RBAC

简介

Service account 是为了方便 Pod 里面的进程调用 Kubernetes API 或其他外部服务而设计的。它与 User account 不同

  • User account 是为人设计的,而 service account 则是为 Pod 中的进程调用 Kubernetes API 而设计;
  • User account 是跨 namespace 的,而 service account 则是仅局限它所在的 namespace;
  • 每个 namespace 都会自动创建一个 default service account
  • Token controller 检测 service account 的创建,并为它们创建 secret
  • 开启 ServiceAccount Admission Controller 后
    • 每个 Pod 在创建后都会自动设置 spec.*serviceAccount*Name 为 default(除非指定了其他 ServiceAccout)
    • 验证 Pod 引用的 service account 已经存在,否则拒绝创建
    • 如果 Pod 没有指定 ImagePullSecrets,则把 service account 的 ImagePullSecrets 加到 Pod 中
    • 每个 container 启动后都会挂载该 service account 的 token 和 ca.crt/var/run/secrets/kubernetes.io/*serviceaccount*/
[root@k8s-master ~]#  kubectl exec web-0 -it --  ls -l /var/run/secrets/kubernetes.io/serviceaccount/
total 0
lrwxrwxrwx    1 root     root            13 Apr  1 08:34 ca.crt -> ..data/ca.crt
lrwxrwxrwx    1 root     root            16 Apr  1 08:34 namespace -> ..data/namespace
lrwxrwxrwx    1 root     root            12 Apr  1 08:34 token -> ..data/token

创建一个serviceaccount

[root@k8s-master ~]# kubectl create sa admin 
serviceaccount/admin created

查看serviceaccount

[root@k8s-master ~]# kubectl get sa
NAME      SECRETS   AGE
admin     1         37s
default   1         25d
[root@k8s-master ~]# kubectl describe sa admin 
Name:                admin
Namespace:           default
Labels:              
Annotations:         
Image pull secrets:  
Mountable secrets:   admin-token-vcjv6
Tokens:              admin-token-vcjv6
Events:              

创建一个serviceaccount会自动创建一个secret

[root@k8s-master ~]# kubectl get secret
NAME                    TYPE                                  DATA   AGE
admin-token-vcjv6       kubernetes.io/service-account-token   3      11m

RBAC

Kubernetes 从 1.6 开始支持基于角色的访问控制机制(Role-Based Access Control,RBAC),集群管理员可以对用户或服务账号的角色进行更精确的资源访问控制。在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。
Kubernetes 1.6 中的一个亮点时 RBAC 访问控制机制升级到了 beta 版本(版本为 *rbac*.authorization.k8s.io/v1beta1 )。RBAC,基于角色的访问控制机制,是用来管理 kubernetes 集群中资源访问权限的机制。使用 RBAC 可以很方便的更新访问授权策略而不用重启集群。
从 Kubernetes 1.8 开始,RBAC 进入稳定版,其 API 为 *rbac*.authorization.k8s.io/v1
在使用 RBAC 时,只需要在启动 kube-apiserver 时配置 --authorization-mode=*RBAC* 即可。

RBAC VS ABAC

目前 kubernetes 中已经有一系列 l 鉴权机制。鉴权的作用是,决定一个用户是否有权使用 Kubernetes API 做某些事情。它除了会影响 kubectl 等组件之外,还会对一些运行在集群内部并对集群进行操作的软件产生作用,例如使用了 Kubernetes 插件的 Jenkins,或者是利用 Kubernetes API 进行软件部署的 Helm。ABAC 和 RBAC 都能够对访问策略进行配置。

ABAC(Attribute Based Access Control)本来是不错的概念,但是在 Kubernetes 中的实现比较难于管理和理解,而且需要对 Master 所在节点的 SSH 和文件系统权限,而且要使得对授权的变更成功生效,还需要重新启动 API Server。

RBAC 的授权策略可以利用 kubectl 或者 Kubernetes API 直接进行配置。RBAC 可以授权给用户,让用户有权进行授权管理,这样就可以无需接触节点,直接进行授权管理。RBAC 在 Kubernetes 中被映射为 API 资源和操作。

因为 Kubernetes 社区的投入和偏好,相对于 ABAC 而言,RBAC 是更好的选择。

创建私钥
[root@k8s-master pki]# cd /etc/kubernetes/pki/
[root@k8s-master ~]# (umask 077; openssl genrsa -out piaopiao.key 2048)
[root@k8s-master pki]# ll
total 60
-rw-r--r-- 1 root root 1269 Mar 10 14:55 apiserver.crt
-rw-r--r-- 1 root root 1135 Mar 10 14:55 apiserver-etcd-client.crt
-rw------- 1 root root 1679 Mar 10 14:55 apiserver-etcd-client.key
-rw------- 1 root root 1675 Mar 10 14:55 apiserver.key
-rw-r--r-- 1 root root 1143 Mar 10 14:55 apiserver-kubelet-client.crt
-rw------- 1 root root 1679 Mar 10 14:55 apiserver-kubelet-client.key
-rw-r--r-- 1 root root 1066 Mar 10 14:55 ca.crt
-rw------- 1 root root 1675 Mar 10 14:55 ca.key
drwxr-xr-x 2 root root  162 Mar 10 14:55 etcd
-rw-r--r-- 1 root root 1078 Mar 10 14:55 front-proxy-ca.crt
-rw------- 1 root root 1679 Mar 10 14:55 front-proxy-ca.key
-rw-r--r-- 1 root root 1103 Mar 10 14:55 front-proxy-client.crt
-rw------- 1 root root 1679 Mar 10 14:55 front-proxy-client.key
-rw------- 1 root root 1679 Apr  7 10:44 piaopiao.key
-rw------- 1 root root 1675 Mar 10 14:55 sa.key
-rw------- 1 root root  451 Mar 10 14:55 sa.pub

生成证书签署请求&签署证书
[root@k8s-master pki]# openssl req -new -key piaopiao.key -out piaopiao.csr -subj "/CN=xiaofang"
[root@k8s-master pki]# openssl  x509 -req -in piaopiao.csr  -CA ca.crt  -CAkey ca.key -CAcreateserial -out piaopiao.crt -days 365

创建k8s用户
[root@k8s-master pki]# kubectl config set-credentials xiaofang --client-certificate=./piaopiao.crt --client-key=./piaopiao.key --embed-certs=true

添加用户到集群
[root@k8s-master pki]# kubectl config set-context  xiaofang@kubernetes --cluster=kubernetes --user=xiaofang

[root@k8s-master pki]# kubectl config view 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.0.0.11:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:
    cluster: kubernetes
    user: xiaofang
  name: xiaofang@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: xiaofang
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

Role & ClusterRole RoleBinding & ClusterRoleBinding

Role(角色)是一系列权限的集合,例如一个角色可以包含读取 Pod 的权限和列出 Pod 的权限。Role 只能用来给某个特定 namespace 中的资源作鉴权,对多 namespace 和集群级的资源或者是非资源类的 API(如 /healthz)使用 ClusterRole。
RBAC 的 RoleClusterRole 中包含一组代表相关权限的规则。 这些权限是纯粹累加的(不存在拒绝某操作的规则)。

Role 总是用来在某个名字空间 内设置访问权限;在你创建 Role 时,你必须指定该 Role 所属的名字空间。
与之相对,ClusterRole 则是一个集群作用域的资源。这两种资源的名字不同(Role 和 ClusterRole)是因为 Kubernetes 对象要么是名字空间作用域的,要么是集群作用域的, 不可两者兼具。

ClusterRole 有若干用法。你可以用它来:

  1. 定义对某名字空间域对象的访问权限,并将在各个名字空间内完成授权;
  2. 为名字空间作用域的对象设置访问权限,并跨所有名字空间执行授权;
  3. 为集群作用域的资源定义访问权限。
    如果你希望在名字空间内定义角色,应该使用 Role; 如果你希望定义集群范围的角色,应该使用 ClusterRole。
1,Role

一个Role内类型的角色只能访问他所在的namesoace下的资源

创建一个role
1,使用kubectl create创建
[root@k8s-master ~]# kubectl create role app-role --verb=get,list,create,delete  --resource=pods
2,使用yaml创建
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: app-role
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - create
  - delete

查看role
[root@k8s-master ~]# kubectl describe role app-role  
Name:         app-role
Labels:       
Annotations:  
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get list create delete]

使用Rolebinding绑定role
命令创建
[root@k8s-master ~]# kubectl create rolebinding  app-rolebinding --role=app-role --user=xiaofang 
使用yaml创建
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-rolebinding
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: app-role
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xiaofang

查看rolebinding
[root@k8s-master ~]# kubectl describe rolebindings.rbac.authorization.k8s.io app-rolebinding 
Name:         app-rolebinding
Labels:       
Annotations:  
Role:
  Kind:  Role
  Name:  app-role
Subjects:
  Kind  Name      Namespace
  ----  ----      ---------
  User  xiaofang  
验证
[root@k8s-master ~]# kubectl config use-context xiaofang@kubernetes 
Switched to context "xiaofang@kubernetes".
[root@k8s-master ~]# kubectl get pods 
NAME    READY   STATUS        RESTARTS   AGE
web-0   0/1     Terminating   0          5d23h
web-2   0/1     Terminating   0          5d23h
web-4   0/1     Terminating   0          5d23h
[root@k8s-master ~]# kubectl get pods -n kube-system
Error from server (Forbidden): pods is forbidden: User "xiaofang" cannot list resource "pods" in API group "" in the namespace "kube-system"

#这里切换用户后,查看default的名称空间的pod是可以的而查看其他的namespace中是没有权限的

2,clusterrole

创建clusterrole时不能使用名称空间,因为clusterrole属于集群级别资源

创建一个clusterrole

1,命令创建

[root@k8s-master ~]# kubectl create clusterrole app-clusterrole --verb=get,list,watch,create,delete --resource=pods

2,yaml创建

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: app-clusterrole
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
  - create
  - delete

查看clusterrole
[root@k8s-master ~]# kubectl describe clusterrole app-clusterrole 
Name:         app-clusterrole
Labels:       
Annotations:  
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get list watch create delete]

使用clusterrolebinding绑定
命令创建
[root@k8s-master ~]# kubectl create clusterrolebinding app-clusterrolebinding --clusterrole=app-clusterrole --user=xiaofang
yaml创建
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  creationTimestamp: null
  name: app-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: app-clusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xiaofang
查看clusterrolebinding
[root@k8s-master ~]# kubectl get clusterrolebindings.rbac.authorization.k8s.io app-clusterrolebinding 
NAME                     ROLE                          AGE
app-clusterrolebinding   ClusterRole/app-clusterrole   113s
[root@k8s-master ~]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io app-clusterrolebinding 
Name:         app-clusterrolebinding
Labels:       
Annotations:  
Role:
 Kind:  ClusterRole
 Name:  app-clusterrole
Subjects:
 Kind  Name      Namespace
 ----  ----      ---------
 User  xiaofang 
切换用户验证
[root@k8s-master ~]# kubectl config use-context xiaofang@kubernetes 
Switched to context "xiaofang@kubernetes".
[root@k8s-master ~]# kubectl get pods 
NAME    READY   STATUS        RESTARTS   AGE
web-0   0/1     Terminating   0          6d
web-2   0/1     Terminating   0          6d
web-4   0/1     Terminating   0          6d

[root@k8s-master ~]# kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-6d56c8448f-htht4             1/1     Running   4          28d
coredns-6d56c8448f-m78cl             1/1     Running   4          28d
etcd-k8s-master                      1/1     Running   4          28d
kube-apiserver-k8s-master            1/1     Running   8          28d
kube-controller-manager-k8s-master   1/1     Running   28         28d
kube-flannel-ds-kvzz6                1/1     Running   4          28d
kube-flannel-ds-rwlhk                1/1     Running   8          28d
kube-flannel-ds-x6hdm                1/1     Running   15         28d
kube-proxy-7g68v                     1/1     Running   10         28d
kube-proxy-9zxx6                     1/1     Running   7          28d
kube-proxy-mnqql                     1/1     Running   4          28d
kube-scheduler-k8s-master            1/1     Running   24         28d

#验证现实可以查看其他namespace中的pods,clusterrolebinding不限制在单个的namespace中,是授权在整个集群范围类

使用Rolebinding绑定ClusterRole

使用Rolebinding绑定ClusterRole这种方式会让clusterrole的权限降级,绑定后clusterrole只能对rolebinding的namespace中的资源进行操作,

使用命令创建
[root@k8s-master ~]# kubectl create rolebinding rolebinding-cluster --clusterrole=app-clusterrole --user=xiaofang 

使用yaml创建
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: rolebinding-cluster
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: app-clusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xiaofang
查看rolebinding
[root@k8s-master ~]# kubectl describe rolebindings.rbac.authorization.k8s.io rolebinding-cluster 
Name:         rolebinding-cluster
Labels:       
Annotations:  
Role:
  Kind:  ClusterRole
  Name:  app-clusterrole
Subjects:
  Kind  Name      Namespace
  ----  ----      ---------
  User  xiaofang 
切换用户验证
[root@k8s-master ~]# kubectl config use-context xiaofang@kubernetes 
Switched to context "xiaofang@kubernetes".
[root@k8s-master ~]# kubectl get pods 
NAME    READY   STATUS        RESTARTS   AGE
web-0   0/1     Terminating   0          6d1h
web-2   0/1     Terminating   0          6d1h
web-4   0/1     Terminating   0          6d1h
[root@k8s-master ~]# kubectl get pods -n kube-system
Error from server (Forbidden): pods is forbidden: User "xiaofang" cannot list resource "pods" in API group "" in the namespace "kube-system",
ps:

如果集群中有多个namespace分配给不同的管理员,但是他们的权限是一样的,那么这样可以先定义一个ClusterRole,然后通过RoleBinding将不同namespace的管理员做绑定,这样可以解决多次定义Role的问题。

你可能感兴趣的:(ServiceAccount & RBAC)