KubeBYON HAProxy 公网访问部署 Runbook

最后更新:2026-04-27

注意:本文只覆盖 vCluster 控制面 API 的公网访问,不覆盖用户工作负载的托管业务流量入口。

若你关注的是平台为用户工作负载自动准备 ingress controller、子域名或 TLS, 请改看:docs/architecture/managed-workload-ingress-plan.md

若你关注的是控制台页面 / 后端 API 也想共用 HAProxy 的 443 做 HTTPS, 请改看:docs/runbooks/enable-console-https-on-443.md

本文说明如何把 KubeBYON 的稳定公网入口切换到:

  • HAProxy + TLS SNI
  • vCluster NodePort 后端
  • 不再依赖 k3s ServiceLB

1. 目标形态

用户 kubeconfig / kubectl
  -> api.cluster.example.com:443
  -> HAProxy
  -> 宿主节点 IP:NodePort
  -> vCluster API

2. 前置条件

  1. 宿主机已安装 k3s
  2. KubeBYON 后端使用 deployments/single-node/docker-compose
  3. 你已经为每个需要稳定入口的 vCluster 准备好域名
  4. 这些域名解析到 HAProxy 所在宿主机公网 IP

如果你只是做单机验证,也可以先用:

  • 集群名.<PUBLIC-IP-WITH-DASHES>.sslip.io

例如公网 IP 是 206.189.80.126,可写成:

  • demo.206-189-80-126.sslip.io

3. 禁用 k3s ServiceLB

编辑:

/etc/rancher/k3s/config.yaml

加入:

disable:
  - servicelb

如果你不再需要默认 traefik,也可以一并关闭:

disable:
  - servicelb
  - traefik

然后重启:

systemctl restart k3s

确认旧的 svclb-* 已经清理:

kubectl -n kube-system get pods | grep svclb || true

4. 准备 Compose 运行目录

cd deployments/single-node/docker-compose
cp .env.example .env
cp kubebyon-vcluster-values.example.yaml runtime/kubebyon-vcluster-values.yaml
mkdir -p runtime/haproxy

关键环境变量:

KUBEBYON_PUBLIC_ACCESS_PROVIDER=haproxy
KUBEBYON_HAPROXY_BIND_ADDR=:443
KUBEBYON_HAPROXY_NODE_ADDRESS_TYPE=internal

说明:

  • internal:优先读取宿主集群节点的 NodeInternalIP
  • external:优先读取宿主集群节点的 NodeExternalIP

5. 启动后端与 HAProxy

docker compose --env-file .env up -d --build

确认:

docker compose --env-file .env ps
docker compose --env-file .env logs -f kubebyon-api
docker compose --env-file .env logs -f haproxy

6. 创建集群时的要求

当创建需要稳定公网入口的集群时:

  • public_access_mode = loadbalancer
  • control_plane_host = 你的域名

例如:

{
  "name": "demo",
  "public_access_mode": "loadbalancer",
  "control_plane_host": "api.demo.example.com"
}

注意:不要把 control_plane_host 直接写成 IP。 HAProxy 当前依赖 TLS SNI 做四层转发,必须使用域名。


7. 验证

7.1 KubeBYON 返回 443 入口

确认集群详情里的:

  • api_endpoint = https://api.demo.example.com:443

7.2 HAProxy 配置已生成

cat deployments/single-node/docker-compose/runtime/haproxy/haproxy.cfg

应能看到:

  • req.ssl_sni -i api.demo.example.com
  • 对应 NodePort backend

7.3 kubeconfig 可用

下载 kubeconfig 后执行:

kubectl --kubeconfig ./demo.kubeconfig get ns

7.4 从外部直接验证控制面

curl -sk https://api.demo.example.com/version

如果这是单机测试,也可以把 api.demo.example.com 换成你的 sslip.io 测试域名。


8. 常见问题

8.1 为什么必须用域名

因为 HAProxy 当前按 TLS SNI 做四层路由。
如果你直接用 IP,客户端通常不会发送可用于路由的 SNI。

8.2 为什么底层还是 NodePort

因为 NodePort 只作为 HAProxy 的后端目标:

  • 用户不直接访问它
  • HAProxy 统一把公网 443 转发过去

8.3 为什么要关掉 ServiceLB

为了避免旧的 svclb-* 继续抢占宿主机端口,尤其是 443

8.4 HAProxy 启动时报 Permission denied 无法绑定 443

说明 HAProxy 进程没有拿到宿主机低位端口监听权限。

请确认当前 Compose 配置里的 haproxy 服务:

  • 使用 network_mode: host
  • root 运行

并确认宿主机上没有其他进程占用 443

8.5 旧集群为什么一直不出现在 HAProxy 配置里

如果旧集群的 control_plane_host 是 IP 字面量,例如:

  • 157.245.196.126

那么它会被 HAProxy 同步器跳过,因为当前 SNI 路由只支持域名。

你需要把该集群更新为一个真实域名,再重新观察:

  • 控制台里的 api_endpoint
  • runtime/haproxy/haproxy.cfg