Appearance
安装 Kubernetes Dashboard 控制面板

前言
在 Kubernetes 集群中安装 Dashboard 是一个很常见的需求。本文档将指导你在各种 Kubernetes 环境中安装 Kubernetes Dashboard,包括 Docker Desktop、Minikube、kubeadm 部署的集群等。
注意:本文档基于 Dashboard v2.7.0 版本编写。请查看 Kubernetes Dashboard 发布页面 以确认最新稳定版本。
第一步:准备工作
1.1 拉取镜像(可选)
Dashboard 所需的镜像通常会在部署时自动拉取。但如果你的网络环境较差,或希望提前准备镜像,可以手动拉取。
shell
docker pull kubernetesui/dashboard:v2.7.0
docker pull kubernetesui/metrics-scraper:v1.0.8shell
ctr image pull docker.io/kubernetesui/dashboard:v2.7.0
ctr image pull docker.io/kubernetesui/metrics-scraper:v1.0.8shell
nerdctl pull kubernetesui/dashboard:v2.7.0
nerdctl pull kubernetesui/metrics-scraper:v1.0.8提示
- Docker:适用于 Docker Desktop、使用 Docker 作为运行时的集群
- containerd:适用于 Kubernetes 1.24+ 默认使用 containerd 的集群(如 kubeadm 部署)
- nerdctl:containerd 的 Docker 兼容命令行工具
💡 注意
containerd 的终端工具 ctr 在拉取镜像时,可能会因为网络环境问题而失败,这时可以拷贝一台可以连接国际互联网的代理工具提供的代理地址到该服务器以达到访问国际互联网的目的,话不多话,你懂得~
1. 提取 dashboard
bash
# 将 <your-proxy-ip> 替换为实际代理地址
HTTP_PROXY=http://<your-proxy-ip>:7890 \
HTTPS_PROXY=http://<your-proxy-ip>:7890 \
NO_PROXY=localhost,127.0.0.1,.local,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12 \
ctr image pull docker.io/kubernetesui/dashboard:v2.7.02. 提取 metrics-scraper
bash
# 将 <your-proxy-ip> 替换为实际代理地址
HTTP_PROXY=http://<your-proxy-ip>:7890 \
HTTPS_PROXY=http://<your-proxy-ip>:7890 \
NO_PROXY=localhost,127.0.0.1,.local,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12 \
ctr image pull docker.io/kubernetesui/metrics-scraper:v1.0.8为 kubelet 配置代理(可选)
如果希望 Pod 在调度时自动通过代理拉取镜像,需要为 kubelet 配置代理。在每个节点上执行:
bash
sudo mkdir -p /etc/systemd/system/kubelet.service.d
sudo tee /etc/systemd/system/kubelet.service.d/http-proxy.conf > /dev/null <<EOF
[Service]
Environment="HTTP_PROXY=http://<your-proxy-ip>:7890"
Environment="HTTPS_PROXY=http://<your-proxy-ip>:7890"
Environment="NO_PROXY=localhost,127.0.0.1,.local,10.0.0.0/8,192.168.0.0/16,172.16.0.0/12"
EOF
sudo systemctl daemon-reload
sudo systemctl restart kubelet⚠️ 特别提醒:如果代理 IP 是通过 DHCP 自动分配的,终端设备重启或重新接入网络后,代理 IP 可能会发生变化,导致 kubelet 无法正常拉取镜像。建议使用静态 IP 的代理节点,或在使用完成后及时删除 kubelet 的代理配置。
第二步:安装 Kubernetes Dashboard
Kubernetes Dashboard 项目官方提供了规范化的安装 YAML 清单文件,我们可以直接应用它。你可以通过 kubectl apply -f 应用线上文件,也可以将资源定义文件下载到本地进行存储和部署。
2.1 下载 Kubernetes Dashboard 资源定义
打开终端(Terminal),执行以下命令:
shell
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml -O kubernetes-dashboard.yaml如果 wget 不可用,也可以使用 curl:
shell
curl -L https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml -o kubernetes-dashboard.yaml注意
请务必查看 Kubernetes Dashboard 发布页面 以确认最新稳定版本。上述 URL 中的 v2.7.0 可能会随时间变化。如果遇到问题,请替换为最新的版本号。
2.2 部署 Dashboard 到 Kubernetes 环境
shell
kubectl apply -f kubernetes-dashboard.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 created2.3 验证安装
检查 Dashboard 的 Pod 是否正在运行。它会被创建在 kubernetes-dashboard 命名空间中。
bash
kubectl get pods -n kubernetes-dashboard等待 Pod 的状态变为 Running。输出应类似于:
NAME READY STATUS RESTARTS AGE
dashboard-metrics-scraper-5f44d5f6c6-9k5pj 1/1 Running 0 60s
kubernetes-dashboard-678bc9f755-2nx9r 1/1 Running 0 60s第三步:创建访问 Dashboard 的权限
默认安装的 Dashboard 具有最小的 RBAC(基于角色的访问控制)权限。我们需要创建一个拥有适当权限的 Service Account 来登录和访问集群资源。
3.1 编写 ServiceAccount 及 ClusterRoleBinding 资源定义文件
yaml
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警告
创建一个名为 admin-user 的 Service Account 并将其绑定到 cluster-admin 角色(拥有最高权限)。注意:在生产环境中,应授予更精细的权限。
3.2 部署 ServiceAccount 及 ClusterRoleBinding 资源定义到 Kubernetes 环境
shell
kubectl apply -f dashboard-adminuser.yaml第四步:访问 Dashboard
有几种方法可以访问 Dashboard,最简单的是通过 kubectl proxy。
方法一:使用 kubectl proxy(推荐,安全)
启动代理: 这个命令会在你的本地机器(127.0.0.1)和 Kubernetes API Server 之间创建一个安全的代理通道。
bashkubectl proxy代理启动后,会输出类似于
Starting to serve on 127.0.0.1:8001的信息。让这个终端窗口保持运行。访问 Dashboard: 现在,你可以在浏览器中访问以下 URL:
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/浏览器会打开 Dashboard 的登录界面。
方法二:使用 NodePort(不推荐用于生产,但有时更直接)
修改 Dashboard 服务类型: 默认的 Dashboard Service 是
ClusterIP类型,只能在集群内部访问。我们可以将其改为NodePort。bashkubectl patch svc kubernetes-dashboard -n kubernetes-dashboard -p '{"spec": {"type": "NodePort"}}'查找分配的端口:
bashkubectl get svc -n kubernetes-dashboard在输出中,找到
kubernetes-dashboard服务,你会看到PORT(S)列类似443:3xxxx/TCP。这里的3xxxx就是映射到你本地主机的端口号(NodePort)。访问 Dashboard: 在浏览器中访问:
https://<任意节点IP>:<NodePort>提醒
重要提示:由于证书问题,浏览器会显示安全警告。你需要点击"高级" -> "继续前往" 才能继续。

方法三:使用 Port Forward(快速调试)
如果你只想快速测试,可以使用 Port Forward:
bash
kubectl port-forward -n kubernetes-dashboard service/kubernetes-dashboard 8443:443然后访问:https://localhost:8443
第五步:获取令牌(Token)登录
无论使用哪种访问方法,你都会看到需要一个 Token 或 Kubeconfig 文件来登录。我们使用之前创建的 admin-user 的 Token。
5.1 获取登录令牌
执行以下命令获取 admin-user 的 Token:
shell
kubectl -n kubernetes-dashboard create token admin-usershell
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"这个命令会直接输出一个很长的新令牌。复制整个令牌字符串。
说明
- Kubernetes 1.24+:
create token命令会生成一个带有过期时间的短期令牌(默认 1 小时) - Kubernetes 1.23 及以下:从 Secret 中提取的令牌是长期有效的
- 如果需要创建长期有效的令牌,可以手动创建 Secret,或使用
--duration参数(如--duration=8760h表示 1 年)
5.2 登录 Dashboard
- 在登录界面,选择 Token。
- 将刚才复制的令牌粘贴到输入框中。
- 点击"登录"。
登录成功后,你就可以看到 Kubernetes Dashboard 的管理界面了,可以查看和管理你的集群中的所有资源。

第六步:后续配置建议(可选)
6.1 设置资源限制
在生产环境中,建议为 Dashboard Pod 设置资源限制。可以修改 kubernetes-dashboard.yaml 文件,在部署中添加:
yaml
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "200m"6.2 启用 HTTPS 和 Ingress
如需通过域名访问 Dashboard,建议配置 Ingress 并启用 HTTPS:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
tls:
- hosts:
- dashboard.example.com
secretName: dashboard-tls
rules:
- host: dashboard.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubernetes-dashboard
port:
number: 443故障排除
ImagePullBackOff
确保网络连接正常,能够从 k8s.gcr.io(或其镜像仓库)拉取镜像。国内用户可能会遇到网络问题,可以考虑使用镜像源。
解决方案:
- 修改 YAML 文件中的镜像地址为国内镜像源
- 或者手动拉取镜像到本地节点
无法登录
- 确认你复制了 整个 Token,它非常长,确保没有遗漏开头或结尾的字符
- 检查 Token 是否已过期(Kubernetes 1.24+ 默认 1 小时),可以重新生成
- 确认 ServiceAccount 和 ClusterRoleBinding 已正确创建
权限错误
确保你已经正确创建了 ClusterRoleBinding 并将 admin-user 绑定到了 cluster-admin 角色:
bash
kubectl get clusterrolebinding admin-user -o yaml浏览器无法访问
- 确认
kubectl proxy正在运行 - 检查防火墙是否放行了相关端口
- 如果使用 NodePort,确认节点 IP 和端口正确
Pod 一直处于 Pending 状态
检查节点资源是否充足:
bash
kubectl describe pod -n kubernetes-dashboard
kubectl top nodes卸载 Dashboard
bash
# 删除 Dashboard 资源
kubectl delete -f kubernetes-dashboard.yaml
# 删除管理员账号
kubectl delete -f dashboard-adminuser.yaml
# 删除命名空间(可选)
kubectl delete namespace kubernetes-dashboard参考链接
现在,你已经成功在你的 Kubernetes 集群中安装并运行了 Kubernetes Dashboard!🎉
附件
1. kubernetes-dashboard.yaml
点击查看详细的文件内容
如果您的网络环境无法访问 Github,可以使用博文提供的 kubernetes-dashboard.yaml,该文件与上面 wget 下载的文件内容完全一致!
yaml
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: v1
kind: Namespace
metadata:
name: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kubernetes-dashboard
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-csrf
namespace: kubernetes-dashboard
type: Opaque
data:
csrf: ""
---
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-key-holder
namespace: kubernetes-dashboard
type: Opaque
---
kind: ConfigMap
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-settings
namespace: kubernetes-dashboard
---
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.
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
verbs: ["get", "update", "delete"]
# 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.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster", "dashboard-metrics-scraper"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
rules:
# Allow Metrics Scraper to get metrics from the Metrics server
- apiGroups: ["metrics.k8s.io"]
resources: ["pods", "nodes"]
verbs: ["get", "list", "watch"]
---
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
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubernetes-dashboard
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kubernetes-dashboard
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.7.0
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --namespace=kubernetes-dashboard
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
ports:
- port: 8000
targetPort: 8000
selector:
k8s-app: dashboard-metrics-scraper
---
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: dashboard-metrics-scraper
name: dashboard-metrics-scraper
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: dashboard-metrics-scraper
template:
metadata:
labels:
k8s-app: dashboard-metrics-scraper
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: dashboard-metrics-scraper
image: kubernetesui/metrics-scraper:v1.0.8
ports:
- containerPort: 8000
protocol: TCP
livenessProbe:
httpGet:
scheme: HTTP
path: /
port: 8000
initialDelaySeconds: 30
timeoutSeconds: 30
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser: 1001
runAsGroup: 2001
serviceAccountName: kubernetes-dashboard
nodeSelector:
"kubernetes.io/os": linux
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
volumes:
- name: tmp-volume
emptyDir: {}2. dashboard-adminuser.yaml
点击查看详情的文件内容
该文件与 3.1 编写 ServiceAccount 及 ClusterRoleBinding 资源定义文件 小节描述的文件一致!
yaml
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