LogoTensorFusion 文档
LogoTensorFusion 文档
首页

快速开始

TensorFusion 概览在 Kubernetes 安装在虚拟机/服务器安装(K3S)Helm 快速安装在宿主机/虚拟机安装TensorFusion 架构

应用操作

创建 AI 应用注解使用场景配置自动扩缩容迁移现有应用最佳实践

自定义AI基础设施

生产级部署指南QoS 级别与计价云厂商集成(BYOC)管理许可证

维护与优化

组件更新配置告警GPU 热迁移预加载模型优化 GPU 效率

故障排除

问题处理手册链路追踪/性能分析查询指标和日志

参考

对比

与 NVIDIA vGPU 对比与 MIG/MPS 对比与趋动科技对比与 NVIDIA Run:ai 对比与 HAMi 的对比

生产级部署指南

在生产环境运行 TensorFusion:控制面高可用、外置指标存储、告警、固定版本,以及可灰度、可回滚的迁移

默认的 helm install 只有 1 个 controller 副本、单机 GreptimeDB 和 1 个 Alertmanager 副本,适合试用,不适合生产。本文按实施顺序列出上生产前要做的调整:

  1. controller 和 Alertmanager 改为多副本。
  2. 指标存储换成高可用的 GreptimeDB。
  3. 把告警接到值班渠道。
  4. 固定各组件版本。
  5. 小步迁移工作负载,并保留回滚手段。
  6. 检查调度、组件更新和超卖策略。

前置条件

  • 一个带 GPU 节点的 Kubernetes 集群,并能用 kubectl 和 helm 访问。参见 在 Kubernetes 安装。
  • 至少两个可以运行 controller 的节点,让副本分散开。
  • 集群有默认 StorageClass,供 Alertmanager 存储卷使用。
  • 一个 chart 之外的 GreptimeDB 实例,或者准备在第 2 步部署。

下文命令假定 release 名称和命名空间都是 tensor-fusion-sys。把你的覆盖项写进一个文件(本文称为 my-values.yaml)并纳入版本管理。所有配置项的含义见 Helm 安装 Values 配置。

第 1 步:控制面高可用

以 chart 自带的生产叠加文件为基础,再叠加你自己的文件:

helm upgrade --install tensor-fusion-sys tensor-fusion \
  --repo https://download.tensor-fusion.ai \
  --namespace tensor-fusion-sys --create-namespace \
  -f https://download.tensor-fusion.ai/values-production.yaml \
  -f my-values.yaml

如果集群已接入 TensorFusion 控制台,把控制台安装命令里的 agent.agentId 和 agent.enrollToken 保留在 my-values.yaml 中。

values-production.yaml 做了这些改动:

组件默认值生产叠加文件
controller 副本数12
controller 资源requests 50m CPU / 256Mi,limits 2 CPU / 2Girequests 1 CPU / 1Gi,limits 4 CPU / 4Gi
Alertmanager 副本数13
Alertmanager 存储emptyDir每个副本一个 5Gi 的 PersistentVolume
内置 GreptimeDB安装不安装(greptime.installStandalone: false)

叠加文件只是去掉了内置 GreptimeDB,并没有配置替代实例。完成第 2 步之前,这次安装是不完整的。

controller 默认开启选主(启动命令中的 -leader-elect),同一时刻只有一个副本工作,它故障后由另一个接管。默认的 Pod 反亲和是 preferred。如果要保证副本一定不在同一节点,改成 required:

# my-values.yaml
controller:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - topologyKey: kubernetes.io/hostname
          labelSelector:
            matchExpressions:
              - key: tensor-fusion.ai/component
                operator: In
                values:
                  - operator

第 2 步:使用高可用的 GreptimeDB

TensorFusion 把指标和系统日志存在 GreptimeDB 里,告警规则、自动伸缩和控制台的监控面板都从这里读数据。内置实例是单副本加一个 20Gi 存储卷,生产环境请二选一:

  • Greptime Cloud:托管实例,运维工作量小。
  • GreptimeDB Operator:在自己的 Kubernetes 里部署集群版,至少 3 个 datanode。

使用 Greptime Cloud,或其他需要用户名密码、走 HTTPS 的实例:

# my-values.yaml
greptime:
  installStandalone: false
  isCloud: true
  host: <instance>.<region>.aws.greptime.cloud
  port: 5001
  db: <database>
  user: <user>
  password: <password>

使用不带认证的自建实例:

# my-values.yaml
greptime:
  installStandalone: false
  isCloud: false
  host: <greptimedb-frontend-service>.<namespace>.svc.cluster.local
  port: 4002
  db: public

isCloud: false 时,controller 通过 port 指定的 MySQL 端口查询,指标则写入 http://<host>:4000 的 public 库。请确认 Service 同时暴露了这两个端口。

greptime.password 最终会存进 Kubernetes Secret,但它同样明文出现在 values 文件里。建议从密钥管理系统取出后用 --set greptime.password=... 传入,不要提交到代码仓库。

查看监控面板

接入控制台的集群,在 TensorFusion 控制台里打开对应集群,就能看到 GPU、节点和工作负载的面板。数据仍然留在你的 GreptimeDB 中,控制台通过集群里的 agent 查询。

没有接入控制台时,把 Grafana 连到 GreptimeDB,基于 tf_* 表自建面板。表结构见监控指标定义。

第 3 步:配置告警

controller 针对 GreptimeDB 评估告警规则,把触发的告警发给 Alertmanager。发给哪个 Alertmanager、再转发到哪里,由你决定。

方式 A:使用 chart 自带的 Alertmanager

默认已启用,补上接收器和路由即可:

# my-values.yaml
alert:
  alertManagerConfig:
    global: {}
    receivers:
      - name: default-receiver
        webhook_configs:
          - url: https://<your-alert-webhook>
    route:
      receiver: default-receiver
      group_wait: 10s
      group_interval: 5m
      repeat_interval: 3h

内容遵循 Alertmanager 配置格式。默认配置里只有一个没有目标的接收器,所以在你添加之前,不会有任何通知发出集群。

方式 B:使用已有的 Alertmanager

关闭 chart 自带的 Alertmanager,让 controller 指向你的实例。地址必须带协议。Helm 会整体替换 command 列表,所以其余参数要原样保留:

# my-values.yaml
alert:
  enabled: false
controller:
  command:
    - /manager
    - -metrics-bind-address
    - :9000
    - -leader-elect
    - -enable-auto-scale
    - -enable-alert
    - -enable-auto-expander
    - -alert-manager-addr
    - http://<alertmanager-service>.<namespace>.svc.cluster.local:9093

接收器和路由在你的 Alertmanager 里配置,方法与其他告警相同。

新增或修改告警规则

chart 内置 15 条规则,覆盖 worker 被限流、分配失败、GPU 显存或算力打满、GPU 过热、节点和池的可用容量过低、GPU 空闲等情况,位于 dynamicConfig.alertRules。

新增规则时,先把 chart values.yaml 中默认的 alertRules 列表完整复制到你的文件里,再追加自己的规则。Helm 覆盖列表是整体替换,文件里只写新规则会把内置规则全部删掉。

# my-values.yaml
dynamicConfig:
  alertRules:
    # ... 从 values.yaml 复制的全部内置规则 ...

    - name: GPUTemperatureWarning
      query: |
        SELECT node, pool, uuid, avg(temperature) AS avg_temperature
        FROM tf_gpu_usage
        WHERE temperature > {{ .Threshold }} AND {{ .Conditions }}
        GROUP BY node, pool, uuid
      threshold: 80
      evaluationInterval: 30s
      consecutiveCount: 3
      severity: P2
      summary: "GPU temperature above {{ .Threshold }}°C on {{ .node }} {{ .uuid }}"
      description: "GPU {{ .uuid }} on node {{ .node }} in pool {{ .pool }} averages {{ .avg_temperature }}°C"
      alertTargetInstance: "{{ .uuid }}"
      runbookURL: "https://<your-runbook-url>"

规则修改后 controller 会自动重新加载,不用重启。各字段含义见 dynamicConfig.alertRules。

改完后触发一条测试告警(例如加一条阈值必然被超过的规则),确认通知能送达你的渠道。

第 4 步:固定组件版本

chart 1.8.8 已经固定了大部分镜像版本,但仍有几个使用浮动 tag。建议把所有 tag 都显式写出来,避免 Pod 重启后拉到不同的版本:

组件values 键chart 默认值
controllercontroller.image.tag空,取 chart 的 appVersion(2.17.3)
hypervisorcluster.hypervisorImage(完整镜像地址)tensorfusion/tensor-fusion-hypervisor:2.15.0
accelerator 库和 limiter 库providerConfigs.nvidia.images.middlewaretensorfusion/vgpu-provider-nvidia:1.3.9
clientproviderConfigs.nvidia.images.remoteClienttensorfusion/tensor-fusion-client:v2.25.0
workerproviderConfigs.nvidia.images.remoteWorkertensorfusion/tensor-fusion-worker:v2.25.0
vectorcontroller.vectorAgentImagedocker.io/timberio/vector:latest-alpine(浮动)
内置 GreptimeDBgreptime.image.taglatest(浮动)

controller 和 hypervisor 镜像以同一个版本号一起发布,改其中一个时要核对另一个。可用的 tag 见 Docker Hub。

chart 本身也要固定:在 helm upgrade 命令里加上 --version <chart 版本>。

第 5 步:渐进式迁移工作负载

单个工作负载分批切换

给工作负载加上注解 tensor-fusion.ai/enabled-replicas,只让其中一部分副本使用 TensorFusion,其余副本保持原样,继续使用 nvidia.com/gpu。

apiVersion: apps/v1
kind: Deployment
# ...
spec:
  replicas: 10
  template:
    metadata:
      labels:
        tensor-fusion.ai/enabled: "true"
      annotations:
        # 10 个副本中 3 个使用 TensorFusion,其余 7 个仍使用 nvidia.com/gpu
        tensor-fusion.ai/enabled-replicas: "3"

验证没问题后逐步调大这个数字。需要全部副本都使用 TensorFusion 时,删掉这个注解。

与 NVIDIA device plugin 共存

如果集群里还有 Pod 通过 NVIDIA device plugin 或 GPU Operator 申请 nvidia.com/gpu,请开启渐进式迁移,避免两套分配器把同一张 GPU 分给不同的 Pod:

# my-values.yaml
controller:
  nvidiaOperatorProgressiveMigration: true

开启后:

  • 申请原生 GPU 资源的 Pod 改由 tensor-fusion-scheduler 调度,并且只会落到 TensorFusion 尚未分配任何 GPU 的节点上。
  • 已有 TensorFusion 分配的节点会被打上 PreferNoSchedule 污点,节点重新空闲后自动移除。
  • TensorFusion 不会分配已被 device plugin 分出去的 GPU。

修改这个开关后需要重建 hypervisor Pod,新配置才会生效。

正常情况下,Pod webhook 只处理带 tensor-fusion.ai/enabled: "true" 标签的 Pod。开启渐进式迁移后,集群里所有 Pod 的创建请求都会经过它,而默认的 failurePolicy 是 Fail。开启前请确保 controller 至少有 2 个副本。

回滚

要让工作负载退回原生 GPU 用法,把标签改为 "false",或者把启用副本数改为 "0",然后等 Pod 重建:

apiVersion: apps/v1
kind: Deployment
# ...
spec:
  template:
    metadata:
      labels:
        tensor-fusion.ai/enabled: "false"
      annotations:
        tensor-fusion.ai/enabled-replicas: "0"
    spec:
      containers:
        - name: python
          image: ...
          resources:
            limits:
              # 迁移期间保留这一项,回滚时就不用再改别的地方
              nvidia.com/gpu: 1 // [!code highlight]

完整的迁移流程见迁移现有应用。

第 6 步:检查调度器配置

TensorFusion Pod 由 tensor-fusion-scheduler 调度。它是运行在 controller 进程里的 kube-scheduler,多了两个插件。配置来自 Helm 的 schedulerConfig,保存在 ConfigMap tensor-fusion-sys-config 的 scheduler-config.yaml 键中。

默认配置与原生 kube-scheduler 有两点不同:

  • 优先把节点装满。 NodeResourcesFit 使用 RequestedToCapacityRatio 策略,优先选择已有负载的节点;默认放置策略是 NodeCompactGPULowLoad。空节点因此保持空闲,可以被回收。
  • GPU 的权重高于 CPU 和内存。 nvidia.com/gpu 的权重是 5,CPU 和内存是 1。

最常需要调整的插件参数:

schedulerConfig:
  profiles:
    - schedulerName: tensor-fusion-scheduler
      # ...
      pluginConfig:
        - name: GPUResourcesFit
          args:
            maxWorkerPerNode: 256
            vramWeight: 0.7
            tflopsWeight: 0.3
        - name: GPUNetworkTopologyAware
          args:
            mode: soft
            topologySource: auto
            maxAllowedTier: 1
            unknownTopologyPolicy: treat-as-worst
            preferLeastDamage: true

schedulerConfig 是一个整体对象,修改前先从 values.yaml 把默认内容完整复制出来。改完后重启 controller Deployment。各字段含义见 schedulerConfig。

验证调度结果

controller 提供模拟调度接口,不用真的创建 Pod:

kubectl port-forward deployment/tensor-fusion-sys-controller 8080:8080 -n tensor-fusion-sys

# 模拟调度一个 Pod,请求体是 YAML 格式的 Pod 清单
curl -X POST http://localhost:8080/api/simulate-schedule \
  -H "Content-Type: application/yaml" \
  -d 'apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: default
  labels:
    tensor-fusion.ai/enabled: "true"
  annotations:
    tensor-fusion.ai/tflops-request: "100"
    tensor-fusion.ai/vram-request: "16Gi"
    tensor-fusion.ai/tflops-limit: "100"
    tensor-fusion.ai/vram-limit: "16Gi"
spec:
  schedulerName: tensor-fusion-scheduler
  containers:
  - name: test-container
    image: nvidia/cuda'

# 导出分配器的内存状态
curl http://localhost:8080/api/allocation

返回结果里有选中的节点和 GPU;调度失败时,会列出各候选在哪个过滤阶段被排除。

第 7 步:控制组件的更新方式

修改 GPU 池里 hypervisor、worker 或 client 的配置(例如换镜像)后,controller 可以自动滚动更新。是否更新、更新多快,由池上的 nodePoolRollingUpdatePolicy 决定:

字段作用CRD 默认值chart 默认池
autoUpdateHypervisorhypervisor 配置变化后重建 hypervisor Podfalsetrue
autoUpdateWorkerworker 配置变化后重建 worker Podfalsefalse
autoUpdateClient删除仍在使用旧 client 的业务 Pod,由其所属控制器按新配置重建falsefalse
batchPercentage每批更新的 Pod 比例(百分比)10020
batchInterval两批之间的等待时间1s1s

开关为 false 时,controller 只记录“配置未同步”,不动正在运行的 Pod。这些 Pod 下次重建时才会用上新配置。

生产环境建议 hypervisor 小批量更新,并留出观察时间。worker 和 client 保持关闭:更新它们会重启业务,应当放在你自己的发布流程里做。

apiVersion: tensor-fusion.ai/v1
kind: TensorFusionCluster
# ...
spec:
  gpuPools:
    - name: shared
      isDefault: true
      specTemplate:
        nodeManagerConfig:
          nodePoolRollingUpdatePolicy:
            autoUpdateHypervisor: true
            autoUpdateWorker: false
            autoUpdateClient: false
            batchPercentage: 20
            batchInterval: 5m

CRD 中还有 maintenanceWindow 和 maxDuration 两个字段,但当前版本的 controller 并不处理它们。请把“修改配置”这个动作本身安排在维护窗口内。

每次更新都先在非生产集群验证。参见组件更新。

第 8 步:采用保守的容量策略

超卖

默认池允许调度器分配物理 TFLOPS 的 20 倍(tflopsOversellRatio: 2000),并把主机内存的 50%、主机磁盘的 60% 计入额外 VRAM。这适合突发型的开发类负载。对延迟敏感的生产负载,建议调低:

# my-values.yaml
cluster:
  pool:
    capacityConfig:
      oversubscription:
        # 可调度 TFLOPS = 物理 TFLOPS 的 3 倍
        tflopsOversellRatio: 300  // [!code highlight]
        # 由主机内存承载的额外 VRAM,占主机内存的百分比
        vramExpandToHostMem: 40  // [!code highlight]
        # 由主机磁盘承载的额外 VRAM,占主机磁盘的百分比
        vramExpandToHostDisk: 20

VRAM 扩展会占用 GPU 节点的内存和磁盘,规划节点规格时要留出余量;也可以把两个百分比都设为 0,让 VRAM 严格等于物理显存。

请求与限额

不能被限流的工作负载,请求和限额之间的差距要小:

apiVersion: apps/v1
kind: Deployment
# ...
spec:
  template:
    metadata:
      labels:
        tensor-fusion.ai/enabled: "true"
      annotations:
        # 算力最多突发到请求值的 2 倍
        tensor-fusion.ai/tflops-request: "100"
        tensor-fusion.ai/tflops-limit: "200"
        # VRAM 不允许突发
        tensor-fusion.ai/vram-request: "3Gi"
        tensor-fusion.ai/vram-limit: "3Gi"
    spec:
      containers:
        - name: my-workload
          resources:
            requests:
              memory: 1Gi
              cpu: 1000m
            limits:
              memory: 4Gi
              cpu: 4000m

请求与限额相等的工作负载,默认 QoS 为 high。参见 QoS 级别与计价。

其他建议

  • 节点自动伸缩。 GPU 节点需要自动增减的集群,在池上设置最小、预热和最大容量,既能应对突发流量,又能封住成本上限。参见云厂商集成(BYOC)。
  • 日志级别。 默认池给 hypervisor 设置了 TF_LOG_LEVEL=info,生产环境保持这个级别。debug 级别的日志既刷屏又有额外开销。
  • 远程 vGPU 的网络。 远程模式下,GPU 调用要在 client Pod 和 worker Pod 之间走网络。相关节点之间应使用低延迟、高带宽的网络。
  • webhook 失败策略。 保持 controller.admissionWebhooks.failurePolicy: Fail。设为 Ignore 时,webhook 不可用期间创建的 TensorFusion Pod 会在没有分配 GPU 的情况下启动。

验证部署

# 2 个 controller Pod、3 个 Alertmanager Pod,全部 Running
kubectl get pods -n tensor-fusion-sys -o wide

# 集群和池都处于 Running
kubectl get tensorfusioncluster,gpupool

# GPU 节点和 GPU 已被发现
kubectl get gpunode,gpu

# controller 已连上 GreptimeDB,日志没有报错
kubectl logs -n tensor-fusion-sys deploy/tensor-fusion-sys-controller -c controller --tail=100

最后删掉当前工作的 controller Pod,确认它重启期间新建的 TensorFusion Pod 仍能正常注入和调度。

下一步

  • Helm 安装 Values 配置:chart 的全部配置项和默认值。
  • 云厂商集成(BYOC):自动供给 GPU 节点。
  • QoS 级别与计价:优先级与内部成本分摊。
  • 问题处理手册

最佳实践

在资源估算、运行模式、隔离、优先级和灰度上线这几方面,工作负载注解的各个选项该怎么选

QoS 级别与计价

为工作负载指定 QoS 级别,并设置 TensorFusion 计算工作负载成本和 GPU 节点成本时使用的单价

目录

前置条件
第 1 步:控制面高可用
第 2 步:使用高可用的 GreptimeDB
查看监控面板
第 3 步:配置告警
方式 A:使用 chart 自带的 Alertmanager
方式 B:使用已有的 Alertmanager
新增或修改告警规则
第 4 步:固定组件版本
第 5 步:渐进式迁移工作负载
单个工作负载分批切换
与 NVIDIA device plugin 共存
回滚
第 6 步:检查调度器配置
验证调度结果
第 7 步:控制组件的更新方式
第 8 步:采用保守的容量策略
超卖
请求与限额
其他建议
验证部署
下一步