K8S认证、受权与准入控制(RBAC)详解

相关推荐

本文的kubernetes环境:http://www.javashuo.com/article/p-vjmoqwfx-gm.htmlnode

RBAC官方文档:https://kubernetes.io/docs/reference/access-authn-authz/rbac/nginx


前言

  1. RBAC (Role-Based Access Control,基于角色的访问控制)是一种新型、灵活且使用普遍的访问控制机制,它将权限授予“角色”(role)之上,这一点有别于传统访问控制机制中 将权限直接赋予使用者的方式,简单点来讲就是将权限绑定到role中,而后用户和role绑定,这样用户就拥有了和role同样的权限。
  2. 在任何将资源或服务提供给有限使用者的系统上,认证和受权都是两个必不可少的功 能,认证用于身份鉴别,而受权则实现权限分派 。 Kubemetes 以插件化的方式实现了这两种 功能,且分别存在多种可用的插件。 另外,它还支持准入控制机制,用于补充受权机制以实现更精细的访问控制功能 。
  3. API Server 做为 Kubernetes 集群系统的网关,是访问及管理资源对象的惟一人口,全部须要访问集群资源的组件,以及此前使用的 kubectl 命令等都要经由此网关进行集群访问和管理。
  4. RBAC使用rbac.authorization.k8s.io API Group 来实现受权决策,容许管理员经过 Kubernetes API 动态配置策略,要启用RBAC,须要在 apiserver 中添加参数--authorization-mode=RBAC,若是使用的kubeadm安装的集群,都默认开启了RBAC,能够经过查看 Master 节点上 apiserver 的静态Pod定义文件:
    [root@node-01 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml 
    ···
    - --authorization-mode=Node,RBAC
    ···
  5. 若是是二进制的方式搭建的集群,添加这个参数事后,记得要重启 apiserver 服务。

RBAC API资源对象

Kubernetes有一个很基本的特性就是它的全部资源对象都是模型化的 API 对象,容许执行增、删、改、查等操做,好比下面的这下资源:json

  • Pods
  • ConfigMaps
  • Deployments
  • Nodes
  • Secrets
  • Namespaces

上面这些资源对象的可能存在的操做有:api

  • create
  • get
  • delete
  • list
  • update
  • edit
  • watch
  • exec

用户帐户和用户组

Kubernetes 并不会存储由认证插件从客户端请求中提取出的用户及所属组的信息,它们仅仅用于检验用户是否有权限执行其所请求的操做。tomcat

客户端访问API服务的途径一般有三种:kubectl、客户端库或者直接使用 REST接口进行请求。app

而能够执行此类请求的主体也被 Kubernetes 分为两类:现实中的“人”和 Pod 对象, 它们的用户身份分别对应于常规用户 (User Account )和服务帐号 ( Service Account) 。 ide

  • Use Account(用户帐号):通常是指由独立于Kubernetes以外的其余服务管理的用 户帐号,例如由管理员分发的密钥、Keystone一类的用户存储(帐号库)、甚至是包 含有用户名和密码列表的文件等。Kubernetes中不存在表示此类用户帐号的对象, 所以不能被直接添加进 Kubernetes 系统中 。
  • Service Account(服务帐号):是指由Kubernetes API 管理的帐号,用于为Pod 之中的服务进程在访问Kubernetes API时提供身份标识( identity ) 。Service Account一般要绑定于特定的命名空间,它们由 API Server 建立,或者经过 API 调用于动建立 ,附带着一组存储为Secret的用于访问API Server的凭据。
    K8S认证、受权与准入控制(RBAC)详解

Kubernetes 有着如下几个内建的用于特殊目的的组 。测试

  • system:unauthenticated :未能经过任何一个受权插件检验的帐号,即未经过认证测 试的用户所属的组 。
  • system :authenticated :认证成功后的用户自动加入的一个组,用于快捷引用全部正常经过认证的用户帐号。
  • system : serviceaccounts :当前系统上的全部 Service Account 对象。
  • system :serviceaccounts :<namespace>:特定命名空间内全部的 Service Account 对象。

Role和ClusterRole

  1. Role是只做用于命名空间级别的,用于定义命名空间内资源权限集合。
  2. ClusterRole则用于集群级别的资源权限集合,它们都是标准的 API 资源类型 。
  3. 通常来讲, ClusterRole 的许可受权做用于整个集群,所以经常使用于控制 Role 没法生效的资源类型,这包括集群级别的资源(如Nodes)、非资源类型的端点(如/healthz)和做用于全部命名空间的资源(例如跨命名空间获取任何资源的权限)。

RoleBinding和ClusterRoleBinding

  1. RoleBinding用于将Role上的许可权限绑定到一个或一组用户之上,它隶属于且仅能做用于一个命名空间。绑定时,能够引用同一名称中的Role,也能够引用集群级别的 ClusterRole。jsonp

  2. ClusterRoleBinding则把ClusterRole中定义的许可权限绑定在一个或一组用户之上,它仅能够引用集群级别的ClusterRole。
  3. Role、RoleBinding、ClusterRole和ClusterRoleBinding 的关系如图 所示 。
    K8S认证、受权与准入控制(RBAC)详解spa

  4. 一个命名空间中能够包含多个Role和RoleBinding对象,相似地,集群级别也能够同时存在多个ClusterRole和ClusterRoleBinding对 象。而一个帐户也可经由RoleBinding ClusterRoleBinding关联至多个角色,从而具备多重许可受权。

下面咱们来建立一个User Account,测试访问某些咱们受权的资源:

建立k8s User Account

1、建立证书

  1. 建立user私钥

    [root@node-01 ~]# cd /etc/kubernetes/pki/
    [root@node-01 pki]# (umask 077;openssl genrsa -out billy.key 2048)
    Generating RSA private key, 2048 bit long modulus
    .................................................................................+++
    ..................+++
    e is 65537 (0x10001)
  2. 建立证书签署请求
    O=组织信息,CN=用户名

    [root@node-01 pki]# openssl req -new -key billy.key -out billy.csr -subj "/O=jbt/CN=billy"
  3. 签署证书
    [root@node-01 pki]# openssl  x509 -req -in billy.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out billy.crt -days 365
    Signature ok
    subject=/O=jbt/CN=billy
    Getting CA Private Key

    2、建立配置文件

    建立配置文件主要有如下几个步骤:

    kubectl config set-cluster --kubeconfig=/PATH/TO/SOMEFILE      #集群配置
    kubectl config set-credentials NAME --kubeconfig=/PATH/TO/SOMEFILE #用户配置
    kubectl config set-context    #context配置
    kubectl config use-context    #切换context
  • --embed-certs=true的做用是不在配置文件中显示证书信息。
  • --kubeconfig=/root/billy.conf用于建立新的配置文件,若是不加此选项,则内容会添加到家目录下.kube/config文件中,可使用use-context来切换不一样的用户管理k8s集群。
  • context简单的理解就是用什么用户来管理哪一个集群,即用户和集群的结合。

建立集群配置

[root@node-01 pki]# kubectl config set-cluster k8s --server=https://10.31.90.200:8443 --certificate-authority=ca.crt --embed-certs=true --kubeconfig=/root/billy.conf
Cluster "k8s" set.

[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users: []

建立用户配置

[root@node-01 pki]# kubectl config set-credentials billy --client-certificate=billy.crt --client-key=billy.key --embed-certs=true --kubeconfig=/root/billy.conf
User "billy" set.

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts: []
current-context: ""
kind: Config
preferences: {}
users:
- name: billy
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

建立context配置

[root@node-01 pki]# kubectl config set-context billy@k8s --cluster=k8s --user=billy --kubeconfig=/root/billy.conf
Context "billy@k8s" created.

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: billy
  name: billy@k8s
current-context: ""
kind: Config
preferences: {}
users:
- name: billy
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

切换context

[root@node-01 pki]# kubectl config use-context billy@k8s --kubeconfig=/root/billy.conf
Switched to context "billy@k8s".

#查看配置文件
[root@node-01 pki]# kubectl config view --kubeconfig=/root/billy.conf
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://10.31.90.200:8443
  name: k8s
contexts:
- context:
    cluster: k8s
    user: billy
  name: billy@k8s
current-context: billy@k8s
kind: Config
preferences: {}
users:
- name: billy
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

建立系统用户及k8s验证文件

[root@node-01 ~]# useradd billy     #建立什么用户名均可以
[root@node-01 ~]# mkdir /home/billy/.kube
[root@node-01 ~]# cp billy.conf /home/billy/.kube/config
[root@node-01 ~]# chown billy.billy -R /home/billy/.kube/
[root@node-01 ~]# su - billy
[billy@node-01 ~]$ kubectl get pod
Error from server (Forbidden): pods is forbidden: User "billy" cannot list resource "pods" in API group "" in the namespace "default"
#默认新用户是没有任何权限的。

建立Role

此role只有pod的get、list、watch权限

[root@node-01 rbac]# cat pods-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pods-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

[root@node-01 rbac]# kubectl apply -f pods-reader.yaml 
role.rbac.authorization.k8s.io/pods-reader created

建立Rolebinding

用户billy和role pods-reader的绑定

[root@node-01 rbac]# cat billy-pods-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: billy-pods-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: billy

[root@node-01 rbac]# kubectl apply -f billy-pods-reader.yaml 
rolebinding.rbac.authorization.k8s.io/billy-pods-reader created

验证结果

若是没有指定命名空间的话,默认就是default命名空间。

[billy@node-01 ~]$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
nginx-demo-95bd675d5-66xrm   1/1     Running   0          18d
tomcat-5c5dcbc885-7vr68      1/1     Running   0          18d

[billy@node-01 ~]$ kubectl -n kube-system get pod
Error from server (Forbidden): pods is forbidden: User "billy" cannot list resource "pods" in API group "" in the namespace "kube-system"

因此咱们是能够查看查看default命名空间的pod,可是其余空间的pod是没法查看的。

建立ClusterRole

[root@node-01 rbac]# cat cluster-reader.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

[root@node-01 rbac]# kubectl apply -f cluster-reader.yaml 
clusterrole.rbac.authorization.k8s.io/cluster-reader created

建立ClusterRoleBinding

[root@node-01 rbac]# cat billy-read-all-pods.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: billy-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: billy

[root@node-01 rbac]# kubectl apply -f billy-read-all-pods.yaml 
clusterrolebinding.rbac.authorization.k8s.io/billy-read-all-pods created

验证结果

建立了ClusterRole和ClusterRoleBinding后就能够看到全部命名空间的pod了。

[billy@node-01 ~]$ kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
nginx-demo-95bd675d5-66xrm   1/1     Running   0          18d
tomcat-5c5dcbc885-7vr68      1/1     Running   0          18d

[billy@node-01 ~]$ kubectl -n kube-system get pod
NAME                                        READY   STATUS    RESTARTS   AGE
canal-gd4qn                                 2/2     Running   0          21d
cert-manager-6464494858-wqpnb               1/1     Running   0          18d
coredns-7f65654f74-89x69                    1/1     Running   0          18d
coredns-7f65654f74-bznrl                    1/1     Running   2          54d
...

ServiceAccount

至于ServiceAccount怎么受权,其实相对user account来讲更简单,只需先建立ServiceAccount,而后建立role或者ClusterRole,最后在RoleBinding或ClusterRoleBinding绑定便可。如下简单作一个示例,就不在显示结果了,你们能够本身去验证。

建立SA

kubectl create sa billy-sa

建立Role

[root@node-01 rbac]# cat billy-sa-role.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: billy-sa-role
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

建立Rolebinding

将billy-sa和billy-sa-role的绑定

[root@node-01 rbac]# cat billy-sa-rolebinding.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: billy-sa-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: billy-sa-role
subjects:
- kind: ServiceAccount
  name: billy-sa

验证结果

建立完SA以后系统会自动建立一个secret,咱们能够获取这个secret里面的token去登陆dashboard,就能够看到相应有权限的资源。

kubectl get secret billy-sa-token-9rc55 -o jsonpath={.data.token} |base64 -d

还能够在建立pod时在pod的spec里指定serviceAccountName,那么这个pod就拥有了对应的权限,具体的就不在演示了。

本次的分享就到此,若有问题欢迎在下面留言交流,但愿你们多多关注和点赞,谢谢!

相关文章
相关标签/搜索