一、前言

上一篇文章介绍了从零开始搭建Kubernetes集群,本文将介绍一下如何搭建K8S的Dashboard。

简单的说,K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并展示集群的状态。K8S集群安装好后默认没有包含Dashboard,我们需要额外创建它。

Dashboard设计的还不错,界面友好,功能也比较强大。如果你厌倦了命令行的操作,全程使用Dashboard也是可行的。

因为我们使用kubeadm搭建的集群会默认开启RABC(角色访问控制机制),所以我们必须要进行额外的设置。关于RABC的概念,网上资料很多,大家务必提前了解。

二、RBAC简介

RBAC(Role-Based Access Control )基于角色的访问控制,不懂的可以百度看下
K8S 1.6引进,是让用户能够访问 k8S API 资源的授权方式【不授权就没有资格访问K8S的资源】

2.1、用户

K8S有两种用户:User和Service Account。其中,User给人用,Service Account给进程用,让进程有相关权限。如Dashboard就是一个进程,我们就可以创建一个Service Account给它

2.2、角色

Role是一系列权限的集合,例如一个Role可包含读取和列出 Pod的权限【 ClusterRole 和 Role 类似,其权限范围是整个集群】

2.3、角色绑定

RoleBinding把角色映射到用户,从而让这些用户拥有该角色的权限【ClusterRoleBinding 和RoleBinding 类似,可让用户拥有 ClusterRole 的权限】

2.4、Secret

Secret是一个包含少量敏感信息如密码,令牌,或秘钥的对象。把这些信息保存在 Secret对象中,可以在这些信息被使用时加以控制,并可以降低信息泄露的风险
如下图,灰色是“角色”,蓝色是“用户”,绿色是“角色绑定”,黄色是该角色拥有的权限。简言之 ,角色绑定将角色和用户进行挂钩:
【Kubernetes详解】(三)搭建Kubernetes Dashboard - 图1

三、安装Kubernetes-Dashboard

官方文档:Web UI (K8S Dashboard)

3.1、部署

参考官方文档,在部署好了 k8s 集群环境的前提下,要安装 Kubernetes-Dashboard 只需要一条命令就可以搞定,如下:

  1. kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml

确实如此,但是要通过页面访问还需要进行其他操作

3.2、访问

要想通过页面访问,我们可以先大致看下 recommended.yaml,理解下其中的内容

3.2.1、recommended.yaml 内容

  1. # Copyright 2017 The Kubernetes Authors.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. apiVersion: v1
  15. kind: Namespace
  16. metadata:
  17. name: kubernetes-dashboard
  18. ---
  19. apiVersion: v1
  20. kind: ServiceAccount
  21. metadata:
  22. labels:
  23. k8s-app: kubernetes-dashboard
  24. name: kubernetes-dashboard
  25. namespace: kubernetes-dashboard
  26. ---
  27. kind: Service
  28. apiVersion: v1
  29. metadata:
  30. labels:
  31. k8s-app: kubernetes-dashboard
  32. name: kubernetes-dashboard
  33. namespace: kubernetes-dashboard
  34. spec:
  35. ports:
  36. - port: 443
  37. targetPort: 8443
  38. selector:
  39. k8s-app: kubernetes-dashboard
  40. ---
  41. apiVersion: v1
  42. kind: Secret
  43. metadata:
  44. labels:
  45. k8s-app: kubernetes-dashboard
  46. name: kubernetes-dashboard-certs
  47. namespace: kubernetes-dashboard
  48. type: Opaque
  49. ---
  50. apiVersion: v1
  51. kind: Secret
  52. metadata:
  53. labels:
  54. k8s-app: kubernetes-dashboard
  55. name: kubernetes-dashboard-csrf
  56. namespace: kubernetes-dashboard
  57. type: Opaque
  58. data:
  59. csrf: ""
  60. ---
  61. apiVersion: v1
  62. kind: Secret
  63. metadata:
  64. labels:
  65. k8s-app: kubernetes-dashboard
  66. name: kubernetes-dashboard-key-holder
  67. namespace: kubernetes-dashboard
  68. type: Opaque
  69. ---
  70. kind: ConfigMap
  71. apiVersion: v1
  72. metadata:
  73. labels:
  74. k8s-app: kubernetes-dashboard
  75. name: kubernetes-dashboard-settings
  76. namespace: kubernetes-dashboard
  77. ---
  78. kind: Role
  79. apiVersion: rbac.authorization.k8s.io/v1
  80. metadata:
  81. labels:
  82. k8s-app: kubernetes-dashboard
  83. name: kubernetes-dashboard
  84. namespace: kubernetes-dashboard
  85. rules:
  86. # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
  87. - apiGroups: [""]
  88. resources: ["secrets"]
  89. resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
  90. verbs: ["get", "update", "delete"]
  91. # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
  92. - apiGroups: [""]
  93. resources: ["configmaps"]
  94. resourceNames: ["kubernetes-dashboard-settings"]
  95. verbs: ["get", "update"]
  96. # Allow Dashboard to get metrics.
  97. - apiGroups: [""]
  98. resources: ["services"]
  99. resourceNames: ["heapster", "dashboard-metrics-scraper"]
  100. verbs: ["proxy"]
  101. - apiGroups: [""]
  102. resources: ["services/proxy"]
  103. resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
  104. verbs: ["get"]
  105. ---
  106. kind: ClusterRole
  107. apiVersion: rbac.authorization.k8s.io/v1
  108. metadata:
  109. labels:
  110. k8s-app: kubernetes-dashboard
  111. name: kubernetes-dashboard
  112. rules:
  113. # Allow Metrics Scraper to get metrics from the Metrics server
  114. - apiGroups: ["metrics.k8s.io"]
  115. resources: ["pods", "nodes"]
  116. verbs: ["get", "list", "watch"]
  117. ---
  118. apiVersion: rbac.authorization.k8s.io/v1
  119. kind: RoleBinding
  120. metadata:
  121. labels:
  122. k8s-app: kubernetes-dashboard
  123. name: kubernetes-dashboard
  124. namespace: kubernetes-dashboard
  125. roleRef:
  126. apiGroup: rbac.authorization.k8s.io
  127. kind: Role
  128. name: kubernetes-dashboard
  129. subjects:
  130. - kind: ServiceAccount
  131. name: kubernetes-dashboard
  132. namespace: kubernetes-dashboard
  133. ---
  134. apiVersion: rbac.authorization.k8s.io/v1
  135. kind: ClusterRoleBinding
  136. metadata:
  137. name: kubernetes-dashboard
  138. roleRef:
  139. apiGroup: rbac.authorization.k8s.io
  140. kind: ClusterRole
  141. name: kubernetes-dashboard
  142. subjects:
  143. - kind: ServiceAccount
  144. name: kubernetes-dashboard
  145. namespace: kubernetes-dashboard
  146. ---
  147. kind: Deployment
  148. apiVersion: apps/v1
  149. metadata:
  150. labels:
  151. k8s-app: kubernetes-dashboard
  152. name: kubernetes-dashboard
  153. namespace: kubernetes-dashboard
  154. spec:
  155. replicas: 1
  156. revisionHistoryLimit: 10
  157. selector:
  158. matchLabels:
  159. k8s-app: kubernetes-dashboard
  160. template:
  161. metadata:
  162. labels:
  163. k8s-app: kubernetes-dashboard
  164. spec:
  165. containers:
  166. - name: kubernetes-dashboard
  167. image: kubernetesui/dashboard:v2.0.0
  168. imagePullPolicy: Always
  169. ports:
  170. - containerPort: 8443
  171. protocol: TCP
  172. args:
  173. - --auto-generate-certificates
  174. - --namespace=kubernetes-dashboard
  175. # Uncomment the following line to manually specify Kubernetes API server Host
  176. # If not specified, Dashboard will attempt to auto discover the API server and connect
  177. # to it. Uncomment only if the default does not work.
  178. # - --apiserver-host=http://my-address:port
  179. volumeMounts:
  180. - name: kubernetes-dashboard-certs
  181. mountPath: /certs
  182. # Create on-disk volume to store exec logs
  183. - mountPath: /tmp
  184. name: tmp-volume
  185. livenessProbe:
  186. httpGet:
  187. scheme: HTTPS
  188. path: /
  189. port: 8443
  190. initialDelaySeconds: 30
  191. timeoutSeconds: 30
  192. securityContext:
  193. allowPrivilegeEscalation: false
  194. readOnlyRootFilesystem: true
  195. runAsUser: 1001
  196. runAsGroup: 2001
  197. volumes:
  198. - name: kubernetes-dashboard-certs
  199. secret:
  200. secretName: kubernetes-dashboard-certs
  201. - name: tmp-volume
  202. emptyDir: {}
  203. serviceAccountName: kubernetes-dashboard
  204. nodeSelector:
  205. "kubernetes.io/os": linux
  206. # Comment the following tolerations if Dashboard must not be deployed on master
  207. tolerations:
  208. - key: node-role.kubernetes.io/master
  209. effect: NoSchedule
  210. ---
  211. kind: Service
  212. apiVersion: v1
  213. metadata:
  214. labels:
  215. k8s-app: dashboard-metrics-scraper
  216. name: dashboard-metrics-scraper
  217. namespace: kubernetes-dashboard
  218. spec:
  219. ports:
  220. - port: 8000
  221. targetPort: 8000
  222. selector:
  223. k8s-app: dashboard-metrics-scraper
  224. ---
  225. kind: Deployment
  226. apiVersion: apps/v1
  227. metadata:
  228. labels:
  229. k8s-app: dashboard-metrics-scraper
  230. name: dashboard-metrics-scraper
  231. namespace: kubernetes-dashboard
  232. spec:
  233. replicas: 1
  234. revisionHistoryLimit: 10
  235. selector:
  236. matchLabels:
  237. k8s-app: dashboard-metrics-scraper
  238. template:
  239. metadata:
  240. labels:
  241. k8s-app: dashboard-metrics-scraper
  242. annotations:
  243. seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
  244. spec:
  245. containers:
  246. - name: dashboard-metrics-scraper
  247. image: kubernetesui/metrics-scraper:v1.0.4
  248. ports:
  249. - containerPort: 8000
  250. protocol: TCP
  251. livenessProbe:
  252. httpGet:
  253. scheme: HTTP
  254. path: /
  255. port: 8000
  256. initialDelaySeconds: 30
  257. timeoutSeconds: 30
  258. volumeMounts:
  259. - mountPath: /tmp
  260. name: tmp-volume
  261. securityContext:
  262. allowPrivilegeEscalation: false
  263. readOnlyRootFilesystem: true
  264. runAsUser: 1001
  265. runAsGroup: 2001
  266. serviceAccountName: kubernetes-dashboard
  267. nodeSelector:
  268. "kubernetes.io/os": linux
  269. # Comment the following tolerations if Dashboard must not be deployed on master
  270. tolerations:
  271. - key: node-role.kubernetes.io/master
  272. effect: NoSchedule
  273. volumes:
  274. - name: tmp-volume
  275. emptyDir: {}

3.2.1.1、recommended中包括了下面几个组件

  • Dashboard Service
  • Dashboard Deployment
  • Dashboard Role
  • RoleBinding
  • Dashboard Service Account
  • Dashboard Secret

Dashboard Service

  1. kind: Service
  2. ...
  3. k8s-app: kubernetes-dashboard
  4. ...
  5. spec:
  6. type: NodePort
  7. ports:
  8. - port: 443
  9. targetPort: 8443
  10. nodePort: 30000

Dashboard 对外提供服务设置,也指定了nodePort,这样我们可以通过物理机上的30000端口进行访问

Dashboard Deployment

  1. kind: Deployment
  2. ...
  3. k8s-app: kubernetes-dashboard
  4. ....

Dashboard的Deployment指定了其使用的ServiceAccount是kubernetes-dashboard。并且还将Secret kubernetes-dashboard-certs通过volumes挂在到pod内部的/certs路径。为何要挂载Secret ?原因是创建Secret 时会自动生成token。请注意参数—auto-generate-certificates,其表示Dashboard会自动生成证书。

Dashboard Role

  1. kind: Role
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. metadata:
  4. labels:
  5. k8s-app: kubernetes-dashboard
  6. name: kubernetes-dashboard
  7. namespace: kubernetes-dashboard
  8. rules:
  9. ...

如上定义了Dashboard 的角色,其角色名称为 kubernetes-dashboard,rules中清晰的列出了其拥有的多个权限。

RoleBinding

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: RoleBinding
  3. metadata:
  4. labels:
  5. k8s-app: kubernetes-dashboard
  6. name: kubernetes-dashboard
  7. namespace: kubernetes-dashboard
  8. roleRef:
  9. apiGroup: rbac.authorization.k8s.io
  10. kind: Role
  11. name: kubernetes-dashboard
  12. subjects:
  13. - kind: ServiceAccount
  14. name: kubernetes-dashboard
  15. namespace: kubernetes-dashboard

Dashboard的角色绑定,其名称为 kubernetes-dashboard,roleRef 中为被绑定的角色,subjects中为绑定的用户:kubernetes-dashboard

Dashboard Service Account

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. labels:
  5. k8s-app: kubernetes-dashboard
  6. name: kubernetes-dashboard
  7. namespace: kubernetes-dashboard

如上定义了Dashboard的用户,其类型为ServiceAccount,名称为kubernetes-dashboard

Dashboard Secret

  1. apiVersion: v1
  2. kind: Secret
  3. ...

3.3.2、web 页面

通过暴露的NodePort: 30000 访问 dashboard,页面如图(我这里通过 firefox 才能访问,chrome 都不行):https://localhost:30000/
【Kubernetes详解】(三)搭建Kubernetes Dashboard - 图2
这里有两种登录方式:

  • Token
  • Kubeconfig

我们使用 Token 的方式登录,获取 Token 方式如下:

  1. kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep kubernetes-dashboard | awk '{print $1}')

【Kubernetes详解】(三)搭建Kubernetes Dashboard - 图3
复制token,点击登录即可

3.3、到这里还没有完

通过3.2的步骤会出现下面问题:
【Kubernetes详解】(三)搭建Kubernetes Dashboard - 图4
出现上述问题的原因是因为,kubernetes-dashboard 这个账户的角色权限不够
解决:

3.3.3、创建dashboard-adminuser.yaml

  1. cat > dashboard-adminuser.yaml << EOF
  2. apiVersion: v1
  3. kind: ServiceAccount
  4. metadata:
  5. name: admin-user
  6. namespace: kubernetes-dashboard
  7. ---
  8. apiVersion: rbac.authorization.k8s.io/v1
  9. kind: ClusterRoleBinding
  10. metadata:
  11. name: admin-user
  12. roleRef:
  13. apiGroup: rbac.authorization.k8s.io
  14. kind: ClusterRole
  15. name: cluster-admin
  16. subjects:
  17. - kind: ServiceAccount
  18. name: admin-user
  19. namespace: kubernetes-dashboard
  20. EOF

3.3.2、创建登录用户

  1. kubectl apply -f dashboard-adminuser.yaml

说明:上面创建了一个叫 admin-user 的服务账号,并放在kubernetes-dashboard 命名空间下,并将 cluster-admin 角色绑定到admin-user账户,这样admin-user账户就有了管理员的权限。默认情况下,kubeadm创建集群时已经创建了cluster-admin角色,我们直接绑定即可。

3.3.3、查看admin-user账户的token

  1. kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')

重新登录即可
【Kubernetes详解】(三)搭建Kubernetes Dashboard - 图5

四、一些命令

  1. # 查看dashboard的角色(Role)
  2. kubectl get role -n kubernetes-dashboard
  3. # 查看dashboard的账户
  4. kubectl get ServiceAccount -n kubernetes-dashboard
  5. # 查看secret
  6. kubectl get secret -n kuberntes-dashboard
  7. # 查看集群的角色(ClusterRole)
  8. kubectl get ClusterRole -n kubernetes-dashboard