单机 k8s 部署

要在单台/已有 k8s 集群上部署完整平台、或部署后打不开/排障时读这篇

02-部署安装 / 部署方式 / 单机与docker-compose
单机部署k8s部署kubernetesrancherstart.shistio-ingressgatewayNodePortipvsiptablescontainerdnerdctl域名访问virtual.yamlSERVICE_EXTERNAL_IPnginx反向代理https

单机 k8s 部署

本篇讲在机器上以 k8s 形态部署完整平台:先有一个 k8s 集群(不熟 k8s 可用 rancher 起),再用 start.sh 把 CubeStudio 部署到 k8s 上。部署完成后能调度真实的 pipeline / notebook / 推理任务。

机器规格、操作系统、k8s 版本等前置要求见 部署总览与前置要求

部署提前预备内容

  1. 分布式存储:挂载到 /data/k8s 目录下(单机可忽略)。NFS 等分布式存储的搭建可参考仓库内 install/kubernetes/nfs/NFS离线部署.md;存储目录约定见 04-运维管理/分布式存储目录.md
  2. 私有镜像仓库:在每台机器的 docker 配置中添加 Insecure Registries(体验可忽略)。Harbor 搭建见 04-运维管理/私有镜像仓库Harbor.md(仓库内对应 install/harbor/readme.md)。
  3. GPU / IB 驱动:GPU 机器要安装 nvidia-docker2,并安装对应厂商驱动;IB 设备也需安装对应驱动(CPU 机器可忽略)。可参考仓库内 install/rancher 目录。

1、对于不熟悉 k8s 的同学

可以先用 rancher 部署 k8s,再部署 CubeStudio。

2、对于已有 k8s 的同学

  1. ipvs 模式的 k8s
    • (1)把 start.sh 脚本最后面的 kubectl patch 注释掉,然后手动把 istio-system 命名空间的 istio-ingressgateway 服务类型改为 NodePort。
    • (2)把 k8s overlay 配置文件 install/kubernetes/cube/overlays/config/config.py 中的 K8S_NETWORK_MODE 改为 ipvs(默认 iptables)。
  2. containerd 运行时的 k8s
    • (1)把 install/kubernetes/cube/overlays/config/config.py 中的 CONTAINER_CLI 改为 nerdctl(默认 docker)。
  3. 服务可用端口范围要放大到 10 ~ 60000。

配置项含义与位置说明见 04-运维管理/配置文件管理.md

注意:平台入口是 istio-system 命名空间的 istio-ingressgateway,不是 CubeStudio 的前端部分。

平台部署命令:把 k8s 集群的 kubeconfig 文件复制到 install/kubernetes/config 文件中。对于双网卡的机器,记得 rancher 里 current-context 切换为内网的连接形式,然后执行如下命令,其中 xx.xx.xx.xx 为机器内网 IP(不是外网 IP):

# 在 k8s worker 机器上执行
sh start.sh xx.xx.xx.xx

3、对于隔离内网部署的同学

参考仓库内 install/kubernetes/offline.md(离线部署流程 + 离线镜像)。

修改为非 80 端口

修改 istio-system 命名空间下名为 istio-ingressgateway 的 service,将服务类型改为 NodePort。将 80 端口的 nodePort 改为其他可访问的端口,注意不要删除 80 端口的配置,因为 gateway 中会读取这个 80 参数。

同时商业版需修改 kubeflow 命名空间 labelstudio deployment 中环境变量 LABEL_STUDIO_HOST 的值,添加上暴露出来的端口号。

域名访问

修改 install/kubernetes/virtual.yaml,将其中 hosts 参数 * 改为域名,然后重新部署:kubectl apply -f virtual.yaml

配置文件 config.py 中修改 SERVICE_EXTERNAL_IP,将域名作为外网 IP,比如设置为 ['192.168.3.22|localhost.example.com'];如果是多个集群,则修改 CLUSTERS 的每个集群的 HOST 字段。删除后重启后端 pod,使配置生效(配置文件说明见 04-运维管理/配置文件管理.md)。

然后删除所有之前创建的虚拟服务:

kubectl delete vs --all -n jupyter
kubectl delete vs --all -n service
kubectl delete vs --all -n automl
kubectl delete vs --all -n aihub

修改域名后,notebook / 内部服务 / 推理服务要清理、重启才能打开。

如果没有域名但想通过域名访问,除上面的修改外,还需在本地 hosts 文件中添加域名解析:

xx.xx.xx.xx  your.host.com

若使用域名访问前,没有清理重启 notebook、内部服务、推理服务和 aihub 应用,那么在使用域名访问后,reset notebook 和部署服务会造成平台无法域名访问。这是因为 istio 代理中 IP 代理优于域名代理,此时要用 IP 进入平台,把 jupyter 和 service 命名空间的所有 notebook、内部服务、推理服务全部清理掉,再重新用域名访问。

内部 IP 和外部 IP

  1. 部署 CubeStudio 时,start.sh 脚本后面要填内网 IP,浏览器访问使用外网 IP(公网 IP),并修改 config.py 中 SERVICE_EXTERNAL_IP['内网ip|外网ip'](见 04-运维管理/配置文件管理.md)。
  2. 标注平台:修改 kubeflow 命名空间 labelstudio 的 deployment 中前后端环境变量 LABEL_STUDIO_HOST,改为公网 IP 和端口。

nginx 反向代理 istio-ingressgateway

有时浏览器只能打开物理机 IP,而部署 CubeStudio 用的是虚拟机,需要加 nginx 代理。注意 nginx 访问超时时长要设大一些,否则 websocket 协议的 webshell 执行命令会失败。

nginx 配置参考仓库内 install/kubernetes/nginx-https/nginx.conf,相关说明见 04-运维管理/平台HTTPS配置.md

内网穿透形式

内网穿透参考仓库内 install/kubernetes/frp/readme.md

https 协议

因为 istio-ingressgateway 只暴露 80 端口,需要通过 nginx 代理 https 协议,以 http 协议格式代理到 istio-ingressgateway。nginx 的 https 代理参考仓库内 install/kubernetes/nginx-https/readme.md(见 04-运维管理/平台HTTPS配置.md)。

由于从 nginx 流出后均为 http 协议,后端返回某项数据或协议时可能无法识别前端是 http,所以还需要修改前端镜像构建用的 install/docker/dockerFrontend/nginx.80.conf,取消注释:

proxy_set_header X-Forwarded-Proto https;

同时在 config.py 中为 AIHUB_ENV 增加 "PROTOCOL":"https" 环境变量,重启后端 pod。

部署后排查

部署后打不开 / 任务起不来时,按下面顺序排查。先了解 平台基础组件,机器标签管理可参考 03-平台使用/02-资源与存储/机器资源配置.md

  1. kubectl version 查看是否存在 kubectl。内网中可能 kubectl 不存在又无法下载,可改 start.sh 脚本手动下载 kubectl。
  2. rancher 部署的是 iptables 模式,kubekey 部署是 ipvs 模式。若 k8s 采用 ipvs 网络模式,把 istio-ingressgateway 改为 nodeport 模式(而非 externalIPs),并在 config.py 中把 K8S_NETWORK_MODE 由 iptables 改为 ipvs。
  3. 查看机器是否打了标签:
    kubectl get nodes --show-labels
    
    没有标签则用下面命令添加(替换 $node 变量):
    kubectl label node $node train=true cpu=true notebook=true service=true org=public istio=true knative=true kubeflow=true kubeflow-dashboard=true mysql=true redis=true monitoring=true logging=true --overwrite
    
  4. pv 和 pvc 是否绑定。有些 k8s 平台会自动为 pvc 添加 Storage Classes,需要对应 pv 也添加完成绑定。
  5. infra 命名空间其他组件是否成功,它们会连接 mysql 完成数据库初始化。kubeflow 数据库由 kubeflow-dashboard.infra 组件完成初始化。
    • 4.1 数据库如果库表不全,可把对应库删掉重启相应组件:rm -rf /data/k8s/infra/mysql,然后重启 infra 命名空间 mysql 的 pod,再重启 kubeflow-dashboard 相关 pod。
    • 4.2 如果 kubeflow-dashboard 报 core dump,可能是 linux 系统内核版本太低,需要升级系统内核。
  6. kube-system 命名空间 coredns 的 pod 是否正常,看日志是否有 timeout 报错。
    • 5.1 可以放开流量代理:
      /sbin/iptables -P FORWARD ACCEPT
      /sbin/iptables -P INPUT ACCEPT
      /sbin/iptables -P OUTPUT ACCEPT
      
      放开后重启 coredns 的 pod。
    • 5.2 查看 53 端口是否被占用(比如 bind 服务),关闭主机原有 53 端口服务:systemctl stop bind9 && systemctl disable bind9(注意机器重启后原 53 端口服务可能被重新打开)。
    • 5.3 参考 https://www.cnblogs.com/zhaichao93/p/16224163.html 修正 dns 配置。
  7. istio-system 空间下,istio-ingressgateway 的 svc 是否以 externalIPs 形式暴露了内网 IP。如果有双网卡,执行 sh start.sh xx.xx.xx.xx 时用的是内网 IP,浏览器打开的是外网 IP。
  8. istio-ingressgateway 暴露 80 后仍无法打开,可能原因:(1)80 被内网封禁(2)80 被其他服务占用(3)没有禁用 nginx-ingress(4)防火墙限制,可执行 /sbin/iptables -P FORWARD ACCEPT
  9. istio-ingressgateway 暴露其他端口:如果 80 被占用,可修改 istio-system/svc/istio-ingressgateway 类型为 NodePort,同时商业版需修改 kubeflow 命名空间 labelstudio deployment 中环境变量 LABEL_STUDIO_HOST 的值,加上暴露出来的端口号。
  10. 镜像拉取不下来:可离线拉取一遍平台镜像(仓库内脚本 install/kubernetes/pull_image_kubeflow.sh);对于其他仓库镜像最好设为 public,否则更新每个命名空间 hubsecret 的账号密码。配置在“在线开发 -> 镜像仓库”中 hubsecret 的账号密码为自己的 dockerhub 账号密码。
  11. 如果报错 failed to create fsnotify watcher: too many open files,一般由于机器算力太小,执行下面命令修复:
    sudo sysctl -w fs.inotify.max_user_watches=2099999999
    sudo sysctl -w fs.inotify.max_user_instances=2099999999
    sudo sysctl -w fs.inotify.max_queued_events=2099999999
    

命令、脚本路径与配置项以源码(install/kubernetes/install/docker/config.py)为准,仅供导航。

最后更新 2026-07-09完整文档以官方仓库为准:GitHub Wiki