Cloud Native应用交付

  • 首页
  • 关于本站
  • 个人介绍
  • Downloads
  • Repo
    • Github
    • Container
  • F5
    • F5 Python SDK
    • F5-container
    • F5-LBaaS
  • 社交
    • 联系我
    • 微信/微博
    • 公众号
    • 打赏赞助
行至水穷处 坐看云起时
Cloud Native Application Services: cnadn.net
  1. 首页
  2. 容器/k8s
  3. 正文

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

2018年08月6日 16962点热度 3人点赞 0条评论

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对应,这样就完成了验证和授权

1
2
3
4
5
6
7
8
BEI-ML-JLIN-:~ jlin$ kubectl get clusterrolebinding  -o wide -n kube-system
NAME                                                   AGE       ROLE                                                               USERS                            GROUPS                                         SERVICEACCOUNTS
canal-calico                                           15h       ClusterRole/calico                                                                                                                                 kube-system/canal
canal-flannel                                          15h       ClusterRole/flannel                                                                                                                                kube-system/canal
cluster-admin                                          16h       ClusterRole/cluster-admin                                                                           system:masters
system:aws-cloud-provider                              16h       ClusterRole/system:aws-cloud-provider                                                                                                              kube-system/aws-cloud-provider
system:basic-user                                      16h       ClusterRole/system:basic-user                                                                       system:authenticated, system:unauthenticated
system:controller:attachdetach-controller              16h       ClusterRole/system:controller:attachdetach-controller                                                                                              ku

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

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

dashboard的安装与访问

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

  1. 拿到一个证书和key,放到一个目录下,然后跑个命令产生以下secret
    1
    kubectl create secret generic kubernetes-dashboard-certs --from-file=$HOME/certs -n kube-system

    这个命令的作用是为了设置dashboard作为web server,配置的服务器侧证书的,把它存到secret里,然后在pod里mount这个secret,然后作为证书配置配置给pod
  2. 跑一下他们的dashboard yaml文件
    1
    kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

    yaml文件很长,解读一下相关的关键:
    A. 它也创建了一个名字叫kubernetes-dashboard-certs的secret, 所以实际上跑yaml时候系统会报相关secret已存在
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # ------------------- Dashboard Secret ------------------- #
     
    apiVersion: v1
    kind: Secret
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard-certs
      namespace: kube-system
    type: Opaque

    B. 创建了一个sa,名字叫kubernetes-dashboard, 这个sa和一个自定义的kubernetes-dashboard-minimal的role进行了绑定
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # ------------------- Dashboard Service Account ------------------- #
     
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kube-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: kubernetes-dashboard-minimal
      namespace: kube-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: kubernetes-dashboard-minimal
    subjects:
    - kind: ServiceAccount
      name: kubernetes-dashboard
      namespace: kube-system

    C.将kubernetes-dashboard-certs这个secret mount到了container上, 挂到了/certs这个目录上
    1
    2
    3
    volumeMounts:
            - name: kubernetes-dashboard-certs
              mountPath: /certs

    D. 设置了容器运行命令参数 --auto-generate-certificates,这个是干嘛的呢,是自动产生服务器侧证书的,也就是说这个yaml实际上没有用上面mount进去的证书。
    1
    2
    3
    4
    5
    6
    7
    8
    9
        spec:
          containers:
          - name: kubernetes-dashboard
            image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.8.3
            ports:
            - containerPort: 8443
              protocol: TCP
            args:
              - --auto-generate-certificates

    所以,这个时候如果你去访问dashboard,浏览器上显示的证书都是临时签发的证书,并不是/certs里的证书,要想实现是自己指定的证书,需要将自动产生这个参数换掉,换成如下
    1
    2
    3
    4
        Args:
          --tls-cert-file=/certs/kubernetes-dashboard.pem
          --tls-key-file=/certs/kubernetes-dashboard-key.pem
          --default-cert-dir=/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本身不就希望代理权限吗?不管它,关于这里的认证授权后面再分析。

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "services \"https:kubernetes-dashboard:\" is forbidden: User \"system:anonymous\" cannot get services/proxy in the namespace \"kube-system\"",
  "reason": "Forbidden",
  "details": {
    "name": "https:kubernetes-dashboard:",
    "kind": "services"
  },
  "code": 403
}

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

1
2
3
4
5
6
7
8
9
10
11
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
 
  },
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

 

比如,下图显示浏览器访问6443已经可以获得正常的API权限

 

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

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

dashboard身份验证与授权

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

As of release 1.7 Dashboard supports user authentication based on:

  • Authorization: Bearer <token> header passed in every request to Dashboard. Supported from release 1.6. Has the highest priority. If present, login view will not be shown.
  • Bearer Token that can be used on Dashboard login view.
  • Username/password that can be used on Dashboard login view.
  • Kubeconfig file that can be used on Dashboard login view.

简单的来说,就是只支持两种方法,一种是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 看到如下输出

1
2
3
4
5
{
  "modes": [
   "token"
  ]
}

很显然,指明了token方式

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

1
2
3
4
5
{
  "tokenPresent": false,
  "headerPresent": false,
  "httpsMode": true
}

可以看到,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上,这样就有了全部的权限
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    BEI-ML-JLIN-:~ jlin$ kubectl create serviceaccount dashboard-gui -n kube-system
    serviceaccount "dashboard-gui" created
    BEI-ML-JLIN-:~ jlin$ kubectl get sa -n kube-system
    NAME                   SECRETS   AGE
    canal                  1         22h
    coredns                1         22h
    dashboard-gui          1         11s
    default                1         23h
    kubernetes-dashboard   1         10h
     
    BEI-ML-JLIN-:~ jlin$ kubectl create clusterrolebinding dashboard-gui-rolebind --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-gui -n kube-system
    clusterrolebinding.rbac.authorization.k8s.io "dashboard-gui-rolebind" created
     
    BEI-ML-JLIN-:~ jlin$ kubectl get clusterrolebinding dashboard-gui-rolebind -o wide -n kube-system
    NAME                     AGE       ROLE                        USERS     GROUPS    SERVICEACCOUNTS
    dashboard-gui-rolebind   6m        ClusterRole/cluster-admin                       kube-system/dashboard-gui

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

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

附:

如何利用kubeconfig登录dashboard?

如果只是简单的将诸如kubectl所用的kubeconfig拿来登录,系统会提示:

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

 

参考:

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

 

尊重原创,转载请署名。

相关文章

  • 密码保护:F5OS tenant部署后的容器情况、网络接口情况
  • 密码保护:F5OS tenant镜像实例化后信息
  • 密码保护:F5OS docker-compose.yml
  • 密码保护:F5OS 底层容器、网络及k8s状态
  • 优雅下线业务Pod的方法
本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: clusterrolebinding dashboard rolebinding 证书 验证
最后更新:2018年08月7日

纳米

linjing.io

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

页面AI聊天助手
文章目录
  • k8s验证与授权思路综述
  • dashboard的安装与访问
  • dashboard身份验证与授权
    • 尊重原创,转载请署名。

纳米

linjing.io

☁️迈向Cloud Native ADC ☁️

认证获得:
TOGAF: ID 152743
Kubernetes: CKA #664
Microsoft: MCSE MCDBA
Cisco: CCNP
Juniper: JNCIS
F5:
F5 Certified Solution Expert, Security
F5 Certified Technology Specialist, LTM/GTM/APM/ASM
F5 Certified BIG-IP Administrator
  • 点击查看本博技术要素列表
  • 归档
    分类
    • AI
    • Automation
    • Avi Networks
    • Cisco ACI
    • CISCO资源
    • F5 with ELK
    • F5-Tech tips
    • F5技术
    • Juniper
    • Linux
    • NGINX
    • SDN
    • ServiceMesh
    • WEB编程
    • WINDOWS相关
    • 业界文章
    • 交换机技术
    • 化云为雨/Openstack
    • 协议原理
    • 容器/k8s
    • 我的工作
    • 我的生活
    • 网站技术
    • 路由器技术
    • 项目案例
    标签聚合
    nginx istio api network irule docker bigip flannel openstack neutron envoy k8s F5 DNS gtm
    最近评论
    汤姆 发布于 8 个月前(09月10日) 嗨,楼主,里面的json怎么下载啊,怎么收费啊?
    汤姆 发布于 8 个月前(09月09日) 大佬,kib的页面可以分享下吗?谢谢
    zhangsha 发布于 1 年前(05月12日) 资料发给我下,谢谢纳米同志!!!!lyx895@qq.com
    李成才 发布于 1 年前(01月02日) 麻烦了,谢谢大佬
    纳米 发布于 1 年前(01月02日) 你好。是的,因为以前下载系统插件在一次升级后将所有的下载生成信息全弄丢了。所以不少文件无法下载。DN...
    浏览次数
    • Downloads - 183,775 views
    • 联系我 - 118,966 views
    • 迄今为止最全最深入的BIGIP-DNS/GTM原理及培训资料 - 116,512 views
    • Github - 103,663 views
    • F5常见log日志解释 - 79,774 views
    • 从传统ADC迈向CLOUD NATIVE ADC - 下载 - 74,627 views
    • Sniffer Pro 4 70 530抓包软件 中文版+视频教程 - 74,320 views
    • 迄今为止最全最深入的BIGIP-DNS/GTM原理及培训资料 - 67,770 views
    • 关于本站 - 60,915 views
    • 这篇文档您是否感兴趣 - 55,495 views
    链接表
    • F5SE创新
    • Jimmy Song‘s Blog
    • SDNlab
    • Service Mesh社区
    • 三斗室
    • 个人profile
    • 云原生社区

    COPYRIGHT © 2023 Cloud Native 应用交付. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang

    京ICP备14048088号-1

    京公网安备 11010502041506号