KubeBYON 控制台 / API 共用 443 HTTPS 部署记录
最后更新:2026-04-29
本文记录当前为了让:
- 前端控制台走
https://<DOMAIN>:443 - 后端 API 也走
https://<DOMAIN>:443/api/... - 同时不破坏 HAProxy 已经承接的 vCluster 控制面
443
而采用的一套实现方式。
适用前提:
- KubeBYON 后端通过
deployments/single-node/docker-compose部署- vCluster 稳定公网入口已经使用 HAProxy + TLS SNI
- Web Console 通过仓库内的
web/Dockerfile构建为静态站点镜像
补充说明:这份文档描述的是 HAProxy + Caddy 的平台站点方案。
如果你当前做的是 Helm in-cluster + Gateway API Phase 3(平台 hostname 下/api、/healthz到 API,/到 in-cluster web),请优先参考:
docs/runbooks/deploy-gateway-api-public-access.md
1. 为什么不能直接让站点自己监听 443
当前单机部署里:
- HAProxy 已经监听宿主机
443 - 它负责把不同
control_plane_host的 TLS 流量按 SNI 转发到对应 vCluster NodePort
如果再让前端站点或普通反向代理直接占用宿主机 443,会立刻和 HAProxy 冲突。
因此最终做法不是“替换掉 HAProxy”,而是:
- 保留 HAProxy 继续占用外部
443 - 给 HAProxy 增加一条“静态 TLS SNI 直通规则”
- 当 SNI 命中平台主站域名时,转发给本机另一个 TLS 终结器(这里用 Caddy)
- Caddy 再把:
/api/*、/healthz转给127.0.0.1:8080- 其余页面请求转给
127.0.0.1:3000
2. 最终拓扑
浏览器
-> https://kubebyon.example.com:443
-> HAProxy:443
-> 若 SNI = kubebyon.example.com
-> 127.0.0.1:8443 (Caddy)
-> /api/*, /healthz -> 127.0.0.1:8080 (kubebyon-api)
-> 其他路径 -> 127.0.0.1:3000 (Next.js web)
-> 否则
-> 继续按既有规则转发到各 vCluster NodePort backend
这里的关键点是:
- 对外仍然只有一个 443
- HAProxy 仍是最外层 TCP 入口
- 平台站点只是其中一个特定 SNI host 的后端
- vCluster 控制面公网入口逻辑不受影响
3. 为此做过的代码改动
3.1 给 HAProxy 同步器增加“静态 TLS SNI backend”能力
新增环境变量:
KUBEBYON_HAPROXY_EXTRA_TLS_SNI_HOSTSKUBEBYON_HAPROXY_EXTRA_TLS_BACKEND_ADDR
语义:
KUBEBYON_HAPROXY_EXTRA_TLS_SNI_HOSTS:额外静态匹配的一组 SNI hostKUBEBYON_HAPROXY_EXTRA_TLS_BACKEND_ADDR:这些 host 命中后要转发到的固定后端地址,例如127.0.0.1:8443
涉及文件:
internal/infra/config/config.gocmd/kubebyon-api/main.gointernal/infra/vcluster/haproxy_sync.gointernal/infra/vcluster/haproxy_sync_test.godeployments/single-node/docker-compose/docker-compose.yml
当前行为:
- 正常的 cluster
loadbalancerSNI 规则继续自动生成 - 额外静态 host 会先生成一组固定
use_backend规则 - 如果配置了固定后端地址,则渲染一个静态 backend,例如:
use_backend kubebyon_static_tls_backend if { req.ssl_sni -i kubebyon.example.com }
server static_tls_1 127.0.0.1:8443 check
3.2 给 Compose 增加环境变量透传
deployments/single-node/docker-compose/docker-compose.yml 里补充了:
KUBEBYON_HAPROXY_EXTRA_TLS_SNI_HOSTSKUBEBYON_HAPROXY_EXTRA_TLS_BACKEND_ADDR
否则即使后端支持了,这两个变量也不会真正进入 kubebyon-api 容器。
3.3 为静态 TLS backend 增加测试
新增测试覆盖:
TestHAProxyConfigSyncerRenderConfigIncludesStaticTLSBackend
验证点:
- SNI host 会被规范化
- 渲染结果里会出现静态
req.ssl_sni规则 - backend 会正确指向
127.0.0.1:8443
4. 远程机器上的实际部署步骤
以下示例使用域名:
kubebyon.youguess.me
4.1 后端 .env 需要增加 / 修改
在:
/opt/kubebyon/deployments/single-node/docker-compose/.env
写入:
KUBEBYON_SESSION_COOKIE_SECURE=true
KUBEBYON_CORS_ALLOWED_ORIGINS=https://kubebyon.youguess.me
KUBEBYON_HAPROXY_EXTRA_TLS_SNI_HOSTS=kubebyon.youguess.me
KUBEBYON_HAPROXY_EXTRA_TLS_BACKEND_ADDR=127.0.0.1:8443
说明:
KUBEBYON_SESSION_COOKIE_SECURE=true:站点改走 HTTPS 后,登录 cookie 必须标记为SecureKUBEBYON_CORS_ALLOWED_ORIGINS:如果浏览器中的 Web Console 与 API 存在同站跨 origin 访问,必须显式写入 Console origin;不要用*承载 cookie session。任意 cross-site 前端仍会被Sec-Fetch-Site: cross-site与SameSite=Laxcookie 策略阻止,需改用 Bearer/API token 或重新设计SameSite=NoneKUBEBYON_HAPROXY_EXTRA_TLS_SNI_HOSTS:告诉 HAProxy 这个主站域名也要在 443 上接入KUBEBYON_HAPROXY_EXTRA_TLS_BACKEND_ADDR:命中后把 TLS 直通给本地 Caddy
完成后重建后端:
cd /opt/kubebyon/deployments/single-node/docker-compose
docker compose --env-file .env up -d --build
4.2 Web Console 运行在 3000
当前做法是让 Web Console 自己运行在宿主机 3000,再交给 Caddy 反代。
如果需要先在宿主机本地验证静态导出,可执行:
cd /opt/kubebyon/web
npm ci
npm run build
正式运行建议直接复用仓库内的 Dockerfile 构建静态站点镜像:
docker build -f web/Dockerfile -t kubebyon-web:local .
docker run --rm -p 3000:3000 \
-e API_UPSTREAM=http://127.0.0.1:8080 \
kubebyon-web:local
当前 web/Dockerfile 会:
- 先
npm ci - 再
npm run build - 最后用 Nginx 提供静态站点,并暴露
3000
如果你使用 systemd 管理容器,可参考:
[Unit]
Description=KubeBYON Web Console
After=network.target docker.service
Requires=docker.service
[Service]
Type=simple
ExecStartPre=-/usr/bin/docker rm -f kubebyon-web
ExecStart=/usr/bin/docker run --name kubebyon-web --rm -p 3000:3000 -e API_UPSTREAM=http://127.0.0.1:8080 kubebyon-web:local
ExecStop=/usr/bin/docker stop kubebyon-web
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
说明:
- 当前 Docker 镜像使用 Nginx 提供静态站点,并通过
API_UPSTREAM配置/api上游 - 浏览器侧通常不需要额外设置
NEXT_PUBLIC_KUBEBYON_API_BASE_URL - 因为站点最终通过同域
/api/...访问后端即可 - 只有当浏览器必须直连不同 origin 的 API 时,才建议显式设置
NEXT_PUBLIC_KUBEBYON_API_BASE_URL
4.3 安装 Caddy 作为站点 TLS 终结器
当前做法使用 Caddy:
80:处理明文跳转与 ACME HTTP challenge8443:真正提供站点 TLS
注意:这里 Caddy 监听的是 8443,不是外部 443。
外部 443 仍然是 HAProxy;HAProxy 只是把特定 SNI 的 TLS 直通到127.0.0.1:8443。
可参考配置:
{
auto_https disable_redirects
}
http://kubebyon.youguess.me {
redir https://kubebyon.youguess.me{uri} 308
}
https://kubebyon.youguess.me:8443 {
encode zstd gzip
@api path /api/* /healthz
reverse_proxy @api 127.0.0.1:8080
reverse_proxy 127.0.0.1:3000
}
启用后检查:
systemctl enable --now caddy
systemctl status caddy --no-pager
ss -lnt | grep -E ':(80|8443)\s'
5. 管理后台里还要补的设置
站点已经切到 HTTPS 后,还需要登录管理员后台更新:
public_base_url = https://kubebyon.youguess.mejoin_base_url = https://kubebyon.youguess.me
这样影响到:
- 控制台内展示 / 生成的站点链接
- Join 命令中的 base URL
- 一些需要绝对 URL 的跳转 / 邮件 / 回调场景
6. 验证方式
6.1 检查 HTTP 是否跳转到 HTTPS
curl -I http://kubebyon.youguess.me
预期:
308跳转到https://kubebyon.youguess.me/...
6.2 检查 HTTPS 站点是否可用
curl -I https://kubebyon.youguess.me/login
curl -I https://kubebyon.youguess.me/healthz
curl -I https://kubebyon.youguess.me/api/auth/providers
6.3 检查登录 cookie 是否带 Secure
curl -i \
-H 'Content-Type: application/json' \
-d '{"email":"admin@kubebyon.local","password":"YOUR_PASSWORD"}' \
https://kubebyon.youguess.me/api/auth/login
预期响应头中应出现:
Set-Cookie: ...; Secure; HttpOnly; SameSite=Lax
6.4 检查 HAProxy 最终渲染结果
sed -n '1,240p' deployments/single-node/docker-compose/runtime/haproxy/haproxy.cfg
预期至少能看到:
use_backend kubebyon_static_tls_backend if { req.ssl_sni -i kubebyon.youguess.me }server static_tls_1 127.0.0.1:8443 check
7. 常见问题
7.1 为什么 Caddy 不是直接监听 443
因为宿主机外部 443 已经被 HAProxy 占用,用于承接:
- 平台主站
- 各个 vCluster 控制面域名
所以站点 TLS 必须挂在 HAProxy 后面,而不是和 HAProxy 抢端口。
7.2 这样会不会影响 vCluster 控制面流量
不会。
因为平台站点只占用:
KUBEBYON_HAPROXY_EXTRA_TLS_SNI_HOSTS指定的少数固定域名
其他 SNI host 仍按原来的 cluster 动态 backend 规则处理。
7.3 为什么后端 API 不是直接开放 https://IP:8080
因为目标是:
- 前后端统一域名
- 统一 443
- 浏览器 Cookie / SameSite / Secure 语义更稳定
- 避免用户记多个端口
7.4 如果以后主站域名不止一个怎么办
可以继续扩展:
KUBEBYON_HAPROXY_EXTRA_TLS_SNI_HOSTS=console.example.com,api.example.com,...
前提是:
- 这些域名都要能由同一个本地 TLS 终结器处理
- Caddy / Nginx 也要同步配置这些站点
8. 相关文档
deployments/single-node/docker-compose/README.mddocs/runbooks/deploy-kubebyon-backend-docker-compose.mddocs/runbooks/deploy-haproxy-public-access.md