K8s集群认证之RBAC

kubernetes认证,授权概括总结:

RBAC简明总结摘要:
API Server认证授权过程:
  subject(主体)----->认证----->授权【action(可做什么)】------>准入控制【Object(能对那些资源对象做操作)】

认证:
  有多种方式,比较常用的:token,tls,user/password
账号:
  k8s中账号的概念不是我们理解的账号,它并不真的存在,它只是形式上存在。
  它有两种账号: UserAccount(人使用的账号), ServiceAccount(Pod使用的账号)

授权:RBAC
  k8s中的授权机制也有很多,但目前主流是RBAC(基于角色的访问控制)
  RBAC中的核心概念:
      基于单个名称空间:
    role, clusterrole, rolebinding

   整个集群级别:
    clusterrole , clusterrolebinding

role, clusterrole : 是定义职务,权限,就像公司成立时,就事先制定好有CTO,CEO,总监,经理等职务
rolebinding, clusterrolebinding: 是将具体的账号(Subject) 和 某个role/clusterrole关联,即授权,或叫任职。

subject:
  在k8s中,主体是个泛称,它表示k8s中的三类主体, user, group, serviceAccount

object:
  Object这个词,含义比较丰富,在不同场景理解要有变化,在k8s中我们通过
  # kubectl describe role myrole
  Name: myrole
  .............
  Resources    Non-Resource URLs    Resource Names   Verbs
  ---------      -----------------        --------------        -----
  deployments     []            []        [get list watch]
  pods          []            []        [get list watch]
  其中,Resources: 它可被称为Resource Group
    Resource Names: 它可被称为 Resource,它表ResourceGroup中具体的单个资源
    Non-Resource URLs: 它被称为非资源URL
  而这三类Object是k8s系统基本的Object。
  在yaml清单中,经常看到某种属性为<[]Object>它实际上是yaml语法中的字典 或叫映射(map)。这在报错时,经常看到。
  它和这里说的Object可不是一回事。

action:
  即具体能对Ojbect做什么,它有: get, list, watch, patch, delete, update, create 等。。。

RBAC核心概念公式
  role/clusterrole = object + action
  授权单个名称空间: rolebinding = subject + role/clusterRole
  授权集群: clusterRoleBinding = subject + clusterRole

 

基本原理:

K8s中的认证和授权机制:
  在K8s中我们操作任何资源都需要经历三个检查步骤:认证、授权 和 准入控制。
  当然这些仅针对普通用户,k8s中默认clusteradmin是拥有最高权限的。

  • 认证: 即用户要登陆k8s上操作资源,你必须提供合法的用户名和密码。
  • 授权: 用户认证通过后,要查看该用户能操作什么资源,若其要操作的资源在其允许操作的资源范围内则通过。
  • 准入控制: 用户要操作的资源,也许需要级联其它相关资源或级联了其它相关操作,那么这些级联的资源 或 级联的操作该用户是否有权限访问?这个就是有准入控制来检查的,若不允许访问级联资源,那么该资源也将无法访问。因为k8s是高度模块化设计,因此,这三种检查都允许用户自定义使用何种检测机制来进行访问控制。

认证:

  • token: 此方式又称为预共享密钥方式的认证,即用户名和密码,如同MySQL中root要登陆,必须事先在user表中创建root密码.
  • TLS: 此中方式为证书认证方式,此时K8s服务端 和 客户端要做双向证书认证,即客户端要认证服务端的证书是否为自己认可的CA所签发的证书,且证书中的subject信息CN(主机名)必须与服务端的主机名一致,等等;而服务器端也要认证客户端的证书,也要认可签发该证书的CA,以及证书中的信息也要匹配。以上是两种比较常用的认证方式,还有其它认证,可自行研究。需要注意的是 认证插件中只有一个认证通过,其它插件就无需再次认证了。

授权:
  它也是模块化设计,它和认证一样都同时支持多个模块并存,但只要有一个模块认证通过,即通过了此关,可进入下一关进一步检查。
  除了下面几种常用授权模块,我们也可在测试时,使用“总是允许” 或 “总是拒绝”来测试账号。

  • RBAC:基于角色的访问控制机制,它只有允许授权,没有拒绝授权,因为默认是拒绝所有,我们仅需要定义允许该用户做什么即可。默认kubectl创建的K8s资源,都是默认启用强制RBAC的
  • ABAC
  • 基于Node的授权
  • Web-huke的授权(这是一种通过Web的回调机制实现的授权)

准入控制:
  这块主要是对认证授权通过后,后期对要操作的级联对象操作的检查,无需过多关注。


K8s上的用户账户:
  k8s客户端(一般用:kubectl) ------>API Server
  APIServer需要对客户端做认证,默认使用工具安装的K8s,会在用户家目录下创建一个认证配置文件 .kube/config 这里面保存了客户端访问API Server的密钥相关信息,这样当用kubectl访问k8s时,它就会自动读取该配置文件,向API Server发起认证,然后完成操作请求。

通常一个正常的API请求是包含: 用户认证信息,API请求的URL,共同组成。
1. 在K8s中用户账户为:
  user: username + userID
  group:
  extra: 一些扩展信息

2. 在k8s中发起API请求,其内部实际是一个URL请求路径:
  格式: http://API_Server_IP:6443/apis/apps/v1/namespaces/default/deployments/myapp-deploy/
  一个普通的HTTP请求有:
    get, post, put, delete
  在K8s中实际用的还是基本的请求方法,但K8s将这些基本方法,又做了更细致的封装,于是就有以下API 请求命令:
    get, list, create, update, patch, watch, proxy, redirect(重定向), delete,deletecollection(级联删除)
  一个API请求的URL拆解开后会包含以下信息,当然这些信息是不包含认证,仅是资源:
    API Group
    Namespace
    Resource
    Subresource
  #再进一步理解授权:
    若当前仅授权某用户可get资源,那么它就不能做create,update,delete等操作。

 

在k8s中访问资源,其实就是对URL发起增删改查的操作.
验证方式:
  1. 在安装了kubectl的节点上,启动kubectl的代理. 【注: kubectl所在节点必须有认证配置信息,即 .kube/config】
    kubectl proxy --port=8888
  2. 接着就可以在本地使用HTTP访问8888来向运行在HTTPS协议上的API Server发起请求了
    curl   http://localhost:8888/....

#注意:一定要先启动一个Proxy,因为,kubectl自身是有认证信息的,你每次执行kubectl命令时,它都会读取 ~/.kube/config 文件中的认证信息,所以你不需要输入任何认证信息,其实背后,是自动做了认证数据传递的。但你若直接使用curl 来请求APIServer,你就必须给 curl 制作一个API Server认可的认证信息,否则,curl是获取不到任何信息的!所以为了简单演示期间,可以使用上面的命令,先启动一个kubectl代理,然后,curl向它发起请求,这样curl就不需要提供任何认证信息,所有认证都将在kubectl proxy 和 API Server之间自动进行,但通常为了安全,通常仅将代理启动为监听在127.0.0.1上,然后在本地做 curl 请求。

kind(即:类型):
它有三种类型:【每种类型都有一个固定的JSON表达方式,配置清单使用yaml写,但在提交时,会被自动转换为JSON格式】
    1. 对象类型,如: Pod, deployment, service,namespace等这些都称为对象,它们都是可在集群上创建出来的具体实体。
    2. 列表类型,在RESTful风格下它被称为集合,在K8s上称为列表(list)
    # curl  http://localhost:8888/api/v1/namespaces   #注意:namespaces其实就是一个集合,它会列出该对象集合中的所有子资源.
    # curl http://localhost:8888/api/v1/namespaces/default
            {
              "kind": "Namespace",
              "apiVersion": "v1",
              "metadata": {
                "name": "default",
                "selfLink": "/api/v1/namespaces/default",
                "uid": "2486e6a1-a8a6-11e9-8872-000c291a5fb6",
                "resourceVersion": "4",
                "creationTimestamp": "2019-07-17T15:18:34Z"
              },
              "spec": {
                "finalizers": [
                  "kubernetes"
                ]
              },
              "status": {
                "phase": "Active"
              }
            }
RESTful: REST 称为表针状态转移,通常用于承载对象数据状态的格式,也称为序列化的数据结构,一般用于流式化数据的格式有xml,yaml,json。
在K8s中,使用的都是Json来作为其输出输入数据的格式,即便我们编写的所有清单文件都是yaml格式,但kubectl在将清单信息提交给API Server 前还是会自动将其转换为Json格式再提交给API Server去处理。

curl  http://localhost:8888/apis/apps/v1/namespaces/kube-system/deployments/coredns
    注意:
        以上两个URL,一个是起始于api ,一个是起始于apis 
        区别: api 它是一个特殊链接,只有在核心v1群组中的对象才能使用。
              apis 它是一般API访问的入口固定格式名。
在K8s上有两类客户端需要访问API Server:
1. 远程的kubectl  ,我们经常在Master上使用kubectl来操作k8s,很容易以为,kubectl是只能在Master上运行的,
    其实不是,这样做仅仅是为了方便访问,才将kubectl安装在Master上,其实你可以在Windows上安装一个kubectl
    然后,将~/.kube/config 这个记录了认证信息的文件拷贝过去,就可以在Windows上使用了。因此它其实是个远程客户端.
    
2. Pod,如: coreDNS, K8s的仪表盘图型界面接口
   像kube-dns 它本身也是需要访问API Server的,因为当集群中新增资源对象时,它需要动态的生成一条该资源对象的A记录,
   所以它需要访问API Server来获取这个对象的信息,Dashboard也需要,因为它提供了一个Web界面,可让我们通过图像界面
   来管理操作k8s,如创建,删除Pod,创建删除名称空间等,所以它也需要访问API Server。

Pod中访问API Server通常是人去访问,或写的脚本去访问,所以这类访问使用的账号为:UserAccount
而Pod自身去连接API Server时,使用的账号是:ServiceAccount

集群中的Pod如何访问API Server?
kubectl  get  svc
kubectl  describe  svc  kubernetes  #可以看到API Server被映射为K8s上的Service了,Pod就是通过这个Service访问API Server的.
  注:
    由于API Server的访问必须要通过证书认证,它是双向认证,即客户端Pod要验证API Server的身份,API也要验证客户端的身份.
    所以对于Pod来说,它访问API Server时,使用的地址是Service的地址.假如是10.96.0.1,而真实API Server所在Node节点的IP为
    172.20.0.1。这就导致我们在创建API Server的证书时,必须要能够实现,Pod获取API Server的证书,去验证里面的主机名时,
    解析到的IP中必须有10.96.0.1,这就意味着DNS上要有两条A记录,一条解析为10.96.0.1,一条解析为172.20.0.1,这样Pod
    验证API Server才能通过,而kubectl这种外部客户端访问验证API Server解析的地址中有172.20.0.1,也能验证API身份通过。
    或者在证书中直接写两个IP地址,也是可以的。
    但是我们又该知道,Pod验证API Server是必须,但我们更需要的是API Server去验证客户端!
    Pod中的应用要访问API Server,它事先是不可能专门为API Server设计一个读取kubernetes认证信息的功能的,
    就如: nginx 它是不可能直接去读取kubernetes的认证信息,然后去访问API Server的!
    所以,访问API Server时的认证信息要由Pod本身来完成。
       kubectl  describe  pods  myapp-1        
            #可看到它默认挂载了一个存储卷,类型是secret的.它其实就是Pod访问APIServer
            时提供的认证信息,不过默认的token是普通用户,它仅能查看自己的相关信息.
       kubectl  get  secret   
            #使用它可看到,当前名称空间的默认token,即 default-token-...
            它就是当名称空间中所有Pod ,默认访问API Server时,提供的认证信息,当然你可加“ -n  名称空间名” 来查看
            其它名称空间中的默认token,而且其中一定有一个default-token-xxx..的标准k8s资源。
            
            #所以结合上面提到的两类账号,这里的default-token 其实就是第二类账号,即serviceAccount。
            #下面还有部分关于serviceAccount的说明,但为了让知识点集中,在这里继续深入
             kubectl  create  serviceaccount  admin
             此命名创建了一个admin的serviceAccount,即可通过该账号登录k8s,但此自定义账号并不能做任何事,因为
         这里仅是创建了认证信息,真正决定是否能操作k8s资源对象的是 授权 ,这点需要注意!!
            
    知道了这些,若我们需要运行一个Pod,这个Pod是用来管理其它Pod,Service,deployment等资源的,那么,我们就需要
    给该Pod提供一个secret,它里面要包含足够的权限的认证信息,这样该Pod就可以用于管理K8s上的资源了。

创建清单文件的快捷方式:
方式一:               
   kubectl  create  serviceaccount  mysa  -o  yaml  --dry-run  > mysa-serviceaccount.yaml
     注:
      只有支持create创建的K8s资源,都可以使用这种方式生成一个yaml格式的配置清单文件,我们就可以
      使用该清单模板来修改出我们需要的清单。
      --dry-run: 它是测试运行,并不真正执行。
方式二:
    kubectl  get  pods  myapp-1  -o  yaml   --exprots 

 

关于serviceaccount:
    Pod中访问API Server通常是人去访问,或写的脚本去访问,所以这类访问使用的账号为:UserAccount
    而Pod自身去连接API Server时,使用的账号是:ServiceAccount
    总结如下: 
            useraccount: 它是现实中的人使用的用户名和密码的认证账户。
            serviceaccount: 它是Pod中应用程序使用的认证账户和密码。
     另外,在创建serviceAccount时,也可以指定docker私有镜像服务器的认证信息,并且这样做会更加安全,
     可避免docker私钥信息泄露。
     先前在说secret时,它里面有一种类型叫 docker-registry,它可用来创建连接docker私有镜像服务器的信息,
     但这种方式定义的secret,需要在Pod定义中指定 imagePullSecrets来指明使用哪个secret,但这样很不安全.
     很容易泄漏私有镜像的认证信息。
     因此可将认证信息添加到serviceAccount中,这样在定义pod时,只需要指明使用那个SA就可以了,因为sa
     的访问权限,一般只有集群管理员才能访问。
     # kubectl describe sa mysa
            Name:                mysa
            ..........
            Image pull secrets:  <none>    
            。。。。。
            
        
创建一个serviceaccount的示例:
# kubectl  create  serviceaccount   mysa
 
# kubectl  get  sa
 
# kubectl  describe  sa  mysa       #可看到一个Tokens信息,以及它所挂载的secret。这是k8s自动生成的认证信息,
                                                使用该信息就可以登陆到K8s上,但是需要注意,登陆可以,但该账户是没有任何
                                                 权限的,因为权限是由授权来完成的。
    Name:                mysa
    Namespace:           default
    Labels:              <none>
    Annotations:         <none>
    Image pull secrets:  <none>
    Mountable secrets:   mysa-token-cwgpg
    Tokens:              mysa-token-cwgpg
    Events:              <none>

 # kubectl get secrets 
    NAME                     TYPE                                  DATA   AGE
    default-token-6xlcj      kubernetes.io/service-account-token   3      4d14h
    mysa-token-cwgpg         kubernetes.io/service-account-token   3      112s
 
 # kubectl   describe   secrets   mysa-token-cwgpg 
    Name:         mysa-token-cwgpg
    Namespace:    default
    ............
    Type:  kubernetes.io/service-account-token
    Data
    ====
    ca.crt:     1346 bytes
    namespace:  7 bytes
    token:      eyJhb.................72gU_ViYAHUZC-jmB8t7Xg
         
         
创建一个使用自定义ServiceAccount的Pod示例:
vim  pod-sa-demo.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-sa-demo
      namespace: default
      labels:
         app: myapp
         tier: frontend
      annotations:
         test.com/created-by: “cluster admin”
   spec:
      containers:
      -  name: myapp
         image: ikubernetes/myapp:v1
         ports:
         - name:  http
           containerPort:  80
      serviceAccountName: admin

kubectl  apply  -f  pod-sa-demo.yaml
kubectl  describe  pods  pod-sa-demo            #这里就可以看到,此Pod使用了自定义的admin认证信息。
            
任何需要访问API Server的应用都可认为是API Server的客户端,则这些客户端都需要被API Server所认证,
这些客户端包括: kubectl, kubelet, kube-proxy等等,那么它们要被API Server所认证,就必须提供用户认证信息,
那么它们是如何知道使用那些认证信息的? 其实默认它们使用的都是 ~/.kube/config 中的认证信息,但是若我们
需要使用多个不同权限的账户来访问集群,是不是要不断的切换系统账户,才能使用不同的~/.kube/config ?
若有多个集群,是否也需要创建多个系统账户,在不同系统账户的家目录下创建不同的.kube/config ?
其实这是不必的,在K8s中,认证信息被称为kubeconfig, 它可使用下面命令查看:
# kubectl  config  view
apiVersion: v1
kind: Config
preferences: {}
clusters:                       #这是定义一个要管理的K8s集群,可定义多个,若需要同时管理多个集群时.
-  cluster:
      #这是服务器端的证书数据,用于客户端验证APIserver的.REDACTED:表示真实数据以隐藏.
      certificate-authority-data: REDACTED
      server: https://172.20.0.70:6443    #指明API Server的地址
   name: kubernetes                       #给这个集群信息取一个名字叫 kubernetes
users:      #这是定义一个登陆某K8s集群时,使用的用户账户信息,若需要管理多个集群,就需要定义多个.
            #当然一个集群也可有多个不同权限的账号.
-   name: kubernetes-admin                #定义这个用户的用户名叫 kubernetes-admin
    user:
        client-certificate-data: REDACTED #定义此用户的证书数据
        client-key-data:REDACTED          #定义此用户的私钥数据
contexts:   #这是定义一个访问集群的上下文信息,即那个users + 那个clusters = 登陆该cluster,它也可定义多个.
-    context:
        cluster: kubernetes               #这里指明要登陆kubernetes这个集群,需要使用
        user: kubernetes-admin            # kubernetes-admin这个用户认证数据。
    name: kubernetes-admin@kubernetes     #为这个上下文定义一个引用名字
current-context: kubernetes-admin@kubernetes  #指明当前使用kubernetes-admin@kubernetes这个上下文来登陆集群。
       
      
创建一个自定义用户来登陆API Server:
 cd  /etc/kubernetes/ssl      #这是kubeasz部署后,CA证书默认存放位置。
 cp  admin-csr.json   test-csr.json
vim test
-csr.json { "CN": "test", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "HangZhou", "L": "XS" } ] } # grep -A1 'profile' ca-config.json   "profiles": {     "kubernetes": { # cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes test-csr.json | cfssljson -bare test 查看创建的证书: openssl x509 -in test.pem -text -noout #-text:使用文本输出, -noout: 不适应base64编码. 注: Issuer: 显示当前证书是由谁来签署的. Subject: 中显示的CN是连入K8s集群的用户账户名 Validity: 这是显示当前证书的有效期限. 创建k8s的认证信息(kubeconfig): kubectl config set-credentials testuser --client-certificate=./test.crt \ --client-key=./test.key --embed-certs=true 注: --embed-certs: ture:表示将证书和私钥包含到k8s中,并且隐藏不显示具体数据. 若需要创建token认证信息: kubectl config set-credentials testuser --token=预共享的密钥 若需要创建基于用户名和密码的认证信息: kubectl config set-credentials testuser --username=test --password=PU@&@Xs 若要基于外部认证信息需要使用: --auth-provider= 和 --auth-provider-arg=.. 等信息。 查看kubeconfig的信息: kubectl config view #可以看到刚创建的testuser的相关信息. 接着让test可以访问kubernetes集群: kubectl config set-context test@kubernetes --cluster=kubernetes --user=test 使用自己定义的用户做为当前连接K8s集群的用户: kubectl config use-context test@kubernetes kubectl get pods #将看到权限被拒绝的错误 切换回管理员权限: kubectl config use-context ... 创建一个新集群配置信息: kubectl config set-cluster mycluster --kubeconfig=/tmp/test.conf --server="https://1.1.1.2:6443" \ --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true 查看: kubectl config view --kubeconfig=/tmp/test.conf

 

K8s的授权插件:
  Node, ABAC, RBAC, Webhook
  下面主要以RBAC(Role-based Access Controller)来介绍。

RBAC: 基于角色的授权认证
   重要概念:
  Role(角色):它通过内生的一种叫“角色”的概念,来完成对权限的授予和分配等,所以从此角度讲 角色 是一个组织或任务中的职位或位置,它通常代表一种权力或资格。
  Permission(许可):其实就是权限,而权限是多种Operations(操作)的集合,而Operations是附加在对象(Object)上的具体Action(动作),每一个Action就是一个Operation,
多个Operation就是Operations,即权限。


RBAC授权的过程:
  首先,K8s中访问资源其实就是发起HTTP访问, HTTP访问的通用URL格式为:
  http://API_SERVER:PORT/<API_GROUP>/<API_VERSION>/namespaces/<NAMESPACE_NAME>/<KIND>[/OBJECT_ID]

  而授权是一个组合userAccount或serviceAccount ,role 和 permission 的过程。
  第一步要先组合Permission,因为Permission是有 Action组成的,而Action=Operation+Object。
  Operation(操作): 它是GET,PUT,POST,DELETE,PATCH等,当然我这里列出的HTTP的原始方法,在K8s中它们是CREATE,GET,PATCH,DELETE,PROXY,WATCH,UPDATE等
  Object(对象): 在K8s中,一切皆对象,它的对象分为三类:
    1. 一般对象:基本上涵盖了绝大部分资源主体。
    2. 对象列表:就如:namespaceList
    3. 虚拟对象(或叫 非对象资源):这部分通常是一些URL,很少。
  知道了Operation和Object,那么Action就是它俩的组合。
  比如:我定义一个Action是 GET + /api/v1/namespaces/default/pod/myapp-0 ,这就表示,我定义了一个只能列出默认名称空间下pod类型资源中myapp-0的动作。
    类似这种Action,我可以定义很多个,然后将其打包成Permissions,这样我就有了一个授权。

  第二步 就是要定义一个role
    Role(角色):实际上,role可理解为一组Permissions的组合,即 我将一组权限打包后,取一个名字。
          这就类似于公司中的职位一样,技术部主管,就相当于一个Role,他的Permission就是能做什么,他能管理职员,他能管理部门内资源配置等。

  第三步 就是将user 和 role关联绑定,称为rolebinding
    这就相当于公司的中职位授予,如:A能力很强,公司授予他,技术部总监,另外还兼职公司副CTO等。

  用上面两个集群来说明Role,RoleBinding 和 clusterRole,clusterRoleBinding
 集群1:
   每个名称空间(Namespace)中,为了定义一个此名称空间的管理员,不得不每个名称空间都创建相同的Admin Role,然后使用roleBinding将AdminRole关联到用户上,来让指定用户成为此名称空间中的管理员。这样做很显然,非常繁琐,若名称空间很多,就要在这些名称空间中都要做相同操作,很麻烦。

 集群2:
  在整个k8s集群级别创建一个admin role,然后,使用roleBinding来引用它,并将它和自己名称空间中的用户关联,这样该用户就成功的拥有了对当前名称空间的管理员权限。
这样就很省事了。只需要创建一个集群级别的admin role即可。为啥这样做可以? 因为所有名称空间里的管理员操作基本都一样,都是GET pod,update pod等等这些操作,因此将这些相同操作都定义为集群role,这样就可让所有名称空间都可以引用它了,它就相当于一个模板了。但具体在自己的名称空间中时,它就相当于被具体化为本名称空间中的admin role了。

若现在还想创建一个用户拥有管理所有名称空间中的所有资源,就需要使用ClusterRoleBinding了,它能将ClusterRole具体化为集群级别的role,让授予此role的用户具有集群管理员的权限。

总的来说:
  roleBinding可绑定名称空间内部的role,也可绑定ClusterRole,但roleBinding绑定后,具体化的role是具体化成本名称空间的role。
  clusterRoleBinding:它仅可绑定ClusterRole,它具体化的role,就可访问整个集群中所有的资源。

创建Role:
kubectl  create  role   myrole   --verb=get,list,watch   --resource=pods  --dry-run  -o  yaml   >  role-demo.yaml

#修改role-demo.yaml 
vim  role-demo.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: myrole
      namespace: default
    rules:
    - apiGroups:
      - ""
      resources:
      - pods
      - deployments
      verbs:
      - get
      - list
      - watch

#  kubectl  apply  -f   role-demo.yaml
        
# kubectl describe role myrole 
        Name:         myrole
        .............
          Resources     Non-Resource URLs    Resource Names     Verbs
          ---------    -----------------    --------------      -----
          deployments          []              []           [get list watch]
          pods                 []              []           [get list watch]
    
 #这里要注意:
 #     若不定义Resource Names,则表示对Resources这个一类资源都可操作Verbs所指定的动作。
 #     Non-Resource URLs:这就是前面提到的非资源对象,或称为虚拟URL对象, 它们是k8s中所需要的特殊动作。
             
             
创建roleBinding
  kubectl create rolebinding test-read-pods --role=myrole --user=test --dry-run -o yaml > rolebinding-demo.yaml

  vim  rolebinding-demo.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: test-read-pod
      namespace: default
    roleRef:           #指定要引用的role,在那个API组中,它的类型是role,还是clusterRole,还有要引用role的具体名称。
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: myrole
    subjects:          #注意:subjects是对k8s中两种访问资源的账号的统称,这两种账号是 userAccount 和 serviceAccount
    - apiGroup: rbac.authorization.k8s.io
      kind: User       #此处的kind并非真实的k8s资源类型,仅用于标识, 它只能是 user, group,serviceAccount
      name: test                        
      namespace: default  #因为test用户可能在多个名称空间都有,因此最好加上namespace做限定。
    
#kubectl  apply  -f  rolebinding-demo.yaml

#kubectl  describe  rolebinding   test-read-pod
  ....................
    Role:
      Kind:  Role
      Name:  myrole
    Subjects:
      Kind  Name  Namespace
      ----  ----  ---------
      User  test  

测试切换到test用户,查看权限是否生效
 kubectl config  use-context  test@kubernetes
 
 #但测试发现,test用户可以列出所有名称空间的所有资源,这个我很是不解?
 # 此问题:注解部分在: k8s集群认证 > admin权限问题  但其中原理还是不明。
     
创建clusterRole:
    kubectl  create  clusterrole   clusterRole-manger-pods   \
            --verb=get,list,watch,create,update,delete   \
            --resource=pods,rs.extensions  \
             --dry-run  -o  yaml  > clusterrole-pod-manger.yaml

vim  clusterrole-pods-manger.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: null
  name: clusterRole-manger-pods
rules:
- apiGroups:     #注意: pods就是主API,它没有子API,因此其api组为空
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
  - delete
  - create
  - update
- apiGroups:     #replicaSet控制器有两个子API组,一个是apps,一个是extensions,所以这里必须指定,你要授予那个子API组权限.
  - extensions   #否则,绑定此role的用户仅能访问replicSet主组的资源,但replicaSet其实没有主组,因此实际上就没有给绑定用户访问replicaSet的权限.
  resources:
  - replicasets
  verbs:
  - get
  - list
  - watch
  - delete
  - create
  - update

#创建此ClusterRole
  kubectl  apply  -f  clusterrole-pods-manger.yaml
  
#使用rolebinding来绑定此clusterRole
   kubectl  create  rolebinding   rbind-clusterRoleMangerPods   \
            --clusterrole=clusterRole-manger-pods  --user=test  \
            --dry-run -o yaml  >rbind-clusterRoleMangerPods.yaml 
   
   
# vim   rbind-clusterRoleMangerPods.yaml 
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: rbind-clusterRoleMangerPods
      namespace:  default               #这里指定将该rolebinding创建在default 名称空间中
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: clusterRole-manger-pods
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: test

#创建此rolebinding
  kubectl  apply  -f   rbind-clusterRoleMangerPods.yaml
  
#测试此clusterRole
  kubectl  config  use-context   test@kubernetes

#测试是否能获取pod 和 replicasets.extensions 的资源
  kubectl  get   pods
  kubectl  get   rs
          
#创建clusterRoleBinding
 kubectl  create  clusterrolebinding   cbind-crolePodManger   \
             --clusterrole=clusterRole-manger-pods  --user=test  \
             --dry-run  -o  yaml  > cbind-demo.yaml
 
 vim  cbind-demo.yaml 
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: cbind-crolePodManger
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: clusterRole-manger-pods
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: test

#切换用户
  kubectl  config  use-context   test@kubernetes
  
#测试是否能看不同名称空间的资源.
    kubectl  get  pod  -n  kube-system
    kubectl  get  rs  -n  ingress-nginx

 

posted @ 2019-08-02 17:09  张朝锋  阅读(4013)  评论(0编辑  收藏