KubeBYON 后端 Helm 部署 Runbook

最后更新:2026-05-23

本文档记录一套已经实机验证过的 KubeBYON 后端 Helm 部署流程

当前这套 Helm chart 的目标形态是:

  • KubeBYON API in-cluster 部署
  • 可选 KubeBYON web / Next.js 控制台 in-cluster 部署
  • hostNetwork: true(默认)
  • 宿主集群连接走 in-cluster config
  • 可选启用 publicAccess.provider=haproxy(默认)或 publicAccess.provider=gatewayapi
  • 可选启用内置 PostgreSQL 子 chart
  • 可选启用 admission webhook
  • 可选通过 bootstrap hook 自动写入 vCluster platform access key
  • 默认使用 scoped RBAC 访问宿主集群;仅在临时回退时才设置 rbac.clusterAdmin=true

正式或公网环境必须显式启用生产模式,请在 values 中设置:

runtime:
  environment: production
  production: true

否则仍会按开发模式启动,不会执行生产安全拒启动校验。runtime.environment: production 会强制进入生产模式,runtime.production: false 不能覆盖它。

所有环境都会拒绝缺失的数据库 DSN。生产模式会额外拒绝默认管理员密码、cors.allowedOrigins: ["*"]session.cookieSecure: false,以及启用 admission webhook 时缺失的 TLS cert/key 或 shared secret。


1. 适用场景

适用于以下情况:

  • 宿主机已经有可用 Kubernetes / k3s 集群
  • 想把 KubeBYON 后端作为宿主集群上的一个工作负载来运行
  • 希望继续保留 HAProxy 稳定公网入口能力,或切换到 Gateway API 控制面 / 平台 API provider 组合
  • 不想依赖 docker compose

当前这套 chart 不会帮你创建宿主 Kubernetes 集群本身
它负责在现有宿主集群里安装 KubeBYON 后端。


2. 当前 chart 结构

2.1 publicAccess.provider=haproxy(默认)

kubebyon-helm-test Pod
├─ kubebyon-api
└─ haproxy

同一 namespace 内:
├─ Service (8080 / 9443)
├─ ServiceAccount + scoped RBAC
├─ ConfigMap / Secret
├─ bootstrap hook Job
└─ PostgreSQL StatefulSet(可选)

关键点:

  • kubebyon-api 负责控制面逻辑
  • haproxy sidecar 负责稳定公网入口配置
  • hostNetwork: true 让 Pod 直接监听宿主机 8080/9443/443
  • admission webhook 默认通过 https://<service>.<ns>.svc:9443 回调

2.2 publicAccess.provider=gatewayapi

kubebyon-helm-test Pod
└─ kubebyon-api

同一 namespace / 指定 gateway namespace 内:
├─ Service (8080 / 9443)
├─ shared Gateway(gateway.networking.k8s.io/v1)
├─ ServiceAccount + scoped RBAC
├─ ConfigMap / Secret
├─ bootstrap hook Job
└─ PostgreSQL StatefulSet(可选)

关键点:

  • 不再部署 haproxy sidecar
  • 不再挂载 runtime/haproxystart-haproxy.sh
  • chart 会创建一个 shared Gateway,供后端后续绑定每个 vCluster 的控制面路由
  • gatewayAPI.addressMode 用于决定 control-plane / platform / workload 三类 Gateway 的默认 GatewayClass 解析方式
    • dual(默认):control-plane / platform 默认走 edge profile,workload 默认走 workload profile
    • single:control-plane / platform / workload 默认都走 shared profile
    • profile 留空时最终回退到 gatewayAPI.gatewayClassName
  • 当前至少覆盖 vCluster control plane passthrough;若额外启用 gatewayAPI.platform.enabled=true,还会为平台站点创建独立 Gateway + HTTPRoute
    • 默认路由 /api 前缀与 /healthz 到 API
    • 若再启用 web.enabled=true,则在同 host 下额外路由 / 到 in-cluster web
    • 若再启用 gatewayAPI.workload.enabled=true,则会额外创建独立 workload shared Gateway;Helm render 保留 HTTP:80tls.enabled=true 时由 runtime syncer 动态维护 HTTPS listener / 证书

3. 前置条件

3.1 目标机器

至少需要:

  • 一台宿主集群控制面机器
  • 一台可对外暴露端口的工作节点(推荐)

本次实测环境:

  • 宿主控制面:206.189.80.126
  • 公网工作节点:157.245.196.126

3.2 基础软件

目标机器至少需要:

  • Docker
  • k3s
  • Helm 3

示例:

curl -fsSL https://get.docker.com | sh
systemctl enable --now docker

curl -sfL https://get.k3s.io | \
  INSTALL_K3S_EXEC="server --write-kubeconfig-mode 644 --tls-san YOUR_PUBLIC_IP" sh -

curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

如果你使用的是 k3s 默认 traefik(Service=LoadBalancer),并且保持 chart 默认 publicAccess.provider=haproxy + hostNetwork: true + haproxy :443,需要先释放宿主机 443,否则 API Pod 会因端口冲突 Pending

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

kubectl -n kube-system patch svc traefik --type merge -p '{"spec":{"type":"ClusterIP"}}'
kubectl -n kube-system delete ds -l svccontroller.k3s.cattle.io/svcname=traefik

3.3 如果改用 Gateway API provider

请先完成:

  • Gateway API CRD 安装
  • Gateway controller 安装(推荐 Envoy Gateway)
  • controller 对外暴露能力准备完成(LoadBalancer、MetalLB、或你的集群自定义暴露方式)
  • 根据你的公网入口规划决定 address mode:
    • single:适用于只有一个公网 IP / 一个共享 GatewayClass / 一个共享 LB 暴露面的环境
    • dual:适用于希望把 control-plane + platform 与 workload edge 分离到不同公网入口的环境
  • 如果选择 dual,还要确认 Gateway controller / 云 LB / IP 池策略确实能让 edgeworkload 这两类 GatewayClass 落到不同的数据面或公网地址;否则 chart 语义虽分离,最终仍可能共用同一公网地址

详见:

说明:当前第一阶段控制面 passthrough 依赖 TLSRoute,因此通常需要安装 Gateway API experimental bundle,而不只是 Gateway/HTTPRoute 的 standard bundle。


4. 同步源码到远程服务器

如果远程目录不是 git 仓库,推荐直接同步最小构建上下文:

ssh root@YOUR_SERVER 'mkdir -p /opt/kubebyon'

tar czf - cmd internal deployments web go.mod go.sum \
  | ssh root@YOUR_SERVER 'cd /opt/kubebyon && tar xzf -'

5. 远程构建镜像

本 runbook 按用户要求,镜像构建在远程执行,不在本地构建。

进入远程目录:

ssh root@YOUR_SERVER
cd /opt/kubebyon

至少构建后端镜像:

docker build \
  -f deployments/single-node/docker-compose/Dockerfile \
  -t kubebyon-api-compose:helm-test .

如果你计划启用 web.enabled=true,还需要额外构建前端镜像:

docker build \
  -f web/Dockerfile \
  -t kubebyon-web:helm-test \
  .

当前 web/Dockerfile 会从仓库根目录读取 docs/,导出 Next.js 静态站点,并通过 Nginx 监听 3000

如果你没有把镜像推到公共/私有镜像仓库,而是像本次一样直接用宿主机本地镜像,则还需要把镜像导入 所有可能调度到的 k3s 节点

控制面节点导入:

docker save kubebyon-api-compose:helm-test | sudo k3s ctr images import -

如果启用了 web,也别忘了导入:

docker save kubebyon-web:helm-test | sudo k3s ctr images import -

导入到另一台工作节点:

ssh root@CONTROL_PLANE 'docker save kubebyon-api-compose:helm-test' \
  | ssh root@WORKER_NODE 'sudo k3s ctr images import -'

如启用了 web,同样导入:

ssh root@CONTROL_PLANE 'docker save kubebyon-web:helm-test' \
  | ssh root@WORKER_NODE 'sudo k3s ctr images import -'

如果你使用的是镜像仓库,则可以跳过这一步,直接在 values 里填写仓库地址即可。


6. 准备 Helm 依赖

先添加 Bitnami 仓库:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

然后构建 chart 依赖:

cd /opt/kubebyon/deployments/single-node/helm/kubebyon
helm dependency build

注意:当前 chart 已提交 Chart.lock,但远程首次执行时仍建议显式 helm repo add bitnami


7. 准备 values 文件

7.1 HAProxy provider 示例(兼容默认行为)

image:
  repository: kubebyon-api-compose
  tag: helm-test
  pullPolicy: IfNotPresent

postgresql:
  enabled: true
  auth:
    username: kubebyon
    password: ChangeMe123!
    database: kubebyon
  primary:
    persistence:
      enabled: false

admission:
  enabled: true

managedIngress:
  chart:
    version: ""

kubernetes:
  configMode: incluster

nodeSelector:
  kubernetes.io/hostname: kubebyon-lb-node-20260411

platform:
  apiKeySourceNamespace: kubebyon-helm-system
  apiKeySecretName: vcluster-platform-api-key
  bootstrap:
    enabled: true
    mockHost: https://vcluster.pp.ua:18443
    insecure: true
    project: default

admin:
  displayName: Helm Admin
  email: admin-helm@kubebyon.local
  password: ChangeMe123!

7.2 Gateway API provider 推荐 values

方案 A:addressMode=dual(默认,推荐给双公网 IP / 双入口场景)

适用场景:

  • 希望 control-plane + platform 站点 共用一类公网入口
  • 同时让 workload edge 走另一类公网入口
  • Gateway controller / LB 能根据不同 GatewayClass 提供不同数据面或不同公网 IP
image:
  repository: kubebyon-api-compose
  tag: helm-test
  pullPolicy: IfNotPresent

postgresql:
  enabled: true
  primary:
    persistence:
      enabled: false

kubernetes:
  configMode: incluster

publicAccess:
  provider: gatewayapi

gatewayAPI:
  # 全局 fallback;若 profile / override 都未命中,则回退到这里。
  gatewayClassName: eg
  addressMode: dual
  gatewayClassProfiles:
    # dual 模式下 control-plane / platform 默认使用 edge。
    edge: eg-edge
    # dual 模式下 workload 默认使用 workload。
    workload: eg-workload
    # single 模式才会默认用到 shared;这里保留为空即可。
    shared: ""
  # 留空时使用 release namespace
  namespace: ""
  # 留空时默认生成 <release>-kubebyon-gateway
  name: ""
  listenerName: control-plane
  syncIntervalSeconds: 10
  platform:
    enabled: true
    hostname: kubebyon.example.com
    tlsSecretName: kubebyon-platform-tls
    # web.enabled=true 时,HTTP redirect 会覆盖 /;否则仅覆盖 /api 与 /healthz。
    httpToHttpsRedirect: false
  workload:
    enabled: true
    # 如需给 workload 单独指定 class,可继续显式 override。
    gatewayClassName: ""
    namespace: ""
    name: ""
    listenerName: ""
    nodeAddressType: internal

web:
  enabled: true
  image:
    repository: kubebyon-web
    tag: helm-test
    pullPolicy: IfNotPresent
  service:
    create: true
    port: 3000
  env:
    # 留空时默认回落到 in-cluster API Service。
    apiBaseURL: ""
    # 同 host Gateway 路由场景下通常保持留空,让浏览器继续访问当前站点 /api。
    nextPublicAPIBaseURL: ""
    # 留空时默认注入 0.0.0.0。
    hostname: ""

platform:
  apiKeySourceNamespace: kubebyon-helm-system
  apiKeySecretName: vcluster-platform-api-key
  bootstrap:
    enabled: true
    mockHost: https://vcluster.pp.ua:18443
    insecure: true
    project: default

admin:
  displayName: Helm Admin
  email: admin-helm@kubebyon.local
  password: ChangeMe123!

方案 B:addressMode=single(推荐给单公网 IP / 单入口场景)

适用场景:

  • 只有一个公网 IP / 一个共享 LB
  • Gateway controller 当前只准备了一个主要 GatewayClass
  • 希望 control-plane / platform / workload 默认都落在同一类入口能力上
image:
  repository: kubebyon-api-compose
  tag: helm-test
  pullPolicy: IfNotPresent

postgresql:
  enabled: true
  primary:
    persistence:
      enabled: false

kubernetes:
  configMode: incluster

publicAccess:
  provider: gatewayapi

gatewayAPI:
  # 全局 fallback;若 shared 为空,则回退到这里。
  gatewayClassName: eg
  addressMode: single
  gatewayClassProfiles:
    # single 模式下 control-plane / platform / workload 默认都走 shared。
    shared: eg-shared
    edge: ""
    workload: ""
  namespace: ""
  name: ""
  listenerName: control-plane
  syncIntervalSeconds: 10
  platform:
    enabled: true
    hostname: kubebyon.example.com
    tlsSecretName: kubebyon-platform-tls
    httpToHttpsRedirect: false
  workload:
    enabled: true
    namespace: ""
    name: ""
    listenerName: ""
    nodeAddressType: internal

web:
  enabled: true
  image:
    repository: kubebyon-web
    tag: helm-test
    pullPolicy: IfNotPresent
  service:
    create: true
    port: 3000
  env:
    apiBaseURL: ""
    hostname: ""

platform:
  apiKeySourceNamespace: kubebyon-helm-system
  apiKeySecretName: vcluster-platform-api-key
  bootstrap:
    enabled: true
    mockHost: https://vcluster.pp.ua:18443
    insecure: true
    project: default

admin:
  displayName: Helm Admin
  email: admin-helm@kubebyon.local
  password: ChangeMe123!

保存为:

/root/kubebyon-helm-values.yaml

7.3 关键字段说明

kubernetes.configMode: incluster

表示:

  • kubebyon-api 通过 Pod 自身的 service account 访问宿主集群
  • 不再依赖额外挂载 kubeconfig 文件

rbac.clusterAdmin

默认值为 false,表示 chart 会创建并绑定 KubeBYON 自己的 scoped ClusterRole,而不是直接绑定宿主集群内置 cluster-admin

升级注意:这是一次默认 RBAC 行为变更。旧 release 如果已经以 rbac.clusterAdmin=true 安装,直接升级到默认 scoped mode 时会尝试修改既有 ClusterRoleBinding.roleRef;该字段在 Kubernetes 中不可变,升级可能失败。若需要从旧行为切换到 scoped mode,请先删除旧的 KubeBYON ClusterRoleBinding 后再升级,或本次升级继续显式设置 rbac.clusterAdmin=true

当前 scoped RBAC 覆盖已有功能所需的宿主集群权限,包括:

  • vCluster Helm 安装 / 升级 / 卸载过程中可能涉及的 Namespace、Secret、Service、ServiceAccount、PVC、Pod、Job、RBAC、CRD 等资源
  • admission webhook 管理:MutatingWebhookConfiguration / ValidatingWebhookConfiguration
  • Gateway API:GatewayHTTPRouteTLSRoute
  • cert-manager Certificate
  • 托管业务入口使用的 IngressClass
  • workload route plan CRD 与 /status 子资源

如遇到自定义 chart 或插件确实申请了 scoped RBAC 未覆盖的新权限,可临时设置:

rbac:
  clusterAdmin: true

这会回退到历史行为:将 KubeBYON ServiceAccount 绑定到宿主集群内置 cluster-admin。生产环境建议优先扩展 scoped RBAC,而不是长期启用该回退选项。

publicAccess.provider

支持:

  • haproxy:保留当前 sidecar 兼容行为
  • gatewayapi:不再部署 HAProxy sidecar,而是创建 shared Gateway

gatewayAPI.*

用于传递 Gateway API provider 需要的网关元数据:

  • gatewayClassName:默认示例为 Envoy Gateway 的 eg;同时也是 profile / explicit override 都未命中时的全局 fallback
  • namespace:control-plane shared Gateway 所在 namespace;留空时默认 release namespace
  • name:control-plane shared Gateway 名称;留空时 chart 自动生成
  • listenerName:固定 listener 名称,后端会引用它绑定控制面路由
  • syncIntervalSeconds:后端/worker 与 Gateway API route 同步周期
  • 启用 gatewayAPI.workload.enabled=true 时,kubebyon-api 还会额外收到 workload Gateway 的 namespace / name / listener / nodeAddressType 运行时 env
  • 启用 gatewayAPI.workload.tls.enabled=true 时,Helm render 仍只保留 workload Gateway 的 HTTP:80 listener;kubebyon-api 会额外收到 workload HTTPS listener / TLS secret / shared + self-managed cert-manager issuer 元数据

gatewayAPI.addressMode

支持:

  • dual(默认)
    • control-plane shared Gateway:默认走 gatewayAPI.gatewayClassProfiles.edge
    • platform Gateway:默认走 gatewayAPI.gatewayClassProfiles.edge
    • workload Gateway:默认走 gatewayAPI.gatewayClassProfiles.workload
  • single
    • control-plane / platform / workload 默认都走 gatewayAPI.gatewayClassProfiles.shared

如果对应 profile 留空,则最终回退到 gatewayAPI.gatewayClassName

gatewayAPI.gatewayClassProfiles.shared / edge / workload

语义:

  • shared
    • addressMode=single 时的默认 GatewayClass
    • 适合只有一个公网 IP / 一个共享入口面的环境
  • edge
    • addressMode=dual 时 control-plane / platform 的默认 GatewayClass
    • 适合平台侧入口单独使用一类 GatewayClass / 一组 IP
  • workload
    • addressMode=dual 时 workload Gateway 的默认 GatewayClass
    • 适合托管 workload edge 单独使用另一类 GatewayClass / 一组 IP

运维上要注意:dual 只是 chart 的解析语义;是否真的落到两个不同公网地址,仍取决于你的 Gateway controller、LB 暴露方式、地址池与对应 GatewayClass 的实现。

GatewayClass 解析优先级

当前单机 chart 保持以下兼容逻辑:

  • control-plane shared Gateway
    • 无单独显式 override
    • 解析顺序:addressMode 对应 profile -> gatewayAPI.gatewayClassName
  • platform Gateway
    • gatewayAPI.platform.gatewayClassName
    • 否则 addressMode 对应 profile
    • 否则 gatewayAPI.gatewayClassName
  • workload Gateway
    • gatewayAPI.workload.gatewayClassName
    • 否则 addressMode 对应 profile
    • 否则 gatewayAPI.gatewayClassName

如果还要同时暴露平台 API,可再配置:

  • gatewayAPI.platform.enabled=true
  • gatewayAPI.platform.hostname=<PLATFORM_HOST>
  • gatewayAPI.platform.tlsSecretName=<TLS_SECRET>
  • gatewayAPI.platform.httpToHttpsRedirect=true|false

默认情况下,platform Gateway/HTTPRoute 会路由:

  • /api 前缀
  • /healthz

如果再启用 web.enabled=true,还会额外路由:

  • /

其中 /api 前缀与 Exact /healthz 会因更具体的 Gateway API 路径匹配优先进入 API,/ 只兜底 web 站点流量。

无论是否启用 web,admission :9443 都不会通过 platform Gateway 暴露。

如果还要启用 Phase 4B workload edge shared Gateway,可再配置:

  • gatewayAPI.workload.enabled=true
  • gatewayAPI.workload.gatewayClassName=<optional-class>
  • gatewayAPI.workload.namespace=<optional-namespace>
  • gatewayAPI.workload.name=<optional-name>
  • gatewayAPI.workload.listenerName=<optional-http-listener>
  • gatewayAPI.workload.nodeAddressType=internal|external
  • gatewayAPI.workload.backendStrategy=auto|nodeport|podip
  • gatewayAPI.workload.podCIDRRoute.enabled=true|false
  • gatewayAPI.workload.podCIDRRoute.mode=routeagent|local
  • gatewayAPI.workload.podCIDRRoute.controlNamespace=<optional-namespace>
  • gatewayAPI.workload.podCIDRRoute.targetNodeSelector.<key>=<value>
  • gatewayAPI.workload.tls.enabled=true|false
  • gatewayAPI.workload.tls.secretName=<optional-secret-name>
  • gatewayAPI.workload.tls.httpToHttpsRedirect=true|false
  • gatewayAPI.workload.tls.httpListenerName=<optional-http-listener>
  • gatewayAPI.workload.tls.httpsListenerName=<optional-https-listener>
  • gatewayAPI.workload.certManager.enabled=true|false
  • gatewayAPI.workload.certManager.issuerRef.name=<issuer-or-clusterissuer>
  • gatewayAPI.workload.certManager.selfManaged.enabled=true|false
  • gatewayAPI.workload.certManager.selfManaged.issuerRef.name=<optional-override-issuer>

workload Gateway 当前语义:

  • 会创建一个独立于 control-plane / platform 的 shared Gateway
  • Helm render 当前保持 HTTP:80 listener
  • tls.enabled=true 时,workload HTTPS listener / redirect / Certificate 由 kubebyon-api runtime syncer 动态维护
  • kubebyon-api 进程会运行 workload edge HTTP syncer
  • syncer 会按 cluster 在宿主 namespace 中维护 HTTPRouteServiceEndpointSlice
  • HTTPRoute 会把 cluster 级 managed_workload_ingress_cname_target 与 hostname bindings 挂到该 Gateway
  • 这些 shim 资源优先把流量转到目标 vCluster 内托管 ingress controller 的 PodIP:80,不满足条件时再回退到宿主节点 IP + NodePort
  • PodCIDR 路由可由 kubebyon-api 本地同步,或在 mode=routeagent 时由 kubebyon-route-agent DaemonSet 按 RoutePlan 在各宿主节点收敛
  • 若启用 gatewayAPI.workload.certManager.enabled=true,platform-managed 共享 Certificate 会由 kubebyon-api runtime syncer 在 workload Gateway namespace 动态维护
  • 若启用 gatewayAPI.workload.certManager.selfManaged.enabled=true,self-managed 外部 hostname 还可额外走独立 CertificateselfManaged.issuerRef 留空时回退到默认 certManager.issuerRef
  • 当前最小范围仍只会把 managed_workload_ingress_cname_target 与平台可托管 hostname bindings 聚合进共享 Certificate 的 SAN;self-managed 外部 hostname 使用独立证书时不纳入这个共享 SAN

web.enabled / web.image / web.service / web.env

用于启用 Phase 3 的 in-cluster web:

  • web.enabled=true 时会创建独立 web Deployment + Service
  • 同时要求:
    • gatewayAPI.platform.enabled=true
    • web.service.create=true
  • web.image.* 用于指定 web/Dockerfile 产出的镜像
  • web.service.port 默认为 3000
  • web.env.apiBaseURL
    • 推荐用于 server-side / SSR 访问后端
    • 留空时 chart 会默认生成 in-cluster API Service 地址
  • web.env.nextPublicAPIBaseURL / NEXT_PUBLIC_KUBEBYON_API_BASE_URL
    • 当前 single-node / multi-node chart 都支持通过 web.env.nextPublicAPIBaseURL 注入浏览器侧 API 基地址
    • 推荐同 host /api 路由场景下保持留空,让浏览器继续访问当前站点下的 /api
    • 只有当浏览器必须直连不同 origin API 时,才建议显式配置这个字段

当前 web/Dockerfile 本身不额外声明自定义 build args,因此 Helm/Gateway API Phase 3 更推荐依赖:

  • Gateway API 同 host /api 路由
  • web 容器运行时的 KUBEBYON_API_BASE_URL

nodeSelector

如果仍使用 publicAccess.provider=haproxy,建议把 Pod 固定调度到一台对外可访问的公网节点, 因为默认会保留:

  • hostNetwork: true
  • haproxy sidecar

如果切到 gatewayapi,chart 本身不再占用 API Pod 的 443,但 Gateway controller 的数据面暴露方式仍需你自己规划。

如果启用了 gatewayAPI.platform.enabled=true,还建议同步检查:

  • session.cookieSecure=true
  • cors.allowedOrigins 是否符合你的站点域名策略;浏览器 cookie session 同站跨 origin 调用必须显式配置 Console origin,不建议使用 *
  • rateLimits.join.*rateLimits.auth.* 是否符合你的流量规模;触发限流时 API 返回 429 + Retry-After
  • 管理后台中的 public_base_url / join_base_url 是否已更新为你的最终站点 URL

安全相关 values:

cors:
  allowedOrigins:
    - https://console.example.com
session:
  cookieSecure: true
rateLimits:
  join:
    windowSeconds: 3
    burst: 5
    maxEntries: 10000
  auth:
    windowSeconds: 30
    burst: 5
    maxEntries: 5000

cors.allowedOrigins: ["*"] 只适合不依赖浏览器 cookie 的调用场景;后端不会为 wildcard CORS 返回 credentials,也不会把 wildcard 加入 CSRF 信任列表。

浏览器 cookie session 通常只支持同站跨 origin(例如 console.example.com -> api.example.com);任意 cross-site 前端仍会被 Sec-Fetch-Site: cross-siteSameSite=Lax cookie 策略阻止,需改用 Bearer/API token 或重新设计 SameSite=None

platform.bootstrap.*

用于 hook job 启动后自动写入:

  • platform.apiKeySourceNamespace
  • platform.apiKeySecretName

对应的 Secret。

如果你已经手工准备好了 access key,也可以关闭 bootstrap。

postgresql.enabled

若设为 true,会启用内置 PostgreSQL 子 chart。
本次已实测可用。

managedIngress.chart.*

用于控制托管业务流量入口内置 controller 的 chart 配置。

当前建议:

  • managedIngress.chart.name 保持默认 ingress-nginx
  • managedIngress.chart.repo 保持默认 https://kubernetes.github.io/ingress-nginx
  • 按需只覆盖 managedIngress.chart.version

更多边界说明见:

  • docs/architecture/managed-workload-ingress-plan.md

8. 安装 / 升级

首次安装:

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

kubectl create namespace kubebyon-helm-test

helm upgrade --install kubebyon-helm-test \
  /opt/kubebyon/deployments/single-node/helm/kubebyon \
  -n kubebyon-helm-test \
  -f /root/kubebyon-helm-values.yaml \
  --wait \
  --timeout 15m

后续升级:

export KUBECONFIG=/etc/rancher/k3s/k3s.yaml

cd /opt/kubebyon/deployments/single-node/helm/kubebyon
helm dependency build

helm upgrade --install kubebyon-helm-test . \
  -n kubebyon-helm-test \
  -f /root/kubebyon-helm-values.yaml \
  --wait \
  --timeout 15m

卸载:

helm uninstall kubebyon-helm-test -n kubebyon-helm-test
kubectl delete namespace kubebyon-helm-test

9. 验证步骤

9.1 Helm release 状态

helm ls -n kubebyon-helm-test -a
kubectl -n kubebyon-helm-test get pods,svc,deploy,job -o wide

期望:

  • release STATUS=deployed
  • kubebyon-api Pod Ready
  • publicAccess.provider=haproxyhaproxy sidecar Ready
  • PostgreSQL Ready(若启用)

9.2 健康检查

如果 Pod 调度在 157.245.196.126

curl -fsS http://157.245.196.126:8080/healthz

期望:

{"status":"ok"}

9.3 admission 端口探活

当前 admission 服务只暴露 webhook 路径,没有单独的 /healthz
因此可用下面的方法确认 9443 TLS 监听已经起来:

curl -k -s -o /dev/null -w '%{http_code}\n' https://157.245.196.126:9443/

若返回:

404

说明 TLS 监听已正常建立,只是访问了不存在的路径。

9.4 Gateway API provider 额外检查

如果使用 publicAccess.provider=gatewayapi

kubectl -n kubebyon-helm-test get gateway
kubectl -n kubebyon-helm-test describe gateway kubebyon-helm-test-kubebyon-gateway

重点确认:

  • Accepted=True
  • Programmed=True(或 controller 等价状态)
  • listener 名称与 values 中的 gatewayAPI.listenerName 一致
  • control-plane shared Gateway 的 GatewayClassgatewayAPI.addressMode + gatewayAPI.gatewayClassProfiles.* 的解析结果一致

如果你把 shared Gateway 放在其他 namespace,请把上面的 namespace / 名称替换为你的实际值。

如果同时启用了 gatewayAPI.platform.enabled=true,再额外检查:

kubectl -n kubebyon-helm-test get gateway <platform-gateway-name>
kubectl -n kubebyon-helm-test get httproute
kubectl -n kubebyon-helm-test describe httproute <platform-api-route-name>

重点确认:

  • platform GatewayHTTPS listener 已被 controller 接受
  • platform GatewayGatewayClass 与下面的优先级一致:
    • gatewayAPI.platform.gatewayClassName
    • 否则 gatewayAPI.addressMode 对应 profile
    • 否则 gatewayAPI.gatewayClassName
  • HTTPRouteResolvedRefs=True
  • HTTPRouteAccepted=True
  • TLS Secret 位于 platform Gateway namespace
  • 若启用 web.enabled=true/ 会被额外转发到 web Service

如果启用了 web.enabled=true,建议再额外检查:

kubectl -n kubebyon-helm-test get deploy,svc | rg 'kubebyon-web|web'
kubectl -n kubebyon-helm-test describe httproute <platform-web-route-name>

如果同时启用了 gatewayAPI.workload.enabled=true,再额外检查:

kubectl -n <workload-gateway-namespace> get gateway <workload-gateway-name>
kubectl -n <workload-gateway-namespace> describe gateway <workload-gateway-name>
kubectl get httproute -A
kubectl get httproute,svc,endpointslice -A -l 'app.kubernetes.io/managed-by=kubebyon,kubebyon.app/gateway-api-sync-kind=workload-edge'

重点确认:

  • workload Gateway 已创建,且与 control-plane / platform Gateway 分离
  • workload GatewayGatewayClass 与下面的优先级一致:
    • gatewayAPI.workload.gatewayClassName
    • 否则 gatewayAPI.addressMode 对应 profile
    • 否则 gatewayAPI.gatewayClassName
  • tls.enabled=false 时 listener 为 HTTP:80
  • tls.enabled=true 时,Helm render 仍只保留 HTTP:80 listener;runtime syncer 收敛后应能看到动态维护的 HTTPS listener
  • cluster 已生成 managed_workload_ingress_cname_target 或配置 hostname bindings 后,能看到 runtime syncer 在对应 cluster 宿主 namespace 中动态维护的 HTTPRouteServiceEndpointSlice
  • HTTPRoutehostnames 应覆盖 cluster 级 CNAME target 与已绑定 hostname,backend 指向同 namespace 的 shim Service
  • 这些 shim 资源优先转发到目标 vCluster 内托管 ingress controller 的 PodIP:80,不满足条件时再回退到宿主节点 IP + NodePort
  • gatewayAPI.workload.podCIDRRoute.mode=routeagent,还需要确认 kubebyon-route-agent DaemonSet 运行正常,且 RoutePlan 已在目标宿主节点进入 ready
  • 若启用 certManager.enabled=true,还能看到 runtime syncer 在 workload Gateway namespace 动态维护的共享 Certificate
  • 若启用 certManager.selfManaged.enabled=true,对 self-managed 外部 hostname 还应看到独立 Certificate

9.5 bootstrap Secret

kubectl -n kubebyon-helm-system get secret vcluster-platform-api-key -o yaml

确认其中存在:

  • host
  • accessKey
  • project
  • insecure

9.6 控制台登录与集群创建

实测可以直接用管理员账号登录:

  • 邮箱:admin-helm@kubebyon.local
  • 密码:ChangeMe123!

创建测试集群示例:

curl -c cookie.txt \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin-helm@kubebyon.local","password":"ChangeMe123!"}' \
  http://157.245.196.126:8080/api/auth/login

curl -b cookie.txt \
  -H 'Content-Type: application/json' \
  -d '{"name":"helm-smoke","kubernetes_version":"v1.31.2"}' \
  http://157.245.196.126:8080/api/console/clusters

本次实测结果:

  • 可以成功登录
  • 可以成功创建 vCluster
  • 集群最终状态变为 ready
  • api_endpoint 会返回宿主节点上的 NodePort 地址

10. 常见问题

10.1 helm dependency build 报仓库不存在

现象:

Error: no repository definition for https://charts.bitnami.com/bitnami

处理:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm dependency build

10.2 PostgreSQL 刚起来时 API 以前会 CrashLoop

这个问题已经在本轮修复:

  • 启动阶段会对 PostgreSQL Ping 做有限次重试
  • 实测 fresh install 时 kubebyon-api Restart Count = 0

10.3 为什么 admission 根路径返回 404

因为 admission 服务只提供:

  • /api/internal/admission/.../mutate-pod
  • /api/internal/admission/.../validate-pod

所以:

  • 404 代表“端口已监听,但路径不存在”
  • 不代表 admission TLS 没启动

10.4 删除测试 vCluster 后 namespace 还在

当前删除流程会先删除 vCluster 本体;
某些情况下 vCluster namespace 可能保留为空 namespace。

如果你希望顺手清理:

kubectl delete namespace YOUR_VCLUSTER_NAMESPACE

10.5 Gateway API provider 安装时报 CRD/Kind 不存在

请先检查:

  • 是否已经安装 Gateway API CRD
  • 是否安装的是 experimental bundle(第一阶段 passthrough 需要 TLSRoute
  • Gateway controller 是否已经 Ready

建议先按:

完成前置条件,再安装 KubeBYON chart。


11. 本次实测记录

部署后应确认:

  • Helm chart 依赖构建成功
  • Release 安装成功
  • kubebyon-api + haproxy Ready
  • 内置 PostgreSQL Ready
  • http://<HOST>:8080/healthz 返回 200
  • 如果启用 admission,https://<HOST>:9443/ 返回 404(TLS 监听正常)
  • bootstrap hook 成功写入 platform Secret
  • 可以登录控制台
  • 可以成功创建 vCluster
  • 创建后的集群状态可收敛到 ready