
1. 确认集群状态部署面板前必须解决的三个前置问题先说明一下我这边的环境避免后面讲的步骤大家照着做对不上号。我用的是三台 Rocky Linux 9 组成的 k8s 集群版本是 1.28 和 1.30 各跑过一轮热词里有人提到 rocky 装 k8s 1.36那个比较新我还没在生产环境验证过后面会提一下注意事项。master 节点初始化的时候也踩过 api server not healthy 的经典坑这部分我放到后面专门讲。任何 k8s 部署 dashboard 面板的教程只要不是从集群状态检查开始都是在坑你。原因很简单dashboard 本身只是一个控制面插件它依赖集群的 api server、etcd、coredns 这些基础组件正常工作。集群都没起来面板装上去只会看到一片报错。动手之前我习惯先跑三组命令确认状态。kubectl version --short注意看 Server 版本是否正常显示如果这里直接报 connection refused说明 kubeconfig 的 server 地址配置有问题或者 master 组件的容器没有正常启动。kubectl get nodes看所有节点是否处于 Ready 状态。如果某个节点一直是 NotReady先排查该节点上的 kubelet 日志而不是急着装 dashboard。kubectl get pods -n kube-system看 coredns 和其他系统组件的状态。这里尤其注意 coredns 是否为 Runningdashboard 的很多操作依赖 DNS 解析coredns 挂了dashboard 登录后大概率会出现各种内部请求超时。这里有个很多人忽略的细节dashboard 部署之前最好确认一下集群的存储类StorageClass是否存在。如果后面想给 dashboard 开启指标持久化或者做其他扩展没有默认存储类会比较被动。查看方式kubectl get sc1.1 版本匹配问题dashboard 和 k8s 的兼容性不能想当然k8s 的版本迭代非常快dashboard 的 release 页面会明确标注支持哪些 k8s 版本范围。拿热词里有人提到的 k8s 1.36 来说如果集群刚升级到 1.36而 dashboard 官方还没有发布针对性的兼容测试最稳妥的做法是先用最新 stable 版本同时关注 dashboard 项目的 release note。我自己实际部署的经验是dashboard v2.7.0 用在 k8s 1.24 到 1.28 上都比较稳dashboard v3.x 在新版本集群上表现更好比如支持了更细粒度的权限控制。所以刚上手的人建议直接去 dashboard 的 GitHub releases 页面看当前最新稳定版而不是随便百度找一个旧版本的命令复制粘贴。另外说个很多人不知道的点dashboard 的镜像 tag 是跟着 dashboard 版本走的比如kubernetesui/dashboard:v2.7.0跟 k8s 的版本号没有直接对应关系。判断镜像是否匹配集群版本以官方推荐的recommended.yaml为准那个文件里写的镜像版本是经过官方测试组合的。配一张我当时整理的选择参考基于 dashboard 官方信息和个人经验Dashboard 版本兼容的 k8s 版本我的使用体验v2.7.01.24 ~ 1.28稳定老项目首选v3.0.x1.27 ~ 1.31权限模型更清晰最新 v3.1.x1.28优先推荐UI 响应更快2. 下载并修改 YAML两个必须动手改的字段网上搜 k8s dashboard 部署教程百分之九十会让你执行一句kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml然后没了。这句话本身没问题但直接用了会踩两个坑。第一个坑GitHub raw 地址在国内网络环境经常拉取超时。我之前在公司网络下执行的时候连续三次卡在下载中间直接断连。解决办法是去能访问的机器上下载好 YAML 文件传上来或者用代理的方式拉取。考虑到不少刚接触 k8s 的朋友用的是云服务器我这里给两条稳妥路径方式一有公网访问条件的话直接在服务器上用 curl 或 wget 把文件拉下来然后断网场景下也可以留着备份再用。方式二如果拉不下来可以在有网络的本机上下载再通过 scp 传到服务器。第二个坑是关键——直接 apply 默认 YAML 后dashboard 的 Service 类型是 ClusterIP这意味着你只能在集群内部访问它。外部浏览器根本打不开。所以修改 YAML 的时候必须把 Service 的类型改成 NodePort或者用 kubectl proxy 的方式转发。我这次记录的是改成 NodePort 的方案因为操作直观、适合验证环境而且不需要额外代码。直接在下载好的 YAML 里定位到kubernetes-dashboard这个 Service 的定义把type: ClusterIP改成type: NodePort。2.1 离线环境的镜像处理思路再讲一个大家迟早会遇到的情况服务器在内网环境根本无法直接拉取 Docker Hub 的镜像。dashboard 的 recommended.yaml 会在集群里创建好几个 Deployment它们需要的镜像主要是kubernetesui/dashboardkubernetesui/metrics-scraper内网环境的处理逻辑是在一台有外网的机器上先 docker pull 这些镜像然后 docker save 打成 tar 包传到内网节点上再用 docker load 导入。导入之后还要注意——如果你没有修改 YAML 里的 image 字段节点会尝试按原地址拉取发现本地已有镜像时才不会去远端拉。这里有个小坑值得单独说明如果节点的容器运行时是 containerd而不是 docker那么docker load是没用的。你需要用ctr -n k8s.io images import的方式来导入镜像否则 dashboard 的 Pod 起来后会一直报拉取镜像失败。我用的 containerd 导入命令是这个格式ctr -n k8s.io images import dashboard.tar如果集群里装了 nerdctl也可以用nerdctl load -i dashboard.tar效果一样。总之先搞清楚你节点的容器运行时是什么再去决定导入镜像的工具链。3. 部署并验证从 apply 到页面弹出的完整过程我习惯先把 YAML 文件放到一个固定目录里比如/opt/k8s/dashboard/然后执行 apply。这里再提醒一句如果你改过 Service 类型apply 的 YAML 必须是你本地修改过的版本不要又去 apply 线上原始版的 URL。kubectl apply -f recommended.yaml正常输出应该是 namespace、serviceaccount、secret、configmap、deployment、service、ingress 等资源依次显示 created。如果有资源显示 already exists说明你之前已经部署过一次了这时候建议先确认版本是否一致再决定是否继续。apply 完后查看 dashboard 相关的 Pod 状态kubectl get pods -n kubernetes-dashboard正常情况下会看到类似这样的输出Pod 名称状态dashboard-metrics-scraper-xxxRunningkubernetes-dashboard-xxxRunning如果 Pod 一直处于 ContainerCreating用kubectl describe pod -n kubernetes-dashboard pod名称查看事件最常见原因是镜像拉取失败上面提到的离线环境导入问题或者镜像不兼容当前架构。比如在 arm64 架构的节点上拉取了 amd64 镜像就会出现执行格式错误的报错。Pod 状态变成 Running 后查看 Service 自动分配的 NodePort 端口kubectl get svc -n kubernetes-dashboard输出里会有一列 PORT(S)类似443:30412/TCP那么 30412 就是这个集群节点上暴露出来的 HTTPS 端口。浏览器访问方式为https://任意节点IP:30412注意是 HTTPS浏览器会提示证书不受信任这一点在后一节详细说先不用管。3.1 证书不受信任的处理方式浏览器第一次访问 dashboard 的 HTTPS 端口几乎必然看到“您的连接不是私密连接”的警告。这是正常的因为 dashboard 用的证书是自己生成的、没有经过权威 CA 签署。两个处理思路思路一适合测试环境在浏览器警告页选择“高级” - “继续前往”强行进入页面。Chrome 的提示顺序可能不同版本稍有差异但逻辑一致。这种方法最省事我自己测试环境就是这么干的。思路二适合正式环境让 dashboard 使用一个受信任的证书。做法是把你的正式证书和私钥放到 Kubernetes 的 Secret 中然后在 dashboard 的 Deployment 里配置证书路径。dashboard 支持通过--tls-cert-file和--tls-key-file参数指定证书。实践来看大部分玩家部署 dashboard 都是测试和验证用途思路一足够了。等真到了生产环境通常也不会直接暴露 dashboard 端口而是通过 Ingress Controller 正式证书来做访问入口。所以证书问题并不用过度纠结。3.2 端口是否可以修改NodePort 默认分配的 30000-32767 区间的端口是随机挑选的你不一定喜欢。如果想固定到一个好记的端口比如 30001可以直接修改 Service YAML 中nodePort字段spec: type: NodePort ports: - port: 443 targetPort: 8443 nodePort: 30001修改后执行kubectl apply -f recommended.yaml如果端口已经被占用会提示失败。换个端口即可。4. 创建管理员账号并获取 Token完整的登录链路dashboard 部署起来只是第一步登录才是大部分人卡壳的地方。dashboard 默认不走 kubeconfig 登录而是需要创建一个 ServiceAccount 并绑定管理员权限然后拿这个账号的 Token 去登录页面换取认证。如果你跳过这个过程直接用kubectl get secrets随便拿一个 Secret 里的 Token 去登录大概率会得到“禁止访问”的提示。这一步涉及 Kubernetes 的 RBAC 权限模型。Dashboard 登录后的操作都走 API Server 的权限校验你给这个 ServiceAccount 绑定什么权限登录后就能看到什么功能。只给只读权限那资源列表可以看但无法创建或删除。我的建议是从一开始就创建一个管理员账号省得后面反复调整。以下是完整的 YAML 文件apiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboardapiVersion: 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保存为dashboard-admin.yaml然后执行kubectl apply -f dashboard-admin.yaml这个 ClusterRoleBinding 将 admin-user 绑定了 cluster-admin 集群角色即拥有整个集群的最高管理权限。实战中如果你只想给某个团队单独管理某个 namespace 的权限可以自定义 Role 和 RoleBinding但这里按下不表。4.1 获取 Token一个新版本必须踩过的命令差异k8s 1.24 版本之后ServiceAccount 的 Secret 不再是自动创建的情况发生了明显变化。你如果按老的教程执行kubectl get secret -n kubernetes-dashboard会发现根本没有新的 Secret 被创建出来。这是因为 k8s 1.24 开始ServiceAccount 默认不再自动生成长期有效的 Secret Token而是使用 TokenRequest API 动态生成短时 Token。但 dashboard 的登录页需要一个静态的 Token怎么办呢两种方式方式一手动为 admin-user 创建 Secret并绑定 annotation 让它关联到 ServiceAccount。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然后 apply 之后再获取kubectl get secret admin-user-token -n kubernetes-dashboard -o jsonpath{.data.token} | base64 -d方式二直接用 kubectl create token 命令动态生成一个 Tokenkubectl create token admin-user -n kubernetes-dashboard但这里有个差异值得注意kubectl create token默认生成的 Token 有效期较短默认1小时如果你拿这个 Token 去登录过一会儿会失效。而用 Secret 方式获取的 Token 是长期有效的除非手动删除这个 Secret。两种方式的适用场景不同。临时登录验证方式二很方便长期使用方式一更靠谱。4.2 Token 过期后如何重新登录如果你用的是短时 Token登录进去后过一小时再去操作页面会跳回登录页或者提示 token expired。处理方式就是重新用kubectl create token admin-user -n kubernetes-dashboard生成一个新的再粘贴登录。而用长期 Secret Token 方式登录一般不会遇到这个问题。这就是我建议用方式一的原因少一些折腾。5. 部署后必查项网络、权限、存储和日志排查思路Dashboard 能登录只是第一个里程碑。登录进去之后常见的几个问题会依次浮出水面。我把这些问题集中放在一个小节里方便大家按图索骥。5.1 关于热词中“master 初始化显示 the api server is not healthy after 4m”的排查回顾这个报错是 kubeadm init 阶段最常见的坑之一很多人在装完 cluster 准备部署 dashboard 之前就被这一步挡住了。我当时踩这个坑时的现象是执行kubeadm init之后日志里反复出现the api server is not healthy after 4m0.00747357s最终 init 失败。定位了一圈最核心的原因是 kubelet 的容器运行时配置与 kubeadm 默认的 CRI 套接字不匹配或者节点的 swap 未关闭、系统参数不符合要求。针对这个情况我的排查链路是这样走的第一步检查容器运行时。确认 containerd 是否已安装并正常运行systemctl status containerd如果 containerd 没启动kubelet找不到 CRI 套接字api server 自然无法健康检查通过。第二步检查 kubelet 配置。看/var/lib/kubelet/kubeadm-flags.env或/etc/sysconfig/kubelet里的参数是否有关于容器运行时的错误指定。比如把运行时的--container-runtime-endpoint指向了 docker 的 socket而实际使用的是 containerd就会出问题。第三步看 kubelet 日志。日志里一般会说明 api server 健康检查失败的具体原因journalctl -u kubelet -f最常见的日志信息是连接某个端口超时或 tls 握手失败。第四步检查系统约束。swapoff -a是必须要做的并且要在/etc/fstab中注释掉 swap 挂载行。还有模块加载br_netfilter和overlay这些也是 kubelet 和容器网络正常工作的基础。我当时的问题就在于/etc/fstab里的 swap 没有彻底关闭导致 kubelet 启动后频繁重启api server 容器起来又挂掉最终 init 失败。如果你也遇到热词里这个报错不要急着去重装整个集群先按上面步骤把环境和容器运行时检查一遍。5.2 Dashboard 页面打不开或白屏应用部署好、Pod 也在运行但浏览器打不开。我见过的原因主要分三种第一防火墙或者安全组没有放行对应端口。云服务器的话安全组入方向规则里必须放行你设置的 NodePort 端口。本地虚拟机的话检查 firewalld 或 iptables 是否有拦截规则。firewall-cmd --list-all # 查看现有规则 firewall-cmd --add-port30001/tcp --permanent firewall-cmd --reload第二访问的节点 IP 和端口不匹配。NodePort 是在所有节点上都会监听的端口你在哪个节点都能访问前提是 IP 正确且节点之间网络本来就是互通的。如果访问的节点处于 NotReady 状态或者网络不通自然打不开。第三Dashboard 的 HTTPS 证书方式导致页面空白。常见于新版浏览器强制升级 HTTPS 连接时如果浏览器拦截了不安全证书且没有允许继续访问的按钮页面会一直停留在错误页。这时候用curl -k https://节点IP:端口确认服务响应是正常的排除服务问题。5.3 CPU 和内存消耗异常dashboard 部署后发现某个节点 CPU 占用明显上升。大多数情况下是 dashboard 的资源请求和节点本身配置不匹配导致的。recommended.yaml 里默认的 resources 配置对小型实验环境来说偏高可以通过修改 Deployment 里的 resources 字段来调整resources: requests: memory: 200Mi cpu: 100m limits: memory: 300Mi cpu: 200m修改后重启 Podkubectl rollout restart deployment kubernetes-dashboard -n kubernetes-dashboard5.4 登录后某个页面一直转圈登录后打开节点或工作负载页面不停加载数据。这个现象通常指向集群内部的 DNS 解析问题或 metrics-server 没装。Dashboard 首页的工作负载图表数据依赖 metrics-server 提供指标如果 metrics-server 没部署force 刷新会一直转圈各项指标显示不出来。验证方法kubectl get pods -n kube-system | grep metrics-server如果没有相关的 Pod就需要部署 metrics-server。这是 dashboard 展示曲线数据的前提也是一个被很多人忽略的隐藏依赖。装好之后回到 dashboard 页面刷新图表数据就会逐渐出来。6. 生产环境的一点额外建议虽然前面的步骤已经能让你在测试环境完整体验 dashboard 功能了但如果你这个面板是给团队正式使用的几个细节值得额外考虑。第一不要直接暴露 NodePort 给公网。Dashboard 是集群管理入口直接暴露公网意味着任何拿到 URL 的人都有可能发起暴力破解尝试。我的实践是用 Ingress 证书做 HTTPS 入口同时在前置网关限制来源 IP。第二Token 的保管方式。管理员 Token 的权限是集群最高权限千万不要直接写在代码里或者随意分享给无关人员。第三定期查看 dashboard 自身的日志。Dashboard 不是静态资源它会和 API Server 有大量交互。如果某个功能突然不可用优先查看 dashboard Pod 的日志kubectl logs -f deployment/kubernetes-dashboard -n kubernetes-dashboard日志里会有清晰的错误原因比如权限不足、访问超时等比瞎猜高效得多。我自己在大大小小的集群上部署过很多次 dashboard每次步入正轨后最先做的一步其实还是顺手翻一眼 Pod 日志和系统事件。部署本身不难难的是部署之后真正把它作为集群驾驶舱来使用遇到异常能用正确的排查思路去定位。希望我这里记录的踩坑经历能让你在部署 dashboard 的路上少走几段弯路。