让headlamp控制台能访问

markdown 复制代码
# 2026-07-23 K3s 基准环境与 Headlamp 浏览器访问复盘 SOP
本文记录 2026-07-23 的排障过程。今天暂时不关注 CAS 和业务页面,只关注 K3s 基准环境、Gateway、ops-prod 中间件入口,以及通过浏览器访问 worker 节点上的 Headlamp 控制台。
## 一、今天目标
今天目标从"业务页面打开"收敛为:
```text
K3s 集群健康
节点标签正确
Gateway 入口健康
ops-prod 基准控制台 Headlamp 可用
Windows 浏览器可以访问 192.168.3.*** 上的 NodePort

最终成功打开:

text 复制代码
http://192.168.3.***:31116/headlamp/

这说明:

text 复制代码
Windows 浏览器
  -> 192.168.3.***:31116
  -> K3s NodePort
  -> ops-prod/headlamp Service
  -> headlamp Pod

这条基准访问链路已经打通。

二、当前角色与访问方式

机器角色

text 复制代码
192.168.3.*** = k3s-master-01
192.168.3.*** = k3s-worker-01
Windows 客户端 = 192.168.100.***

浏览器访问注意点

项目不是直接把服务暴露在 80 端口上,而是通过 NodePort 暴露。

所以不能只访问:

text 复制代码
http://192.168.3.***

要访问:

text 复制代码
http://192.168.3.***:<NodePort>/<path>

今天验证成功的是:

text 复制代码
Headlamp: http://192.168.3.***:31116/headlamp/

注意末尾必须有:

text 复制代码
/headlamp/

之前访问:

text 复制代码
http://192.168.3.***:31116

返回 404,是因为 Headlamp 配置了:

text 复制代码
-base-url=/headlamp

三、今天已确认健康的部分

1. K3s 节点健康

执行:

bash 复制代码
cd /root/k8s-config
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get nodes -o wide

现场输出:

text 复制代码
NAME            STATUS   ROLES           VERSION        INTERNAL-IP
k3s-master-01   Ready    control-plane   v1.35.5+k3s1   192.168.3.***
k3s-worker-01   Ready    <none>          v1.35.5+k3s1   192.168.3.***

结论:

text 复制代码
master Ready
worker Ready
K3s 集群基础状态正常

2. 节点标签正确

执行:

bash 复制代码
kubectl get nodes --show-labels | grep -E 'ingress-ready|middleware-role'

现场确认:

text 复制代码
k3s-master-01:
  middleware-role=core
  workload=control-plane
k3s-worker-01:
  ingress-ready=true
  middleware-role=general
  workload=ingress

这些标签符合项目里的调度设计:

text 复制代码
Nacos / RabbitMQ -> middleware-role=core
Redis / RocketMQ / MinIO / MongoDB / Headlamp -> middleware-role=general
Gateway 数据面 -> ingress-ready=true

如后续缺标签,可按实际节点名补:

bash 复制代码
kubectl label node k3s-master-01 middleware-role=core workload=control-plane --overwrite
kubectl label node k3s-worker-01 ingress-ready=true middleware-role=general workload=ingress --overwrite

3. Gateway 健康

执行:

bash 复制代码
kubectl get gateway -A
kubectl get svc private-gateway-nginx -n ops-prod
kubectl get pods -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -o wide
kubectl get endpoints private-gateway-nginx -n ops-prod

现场输出关键点:

text 复制代码
private-gateway PROGRAMMED=True
private-gateway-nginx NodePort 8080:30080/TCP
private-gateway-nginx Pod 1/1 Running
private-gateway-nginx Endpoint 10.42.1.***:8080

结论:

text 复制代码
Gateway 入口已经健康
今天不需要继续改 Gateway

4. Headlamp Pod 和 Service 健康

执行:

bash 复制代码
kubectl get pod,svc -n ops-prod | grep headlamp

现场输出:

text 复制代码
pod/headlamp-6cdc4bc94d-bjz9c   1/1 Running
service/headlamp                NodePort 80:31116/TCP

结论:

text 复制代码
Headlamp 已部署
Headlamp Pod 正常
Headlamp NodePort 为 31116

四、今天遇到的问题与解决

问题 1:重新梳理项目目标,先不关注 CAS

现象

之前排障过程中混在一起的层级很多:

text 复制代码
Gateway
Nacos
CAS
HTTPRoute
业务页面
中间件
浏览器访问

容易误以为浏览器打不开就一定是 CAS 或 Gateway 问题。

重新收敛后的目标

今天明确只关注:

text 复制代码
K3s 基准环境
ops-prod 中间件底座
浏览器能访问 worker 上的基础控制台

暂时不处理:

text 复制代码
CAS
业务服务
业务 UI

经验

排障时要先定层级,不要跨层乱查。

今天的最小闭环是:

text 复制代码
节点 Ready
-> 标签正确
-> Headlamp Pod Running
-> Headlamp NodePort 存在
-> 服务器 curl 200
-> Windows TCP 端口可达
-> 浏览器打开 Headlamp

问题 2:浏览器访问 192.168.3.*** 超时

现象

浏览器显示:

text 复制代码
This site can't be reached
192.168.3.*** took too long to respond.
ERR_CONNECTION_TIMED_OUT

判断

直接访问:

text 复制代码
http://192.168.3.***

默认访问的是 80 端口。

但项目当前主要入口是 NodePort:

text 复制代码
Headlamp: 31116
Gateway: 30080
Nacos: 30603

所以浏览器应访问:

text 复制代码
http://192.168.3.***:31116/headlamp/

经验

K8s NodePort 服务必须带端口访问。

格式:

text 复制代码
http://<worker-ip>:<nodeport>/<path>

问题 3:服务器上 curl 正常,但 Windows 访问超时

现象

服务器上测 NodePort 都返回 200:

bash 复制代码
curl -I http://192.168.3.***:31116/headlamp/
curl -I http://127.0.0.1:31116/headlamp/

但是 Windows PowerShell 测试失败:

powershell 复制代码
Test-NetConnection 192.168.3.*** -Port 31116

输出:

text 复制代码
PingSucceeded       : True
TcpTestSucceeded    : False

判断

这说明:

text 复制代码
IP 能 ping 通
TCP 端口 31116 不通

也就是说 K3s 和 Headlamp 自身没有坏,问题在 Windows 到 worker 的 TCP 端口访问。

解决

在 worker 192.168.3.*** 上检查 firewalld:

bash 复制代码
firewall-cmd --state
firewall-cmd --list-ports

放行本次需要的端口:

bash 复制代码
firewall-cmd --permanent --add-port=31116/tcp
firewall-cmd --permanent --add-port=30080/tcp
firewall-cmd --permanent --add-port=30603/tcp
firewall-cmd --reload
firewall-cmd --list-ports

现场最终端口列表:

text 复制代码
8848/tcp
80/tcp
6443/tcp
8472/udp
10250/tcp
30000-32767/tcp
31116/tcp
30080/tcp
30603/tcp

说明:

text 复制代码
31116 = Headlamp
30080 = Gateway
30603 = Nacos 控制台备用 NodePort
30000-32767/tcp = Kubernetes NodePort 默认范围

验证

回到 Windows PowerShell:

powershell 复制代码
Test-NetConnection 192.168.3.*** -Port 31116

期望:

text 复制代码
TcpTestSucceeded : True

随后浏览器访问:

text 复制代码
http://192.168.3.***:31116/headlamp/

今天最终已经成功进入 Headlamp 页面。

问题 4:/nacos/ 访问 500,不是 Gateway 问题,而是 Nacos 没部署

现象

访问:

bash 复制代码
curl -I -H "Host: jyjzhfw.qiantang.gov.cn" http://192.168.3.***:30080/nacos/

返回:

text 复制代码
HTTP/1.1 500 Internal Server Error

查询 Nacos 资源:

bash 复制代码
kubectl get pods -n ops-prod -l app=nacos -o wide
kubectl get svc nacos -n ops-prod -o wide
kubectl get endpoints nacos -n ops-prod
kubectl get endpointslice -n ops-prod -l kubernetes.io/service-name=nacos -o wide

输出:

text 复制代码
No resources found
services "nacos" not found
endpoints "nacos" not found

查询 HTTPRoute:

bash 复制代码
kubectl get httproute nacos-route -n ops-prod -o yaml
kubectl describe httproute nacos-route -n ops-prod

关键状态:

text 复制代码
Accepted=True
ResolvedRefs=False
Reason=BackendNotFound
Message=spec.rules[0].backendRefs[0].name: Not found: "nacos"

判断

nacos-route 配置本身是对的:

text 复制代码
Host: jyjzhfw.qiantang.gov.cn
Path: /nacos
Backend: nacos:8080

但后端 Service nacos 不存在。

结论

text 复制代码
/nacos/ 500 的原因不是 Gateway
而是 Nacos 中间件尚未部署

后续处理方向

后面要部署 Nacos,需要先准备外部 MySQL:

text 复制代码
导入 nacos.sql
配置 mysql-external
创建 nacos-secret
部署 Nacos
暴露 30603
浏览器访问 /nacos/

问题 5:nacos.sql 有用,但不是 kubectl apply 文件

发现

项目中有:

text 复制代码
k3s-private/middleware/nacos/data/nacos.sql

确认该 SQL 中包含:

text 复制代码
Data ID: tianyin-cas-prod.properties
Group: DEFAULT_GROUP
tenant_id: f54ff835-1dda-4b27-a174-fe40f416789e
type: properties

这说明它是一个 Nacos 数据库 dump,里面包含 Nacos 的配置表数据。

关键点

这个文件不是 Kubernetes YAML,不能执行:

bash 复制代码
kubectl apply -f nacos.sql

它应该导入外部 MySQL 的 nacos 数据库:

bash 复制代码
mysql -h <外部MySQL地址> -P 3306 -u <用户> -p nacos < /root/k8s-config/k3s-private/middleware/nacos/data/nacos.sql

风险

该 SQL 是完整 dump,包含:

text 复制代码
DROP TABLE
CREATE TABLE
INSERT INTO

所以导入前必须确认:

  • 是否是全新的 Nacos 库
  • 如果已有数据,必须先备份
    备份命令:
bash 复制代码
mysqldump -h <外部MySQL地址> -P 3306 -u <用户> -p nacos > /root/nacos-backup-$(date +%F-%H%M).sql

五、可复用 SOP:从零确认 Headlamp 浏览器访问

SOP 1:固定 kubectl 环境

在 master 上执行:

bash 复制代码
cd /root/k8s-config
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

SOP 2:检查节点

bash 复制代码
kubectl get nodes -o wide
kubectl get nodes --show-labels | grep -E 'ingress-ready|middleware-role'

期望:

text 复制代码
k3s-master-01 Ready middleware-role=core
k3s-worker-01 Ready ingress-ready=true middleware-role=general

缺标签时补:

bash 复制代码
kubectl label node k3s-master-01 middleware-role=core workload=control-plane --overwrite
kubectl label node k3s-worker-01 ingress-ready=true middleware-role=general workload=ingress --overwrite

SOP 3:检查 Gateway 基准入口

bash 复制代码
kubectl get gateway -A
kubectl get svc private-gateway-nginx -n ops-prod
kubectl get pods -n ops-prod -l gateway.networking.k8s.io/gateway-name=private-gateway -o wide
kubectl get endpoints private-gateway-nginx -n ops-prod

期望:

text 复制代码
Gateway PROGRAMMED=True
private-gateway-nginx NodePort 8080:30080/TCP
private-gateway-nginx Pod 1/1 Running
Endpoint 非空,例如 10.42.1.***:8080

Gateway 只用于统一域名入口。

Headlamp 当前直接用 NodePort 31116 访问,不依赖 Gateway。

SOP 4:检查 Headlamp

bash 复制代码
kubectl get pod,svc -n ops-prod | grep headlamp

期望:

text 复制代码
pod/headlamp-xxx 1/1 Running
service/headlamp NodePort 80:31116/TCP

如果 Headlamp 不存在,单独部署:

bash 复制代码
kubectl apply -f k3s-private/middleware/headlamp/rbac.yaml
kubectl apply -f k3s-private/middleware/headlamp/deployment.yaml
kubectl apply -f k3s-private/middleware/headlamp/service.yaml

如果 Service 不是 NodePort,可临时 patch:

bash 复制代码
kubectl patch svc headlamp -n ops-prod -p '{"spec":{"type":"NodePort","ports":[{"name":"http","port":80,"targetPort":4466,"nodePort":31116}]}}'

观察 Pod:

bash 复制代码
kubectl get pods -n ops-prod -l app=headlamp -w

看到 1/1 Running 后按 Ctrl + C

SOP 5:在服务器上验证 NodePort

在 master 上执行:

bash 复制代码
curl -I http://192.168.3.***:31116/headlamp/

在 worker 上执行:

bash 复制代码
curl -I http://127.0.0.1:31116/headlamp/
curl -I http://192.168.3.***:31116/headlamp/

期望:

text 复制代码
HTTP/1.1 200 OK

如果服务器上能返回 200,说明 K3s、Service、Pod 基本没问题。

SOP 6:在 Windows 上验证端口

Windows PowerShell:

powershell 复制代码
Test-NetConnection 192.168.3.*** -Port 31116

判断:

text 复制代码
TcpTestSucceeded=True  -> Windows 到 worker 端口通
TcpTestSucceeded=False -> 网络或防火墙阻断

如果 PingSucceeded=TrueTcpTestSucceeded=False,说明 IP 通但端口不通。

SOP 7:放行 worker 防火墙端口

在 worker 上执行:

bash 复制代码
firewall-cmd --state
firewall-cmd --list-ports

放行常用端口:

bash 复制代码
firewall-cmd --permanent --add-port=31116/tcp
firewall-cmd --permanent --add-port=30080/tcp
firewall-cmd --permanent --add-port=30603/tcp
firewall-cmd --reload
firewall-cmd --list-ports

如果提示:

text 复制代码
Warning: ALREADY_ENABLED

不是错误,表示已经放行。

再次在 Windows 测:

powershell 复制代码
Test-NetConnection 192.168.3.*** -Port 31116

成功后浏览器访问:

text 复制代码
http://192.168.3.***:31116/headlamp/

SOP 8:生成 Headlamp 登录 Token

在 master 上执行:

bash 复制代码
kubectl create token headlamp-admin -n ops-prod --duration=24h

浏览器中选择 Token 登录,粘贴完整 token。

说明:

text 复制代码
Headlamp 没有独立用户名密码
使用 Kubernetes ServiceAccount Token 登录

SOP 9:如果仍不能访问,使用 MobaXterm SSH Tunnel

如果 Windows 到 worker 的高端口被上级网络策略阻断,可以用 SSH 隧道临时绕过。

MobaXterm Tunnel 配置:

text 复制代码
Forwarded port: 31116
SSH server: 192.168.3.***
SSH login: root
Remote server: 127.0.0.1
Remote port: 31116

然后 Windows 浏览器访问:

text 复制代码
http://127.0.0.1:31116/headlamp/

六、中间件下一步路线

今天已经验证 Headlamp,可继续推进中间件。

中间件部署顺序建议:

text 复制代码
1. 准备外部 MySQL
2. 导入 nacos.sql 到外部 MySQL 的 nacos 库
3. 配置 mysql-external Service
4. 创建 nacos-secret
5. 部署 Nacos
6. 暴露 Nacos 控制台 30603
7. 浏览器访问 http://192.168.3.***:30603/nacos/
8. 再部署 Redis / RabbitMQ / RocketMQ / MinIO / MongoDB / ES 等

Nacos 最小部署命令草稿

先确认 SQL:

bash 复制代码
ls -lh /root/k8s-config/k3s-private/middleware/nacos/data/nacos.sql
grep -o "tianyin-cas-prod.properties" /root/k8s-config/k3s-private/middleware/nacos/data/nacos.sql | head

备份已有 Nacos 库:

bash 复制代码
mysqldump -h <外部MySQL地址> -P 3306 -u <用户> -p nacos > /root/nacos-backup-$(date +%F-%H%M).sql

导入:

bash 复制代码
mysql -h <外部MySQL地址> -P 3306 -u <用户> -p nacos < /root/k8s-config/k3s-private/middleware/nacos/data/nacos.sql

验证配置是否存在:

bash 复制代码
mysql -h <外部MySQL地址> -P 3306 -u <用户> -p nacos -e "select data_id,group_id,tenant_id from config_info where data_id='tianyin-cas-prod.properties';"

配置 MySQL IP 模式:

bash 复制代码
vi k3s-private/middleware/mysql/service-endpoints.yaml
kubectl apply -f k3s-private/middleware/mysql/service-endpoints.yaml

创建 Nacos Secret:

bash 复制代码
kubectl create secret generic nacos-secret -n ops-prod \
  --from-literal=mysql.password='<外部MySQL密码>' \
  --dry-run=client -o yaml | kubectl apply -f -

部署 Nacos:

bash 复制代码
kubectl apply -f k3s-private/middleware/nacos/configmap.yaml
kubectl apply -f k3s-private/middleware/nacos/pvc.yaml
kubectl apply -f k3s-private/middleware/nacos/service.yaml
kubectl apply -f k3s-private/middleware/nacos/statefulset.yaml
kubectl apply -f k3s-private/middleware/nacos/nacos-console-nodeport.yaml

观察:

bash 复制代码
kubectl get pods -n ops-prod -l app=nacos -w

检查:

bash 复制代码
kubectl get svc nacos -n ops-prod
kubectl get endpoints nacos -n ops-prod
kubectl get svc nacos-console-nodeport -n ops-prod

浏览器访问:

text 复制代码
http://192.168.3.***:30603/nacos/

七、今天沉淀的经验

1. 先验证最小闭环

不要一开始就追业务页面。

今天正确闭环是:

text 复制代码
K3s 节点 -> Headlamp Pod -> NodePort -> Windows 端口 -> 浏览器页面

2. 服务器 curl 200 不等于浏览器可访问

服务器本机 curl 成功,只能证明集群内部或服务器本机链路可用。

Windows 浏览器还需要额外确认:

powershell 复制代码
Test-NetConnection <ip> -Port <port>

3. Ping 通不等于端口通

今天 Windows 输出:

text 复制代码
PingSucceeded=True
TcpTestSucceeded=False

说明路由可达,但 TCP 端口被拦。

4. Headlamp 需要完整路径

正确:

text 复制代码
http://192.168.3.***:31116/headlamp/

错误或不完整:

text 复制代码
http://192.168.3.***
http://192.168.3.***:31116

5. HTTPRoute 后端不存在时,不要误判为 Gateway 坏了

nacos-route 的状态:

text 复制代码
Accepted=True
ResolvedRefs=False
BackendNotFound

含义是:

text 复制代码
路由对象被 Gateway 接受
但后端 Service 不存在

这种情况要部署后端中间件,不要反复改 Gateway。

6. SQL 文件和 YAML 文件用途不同

nacos.sql 用于外部 MySQL:

bash 复制代码
mysql ... < nacos.sql

K8s YAML 用于 Kubernetes:

bash 复制代码
kubectl apply -f xxx.yaml

不要混用。

八、当前状态快照

截至本次复盘:

text 复制代码
K3s 节点:Ready
节点标签:正确
Gateway:Programmed=True
Gateway NodePort:30080
Headlamp Pod:1/1 Running
Headlamp Service:NodePort 31116
Worker 防火墙:已放行 31116 / 30080 / 30603
Windows 浏览器:已成功打开 Headlamp
Nacos:尚未部署
Nacos SQL:已确认包含 tianyin-cas-prod.properties,可用于初始化外部 MySQL 的 nacos 库

要访问浏览器时候发现服务器端口无法访问,防火墙关了也没用。那就用mobaxterm ssh tulnel

间有网络策略 / 路由 / 上级防火墙拦截 TCP 高端口。这时直接用 MobaXterm SSH Tunnel:

本地端口: 3111X

SSH server: 192.168.x.251

远程地址: 127.0.0.1

远程端口: 3111x

然后浏览器访问:

http://127.0.0.1:3111x/headlamp/这一步具体在 mobaxterm 怎么操作

MobaXterm 图形界面配置【本地端口转发 Local port forwarding】(对应你的需求)

需求汇总:

本地端口:3111x

SSH 跳板机:192.168.x.251

远程目标:127.0.0.1:3111x(跳板机本机 Headlamp 服务)

访问地址:http://127.0.0.1:3111x/headlamp/

方式 A(独立隧道窗口,推荐,不依赖 SSH 会话)

打开MobaSSHTunnel

隧道参数界面

MobaXterm 顶部菜单:Tools → MobaSSHTunnel (port forwarding)

左下角点击 New SSH tunnel

选中:✅ Local port forwarding

按下面精确填写:

plaintext

Local forwarded port: 3111x

Remote server: 127.0.0.1

Remote port: 3111x

SSH server: 192.168.3.25x

SSH login: 填入登录192.168.x.251的账号(如root)

SSH port: 22(如果你的ssh不是22就改成对应端口)

点击 Save

在隧道列表选中这条规则,点上方 Start tunnel

弹出窗口输入服务器密码(或使用私钥),隧道成功建立

⚠️ 隧道窗口不能关闭,最小化即可;关闭隧道立刻断开。

隧道启动成功验证

Windows cmd 执行:

cmd

netstat -ano | findstr 31116

看到 127.0.0.1:31116 LISTENING 代表本地监听正常

  1. 浏览器打开:

plaintext

http://127.0.0.1:3111x/headlamp/

常见踩坑排查

3111x 端口被本地其他程序占用 → 修改 Local forwarded port 为别的端口

能 ssh 登录 192.168.3.251,但隧道不通:登录服务器执行

bash

curl http://127.0.0.1:311x/headlamp/

看 Headlamp 服务是否真的正常运行

  1. 防火墙拦截:确认 192.168.x.251 本地防火墙没有禁止 127.0.0.1:3x 访问

  2. 注意区分:Local port forwarding 不要选错成 Remote/Dynamic!

相关推荐
liuccn3 小时前
Linux 存储系统:LVM 与直接分区
linux·运维
想会飞的蒲公英3 小时前
用 Streamlit 给文本分类模型做一个演示页面
人工智能·python·机器学习
捷配链3 小时前
六层服务器板行业材料与工艺标准化选型指南
服务器·制造·pcb
老徐聊GEO3 小时前
亲测有效的AI品牌检测公司案例分享
大数据·人工智能·python
华研前沿标杆游学3 小时前
2026年企业对标学习TOP7项目:小米数字化考察上榜
python
大模型码小白4 小时前
Spring AI 框架实战:Java 后端集成大模型的架构设计与工程落地
java·人工智能·python·spring
BerryS3N4 小时前
深度解析:从零构建生产级大模型 RAG(检索增强生成)系统全栈指南
开发语言·python·ai
weixin_BYSJ19874 小时前
「课设设计」springboot校园超市助购系统26449 (附源码)
java·javascript·spring boot·python·django·flask·php
今儿敲了吗4 小时前
Python——函数基础
开发语言·笔记·python