行至水穷处 坐看“云”起时

Cloud Native ADN -> CNadn.Net

聊聊为啥kubernetes的dashboard搞起来这么费劲

k8s验证与授权思路综述

相信很多人装k8s都想顺手装个dashboard看看,毕竟GUI有时候还是比较重要的,哈哈。 相信很多人会有同感,那就是一个dashboard搞的那么复杂,不是不能访问,就是不能登录,要么就是没权限。下面通过自己的一点研究,将问题分析过程记录如下,供参考。如有错误,请拍砖留言。

从两个方面来分析,即:

1.dashboard的安装与访问

2.dashboard的身份验证与授权

首先,我们需要有一个共识就是,k8s这套东西非常的解耦和插件化,它为了能够提供更好的二次开发能力,将很多东西搞的从一个用户角度理解起来很费劲。 比如说用户,k8s里面本身是不能创建用户名这样的实体对象的(API basic,bear token认证所设置的相关用户名不算k8s里面的实体资源对象),它只有role,role定义一系列资源权限,然后把一个sa或者group或者user 映射到这个role上来完成权限分配的关系。 这里为啥突然有个user了呢,这里的user实际上是外部的,就像远程AAA一样,user账号是在外部系统上的。我们知道API server是K8S负责验证的服务,不管是怎么访问都是要经过它,dashboard也一样。那么要想API给你做验证做授权有哪些方法(重要常见的,以下未包含全部)?

  1. 使用http basic 认证,这要求配置APIserver支持这种方式,并传递一个包含用户名密码的list文件给API,API就像是个普通开启了http basic认证的web server一样,会挑战浏览器,要求输入用户名和密码。 API获取到输入的用户名密码后和之前预置的list里比对,匹配了,则验证通过,系统就知道是谁登陆了,然后根据该user与role的binding关系就知道了该用户拥有了哪些权限
  2. Bearer token认证,这种认证方式也要求API server服务配置一个token list文件,这个文件里包含了token,token对应着user名称,原理与basic类似,不同的是这种要求在访问请求的header中要始终包含 Authorization: Bearer <token>这个header而已,授权的方式和basic一样
  3. 证书方式的验证和授权,因为证书里可以包含CN和OU这些信息,CN可以表明一个user身份,OU可以表明一个组身份,如果访问者上送的证书被校验通过,那么证书里的CN和OU就可以用来作为条件去rolebinding里查找,进而就可以授权。当然对于dashboard的访问,截止目前v1.11版本,是还不支持使用证书来验证身份的。
  4. Serviceaccount, SA严格意义上不算是用户身份认证,这个是给运行在k8s里的具体应用服务(你可以理解为pods)提供访问API的一种方法,因为有很多运行在k8s里pod内的应用是需要访问API的,所以SA不代表人,代表服务,给一个具体的服务比如dashboard,创建一个SA,然后将SA关联到pod上,并把SA与一个role进行rolebinding。当然实际上服务出示给API的是一个SA的token(k8s为每一个SA都自动产生一个token并保存在secret资源里),这个token是通过mount的方式将对应的token secret mount到pod上来实现的。所以这又回了API的token认证,token–>知道哪个SA, SA和哪个role对应,这样就完成了验证和授权

上面的rolebinding输出里可以看到一个role关联了 users,groups,以及SAs

说了这么多都是为了背景铺垫,免得下面看起来太费劲。回到上面提到的两个问题:

dashboard的安装与访问

安装比较简单,基本上跑一下官方提供的yaml就可以,这里是官方wiki链接,下面分析下这其中的一些小坑。官方的wiki里大约说了两件事:

  1. 拿到一个证书和key,放到一个目录下,然后跑个命令产生以下secret

    这个命令的作用是为了设置dashboard作为web server,配置的服务器侧证书的,把它存到secret里,然后在pod里mount这个secret,然后作为证书配置配置给pod
  2. 跑一下他们的dashboard yaml文件

    yaml文件很长,解读一下相关的关键:
    A. 它也创建了一个名字叫kubernetes-dashboard-certs的secret, 所以实际上跑yaml时候系统会报相关secret已存在

    B. 创建了一个sa,名字叫kubernetes-dashboard, 这个sa和一个自定义的kubernetes-dashboard-minimal的role进行了绑定

    C.将kubernetes-dashboard-certs这个secret mount到了container上, 挂到了/certs这个目录上

    D. 设置了容器运行命令参数 –auto-generate-certificates,这个是干嘛的呢,是自动产生服务器侧证书的,也就是说这个yaml实际上没有用上面mount进去的证书。

    所以,这个时候如果你去访问dashboard,浏览器上显示的证书都是临时签发的证书,并不是/certs里的证书,要想实现是自己指定的证书,需要将自动产生这个参数换掉,换成如下

     

安装完毕后,就该是如何访问了。官方的yaml默认是clusterip模式发布的服务,这样要想访问到dashbaor的界面,要么通过kubectl proxy,要么通过将服务暴露给外部,要么通过API的端口来代理访问,否则外面咋访问呢???

A. Kubectl proxy方式,kubectl proxy是通过在kubectl上暴露一个服务端口,通常为127.0.0.1:8001的非https访问, 你不能在master或者node上跑这个命令,否则除非你的master或者node有图形化的浏览器,不然还是无法看到图形dashboard。所以要在你自己的本地跑这个命令(所以,我擦,好麻烦,所以你还有在本地设置你kubectl的kubeconfig确保本地kubectl可以有权限操作所有)。然后就可以通过本地浏览器访问http://127.0.0.1:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login 看到界面了。 但是!这个dashboard还是会提示你进行身份认证。。。。不理解为啥,kubectl proxy本身不就希望代理权限吗?不管它,关于这里的认证授权后面再分析。
《聊聊为啥kubernetes的dashboard搞起来这么费劲》

B 通过nodeport或者ingress来暴露出来服务,这种方式比较容易理解,等于正常发布一个服务,所以将官方的的yaml改为nodeport方式即可。

C API server本身的服务端口代理访问,即通过API的端口来代理访问dashboard,URI类似这样 https://<master-ip>:<apiserver-port>/ 首先,这种访问API服务的方式需要浏览器提供客户端证书作为认证,比如你可以把kubectl所用的那张证书导入到浏览器里,这样访问服务的时候,会弹出让你选择证书,等于就是双向SSL过程。然后就可以看到dashboard界面了,但是同样,dashboard依旧会再次出现登录界面提示身份验证,也就是说这种方式和kubectl proxy一样,只是代理了界面入口,验证权限方面并未代理。

浏览器未出示证书的情况下,访问返回403

(这是因为API里启用了RBAC,且默认有个--anonymous-auth=false的参数设定,这意味着匿名用户直接被拒绝验证的。如果将值改为true,虽然可以验证了,但是授权还是通不过,会返回如下401,因为匿名用户没权限

 

比如,下图显示浏览器访问6443已经可以获得正常的API权限
《聊聊为啥kubernetes的dashboard搞起来这么费劲》

 

但是,当真的访问dashboard时候还是提示认证,下图是没有认证通过,提示的无权限界面的(即在界面上点击skip,这个时候系统直接用在安装yaml文件里自定义的sa kubernetes-dashboard来授权了,这个sa只关联到了自定义的一个minimal的一个资源role,所以会报出很多资源没权限的提示)

《聊聊为啥kubernetes的dashboard搞起来这么费劲》

也就是说,dashboard不管从哪种方式来访问,其本身的身份验证都是这个服务自己独立的,那么这个服务的验证到底是怎样的?

dashboard身份验证与授权

官方文档对验证做如下表述:

As of release 1.7 Dashboard supports user authentication based on:

简单的来说,就是只支持两种方法,一种是token,一种是user/password。 kubeconfig凡是只是提供了一种便利,并不是一个新的认证方式,如果要用kubeconfig,里面一样,要么使用username/password,要么使用token。跟踪一下看看,通过API proxy方式的方法来访问 https://172.16.150.100:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/api/v1/login/modes 看到如下输出

很显然,指明了token方式

为什么这样访问,没权限?https://172.16.150.100:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/api/v1/login/status

可以看到,login status已经说明,token也没出示,header方式的携带诸如basic认证的方式的token也没带

所以,对于1.7+之上版本的dashboard来说,验证和授权是dashboard完全自己控制的。

根据上述提示,要想登陆进去,要么用用户名密码,要么用token:

  1. username/password方式
    这种方式需要kube-API配合,配置ABAC授权模式,且配置–basic-auth-file,同时dashboard自身的配置里要启用–authentication-mode=basic 配置
  2. token方式
    这种方式就是在login界面输入一下token,token哪里来能,从系统里的SA账户对应的token来,所以这个SA账户要有足够的API权限。下面的步骤是创建SA并通过clusterrolebinding绑定到了clusterrole/cluster-admin上,这样就有了全部的权限

    《聊聊为啥kubernetes的dashboard搞起来这么费劲》

ok,通过在登录界面输入kubectl describe secret dashboard-gui-token-9l25t -n kube-system ,可以正常访问界面了。

所以,整个dashboard是完全可以通过这样的权限控制(sa,自定义role,role绑定)来实现一个用户在GUI界面上能操作哪些namespace里的哪些资源。

附:

如何利用kubeconfig登录dashboard?

如果只是简单的将诸如kubectl所用的kubeconfig拿来登录,系统会提示:
《聊聊为啥kubernetes的dashboard搞起来这么费劲》

黄色提示很是误导人,实际原因是因为kubeconfig没有包含token也没有username/pwd,  如果将上面的token放置到kubeconfig文件里,一样就可以登录并有权限了

《聊聊为啥kubernetes的dashboard搞起来这么费劲》

 

参考:

https://github.com/kubernetes/dashboard/wiki/Accessing-Dashboard—1.7.X-and-above

https://github.com/kubernetes/dashboard/issues/2474

https://github.com/kubernetes/dashboard/wiki/Access-control

 

尊重原创,转载请署名。

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注