访问K8s Dashboard的几种方式

一. 背景知识

Kubernetes Dashboard 是 Kubernetes 的官方 Web UI. 通过Kubernetes Dashboard, 我们可以方便地管理资源和部署应用. 从 dashboard-1.7.x 起, 只允许 localhost 访问. 那么如何方便从本地访问dashboard呢? 本文介绍几种方案.

二. 安装

2.1 安装Dashboard

参考官方文档, 执行下面的命令可以快速安装dashboard v2.0.0:

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

以上文件在国内因为众所周知的原因可能无法正常下载. 简单的解决方案就是在 github 上打开 recommended.yaml, 然后复制代码保存到本地, 然后再执行:

kubectl apply -f ./recommended.yaml

输出类似于:

namespace/kubernetes-dashboard created
serviceaccount/kubernetes-dashboard created
service/kubernetes-dashboard created
secret/kubernetes-dashboard-certs created
secret/kubernetes-dashboard-csrf created
secret/kubernetes-dashboard-key-holder created
configmap/kubernetes-dashboard-settings created
role.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created
deployment.apps/kubernetes-dashboard created
service/dashboard-metrics-scraper created
deployment.apps/dashboard-metrics-scraper created

查看状态:

$ kubectl get deployment --namespace=kubernetes-dashboard kubernetes-dashboard
# 或
$ kubectl describe deployment --namespace=kubernetes-dashboard kubernetes-dashboard

# 查看service
$ kubectl get service --namespace=kubernetes-dashboard kubernetes-dashboard

# 另外查看pod状态
$ kubectl --namespace=kubernetes-dashboard get pod -o wide | grep dashboard

$ kubectl --namespace=kubernetes-dashboard get pod -o wide | grep dashboard
# 输出
dashboard-metrics-scraper-6b4884c9d5-czx9f   1/1     Running             1          11h     10.244.0.12   ttg12   <none>           <none>
kubernetes-dashboard-7b544877d5-cd2b7        0/1     ContainerCreating   0          8m28s   <none>        ttg12   <none>           <none>

# 如果状态一直是, 使用describe查看具体过程
$ kubectl describe pod --namespace=kubernetes-dashboard
# 输出
...
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned kubernetes-dashboard/kubernetes-dashboard-7b544877d5-cd2b7 to ttg12
  Normal  Pulling    9m36s      kubelet, ttg12     Pulling image "kubernetesui/dashboard:v2.0.0"

如果image一直pull不下来, 可以用dao先pull下来:

dao pull kubernetesui/dashboard:v2.0.0

如果 pod 状态都为 Running, 表示安装已经成功:

kubectl --namespace=kubernetes-dashboard get pod -o wide | grep dashboard

输出类似于:

dashboard-metrics-scraper-6b4884c9d5-czx9f   1/1     Running   1          11h   10.244.0.12   ttg12   <none>           <none>
kubernetes-dashboard-7b544877d5-cd2b7        1/1     Running   0          27m   10.244.0.14   ttg12   <none>           <none>

2.2 添加用户和 Token

Dashboard支持 KubeconfigToken 两种认证方式. 本文是Demo演示, 所以通过配置文件 dashboard-admin.yaml 为Dashboard默认用户赋予 admin 权限. 具体可参考官方文档.

2.2.1 添加用户和绑定角色

新建 dash-admin-user.yml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard

应用新建的配置:

$ kubectl apply -f dash-admin-user.yaml
# 输出
serviceaccount/admin-user created
clusterrolebinding.rbac.authorization.k8s.io/admin-user created

2.2.2 生成登录token

执行下面的命令, 生成登录用的token:

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

输出类似于:

get secret | grep admin-user | awk '{print $1}')ashboard describe secret $(kubectl -n kubernetes-dashboard g
Name:         admin-user-token-795sl
Namespace:    kubernetes-dashboard
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: c628f987-abdc-4ef3-a237-ff47ec177a31

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  20 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6I.................f8zqqH7Q

最后这一行的token, 复制下来, 下一步登录要用.

三. 访问Dashboard

3.1 本地安装了 kubectl, 并且可以直接访问到 master 的 IP

如果本地(工作电脑)上安装了 kubectl, 并且可以直接访问到 master 的 IP, 那么就很简单, 可以直接在本地启动 k8s proxy:

# 前台启动, 注意会占用终端窗口
kubectl proxy

然后访问: http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

3.2 本地没有安装 kubectl, 但是可以直接访问到 master 的 IP

如果本地没有安装 kubectl, 但是可以直接访问到 master 的 IP, 那么可以在 master (假设 hostname 为 ttg12, 当然也可以是集群内任意一台安装了 kubectl 的机器, 这里为了简便就简化到 master 上, 下同) 上开启 k8s proxy:

kubectl proxy --address='0.0.0.0' --accept-hosts='^\*$' &

这时候我们可以访问到 Dashboard 的登录页面, http://ttg12:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/, 但是如果我们选择 "Token" 模式, 并输入上面记录的token, 点击"Sign in", 心里默数三下, 等待进入期待已久的主页面...

然后事实却是, 你数了10遍1-2-3, 页面还是没有任何反应.

于是你想到按下F12, 打开浏览器的调试窗口"Networking". 发现登录是登录成功了, 但是config接口却返回了状态401.
image.png

原因是, 即便 proxy 允许外网访问, 但是从 dashboard-1.7.x 起, 只允许 localhost 访问. Github 有人提过 issue, 但是回复说这是 feature, 不是 bug, 怪只怪初学者不懂的太多.

所以, 我们需要通过端口转发来访问localhost. 有如下2种方法.

3.2.1 方法一: kubectl port-forward

注意: 这种方法适合有正式ssl证书的情况. 如果没有, 先用方法二进行访问.

In an environment where one needs to access the dashboard from another host than the kubectl proxy's localhost, one can run: kubectl port-forward --namespace kubernetes-dashboard service/kubernetes-dashboard 10443:443 --address 0.0.0.0 to access the dashboard through HTTPS

然后访问: https://ttg12:10443.

不过因为测试环境没有正式的ssl证书, 所以浏览器会拒绝访问. 需要采用方法二.

3.2.2 方法二: ssh端口转发

在工作电脑(需要能 ssh 连接 k8s master)上, 使用以下命令转发端口:

$ ssh -L localhost:8001:localhost:8001 -NT faceless@ttg12
faceless@ttg12's password:

输入master机器faceless账号的登录密码后, 转发成功.

然后通过如下本地地址访问:
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.

终于见到 Dashboard 主页本尊.
image.png

3.3 本地没有安装 kubectl, 且不可直接访问到 master 的 IP

这种情况一般是 k8s 集群完全在内网, 日常访问通过跳板机进行, 这也是生产环境正常的状态. 这种情况下, 我们有2种方案.

3.3.1 在跳板机启动 kube-proxy, 然后本地 ssh 端口转发

首先在跳板机上启动 kube-proxy (假设跳板机的 hostname 是 ttg11):

kubectl proxy --address='0.0.0.0' --accept-hosts='^\*$' &

然后本地 ssh 端口转发到跳板机:

ssh -L localhost:8001:localhost:8001 -NT weiping@ttg11

然后通过如下本地地址访问:
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.

3.3.2 本地直接通过跳板机 ssh 端口转发到 k8s master

首先在 k8s master (或内网上的其他机器) 上启动 kube-proxy (假定 k8s master的 hostname 是 ttg12):

kubectl proxy --address='0.0.0.0' --accept-hosts='^\*$' &

然后本地端口通过跳板机 (假设跳板机的 hostname 是 ttg11) ssh 转发到 k8s master 上:

# 格式为: ssh -L localhost:<本地使用端口>:<k8s-master-IP或域名>:<k8s-master-port> -NT <跳板机登录账户>@<跳板机IP或域名>
ssh -L localhost:8001:ttg12:8001 -NT weiping@ttg11

然后通过如下本地地址访问:
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.

四. 参考

阅读 227

推荐阅读