最近不少朋友在群里问 k8s dashboard 的部署问题,从单节点测试环境到生产集群都有。其实 dashboard 本身部署不难,难的是部署完之后怎么访问、怎么登录、权限怎么控制,以及出问题时怎么排查。我先后在几个集群上部署过多次 dashboard,中间踩了不少坑,这篇就把整个过程完整梳理一遍,从最基础的安装到安全加固都讲清楚,新手可以直接照着抄,老手可以直接跳到第四节和第六节看访问方式和排障记录。
先说结论:dashboard 是 Kubernetes 官方提供的 Web 管理面板,能让你在一个浏览器界面里看到集群几乎所有资源的状态,包括节点、Pod、工作负载、配置、存储等。它不替换 kubectl,而是补上 kubectl 的短板——你可以在界面上直接看日志、进入容器执行命令、查看事件、编辑 YAML,不用在终端里敲一串串命令。适合的场景很明确:团队里不是每个人都有 kubectl 权限,或者你想快速直观地了解集群当前状态,dashboard 就是最直接的门面。
1. 部署前的环境准备:版本匹配决定成败
1.1 先确认你的集群版本
部署 dashboard 之前,我强烈建议你先确认两件事:第一,集群本身是不是健康的;第二,dashboard 版本和 k8s 版本是否兼容。很多人在第二步栽了跟头——dashboard 版本太旧,和 k8s 1.25+ 的 API 对不上,结果是 Pod 起来了,页面却一直报错。
先看集群状态:
kubectl get nodes kubectl get pods -n kube-system确保所有节点都是 Ready 状态,核心组件(kube-apiserver、kube-controller-manager、kube-scheduler)都正常运行。如果集群本身有问题,比如主节点初始化时出现过The API server is not healthy之类的告警,那得先解决集群的问题,再谈部署 dashboard,否则排查起来会分不清是集群的问题还是 dashboard 的问题。
再对比版本兼容性。官方 dashboard 项目里明确标注了支持矩阵,一般建议选择与集群主版本差距不超过一个小版本的 dashboard 版本。比如 k8s 版本在 1.28 左右,dashboard 用 v2.7.x 系列就比较稳。不要图新直接上未发布的开发版,也不要在新版 k8s 上硬套 v1.x 的老 dashboard,这两个极端我都见过别人踩坑。
1.2 镜像拉取和网络环境要提前准备
dashboard 部署涉及的镜像主要是kubernetesui/dashboard和kubernetesui/metrics-scraper。如果你的集群能正常访问 Docker Hub 等镜像仓库,直接拉取没问题;但很多企业内网环境或者云上环境需要提前 pull 镜像、推到私有仓库,再做一个简单的替换。
我实际用下来的做法是:先在有外网的机器上把指定 tag 的镜像拉下来,然后推送到内网 registry,部署时修改 YAML 里的 image 字段。注意 YAML 里 dashboard 的镜像 tag 必须和拉取的 tag 完全一致,不要默认用 latest,否则内网环境无法解析、Pod 会一直 ImagePullBackOff。
另外提醒一个环境相关的细节:如果你用的是 containerd 作为运行时,拉取镜像时遇到证书问题,要先确认containerd的 registry 配置和config_path是不是指向了正确的/etc/containerd/certs.d,这个排查点很多人想不到。
2. dashboard 安装实操:官方 manifest 是最靠谱的入口
2.1 下载并应用官方清单文件
dashboard 官方提供了完整的部署清单,recommended.yaml里包含了 Deployment、Service、RBAC、ServiceAccount 等一整套资源,不需要你手动拆分。安装命令非常简单:
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml kubectl apply -f recommended.yaml这里有一点要说清楚:不要随便在网上下载转发的旧版本 YAML。我在排查别人集群时遇到过,用的 YAML 是从博客复制来的三年前版本,集群是 1.29,结果 dashboard 一直报 CRD 版本不兼容。官方路径是最稳妥的,如果你需要访问 GitHub 受限,可以把文件先下载到本地再上传到能访问集群的机器上执行。
执行完之后,你会看到创建了kubernetes-dashboard这个 namespace,里面包括 dashboard 和 metrics-scraper 两个核心工作负载,以及一堆 RBAC 相关的资源。可以用下面命令确认状态:
kubectl get pods -n kubernetes-dashboard kubectl get svc -n kubernetes-dashboard正常情况下,dashboard 的 Pod 是 Running 状态,service 名字是kubernetes-dashboard,类型是 ClusterIP。如果你看到 Pod 一直 Pending 或者 CrashLoopBackOff,先按第六节的排障清单排查。
2.2 创建管理员账号:RBAC 配置别省
官方清单默认创建的kubernetes-dashboardServiceAccount 权限非常有限,主要供 dashboard 自身运行使用。你用默认的账号登录进去,会发现几乎什么都看不到,这是因为 dashboard 是以你登录的身份去调用 API server 的,登录身份权限不够,界面自然一片空。
所以部署完 dashboard 之后,紧接着的一步就是创建一个管理员账号。我习惯这么做:
cat <<EOF | kubectl apply -f - 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 EOFadmin-user绑定了cluster-adminClusterRole,也就是集群最高权限。生产环境我不建议给所有日常使用者都发 cluster-admin,但这个账号用来做集群管理员自己的登录入口是合理的。如果只是想在某个 namespace 里看日志、看 Pod,请按最小权限原则创建 Role 和 RoleBinding,而不是一律 cluster-admin。
2.3 验证核心组件是否就绪
安装完成后,不要急着访问,先看两个关键点:metrics-scraper 是否在运行,dashboard 的 Deployment 副本是否就绪。
kubectl get deployment -n kubernetes-dashboard kubectl logs -n kubernetes-dashboard deployment/kubernetes-dashboard --tail=20我在实际部署中遇到过 metrics-scraper 反复重启的情况,最后定位到是 RBAC 权限里缺少metrics.k8s.io的访问权限。如果你的集群装了 metrics-server,dashboard 右上角的 CPU/内存曲线才能显示,否则图表区域是空的,这不是 dashboard 坏了,只是它拿不到指标数据。
检查完这些,dashboard 的 Pod 和 Service 都正常了,接下来才是重头戏——怎么访问它。
3. 三种访问方式:本地代理、NodePort、Ingress 怎么选
3.1 kubectl proxy:最安全也最折腾
kubectl proxy 是官方最推荐的访问方式,因为它不用把 dashboard 暴露到外部网络,直接在你的本机和服务之间建立一条加密通道:
kubectl proxy然后浏览器打开:
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/这个方式的原理是 kubectl 读取了你的 kubeconfig 认证信息,以你的身份去访问 API server,再由 API server 转发到 dashboard Service。好处是不暴露任何额外的网络端口,适合在开发机、办公电脑上快速看一眼集群;坏处是代理进程一旦关掉,页面就断了,而且手机等其他设备没法访问。
这里有个易错点:URL 里那一长串路径不能写错,尤其是https:后面的冒号和 namespace 名字的大小写。如果写成http而不是https,服务会直接 404 或跳转失败。
3.2 NodePort:快速暴露给局域网,但注意端口段
如果想让同网段的同事也能访问 dashboard,把 Service 改成 NodePort 是最快的方案。两种改法,一种是直接编辑官方 Service:
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard把type: ClusterIP改成type: NodePort,保存后:
kubectl get svc -n kubernetes-dashboard你会看到类似8080:31234/TCP的映射,冒号后面的31234就是集群任意节点上的访问端口。浏览器打开https://节点IP:31234就能看到登录页。
也可以用更干净的方式,单独创建一个 NodePort 类型的 Service,不修改官方 YAML:
apiVersion: v1 kind: Service metadata: name: dashboard-nodeport namespace: kubernetes-dashboard spec: type: NodePort ports: - port: 443 targetPort: 8443 nodePort: 30443 selector: k8s-app: kubernetes-dashboardNodePort 的端口范围默认是 30000-32767,如果指定的 nodePort 不在范围内,kube-apiserver 会拒绝创建。另外提醒一句,NodePort 方式下 dashboard 的证书用的是自签名证书,浏览器会提示不安全,需要你手动信任或者自行替换证书,这块第四节和第七节都会再讲。
3.3 Ingress:生产环境真正的打开方式
在正式集群里,我一般推荐用 Ingress 把 dashboard 挂在域名下面。这不仅能用 HTTPS 和自有域名访问,还能统一走 Ingress Controller 的流量管理。
创建 Ingress 之前,先确认集群里已经安装了 Ingress Controller(比如 nginx-ingress 或 traefik)。然后写一个最小配置:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: dashboard-ingress namespace: kubernetes-dashboard annotations: nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" spec: ingressClassName: nginx rules: - host: dashboard.example.com http: paths: - path: / pathType: Prefix backend: service: name: kubernetes-dashboard port: number: 443关键点是backend-protocol: "HTTPS",这个注解必须加。dashboard 的 Service 对外暴露的是 443,Ingress 转发时如果默认按 HTTP 去连后端,dashboard 会返回奇怪的 502 或者在浏览器里出现乱码,这个坑我帮人排查过好几次。
Ingress 的好处是一旦配好,就不用再关心 NodePort 那些端口了,TLS 证书也可以挂在 Ingress 上,统一管理。
4. 登录认证:Token 和 kubeconfig 两种姿势
4.1 获取 Token:2.7 版本前后的差异
访问页面之后,dashboard 会要求你登录,支持 Token 和 kubeconfig 文件两种方式。Token 方式对普通用户最友好。
对于 v2.7.0 及更新的版本,获取管理员 Token 的命令是:
kubectl -n kubernetes-dashboard create token admin-user这条命令会创建一个短期 token,按我自己实测,有效期大约一个多小时,到期后需要重新生成。这也是新版 dashboard 变化比较大的地方——老版本生成的 token 基本是永久有效的,新版本默认加了过期时间。
如果你需要查看一个长期有效的 token,可以找到 admin-user 对应的 Secret:
kubectl -n kubernetes-dashboard get secret kubectl -n kubernetes-dashboard get secret admin-user -o jsonpath="{.data.token}" | base64 -d注意在新版本里,ServiceAccount 默认的 Secret 类型是kubernetes.io/service-account-token,有的环境会自动创建,有的没有,需要手动创建 Secret 并指定注解。命令如下:
apiVersion: v1 kind: Secret metadata: name: admin-user-token namespace: kubernetes-dashboard annotations: kubernetes.io/service-account.name: admin-user type: kubernetes.io/service-account-token创建后用上面那条get secret ... | base64 -d的方式读取。
4.2 用 kubeconfig 文件登录
如果你的本地 kubeconfig 本身就配置了高权限用户,也可以直接选 kubeconfig 方式登录。做法是把集群的 admin kubeconfig(一般是/etc/kubernetes/admin.conf或者云平台提供的 kubeconfig)上传到 dashboard 页面。
但要明确一个安全点:dashboard 会使用 kubeconfig 里指定的用户身份去请求 API server。如果你上传的是一个 cluster-admin 的 kubeconfig,那你在页面上的操作权限就是 cluster-admin。有些团队开发机共享一个高权限 kubeconfig,大家都拿它登录 dashboard,一旦有人误删 namespace,后果很严重。我建议每个使用者单独分发 kubeconfig,哪怕权限相同,也要保证身份可追溯。kubeconfig 文件上传到浏览器之后,会被浏览器存储在本地 IndexedDB 里,不要在公共电脑上用这种方式登录。
4.3 不想登录直接跳过?测试环境才建议
dashboard 支持通过参数跳过登录流程。修改 Deployment 的启动参数,在--auto-generate-certificates后面加上--enable-skip-login,配置成手动登录时浏览器左下方会出现 "Skip" 按钮。这个功能官方并不推荐,因为它会绕过所有鉴权,谁拿到 IP 谁就能以最高权限操作集群。我在测试机、临时环境确实这么干过,图方便;但生产环境我相信你不会想去冒这个险。
5. 核心概念补充:RBAC 和 SA 是 dashboard 背后的关键
5.1 为什么登录用的是 ServiceAccount 而不是普通用户
如果你接触过 OpenShift 或者其他 PaaS 平台的认证体系,可能会觉得 k8s 的登录很原始。其实 k8s 原生的"用户"概念是抽象的:证书里的 CN、token 的持有者,都被视为一种身份。真正对 API server 发请求且能被鉴权的,是 ServiceAccount 或者有效的凭证(kubeconfig 里的 client-certificate)。
所以 dashboard 的登录本质不是它自己去认证,而是把你输入的 token 或 kubeconfig 转交给 API server 去校验。API server 返回"你以什么身份访问",dashboard 再根据这个身份展示对应权限的数据。理解这一点,很多登录后的权限困惑就迎刃而解了:页面右上角有个人图标,点开能看到当前身份和使用的保护范围,如果页面一片空白,先看这里显示的权限是不是 cluster-admin。
5.2 最小权限原则:别把所有账号都绑 cluster-admin
生产环境我建议至少准备两个角色:
- 管理员角色:绑定
cluster-admin,负责集群资源、节点、命名空间的全局管理,这个账号给运维同事用。 - 普通用户角色:按 namespace 绑定
edit或者自定义的 Role,给业务开发同事用,让他们能看日志、改 Deployment、管理 ConfigMap,但对节点和集群级资源没有操作权限。
创建方式大致是:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: app-developer namespace: myapp rules: - apiGroups: ["", "apps", "batch", "networking.k8s.io"] resources: ["pods", "pods/log", "deployments", "statefulsets", "services", "configmaps", "secrets", "ingresses", "jobs"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]然后创建对应的 ServiceAccount 并绑定 Role。这样即使有人拿到这个 token,破坏范围也被限制在myapp这个 namespace 内。
6. 常见问题与排障实录
6.1 Pod 一直 Pending
最常见原因是节点资源不足或者调度失败。先用kubectl describe pod -n kubernetes-dashboard <pod>看事件,如果是Insufficient cpu或Insufficient memory,说明节点资源不够,要么扩容,要么调整 dashboard 的 resources 请求。如果事件显示的是0/1 nodes are available加上 taint 信息,那是节点有污点,去掉或者容忍即可。
还有一类场景是 dashboard 被调度到了有 GPU 或者特殊标签的节点,恰恰这些节点不可用导致 Pending。这种情况给 Deployment 加 nodeSelector 反而更稳。
6.2 页面一直 503 Service Unavailable
这个报错大多出在访问方式上。我遇到过三种情况:
第一种:用 NodePort 访问但 Service 没建对,selector 没有匹配到 dashboard 的 Pod。检查kubectl get endpoints -n kubernetes-dashboard,如果 Endpoints 为空,八成是 selector 的 label 写错了。
第二种:用 Ingress 访问但忘记加backend-protocol: "HTTPS",Ingress 后端以 HTTP 去连 dashboard 的 443 端口,导致请求无法完成。
第三种:dashboard Deployment 有多个副本,但某一个副本 CrashLoopBackOff,外部访问被路由到了不健康的副本上,产生间歇性 503。看所有副本的 Running 状态,而不是只看一个。
6.3 登录后显示 Forbidden 或者一片空白
这种问题基本都是 RBAC 权限导致的。用 token 登录后虽然能进页面,但没有权限列出某种资源,界面就什么都不显示。先用 kubectl 验证当前身份:
kubectl auth can-i list pods -n kubernetes-dashboard --as=system:serviceaccount:kubernetes-dashboard:admin-user如果返回 no,说明 ClusterRoleBinding 没生效或绑错了 namespace。我见过有人把 ServiceAccount 创建在 default namespace,但 binding 的 subjects 里写的是kubernetes-dashboard,结果当然不匹配。检查kubectl get clusterrolebinding admin-user -o yaml,重点看 subjects 的 namespace 和 name。
6.4 metrics-scraper 崩溃导致指标区域空白
metrics-scraper 需要读取 metrics API。如果你确认集群里已经部署了 metrics-server,但 dashboard 的指标图表仍为空白,多是因为 RBAC 没有授权。查看 metrics-scraper 的日志:
kubectl logs -n kubernetes-dashboard deployment/dashboard-metrics-scraper --tail=20日志里通常会有明文报错。按报错内容给 ServiceAccount 补metrics.k8s.io的 get/list/watch 权限即可。
我把高频问题整理成一张速查表,方便你按症状定位:
| 症状 | 大概率方向 | 快速验证命令 |
|---|---|---|
| Pod 一直 Pending | 节点资源不足或污点 | kubectl describe pod <pod> -n kubernetes-dashboard |
| 安装后无法拉取镜像 | 镜像仓库不通或 tag 不对 | kubectl describe pod <pod>查看 Events |
| 页面 503 | Service selector 或 Ingress 后端协议不对 | kubectl get endpoints -n kubernetes-dashboard |
| Token 登录无效 | Token 过期或 SA 不存在 | kubectl get sa -n kubernetes-dashboard |
| 界面一片空白 | RBAC 权限不足 | kubectl auth can-i list pods --as=system:serviceaccount:kubernetes-dashboard:admin-user |
| 指标图表为空 | metrics-server 或 metrics-scraper 异常 | kubectl top nodes先验证 metrics API 是否可用 |
| 浏览器提示证书错误 | 自签名证书 | 临时信任或更换正式证书(见第七节) |
7. 生产环境安全加固建议
7.1 替换自签名证书
dashboard 默认自动生成自签名证书,浏览器会报不安全。生产环境应该把证书换成可信 CA 签发的证书。思路是创建一个包含证书和私钥的 Secret,然后让 dashboard 使用这个 Secret 作为证书来源:
kubectl -n kubernetes-dashboard create secret tls kubernetes-dashboard-certs \ --cert=tls.crt \ --key=tls.key注意 Secret 名字必须是kubernetes-dashboard-certs(官方 Deployment 默认挂载这个名称的 Secret),而且证书文件名需要是tls.crt和tls.key,否则 dashboard 启动时找不到证书文件会直接起不来。改完证书需要重启 Deployment 才能生效。
如果你的域名解析和控制面板权限都到位,更省事的做法是直接用 cert-manager 签发证书,证书以 Secret 形式放在 dashboard 的 namespace 下,自动续期,运维负担会小很多。
7.2 限制资源用量和副本数
dashboard 本身很轻,但一旦集群规模大、访问并发高,内存飙升的情况我也见过。给 Deployment 加上 resources 限制是必要的:
resources: requests: cpu: 100m memory: 200Mi limits: cpu: 500m memory: 800Mi注意如果设置 limits 过低,集群运行一段时间后 dashboard 可能出现 OOMKilled,页面登录后各种操作变卡甚至崩溃。建议内存 limits 不低于 512Mi,然后通过监控逐步调整。
7.3 关闭匿名访问和 Skip 按钮
确认 Deployment 的启动参数里没有--enable-skip-login,也确认没有挂载--enable-insecure-login这类参数。生产环境最好只保留 Token 登录入口,关闭任何绕过鉴权的通道。如果你用 Ingress,还可以前面加一层 BasicAuth 或者 OAuth2 Proxy,把 dashboard 的暴露范围进一步收窄。
7.4 关注审计与访问日志
dashboard 自身的访问是走 API server 的,如果集群开启了审计日志,dashboard 的每个操作都会记录到 apiserver 审计日志里。建议给 admin 级别的角色单独绑定到具体人员,不要大家共用一个 cluster-admin 账号,否则出了事故很难定位是谁干的。集群管理层面,这也是 k8s 面试时常被问到的点——"多个管理员共用一个 ServiceAccount 有什么风险",实际工作中真的会出问题。
8. 部署完之后的下一步:从面板到监控
dashboard 跑起来只是第一步。我一直觉得 dashboard 更适合做"浏览和诊断",而不是长期监控工具。它没有告警、没有趋势报表,看个历史数据也不方便。所以把 dashboard 搭好之后,我建议继续做这几件事:
- 部署 metrics-server,让
kubectl top和 dashboard 的图表都能显示数据。 - 如果集群里没有日志聚合能力,可以考虑加一层 EFK 或者 Loki,dashboard 只是能看 Pod 日志,但对多副本滚动发布期间的日志追溯很弱。
- dashboard 的访问入口统一挂到 Ingress 上,配合公司现有的 SSO 体系,这样才能让团队里非运维同事安全地用上它。
补充一个部署时的小建议:官方 recommended.yaml 里 Service 是与 Deployment 分开定义的,你在改 NodePort 的时候可以直接修改 Service 定义,不用动 Deployment。但如果用kubectl edit修改 Service,保存后如果 selector 或端口被你不小心改乱了,用kubectl delete svc删掉再 apply 新 Service 就好,不会影响已经运行的 dashboard Pod。
最后再说一个大多数人容易忽略的细节:dashboard 在页面上编辑 YAML 时,本身不会校验所有字段的兼容性。有些人在界面里修改 Deployment 的镜像字段,保存后返回 YAML 发现多了或少了字段,导致应用失败。这时候更稳的流程是先在本地改好 YAML,用 kubectl diff 对比,再 apply。面板好用,但底线还是用命令行处理关键变更。
我个人的习惯是:把 dashboard 的部署清单和后续创建的所有 RBAC 资源都收进一个单独的 Git 仓库里,每次集群升级前先看一遍 dashboard 版本兼容性,再决定要不要升级面板。这样才能真正把 dashboard 当成集群基础设施的一部分来管理,而不是"装完就忘"。