Kubernetes Dashboard 是一个 Web UI 的集群管理工具。项目主页在这里
首先根据它的主页上 README 里面的内容直接 kubectl apply -f recommended.yaml
,这样集群中就会创建并运行 dashboard 的 POD。
接下来的问题是如何从外界访问到这个 UI。
我的 k8s 集群环境是一台物理主机上的三台虚拟机,每个虚拟机都是 Headless 启动,也就是说纯命令行没有桌面环境,无法打开浏览器,因此项目主页上说的 kubectl proxy
访问 http://localhost:8001
的方式不适用。
我希望最终能从物理主机上访问到这个 WebUI。
使用 NodePort
我们查看一下 kubernetes-dashboard
使用 recommended.yaml
部署之后 service 的类型是 ClusterIP
$ kubectl get svc --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
default redis-nodeport NodePort 10.96.39.42 <none> 6379:31250/TCP 15d
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 17d
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.96.160.248 <none> 8000/TCP 6m44s
kubernetes-dashboard kubernetes-dashboard ClusterIP 10.96.132.59 <none> 443/TCP 6m45s
ClusterIP 是在 k8s 集群内部可以访问的 IP,在集群之外(例如我的物理主机)是无法 ping 通的,因此改成 NodePort 类型。
运行 edit 命令
$ kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
把 ClusterIP 改成 NodePort,保存并退出。
apiVersion: v1
kind: Service
metadata:
...
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
resourceVersion: "362415"
spec:
clusterIP: 10.96.132.59
externalTrafficPolicy: Cluster
ports:
- nodePort: 32410
port: 443
protocol: TCP
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
sessionAffinity: None
type: NodePort // 原来是 ClusterIP
status:
loadBalancer: {}
之后我们再看 service 的信息。
kubectl get svc --all-namespaces
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17d
default redis-nodeport NodePort 10.96.39.42 <none> 6379:31250/TCP 15d
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 17d
kubernetes-dashboard dashboard-metrics-scraper ClusterIP 10.96.160.248 <none> 8000/TCP 14m
kubernetes-dashboard kubernetes-dashboard NodePort 10.96.132.59 <none> 443:32410/TCP 14m
可见 dashboard 的类型变成了 NodePort 并且 PORT 中多了一个 443:32410
, 意思是 k8s 把集群内部的 443 端口映射到 32410 给集群外部访问。
这时,这个 service 在集群内部还是可以通过 10.96.132.59 端口 443 访问,对应到外部,通过访问集群中的任何一个节点 IP 加端口 32410 即可。
于是通过 https://192.168.56.10:32410/ 可以看到下面的界面
创建 admin role
可以看到 dashboard 让你选择一种方式登录,这里我选择 token 的方式。
用下面这个 yaml 格式配置文件,创建 admin用户并赋予他管理员权限。
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
这种认证方式本质实际上是通过 Service Account 的身份认证加上 Bearer token 请求 API server 的方式,参考 Kubernetes 中的认证。
获取 token
$ kubectl -n kube-system get secret|grep admin-token
admin-token-25s5j kubernetes.io/service-account-token 3 11s
$ kubectl -n kube-system describe secret admin-token-25s5j
Name: admin-token-25s5j
Namespace: kube-system
...
ca.crt: 1025 bytes
namespace: 11 bytes
token: eyJhbG.....
最后把 token 复制到浏览器里就可以登录了。
Role-based Access Control
既然上面提到了 role 和 service account 的概念,那么再多说几句 RBAC。 所谓 RBAC 是 k8s 中管理账户和权限的概念,是 Role-based Access Control 的缩写。 它的基本概念是 Role 和 RoleBinding。
Role是一些 permission 的集合;而 RoleBinding 则是将 Role 授权给某些 User、某些 Group 或某些 ServiceAccount,他们的作用域都是在特定的 Namespace。
此外,k8s 还有一个特殊的 ClusterRole 和 ClusterRoleBinding,它的作用域是整个集群。
以 dashboard 官网上下载的 recommended.yaml 为例,看看这三者的关系。
首先是创建一个 account, ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
然后是 Role,定义了这个 role 的权限。
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
rules:
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
# Allow Dashboard to get metrics.
最后是把 account 绑定到 role 上。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
所以上面 3 个定义做了这样一件事:在 kubernetes-dashboard
的名空间创建名为 kubernetes-dashboard
的账户,和名为 kubernetes-dashboard
的 role,最后把它们绑定在一起。
按照 recommended.yaml 的内容,似乎不需要上面的 “创建 admin role” 这一步骤了,我是根据网上教程加了 admin 这一步。现在回想起来,可能默认的只是在 dashboard 的名空间权限不够,admin role 则是 ClusterRole 的权限。 到底是不是这样以后再说吧,下一步要先把玩一下 kubeflow 。
(完)