KubeBYON 公网访问改造清单(LoadBalancer 方案)
最后更新:2026-04-11
目标:把当前以
NodePort为中心的公网访问实现,改造成支持多宿主机 / 多节点宿主集群的LoadBalancer方案。注:该文档属于设计记录。其中多数改造点已经落地,阅读当前行为时请以
current-architecture.md、http-api.md与相关 runbook 为准。
1. 背景
当前 KubeBYON 的 vCluster 公网访问实现以 NodePort 为主,适合单机或“单固定入口”场景,但对真正的多机宿主集群支持还不完整。
当前代码中的几个关键限制:
- vCluster Service 暴露模式只围绕
NodePort / ClusterIP设计 clusters表只保存一个control_plane_host,默认更像“单固定入口”- 创建和更新流程都默认
public_access_enabled=true -> NodePort - 当时前端与系统设置里还没有“公网暴露模式”概念
- 多机部署时,即使宿主 k3s 能调度多个 vCluster control plane,对外入口仍然容易绑定到某一台宿主机 IP
因此,本次改造选择:
- 保留现有
public_access_enabled - 增加
public_access_mode - 新增并支持
loadbalancer模式 - 第一阶段要求
LoadBalancer模式下显式提供control_plane_host
2. 改造目标
2.1 本次目标
- 支持集群公网访问模式:
nodeportloadbalancer
- 关闭公网访问时仍然落到
ClusterIP - 管理员可配置“新建集群默认公网模式”
- 前端可在创建集群、编辑集群时选择模式
- 后端在
LoadBalancer模式下正确返回:api_endpointkubeconfig- 连接探测结果
- 文档补齐多机部署前提(MetalLB / 云 LB 等)
2.2 第一阶段约束
为避免 TLS SAN 与动态地址不匹配,第一阶段约束如下:
- 当
public_access_enabled=true且public_access_mode=loadbalancer时:control_plane_host必须非空- 后端需把该地址注入 vCluster
extraSANs
也就是说,第一阶段不直接依赖“LB 动态分配出来的 IP”作为证书名,而是要求提前规划:
- 预留 IP
- 统一域名
- 或可稳定访问的 VIP / LB Hostname
3. 非目标
本次不包含以下内容:
- 不把普通 HTTP Ingress 直接用作 Kubernetes API Server 代理
- 不在本次引入 Gateway API / TLSRoute / TCP Route
- 不在本次把默认存储从
local-path替换为共享存储 - 不在本次处理“vCluster control plane 均匀摊到所有宿主机”的调度优化
- 不在本次重新设计 join 脚本主链路
这些能力可作为后续阶段继续推进。
4. 总体设计
4.1 集群公网访问模式语义
建议使用:
public_access_enabled=false:- Service 最终应为
ClusterIP
- Service 最终应为
public_access_enabled=true && public_access_mode=nodeport:- Service 最终应为
NodePort
- Service 最终应为
public_access_enabled=true && public_access_mode=loadbalancer:- Service 最终应为
LoadBalancer
- Service 最终应为
4.2 第一阶段推荐校验规则
| 条件 | 校验 |
|---|---|
public_access_enabled=false | 允许不填 control_plane_host |
public_access_mode=nodeport | 允许按当前逻辑继续使用 |
public_access_mode=loadbalancer | 必须填写 control_plane_host |
4.3 保留字段的兼容策略
public_access_enabled:继续保留,兼容现有开关逻辑public_access_port:- 仅在
nodeport模式下有意义 loadbalancer模式下应清空或忽略
- 仅在
api_endpoint:- 由连接探测逻辑按实际 Service 类型回写
5. 详细改造清单
5.1 领域模型与数据库
目标
在后端模型和数据库里显式保存公网访问模式。
需修改文件
internal/domain/cluster/cluster.gointernal/infra/repository/sql.gointernal/infra/repository/sql_test.godocs/architecture/database-design.md(功能落地后同步更新)
具体改造
- 在
cluster.Cluster中新增字段:PublicAccessMode string(建议后续再收敛成强类型)
- 给
clusters表增加列:public_access_mode TEXT NOT NULL DEFAULT 'nodeport'
- 更新 SQL:
- select columns
- insert
- update
- scan
- 老数据迁移策略:
- 所有历史集群默认回填
nodeport
- 所有历史集群默认回填
验收点
- 旧集群升级后不报错
- 新旧数据都能正确读写
public_access_mode
5.2 系统设置:增加默认公网模式
目标
让管理员在系统设置中配置“新建集群默认采用 NodePort 还是 LoadBalancer”。
需修改文件
internal/domain/settings/system_settings.gointernal/app/admin_system_settings.gointernal/api/http/admin_system_settings.gointernal/infra/repository/sql_system_settings.goweb/lib/console-api.tsweb/app/dashboard/admin/settings/page.tsxweb/i18n/messages/*.json
具体改造
新增系统设置字段,例如:
default_cluster_public_access_mode
建议可选值:
nodeportloadbalancer
推荐默认值
- 单机 / 简化部署:
nodeport - 多宿主机集群:
loadbalancer
验收点
- 管理员保存后可持久化
- 新建集群默认带出该值
5.3 创建集群接口支持 public_access_mode
目标
创建集群时即可指定公网模式。
需修改文件
internal/api/http/handlers.gointernal/app/service.gointernal/api/http/console.goweb/lib/console-api.ts
具体改造
POST /api/console/clusters请求体增加字段:public_access_mode
CreateClusterInput增加字段:PublicAccessMode
- 创建逻辑改为:
- 请求有值 -> 使用请求值
- 请求无值 -> 使用系统默认值
- 第一阶段增加校验:
- 如果
public_access_enabled=true且public_access_mode=loadbalancer - 则
control_plane_host必填
- 如果
验收点
- 能创建
nodeport集群 - 能创建
loadbalancer集群 loadbalancer+ 空control_plane_host被正确拒绝
5.4 更新集群接口支持切换公网模式
目标
让已有集群可以在 nodeport / loadbalancer / 关闭公网 三种状态间切换。
需修改文件
internal/api/http/handlers.gointernal/app/cluster_quota.goweb/app/dashboard/clusters/[id]/page.tsxweb/lib/console-api.tsweb/i18n/messages/*.json
具体改造
updateClusterRequest增加:public_access_mode
UpdateClusterResourcesInput增加:PublicAccessMode *string
hasChanges()增加对 mode 的判断describeClusterSettingsChange()文案同步覆盖 mode- 异步更新逻辑补 mode 的同步与回写
额外注意
切换模式时必须避免旧元数据残留:
nodeport -> loadbalancer- 不能继续向前端暴露旧
public_access_port
- 不能继续向前端暴露旧
loadbalancer -> nodeport- 要重新允许
public_access_port回写
- 要重新允许
public_access_enabled=false- 要清空
api_endpoint - 要清空
kubeconfig_available
- 要清空
验收点
- 模式切换成功
- 前端回显与数据库一致
- 不残留旧模式元数据
5.5 vCluster Helm values 支持 LoadBalancer
目标
让创建与升级流程能把 vCluster Service 改成 LoadBalancer。
需修改文件
internal/infra/vcluster/helm.godeployments/single-node/docker-compose/kubebyon-vcluster-values.example.yaml(文档说明为主)
具体改造
当前 applyClusterOverrides() 里仅支持:
NodePortClusterIP
需要扩展到:
NodePortLoadBalancerClusterIP
并且在第一阶段补充:
- 把
cluster.ControlPlaneHost注入到controlPlane.proxy.extraSANs
关键原因
如果只把 Service 类型切成 LoadBalancer,但证书 SAN 里没有对应 host,
则 kubeconfig 指向新 LB 地址后容易出现 TLS 校验失败。
验收点
loadbalancer集群安装后,values 正确渲染extraSANs含control_plane_host
5.6 Service reconcile 逻辑支持三态
目标
让底层同步逻辑根据模式正确更新 Service。
需修改文件
internal/infra/vcluster/manager.go
具体改造
需要重构这些函数:
desiredPublicAccessServiceType()applyPublicAccessServiceSpec()syncPublicAccessState()
预期行为
开启公网 + nodeport
ServiceTypeNodePortpublic_access_port可写回
开启公网 + loadbalancer
ServiceTypeLoadBalancer- 不应继续沿用
httpsNodePort语义 public_access_port应清空或忽略
关闭公网
ServiceTypeClusterIP- 清理对外暴露相关字段
验收点
- 切换 Service 类型后对象状态正确
- 不会错误保留旧
NodePort
5.7 连接探测与 kubeconfig 生成逻辑补齐约束
目标
让 GetClusterConnection()、kubeconfig 解析、API endpoint 生成在 LoadBalancer 模式下工作正常。
需修改文件
internal/infra/vcluster/kubeconfig.gointernal/infra/vcluster/connection.gointernal/app/service.go
当前现状
kubeconfig.go 已经可以识别:
NodePortLoadBalancerClusterIP
因此这里不是从零开始,而是补约束和状态同步。
具体改造
loadbalancer第一阶段必须保证control_plane_host存在- 解析 endpoint 时优先使用:
control_plane_host- 否则再根据 LB ingress 回退(仅作为兜底)
GetClusterConnection()更新数据库时:- 正确回填
api_endpoint - 不在
loadbalancer模式下误写public_access_port
- 正确回填
observeCluster()/latestClusterForWrite()链路中:- 保证
PublicAccessMode不被旧值覆盖
- 保证
验收点
loadbalancer模式下可正确生成 kubeconfigkubectl version/kubectl get ns可正常访问
5.8 前端:管理员系统设置页面
目标
让管理员可以设置默认公网模式。
需修改文件
web/app/dashboard/admin/settings/page.tsxweb/lib/console-api.tsweb/i18n/messages/zh-CN.jsonweb/i18n/messages/en.json- 其他 locale 文件
具体改造
新增表单项:
- 默认公网访问模式:
- NodePort
- LoadBalancer
并在说明文案中提示:
LoadBalancer适合多机宿主集群- 宿主集群需要提前具备 LB 能力
5.9 前端:创建集群页面
目标
让用户在新建集群时选择公网模式。
需修改文件
- 集群创建页 / 创建弹窗所在前端文件
web/lib/console-api.ts- i18n 文案
具体改造
新增字段:
- 公网访问开关
- 公网访问模式:
- NodePort
- LoadBalancer
当选择 LoadBalancer 时:
- 必须提示填写
control_plane_host - 文案应明确:
- 推荐填可长期访问的域名、VIP 或预留 IP
5.10 前端:集群详情页 / 设置页 / 加入页
目标
让详情展示和编辑能力与新模式一致。
需修改文件
web/app/dashboard/clusters/[id]/page.tsxweb/app/dashboard/clusters/[id]/join/page.tsxweb/lib/console-api.ts- i18n 文案
具体改造
- 展示
public_access_mode - 仅在
nodeport模式下展示public_access_port loadbalancer模式下展示:api_endpointcontrol_plane_host
- 编辑时支持三态:
- 关闭公网
- NodePort
- LoadBalancer
5.11 部署文档与运维前提
目标
明确说明:LoadBalancer 模式不是单靠代码切换就能工作,宿主集群必须先具备 LB 能力。
需修改文档
docs/runbooks/deploy-kubebyon-backend.mddocs/runbooks/deploy-kubebyon-backend-docker-compose.mddeployments/single-node/docker-compose/README.md- 相关 values 示例说明
需补充内容
- 裸金属 / 自建机房:
- 需要 MetalLB、kube-vip + cloud-provider 等能力
- 云环境:
- 需要宿主集群具备可用的 LoadBalancer Provider
control_plane_host规划建议:- 预留 IP
- 域名
- VIP
5.12 历史集群迁移
目标
让现有 NodePort 集群可以平滑迁移到 LoadBalancer。
迁移步骤
- 数据库写入:
public_access_mode = 'loadbalancer'
- 把旧的
control_plane_host从宿主机单 IP 改成:- 新域名 / VIP / 预留 IP
- 触发集群配置更新
- 等待 Service 获取
LoadBalancer地址 - 刷新连接信息:
api_endpointkubeconfig_availableconnection_status
注意
如果直接保留旧 control_plane_host(某一台宿主机 IP),
则即使底层 Service 已切成 LoadBalancer,最终返回的 kubeconfig 仍可能继续指向旧地址。
5.13 测试清单
单元测试
需重点补充:
internal/infra/vcluster/manager_test.gointernal/app/service_test.gointernal/infra/repository/sql_test.gointernal/api/http/handlers_test.go
必测场景
- 创建集群:
enabled + nodeportenabled + loadbalancerdisabled
- 更新集群:
nodeport -> loadbalancerloadbalancer -> nodeportpublic off -> on
- endpoint 解析:
control_plane_host优先loadBalancer.ingress回退
- 元数据清理:
public_access_port不残留api_endpoint不残留旧值
- 老数据兼容:
- 历史集群自动视为
nodeport
- 历史集群自动视为
集成 / E2E 测试
- 宿主 k3s 多节点
- LB Provider 正常工作(MetalLB 或云 LB)
- 创建
loadbalancer模式集群 - kubeconfig 可用
- 关闭再开启公网访问成功
- 多集群并存时地址不串
6. 实施顺序
第一阶段(最小可用)
clusters.public_access_mode- 后端 model / repository / API
helm.go/manager.go支持 LoadBalancercontrol_plane_host注入extraSANs- 前端创建 / 编辑 / 展示支持 mode
- 文档补充宿主集群前提
第二阶段(完善可用性)
- 系统设置支持默认公网模式
- 历史集群迁移脚本 / 管理操作
- 多机 E2E 验证
第三阶段(后续优化)
podAntiAffinity/topologySpreadConstraints- 共享存储替代
local-path - 更正式的域名网关方案(Gateway API / TLS passthrough)
7. 暂不修改的部分
本次原则上不修改以下主链路:
- join command 代理路径
GET /api/join/clusters/{clusterID}/scriptinternal/infra/vcluster/join_script.go- BYON 节点加入协议本身
原因:
当前 join 已经通过 KubeBYON 后端代理到 vCluster 内部地址, 不再强依赖公网 NodePort,因此不属于本轮必须改造项。
8. 验收标准
满足以下条件可视为本次改造完成:
- 新建集群可选择
NodePort或LoadBalancer LoadBalancer模式下可正确生成api_endpoint和 kubeconfig- 前端可查看和修改公网模式
- 历史集群不受影响,默认继续以
nodeport工作 - 文档已说明多机部署前提和配置要求
- 单元测试与至少一轮多机环境 E2E 测试通过
9. 附:本次改造的核心判断
- 短期目标:先让 KubeBYON 真正支持多宿主机场景下的稳定公网入口
- 推荐实现:
LoadBalancer模式 + 显式control_plane_host - 后续方向:再进一步演进到域名化的网关接入方案