导言

目标读者

本书《TensorStack AI 计算平台 - 用户使用手册》 的目标读者是 “TensorStack AI 计算平台” 的使用者,包括:

  • AI 研究人员
  • 建模工程师
  • 数据处理工程师
  • 机器学习工程师
  • AI 应用开发工程师等

系统管理员、运维人员需要参考另外的《TensorStack AI 计算平台 - 管理员手册》系列。

如何使用

概述 介绍了产品的基本功能和使用模式。

用户首次使用可以跟从快速开始的内容,快速完成基本的体验。

然后,用户可以阅读 AI 开发和应用章节,以学习 AI 开发相关的概念。

其他章节内容如下:

  • 账户和安全 讨论用户账户和系统安全问题。
  • 计算资源 讨论如何使用集群计算资源。
  • 存储 章节对平台的存储方面的支持进行了说明。
  • 辅助 章节描述平台提供的一些重要辅助功能,例如如何处理敏感秘密信息,打包容器镜像等。
  • 命令行工具和 SDK 讨论平台的提供的命令行工具和 Python SDK 。
  • 操作示例 章节提供了一些具体的操作指南。
  • 参考 章节对 API 提供了完整的描述。
  • 示例 章节提供了一些具体的应用示例,特别是对 LLM 领域的场景提供了全面的支持演示。
  • 集成 章节讨论了一些优秀的第三方工具在平台上的集成及使用。
  • 附录1:背景 介绍了产品的技术架构和设计思路等。

“TensorStack AI 计算平台” 是一个功能强大且灵活的产品,支持在大规模(10^3 节点)集群上进行各种 AI 场景的计算。用户在一定的时间的学习、使用、探索、积累之后,就能对其功能有深入的理解,并在上面完成各种优秀的工作。

本手册使用的例子一般存放在下列 repos:

反馈

非常欢迎各种反馈,可在 Github Issues 页面 创建 issue。

版权声明

© 2023-2024 TensorStack.

本书/网站的内容版权由 TensorStack 所有,欢迎使用。

概述

产品介绍

“TensorStack AI 计算平台” 是面向 AI 集群的系统软件,针对 AI 集群的硬件架构和 AI 领域的计算任务的特性和需求,提供稳定、可扩展的 AI 技术平台能力,服务 AI 技术研发和规模化落地。

AI 集群的拥有者可以使用这套软件,构建自己的 “AI 私有云” 或 “AI 混合云” 基础设施服务。

通过先进的架构和丰富的 API + 系统服务,“TensorStack AI 计算平台” 合理地隐藏了分布式并行、异构计算、加速计算等技术的复杂细节,提高了抽象层次,并为 AI 领域的各种计算提供了针对性的支持,极大地提升了 AI 技术研究、开发、应用的工作效率。

t9k-arch
图 1:TensorStack AI 计算平台采用云原生架构,由 AI 引擎层(AI Engine, AIE)和 AI 基础层(AI Base, AIB)组成,为上层 AI 应用和底层 AI 算力建立有机连接,提供先进、可扩展的 AI 系统层面的能力。

基本流程

用户使用 “TensorStack AI 计算平台” 的基本交互流程:

  1. 管理员 - 创建 - 项目(Project)并设定项目管理员。
    • 用户以项目管理员或者普通成员的方式使用项目。
    • 用户可以同时使用多个项目。
  2. 管理员 - 创建 - 用户帐户
  3. 用户 - 使用其帐户 - 登录系统。
  4. 用户 - 在项目中 - 完成工作(创建各种计算任务)。
t9k-flow
图 2:用户登陆系统后在 “项目” 中创建计算任务以完成各种工作。

使用功能

用户主要通过创建各种类型 CRD 的实例(instance)使用产品的功能。例如:

  • 创建一个 Notebook CRD 的实例,以使用 Jupyter Notebook;
  • 为了使用 DeepSpeed 进行大规模并行的 LLM 预训练,创建一个 DeepSpeedJob CRD 的实例;
  • 为了部署一个模型推理服务,并支持服务规模的自动伸缩,创建一个 MLService CRD 的实例;
use-t9k
图 3:用户可以通过命令行接口(CLI) 或者可视化的 Web 页面(UI) 创建这些 CRD 的实例。

CLI

CRD 实例(instance)的创建总是可以通过命令行实现,例如使用 kubectl 可以方便地创建一个 Notebook:

# create a notebook
kubectle create -f notebook-tutorial.yaml 
notebook-tutorial.yaml
# notebook-tutorial.yaml
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: tutorial
spec:
  type: jupyter
  template:
    spec:
      containers:
        - name: notebook
          image: t9kpublic/torch-2.1.0-notebook:1.77.1
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
          resources:
            requests:
              cpu: '8'
              memory: 16Gi
              nvidia.com/gpu: 1
            limits:
              cpu: '16'
              memory: 32Gi
              nvidia.com/gpu: 1
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: tutorial

UI

对于很多 CRD,TensorStack 的 Web 控制台(console)提供了通过表单(form)创建其实例的方式。

例如,可使用如下表单创建 Notebook 实例:

create-notebook-detail
图 4:使用 UI 创建 Notebook。

下一步

  • 跟从快速开始的内容,快速完成基本的体验。
  • 阅读 AI 开发和应用章节,以学习 AI 开发相关的概念。
  • 阅读背景,了解产品的技术架构和设计思路等。

快速入门

欢迎使用“TensorStack AI 平台”!

本节将带领你快速体验 “TensorStack AI 平台” 的基本功能,并完成一个简单的 AI 项目,涵盖模型的构建、训练、部署等。

使用 TensorStack AI 平台之前,你需要:

  • 拥有一个账户,以登录系统。
  • 成为一个项目的成员,以使用集群资源。

下一步

训练你的第一个模型

本教程带领你使用 Notebook,来构建和训练一个 AI 模型。

创建 Notebook

在 TensorStack AI 平台首页,点击模型构建进入构建控制台(Build Console)。

landing-page

构建控制台(Build Console)的总览页面展示了多种 API 资源,你可以点击右上角的按钮切换 Project,也可以点击事件配额标签页以查看当前 Project 最近发生的事件以及计算资源(CPU、内存、GPU 等)配额。

project

创建 PVC

在创建 Notebook 之前,首先需要创建一个用于存储文件的 PVC(持久卷)。在左侧的导航菜单中点击存储 > 持久卷进入 PVC 管理页面,然后点击右上角的创建 PVC

project

在 PVC 创建页面,如下填写各个参数:

  • Name 填写 mnist
  • Size 填写 1Gi

其他参数保持默认即可。完成之后,点击创建

project

在跳转回到 PVC 管理页面之后,可点击右上角的刷新图标来手动刷新 PVC 状态。下图展示 PVC mnist 已经创建完成。

project

创建 Notebook

在左侧的导航菜单中点击构建 > Notebook 进入 Notebook 管理页面,然后点击右上角的创建 Notebook

create-notebook

在 Notebook 创建页面,如下填写各个参数:

  • 名称填写 mnist
  • 镜像类型选择 Jupyter镜像选择 t9kpublic/torch-2.1.0-notebook:1.77.1
  • 存储卷选择 mnist
  • 调度器选择默认调度器模板选择 large

完成之后,点击创建

create-notebook-detail

在跳转回到 Notebook 管理页面之后,等待刚才创建的 Notebook 准备就绪。第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。点击右上角的刷新图标以手动刷新 Notebook 状态,待 Notebook 开始运行之后,点击右侧的打开进入其前端页面。

connect-notebook

现在 Notebook 已经可以使用了,你可以在这里进行模型的开发与测试。

jupyter

使用 Notebook 训练模型

在 Notebook 的前端页面,点击左上角的 +,然后点击 Notebook 下的 Python3 以新建一个 .ipynb 文件。

jupyter-create-notebook

复制下面的训练脚本到该 .ipynb 文件的代码框中。该脚本基于 PyTorch 框架,建立一个简单的卷积神经网络模型,并使用 MNIST 数据集的手写数字图像进行训练和测试。

torch_mnist.py
import os
import shutil

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms


class Net(nn.Module):

    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.pool = nn.MaxPool2d(2, 2)
        self.dense1 = nn.Linear(576, 64)
        self.dense2 = nn.Linear(64, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = F.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = F.relu(self.dense1(x))
        output = F.softmax(self.dense2(x), dim=1)
        return output


def train():
    global global_step
    for epoch in range(1, epochs + 1):
        model.train()
        for step, (data, target) in enumerate(train_loader, 1):
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()

            if step % 500 == 0:
                train_loss = loss.item()
                print('epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
                      format(epoch, epochs, step, steps_per_epoch, train_loss))
                global_step = (epoch - 1) * steps_per_epoch + step

                writer.add_scalar('train/loss', train_loss, global_step)

        scheduler.step()
        global_step = epoch * steps_per_epoch
        test(val=True, epoch=epoch)


def test(val=False, epoch=None):
    label = 'val' if val else 'test'
    model.eval()
    running_loss = 0.0
    correct = 0

    with torch.no_grad():
        loader = val_loader if val else test_loader
        for data, target in loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            loss = criterion(output, target)
            running_loss += loss.item()
            prediction = output.max(1)[1]
            correct += (prediction == target).sum().item()

    test_loss = running_loss / len(loader)
    test_accuracy = correct / len(loader.dataset)
    msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
        label, test_loss, label, test_accuracy)
    if val:
        msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
    print(msg)

    writer.add_scalar('{:s}/loss'.format(label), test_loss, global_step)
    writer.add_scalar('{:s}/accuracy'.format(label), test_accuracy,
                      global_step)


device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
kwargs = {
    'num_workers': 1,
    'pin_memory': True
} if torch.cuda.is_available() else {}

torch.manual_seed(1)

model = Net().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)

dataset_path = './data'
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5), (0.5))])
train_dataset = datasets.MNIST(root=dataset_path,
                               train=True,
                               download=True,
                               transform=transform)
train_dataset, val_dataset = torch.utils.data.random_split(
    train_dataset, [48000, 12000])
test_dataset = datasets.MNIST(root=dataset_path,
                              train=False,
                              download=True,
                              transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset,
                                           batch_size=32,
                                           shuffle=True,
                                           **kwargs)
val_loader = torch.utils.data.DataLoader(val_dataset,
                                         batch_size=400,
                                         shuffle=False,
                                         **kwargs)
test_loader = torch.utils.data.DataLoader(test_dataset,
                                          batch_size=1000,
                                          shuffle=False,
                                          **kwargs)

log_dir = './log'
if os.path.exists(log_dir):
    shutil.rmtree(log_dir, ignore_errors=True)
writer = SummaryWriter(log_dir)

global_step = 0
epochs = 10
steps_per_epoch = len(train_loader)
train()
test()

torch.save(model.state_dict(), 'model_state_dict.pt')

点击上方的运行按钮,可以看到训练开始进行:

jupyter-training

训练结束后,点击左上角的新建文件夹按钮,为新文件夹命名 first-model,并将当前教程产生的所有文件拖拽移动到其中。

create-folder

下一步

进行并行训练

本教程带领你使用 PyTorchTrainingJob,将教程训练你的第一个模型中的模型训练改进为使用 GPU 加速的数据并行训练。

在 Notebook 中准备并行训练

回到 Notebook mnist,在 HOME 目录(即左侧边栏文件浏览器显示的根目录 /)下,点击左上角的 +,然后点击 Other 下的 Python File 以新建一个 Python 脚本文件。

create-py-file

向该文件复制以下代码,并将其命名为 torch_mnist_trainingjob.py。该脚本在上一篇教程的脚本的基础上进行了修改以支持数据并行训练。

torch_mnist_trainingjob.py
import argparse
import logging
import os
import shutil

import torch
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.parallel import DistributedDataParallel as DDP
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms

parser = argparse.ArgumentParser(
    description='DDP training of PyTorch model for MNIST.')
parser.add_argument(
    '--backend',
    type=str,
    help='Distributed backend',
    choices=[dist.Backend.GLOO, dist.Backend.NCCL, dist.Backend.MPI],
    default=dist.Backend.GLOO)
parser.add_argument('--log_dir',
                    type=str,
                    help='Path of the TensorBoard log directory.')
parser.add_argument('--save_path',
                    type=str,
                    help='Path of the saved model.')
parser.add_argument('--no_cuda',
                    action='store_true',
                    default=False,
                    help='Disable CUDA training.')
logging.basicConfig(format='%(message)s', level=logging.INFO)


class Net(nn.Module):

    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.pool = nn.MaxPool2d(2, 2)
        self.dense1 = nn.Linear(576, 64)
        self.dense2 = nn.Linear(64, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = F.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = F.relu(self.dense1(x))
        output = F.softmax(self.dense2(x), dim=1)
        return output


def train():
    global global_step
    for epoch in range(1, epochs + 1):
        model.train()
        for step, (data, target) in enumerate(train_loader, 1):
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()

            if step % (500 // world_size) == 0:
                train_loss = loss.item()
                logging.info(
                    'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
                    format(epoch, epochs, step, steps_per_epoch, train_loss))
                global_step = (epoch - 1) * steps_per_epoch + step

                if args.log_dir and rank == 0:
                    writer.add_scalar('train/loss', train_loss, global_step)

        scheduler.step()
        global_step = epoch * steps_per_epoch
        test(val=True, epoch=epoch)


def test(val=False, epoch=None):
    label = 'val' if val else 'test'
    model.eval()
    running_loss = 0.0
    correct = 0

    with torch.no_grad():
        loader = val_loader if val else test_loader
        for data, target in loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            loss = criterion(output, target)
            running_loss += loss.item()
            prediction = output.max(1)[1]
            correct += (prediction == target).sum().item()

    test_loss = running_loss / len(loader)
    test_accuracy = correct / len(loader.dataset)
    msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
        label, test_loss, label, test_accuracy)
    if val:
        msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
    logging.info(msg)

    if args.log_dir and rank == 0:
        writer.add_scalar('{:s}/loss'.format(label), test_loss, global_step)
        writer.add_scalar('{:s}/accuracy'.format(label), test_accuracy,
                          global_step)


if __name__ == '__main__':
    args = parser.parse_args()

    logging.info('Using distributed PyTorch with %s backend', args.backend)
    dist.init_process_group(backend=args.backend)
    rank = dist.get_rank()
    world_size = dist.get_world_size()
    local_rank = int(os.environ['LOCAL_RANK'])

    use_cuda = not args.no_cuda and torch.cuda.is_available()
    if use_cuda:
        logging.info('Using CUDA')
    device = torch.device('cuda:{}'.format(local_rank) if use_cuda else 'cpu')
    kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}

    torch.manual_seed(1)

    dataset_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                'data')
    # rank 0 downloads datasets in advance
    if rank == 0:
        datasets.MNIST(root=dataset_path, train=True, download=True)

    model = Net().to(device)
    model = DDP(model)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001 * world_size)
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)

    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5), (0.5))])
    train_dataset = datasets.MNIST(root=dataset_path,
                                   train=True,
                                   download=False,
                                   transform=transform)
    train_dataset, val_dataset = torch.utils.data.random_split(
        train_dataset, [48000, 12000])
    test_dataset = datasets.MNIST(root=dataset_path,
                                  train=False,
                                  download=False,
                                  transform=transform)
    train_loader = torch.utils.data.DataLoader(train_dataset,
                                               batch_size=32 * world_size,
                                               shuffle=True,
                                               **kwargs)
    val_loader = torch.utils.data.DataLoader(val_dataset,
                                             batch_size=400,
                                             shuffle=False,
                                             **kwargs)
    test_loader = torch.utils.data.DataLoader(test_dataset,
                                              batch_size=1000,
                                              shuffle=False,
                                              **kwargs)

    if args.log_dir and rank == 0:
        if os.path.exists(args.log_dir):
            shutil.rmtree(args.log_dir, ignore_errors=True)
        writer = SummaryWriter(args.log_dir)

    global_step = 0
    epochs = 10
    steps_per_epoch = len(train_loader)
    train()
    test()

    if rank == 0:
        torch.save(model.module.state_dict(), args.save_path)

创建 Job 进行并行训练

回到模型构建控制台,在左侧的导航菜单中点击构建 > Job 进入 Job 管理页面,然后点击右上角的创建 Job > PyTorch

create-job

为了简化操作,在 Job 创建页面,点击预览 YAML,然后直接复制下面的 YAML 配置文件并粘贴到编辑框中,然后点击创建

job.yaml
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: mnist                    # Job 名称
spec:
  tensorboardSpec:               # TensorBoard 服务器规约
    resources:
      limits:
        cpu: 1
        memory: 1Gi
    logDir:
      pvc:
      - name: mnist
        subPath:
        - ./log                  # 日志文件路径
    image: tensorflow/tensorflow:2.14.0
                                 # TensorBoard 服务器使用的镜像
  torchrunConfig:
    enabled: true                # torchrun 启动
    maxRestarts: 3
    procPerNode: "4"             # 每个副本启动的进程数
    rdzvBackend: c10d
    extraOptions: []
  replicaSpecs:
    - type: node
      replicas: 1                # 副本数
      restartPolicy: ExitCode
      template:
        spec:
          securityContext:
            runAsUser: 1000
          containers:
            - name: pytorch
              image: t9kpublic/pytorch-1.13.0:sdk-0.5.2
                                       # 容器的镜像
              workingDir: /t9k/mnt     # 工作路径
              args:                    # `python`命令的参数
                - torch_mnist_trainingjob.py
                - "--log_dir"
                - "log"
                - "--save_path"
                - "./model_state_dict.pt"
                - "--backend"
                - "nccl"
              resources:               # 计算资源
                limits:                # 限制量
                  cpu: 8               # CPU
                  memory: 16Gi         # 内存
                  nvidia.com/gpu: 4    # GPU
                requests:              # 请求量
                  cpu: 4
                  memory: 8Gi
                  nvidia.com/gpu: 4
              volumeMounts:
                - name: data
                  mountPath: /t9k/mnt  # 挂载路径
                - name: dshm
                  mountPath: /dev/shm  # 挂载共享内存
          volumes:
            - name: data
              persistentVolumeClaim:
                claimName: mnist       # 要挂载的 PVC
            - name: dshm
              emptyDir:
                medium: Memory
create-job-detail

在跳转回到 Job 管理页面之后,等待刚才创建的 Job 就绪。第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。点击右上角的刷新图标来手动刷新 Job 状态,待 Job 开始运行之后,点击其名称进入详情页面。

job-created

可以看到,Job 及其创建的 4 个 Worker(工作器)正在运行。

job-detail

切换到副本标签页,点击副本的日志会显示其命令行输出,可以看到并行训练的当前进度。

job-log-view
job-log

torch_mnist_trainingjob.py 训练脚本在训练过程中添加了 TensorBoard 回调并将日志保存在了 log 目录下,Job 相应地启动了一个 TensorBoard 服务器用于可视化展示这些数据。点击 TensorBoard 右侧的 Running 进入其前端页面。

tensorboard

一段时间之后,Job 的状态变为 Done,表示训练已经成功完成。回到 Notebook mnist,将当前教程产生的所有文件移动到名为 parallel-training 的新文件夹下。

下一步

部署模型

本教程带领你使用 SimpleMLService,部署模型为推理服务。

教程训练你的第一个模型进行并行训练训练了相同架构的模型,并且都将模型参数保存为文件 model_state_dict.pt。本教程将这两个模型文件中的任意一个部署为推理服务。

准备模型文件

这里我们使用 TorchServe 部署 PyTorch 模型。回到 Notebook mnist,在 HOME 目录(即左侧边栏文件浏览器显示的根目录 /)下新建以下文件:

model.py
import torch
from torch import nn
import torch.nn.functional as F


class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.pool = nn.MaxPool2d(2, 2)
        self.dense1 = nn.Linear(576, 64)
        self.dense2 = nn.Linear(64, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = F.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = F.relu(self.dense1(x))
        output = F.log_softmax(self.dense2(x), dim=1)
        return output
handler.py
from torchvision import transforms
from ts.torch_handler.image_classifier import ImageClassifier
from torch.profiler import ProfilerActivity


class MNISTDigitClassifier(ImageClassifier):
    image_processing = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5), (0.5))])

    def __init__(self):
        super().__init__()
        self.profiler_args = {
            "activities": [ProfilerActivity.CPU],
            "record_shapes": True,
        }

    # def postprocess(self, data):
    #     return data.argmax(1).tolist()

点击左上角的 +,然后点击 Other 下的 Terminal 以新建一个终端。

create-terminal

执行以下命令以打包一个 torch 的模型包(model archive):

# 使用 Notebook 中训练的模型
torch-model-archiver --model-name mnist \
  --version 1.0 \
  --model-file model.py \
  --handler handler.py \
  --serialized-file first-model/model_state_dict.pt

# 如果使用 Job 中训练的模型,切换参数
# --serialized-file parallel-training/model_state_dict.pt

部署推理服务

在 TensorStack AI 平台首页,点击Deploy进入模型部署控制台。

landing-page

模型部署控制台的总览页面展示了当前部署服务的数量以及资源使用情况。在左侧的导航菜单中点击部署 > SimpleMLService,点击右上角的 + 弹出创建对话框,然后复制下面的 YAML 配置文件并粘贴到编辑框中,最后点击创建

apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
  name: mnist
spec:
  replicas: 1
  storage:
    pvc:
      mountPath: /var/lib/t9k/models
      name: mnist
      subPath: .
  pytorch:
    image: pytorch/torchserve:0.9.0-cpu
    modelsFlag: "mnist=mnist.mar"
    resources: 
      requests:
        cpu: 1
        memory: 1Gi
create-simplemlservice

在跳转回到 SimpleMLService 管理页面之后,等待刚才创建的 SimpleMLService 准备就绪。

  • 第一次拉取镜像可能会花费较长的时间,具体取决于集群的网络状况。
  • 点击右上角的刷新按钮以手动刷新 SimpleMLService 状态。

使用推理服务

查看推理服务地址

在 SimpleMLService 就绪之后,点击其名称进入详情页面。

enter-simplemlservice

页面中展示的 DNS 即为推理服务地址,注意该地址只能从集群内部访问。

simplemlservice-detail

访问推理服务

回到 Notebook mnist,在终端中执行以下命令以下载测试数据,并向推理服务发送请求。注意变量 URL 的值需要修改为实际部署的推理服务的地址。

# 下载测试图像文件
wget https://t9k.github.io/user-manuals/latest/assets/get-started/deployment/{0,1,2}.png

# 注意:此 URL 只适合在集群内当前项目(Project)内部(例如当前项目的 Notebook 中)访问使用
URL="http://mnist.demo.svc.cluster.local/v1/models/mnist:predict"
curl -T 0.png $URL    # 或使用 `1.png`, `2.png`

响应体应是一个类似于下面的 JSON,其预测了图片最有可能是的 5 个数字以及相应的概率:

{
  "0": 1.0,
  "2": 1.7797361302828807e-16,
  "9": 6.094195260341553e-19,
  "6": 1.5410183526346253e-19,
  "5": 7.889719768364669e-20
}

清理

体验结束后,可将当前教程产生的所有文件移动到名为 deployment 的新文件夹下。

也可以将部署的推理服务删除:

# optional, delete service if desired.
kubectl delete SimpleMLService mnist

下一步

AI 开发和应用

TensorStack AI 平台提供了一套完整、全面的工具和服务,对 AI 模型的构建、训练和部署提供全流程的支持,从而助力研究人员轻松、高效地实现 AI 项目,加速 AI 模型的研究、开发和应用。

下图展示了在平台上开发并应用一个深度学习模型的完整流程,以及各个模块发挥的功能:

ai-development

下一步

模型构建

一次完整的模型构建实验由许多步骤组成,包括准备实验数据、开发机器学习算法、选择训练超参数和执行训练等等。

TensorStack AI 平台的模型构建模块可以帮助你在分布式集群中快速方便地完成上述工作。模型构建模块的功能包括:

function
  • Notebook:在线机器学习开发工具,你可以使用此模块直接在平台上开发机器学习脚本。
  • TensorBoard:机器学习可视化工具,实现训练过程可视化、模型可视化。
  • Job:一类任务型资源,其中包括 TensorFlowTrainingJob、MPIJob 等多种资源,使用各种机器学习框架、通信协议来进行分布式计算。其中 TensorFlowTrainingJob 和 PyTorchTrainingJob 集成了 TensorBoard 的创建功能,可以监控训练进程和查看训练结果。
  • AutoTune:超参数调优实验,在给定的搜索空间中查找最优的超参数组合以及机器学习网络结构。AutoTune 在进行超参数调优的过程中需要使用 TrainingJob(根据训练框架选用 TensorFlowTrainingJob、PyTorchTrainingJob 或 XGBoostTrainingJob)对超参数的效果进行验证。

架构

architecture

如上图所示:

  • TensorStack CLI 是 TensorStack AI 平台所使用的命令行工具,可以用于操作几乎所有 TensorStack AI 平台的模块,包括模型构建。
  • Kubernetes API Server 是 Kubernetes 的重要组成部分,负责对外提供接口,接受对集群的操作请求。在此框架中,Kubernetes API Server 需要向模型构建模块提供集群中的资源信息,同时接收资源的创建、删除等请求。
  • 红框中的内容为模型构建模块的组成部分:
    • 控制台(Console):模块的交互界面,你可以通过此界面使用模块的全部功能。
    • 服务器(Server):模块功能的提供者,为你提供查看、创建、修改和删除资源的接口。
    • 控制器(Controller):资源控制器,用于处理资源的创建和修改请求。

下一步

Notebook

JupyterLab 是一款非常流行的机器学习开发工具,它通过友好易用的 Web 界面提供交互式计算环境,支持多种编程语言和执行环境,在机器学习、AI、数据处理、数值模拟、统计建模、数据可视化等领域被广泛使用。

用户可以使用 Notebook CRD 在集群中快速部署一个 JupyterLab 服务,同时本产品还提供 GPU 支持、SSH 访问支持等功能。

创建 Notebook

下面是一个基本的 Notebook 示例:

# notebook-tutorial.yaml
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: tutorial
spec:
  type: jupyter
  template:
    spec:
      containers:
        - name: notebook
          image: t9kpublic/torch-2.1.0-notebook:1.77.1
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
          resources:
            requests:
              cpu: '8'
              memory: 16Gi
              nvidia.com/gpu: 1
            limits:
              cpu: '16'
              memory: 32Gi
              nvidia.com/gpu: 1
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: tutorial

在该例中,spec.template.spec 字段定义所要创建的 Pod 的规约:

  1. 指示 Pod 运行一个 notebook 容器(spec.template.containers),该容器运行的镜像是 t9kpublic/torch-2.1.0-notebook:1.77.1,这是一个 Notebook 镜像
  2. 通过 spec.template.spec.volumesspec.template.containers[].volumeMounts 指示挂载网络文件系统 PVC tutorial/t9k/mnt
  3. 通过 spec.template.spec.containers[].resources 指定使用的 CPU、memory、GPU 资源 。

使用 GPU

Notebook 支持通过申请使用 GPU 资源,例如:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: tutorial
spec:
  type: jupyter
  template:
    spec:
      containers:
        - name: notebook
          image: t9kpublic/torch-2.1.0-notebook:1.77.1
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
          resources:
            limits:
              cpu: '16'
              memory: 32Gi
              nvidia.com/gpu: 1
          command: []
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: tutorial

在该例中:

  • 申请使用 16 个 CPU、32Gi 内存以及一个 NVIDIA GPU;系统会自动将 Notebook 调度到集群中某个能提供这些资源的节点上。

SSH 访问

Notebook 提供运行 SSH Server 的支持。下面的 Notebook 示例运行一个支持 SSH 连接的 JupyterLab 镜像:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: tutorial
spec:
  type: jupyter
  template:
    spec:
      containers:
        - name: notebook
          image: t9kpublic/torch-2.1.0-notebook:1.77.1
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
          resources:
            limits:
              cpu: '16'
              memory: 32Gi
              nvidia.com/gpu: 1
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: tutorial
  ssh:
    authorized_keys:
      - example-user
    enabled: true
    serviceType: ClusterIP

在该例中,用户:

  1. 设置 spec.ssh.enabled 字段的值为 true,T9k 系统将会自动创建一个处理 SSH 请求的 Service
  2. 通过 spec.ssh.serviceType 字段指定服务类型为 ClusterIP
  3. 设置自动挂载存放在 Secret/example-user 中的用户 SSH key;

使用此 SSH 服务需要通过 t9k-pf 工具进行端口转发。

资源回收

T9k 系统提供空闲 Notebook 资源回收的支持。系统在检测到 Notebook 处于空闲状态并超过一定时长时,就会自动删除工作负载以释放计算资源。目前,资源回收仅针对 Jupyter 类型的 Notebook,其他类型(例如 RStudio)的 Notebook 不会被回收。

管理员可设置回收策略,使得:

  • Notebook 没有活跃运行超过 1h(管理员可修改此时长)后,标记该 Notebook 为 Idle
  • Notebook 进入 Idle 状态超过 24h(管理员可修改此时长)后,删除该 Notebook 底层工作负载。

如果需要再次使用该 Notebook,你可以在模型构建控制台中手动点击恢复按钮。

Notebook 镜像

T9k 提供了一些预先构建的镜像,与 JupyterLab 原生镜像相比内置了更丰富的工具包,请参阅 Notebook 标准镜像列表

在这些镜像中:

  • 默认启动一个 JupyterLab 服务。
  • 预装了 Python3 以及 tensorflowpytorchkeraspandasscikit-learn 等常用 Python 包。
  • 身份是一个名为 t9kuser 的非 root 用户(用户 ID 为 1000,组 ID 为 1000),$HOME 目录为 /t9k/mnt
  • 预装了 tensorboard 插件,你可以在网页中创建 TensorBoard 以可视化数据。

用户也可以自行构建镜像,并上载到镜像 registry 中供使用。

常见高级配置

Notebook 底层启动了一个 Pod 来运行 JupyterLab,因此 Pod 相关的配置均可填写到 Notebook 中,详见 PodSpec

下面介绍如何填写一些常见的高级配置。

环境变量

下面的 Notebook 示例设置了一些环境变量:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: tutorial
spec:
  type: jupyter
  template:
    spec:
      containers:
        - name: notebook
          image: t9kpublic/torch-2.1.0-notebook:1.77.1
          env:
            - name: HTTP_PROXY
              value: <host>:<port>
            - name: HTTPS_PROXY
              value: <host>:<port>
            - name: LOCALE
              value: zh-cn
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
          resources:
            requests:
              cpu: '8'
              memory: 16Gi
              nvidia.com/gpu: 1
            limits:
              cpu: '16'
              memory: 32Gi
              nvidia.com/gpu: 1
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: tutorial

在该例中,spec.template.spec.containers[*].env 定义了 Pod 中对应容器的环境变量。环境变量常被用于:

  1. 设置网络代理:HTTP_PROXYHTTPS_PROXY
  2. 设置额外的 Python 包和模块路径:PYTHONPATH
  3. 设置 C 语言静态库和共享库路径:LIBRARY_PATHLD_LIBRARY_PATH
  4. ...

用户可直接在 Notebook 的终端中使用这些环境变量,例如:

# 自动使用,curl 可以自动使用 HTTPS_PROXY 等环境变量
curl https://ifconfig.io

# 通过命令行参数指定 --proxy 指定环境变量的值
curl --proxy $HTTPS_PROXY https://ifconfig.io

用户也可以在 Python 程序中读取并使用这些环境变量,例如:

import os
os.getenv('LOCALE')

共享内存

一些程序的运行可能要求使用共享内存,下面的 Notebook 示例展示了如何设置共享内存:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: tutorial
spec:
  type: jupyter
  template:
    spec:
      containers:
        - name: notebook
          image: t9kpublic/torch-2.1.0-notebook:1.77.1
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
            - name: dshm
              mountPath: /dev/shm
          resources:
            requests:
              cpu: '8'
              memory: 16Gi
              nvidia.com/gpu: 1
            limits:
              cpu: '16'
              memory: 32Gi
              nvidia.com/gpu: 1
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: tutorial
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: "1Gi"

在该例中:

  • spec.template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

设置网络代理

在 Notebook(或者 Job 等其它工作负载)中运行程序时,例如下载训练数据,如果用户需要设置网络代理,可采用如下方式:

全局设置

请按照环境变量一节为 Notebook(或者 Job 等其它工作负载)设置 HTTP_PROXYHTTPS_PROXY 两个环境变量(或者其它更多相关变量)。

无论是通过终端运行 curl、wget 等命令或通过 Python 代码来下载训练数据,下载程序一般都会尊重环境变量 HTTP_PROXYHTTPS_PROXY 的设置,使用这两个环境的值作为网络代理。

临时设置

如果仅在运行特定程序时需要使用代理,可通过临时设置环境变量。例如,curl 支持如下方式设置网络代理:

  1. 命令行参数
curl --proxy <proxy-address> https://ifconfig.io
  1. 环境变量
# 为单个命令设置环境变量
HTTPS_PROXY=<proxy-address> curl  https://ifconfig.io

# 或者,为当前 shell 及子进程设置
export HTTPS_PROXY=<proxy-address>
curl  https://ifconfig.io

在程序里设置

很多网络通讯库支持在调用时设置额外的参数,例如 Python 的 request 库,支持如下使用方法:

import requests 

proxies = {
    'http': 'http://1.2.3.4:8080',
    'https': 'https://1.2.3.4:3128'
}

response = requests.get(url, proxies=proxies)

下一步

用户可尝试如下功能:

参考

TensorBoard

TensorBoard 是 TensorFlow 提供的一种可视化机器学习过程和结果的工具,功能强大且广泛应用于多种框架。

你可以使用本产品在集群中一键部署 TensorBoard,可视化训练模型。

创建 TensorBoard

下面是一个基本的 TensorBoard 示例:

# tensorboard-example.yaml
apiVersion: tensorstack.dev/v1beta1
kind: TensorBoard
metadata:
  name: pytorchtrainingjob-tensorboard
  namespace: t9k-example
spec:
  image: docker.mirrors.ustc.edu.cn/tensorflow/serving:2.6.0-gpu
  trainingLogFilesets:
  - t9k://pvc/pytorchtrainingjob-tensorboard-pvc/log

在该例中,TensorBoard 使用 docker.mirrors.ustc.edu.cn/tensorflow/serving:2.6.0-gpu 镜像,对名为 pytorchtrainingjob-tensorboard-pvc 的 PVC 中 /log 路径下的模型数据进行可视化。

FileSet

FileSet 是一种特殊的资源定位符(URI),是一种用于定位多种存储技术中的资源的字符串。

FileSet 的格式为 t9k://storage-type/storage-identity/path,由下列四部分构成:

  • 协议:t9k://
  • 存储器类型:当前 FileSet 支持 PVC(在 FileSet 中写作 pvc) 和 MinIO(在 FileSet 中写作 minio) 两种存储器。
  • 存储器定位方式:FileSet 使用 PVC 的名称来定位 PVC 存储器,使用记录了 MinIO 地址、用户名和密码的 Secret 来定位 MinIO 存储器。
  • 数据在存储器中的路径:模型在存储器中的准确位置。

下面是两个 FileSet 示例:

  • t9k://pvc/pytorchtrainingjob-tensorboard-pvc/log/model 表示:所指向的资源被存储在名为 pytorchtrainingjob-tensorboard-pvc 的 PVC 中的 log/model 路径下。
  • t9k://minio/secret-name/bucket1/log/model 表示:所指向的资源被存储在一个 MinIO 中名为 bucket1 的 Bucket 中的 log/model 路径下,该 MinIO 的地址、用户名和密码被存储在名为 secret-name 的 Secret 中。

TrainingJob 自动创建 TensorBoard

我们在 TensorFlowTrainingJobPyTorchTrainingJob 中集成了 TensorBoard 的创建,你可以在创建 TrainingJob 后直接进入 TensorBoard 监控训练进程和查看训练结果。

资源回收

TensorBoard 提供空闲资源回收的支持,在检测到 TensorBoard 处于空闲状态并超过一定时长时,删除工作负载以释放计算资源。默认情况下(管理员可修改配置):

  • TensorBoard 无人使用超过 1h 后,标记该 TensorBoard 为 Idle
  • TensorBoard 进入 Idle 状态超过 24h 后,删除该 TensorBoard 底层工作负载。

如果需要再次使用该 TensorBoard,你可以在模型构建控制台中手动点击恢复按钮。

AutoTune

为了降低 AI 开发门槛和逐渐实现机器学习自动化,TensorStack AI 平台提供了自动化机器学习(AutoML)工具 AutoTune。AutoTune 具有以下特点:

  • 内置最新的自动机器学习算法,为用户自动地进行特征工程、神经网络架构搜索、超参调优和模型压缩。
  • 提供可视化展示平台,实时跟踪超参数训练过程,以交互式图形和表格的形式刻画多个不同维度的信息,用户可以借此更好地比较、分析、决策出最优参数。
  • 持海量实验数据的存储,让用户轻松地实现任意实验结果之间的比较。
  • 融合领先的 AI 最佳实践,提供自动化、准确性和协作水平,提高企业 AI 生产效率。

基本结构

concept

在上述结构图中:

  • AutoTune Controller 是 AutoTuneExperiment 的控制器,可以看做是 AutoTune 实验的入口。用户在集群中创建 AutoTuneExperiment 资源后,由控制器创建 AutoTune Server 和 Web 来执行 AutoTune 实验。
  • AutoTune Server 是执行实验的主体,其中包括:
    • Optimizer:超参数调优器,在限定的搜索空间内用特定的调优算法选择合适的超参数组合。
    • Training Manager:训练任务管理器,使用 Optimizer 产生的超参数,创建 TrainingJob 进行训练,并将训练结果反馈给 Optimizer 用于下一次超参数选择。AutoTune 可以同时创建多组 TrainingJob 来测试不同的超参数组合以加快训练效率。目前 AutoTune 支持使用 TensorFlowTrainingJobPyTorchTrainingJobXGBoostTrainingJob 进行训练。
  • AutoTune Web 是 AutoTune 的可视化界面,你可以通过此界面实时查看实验状态,对比各组超参数对实验产生的影响。

AutoTuneExperiment

你可以通过创建 AutoTuneExperiment 来实现自动优化模型超参数。

创建 AutoTuneExperiment

下面是一个基本的 AutoTuneExperiment 示例:

apiVersion: tensorstack.dev/v1beta1
kind: AutoTuneExperiment
metadata:
  name: experiment-sample
spec:
  maxExecSeconds: 7200
  maxTrialNum: 50
  trialConcurrency: 3
  searchSpace: |-
    {
      "batch_size": {"_type": "choice", "_value": [512, 1024, 2048, 4096, 8092]},
      "learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]}
    }
  trainingConfig:
    type: tensorflow
    tasks:
      - type: worker
        replicas: 1
        template:
          spec:
            securityContext:
              runAsUser: 1000
            containers:
              - command:
                  - python3
                  - dist_mnist.py
                workingDir: /mnt/mnist-distributed
                imagePullPolicy: IfNotPresent
                image: t9kpublic/tensorflow-1.15.2:tuner-2.23
                name: tensorflow
  tuner:
    builtinTunerName: TPE
    classArgs: |-
      {
        "optimize_mode": "minimize", 
        "constant_liar_type": "min"
      }

在该例中:

  • 使用 TensorFlowTrainingJob 进行训练(由 trainingConfig 字段指定,详细配置方法请参阅训练框架支持)。
  • 使用 TPE 算法进行超参数调优,算法的参数为 {"optimize_mode": "minimize", "constant_liar_type": "min"}(由 tuner 字段指定,更多参数请参阅超参数调优算法)。
  • 超参数的搜索空间为 {"batch_size": {"_type": "choice", "_value": [512, 1024, 2048, 4096, 8092]},"learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]}}(由 searchSpace 字段指定,搜索空间的格式及含义请参阅搜索空间)。
  • 可以同时测试 3 组超参数,最大测试次数为 50(分别由 trialConcurrencymaxTrialNum 字段指定),实验的最大执行时间为 2 小时(7200 秒,由 maxExecSeconds 字段指定),如果时间超出,实验进入 TIMEOUT 状态。

AIStore 的使用

AutoTuneExperiment 支持将实验数据存储在 AIStore 中,通过设置 spec.aistore 字段以使用 AIStore 数据库,其中:

  • spec.aistore.folder 声明实验数据存储在哪个 AIStore 文件夹中,内容应填写文件夹的 ID。
  • spec.aistore.secret 引用一个 K8s Secret,其中应记录 API Key,用于上传数据时进行身份验证。

下面是一个存储 APIKey 的 Secret 示例:

apiVersion: v1
data:
  apikey: ZDQyMjJjZjUtMmI0Ni00Mjk2LWFiMzYtYWI4NmVhZGUwZjQx
kind: Secret
metadata:
  name: aistore-secret
type: Opaque

搜索空间

搜索空间是实验过程中超参数的设置范围,AutoTuneExperiment 会在此范围中选择超参数进行训练,最后找出最优的超参数组合。

搜索空间是一个 JSON 结构,具体格式请参阅搜索空间

训练框架支持

AutoTuneExperiment 支持对多种训练框架进行超参数的调优,包括 TensorFlow、PyTorch 和 XGBoost。

AutoTuneExperiment 通过设置 spec.trainingConfig 字段实现对上述框架的支持。其中:

  • spec.trainingConfig.type 可设置为 tensorflowpytorchxgboost,分别表示使用 TensorFlow、PyTorch 和 XGBoost 框架进行训练。
  • spec.trainingConfig.tasks 字段的设置请根据所使用的框架种类分别参阅 TensorFlowTrainingJobPyTorchTrainingJobXGBoostTrainingJob

超参数调优算法

AutoTuneExperiment 在调参过程中需要使用超参数调优算法对超参数进行选择,对于不同的训练框架和不同的超参数种类,超参数调优算法的效率和效果也是不一样的。

算法根据功能和定义分为两类:

  • Tuner 算法:超参数调优算法,用于选取合适的超参数组合。
  • Assessor 算法:训练评估算法,用于判断当前训练是否符合预期,如果不符合则终止训练。

算法的详细介绍以及参数配置请参阅超参数调优算法

实验状态

AutoTuneExperiment 的生命周期包括以下五个阶段:

  • PENDING:AutoTune 的相关组件(包括 AutoTune Server 和 AutoTune Web)已经创建成功,等待控制器启动 AutoTuneExperiment。
  • RUNNING:AutoTuneExperiment 运行中。
  • TIMEOUT:如果达到最大执行时间(由 spec.maxExecSeconds 字段指定)后,实验仍未完成(实际训练次数小于 maxTrialNum 字段指定的训练次数),则实验超时,不再创建新的训练。
  • DONE:AutoTuneExperiment 在最大执行时间内完成了 maxTrialNum 字段指定的训练次数(无论成功或失败),则实验完成。
  • ERROR:AutoTuneExperiment 初始化阶段或运行阶段出现错误。
phase

下一步

搜索空间

搜索空间用于定义超参数的范围,AutoTune 会在这一范围内对超参数进行组合并测试,最后得到效果最好的一组训练。

格式

{
  "parameter1": {"_type": "choice", "_value":[1, 2, 3, 4]},
  "parameter2": {"_type": "randint", "_value":[1, 10]},
  ...
}

在上述结构中:

  • 每一个条目都记录了一个超参数的名称和搜索方式:
    • 每一个条目的键值(例如 parameter1parameter2)表示超参数的名称。
    • _type 是超参数搜索方法。
    • _value 表示搜索方法所使用的参数。
  • choicerandint 表示超参数的搜索方法,其具体含义请参阅搜索方法

搜索方法

_type_value 格式详细描述
choice数组(数字或字符串)每次训练选取数组 _value 中一个值作为超参数。例:{"learning_rate":{"_type": "choice", "_value": [0.01, 0.02, 0.1, 0.2]}},进行超参数调优时,每一组训练会从四个值中选取一个。
randint[lower, upper]每次训练选取 lowerupper 之间中的一个随机整数(不包括 upper)作为超参数。例:{"learning_rate":{"_type": "randint", "_value": [1, 10]}},进行超参数调优时,每一组训练可能取到的值有 [1, 2, 3, 4, 5, 6, 7, 8, 9]
uniform[low, high]每次训练从 lowerupper 区间内均匀采样作为超参数。
quniform[low, high, q]取值方法为 clip(round(uniform(low, high) / q) * q, low, high),此公式含义为:从 lowhigh 区间内均匀采样,然后将取值除以 q,并四舍五入为整数,然后将超出 [low, high] 区间的值舍弃,加上 lowupper 两个值,构成选值区间。例:_value[0, 10, 2.5],表示超参数的选值范围时 [0, 2.5, 5, 7.5, 10]_value[2, 10, 5],表示超参数的选值范围时 [2, 5, 10]
loguniform[low, high]取值方法为 exp(uniform(log(low), log(high))),此公式含义为:从 log(low)log(high) 区间内均匀采样得到样本 x,然后计算 exp(x) 得到超参数。
qloguniform[low, high, q]取值方法为 clip(round(loguniform(low, high) / q) * q, low, high)(其中 loguniform(low, high) 表示 exp(uniform(log(low), log(high)))),此公式含义参考 quniformloguniform 条目。
normal[mu, sigma]超参数的取值满足正态分布 N(mu, sigma^2)
qnormal[mu, sigma, q]取值方法为 round(normal(mu, sigma) / q) * q,此公式含义参考 quniform 条目。
lognormal[mu, sigma]取值方法为 exp(normal(mu, sigma)),此公式含义参考 loguniform 条目。
qlognoraml[mu, sigma, q]取值方法为 round(exp(normal(mu, sigma)) / q) * q,此公式含义参考 quniformloguniform 条目。

超参数调优算法

AutoTuneExperiment 在调参过程中需要使用超参数调优算法对超参数进行选择,对于不同的训练框架和不同的超参数种类,超参数调优算法的效率和效果也是不一样的。

算法根据功能和定义分为两类:

  • Tuner 算法:超参数调优算法,用于选取合适的超参数组合。
  • Assessor 算法:训练评估算法,用于判断当前超参数的训练中间结果是否符合预期,如果不符合则终止训练。

Tuner 算法

HyperOpt 类算法

HyperOpt 是一个用于超参数调优的 Python 库,其中主要包含三种超参数调优算法:RandomAnnealTPE。三种算法之间的区别以及算法的使用方法请参阅 HyperOpt 文档

算法支持使用的搜索方法有:choicerandintloguniformqloguniform

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "tuner": {
    "builtinTunerName": "Anneal",
    "classArgs": {
      "optimize_mode": "minimize", 
      "constant_liar_type": "min"
    }
  }
}

Evolution

进化算法(Evolution)是受生物进化启发得到的一种优化算法。进化算法的详细介绍请参阅 Evolutionary algorithm WIKI 文档

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "tuner": {
    "builtinTunerName": "Evolution",
    "classArgs": {
      "optimize_mode": "minimize", 
      "population_size": 32
    }
  }
}

Batch

Batch 是一种最简单的选参算法,此算法只支持一种超参数的优化(搜索空间中只能有一个条目)且仅支持 choice 搜索方法。

下面是 AutoTuneExperiment 使用此算法的一个示例(Batch 算法不需要填写参数):

{
  "searchSpace": {
      "learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]}
  },
  "tuner": {
    "builtinTunerName": "Batch"
  }
}

上述示例中,搜索空间中只有一个超参数,且 _typechoice;Batch 算法不需要传入参数,所以没有填写 tuner.classArgs 字段。

GridSearch

一种基本的选参算法,根据搜索空间中的参数和范围,枚举所有可能的超参数组合,一一测试。

算法支持使用的搜索方法有:choicerandintquniform

下面是 AutoTuneExperiment 使用此算法的一个示例(GridSearch 算法不需要填写参数):

{
  "tuner": {
    "builtinTunerName": "GridSearch"
  }
}

MetisTuner

Metis 算法的详细介绍请参阅论文 Metis: Robustly Optimizing Tail Latencies of Cloud Systems

算法支持使用的搜索方法有:choicerandintuniformquniform

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "tuner": {
    "builtinTunerName": "MetisTuner",
    "classArgs": {
      "optimize_mode": "maximize",
      "no_resampling": true,
      "no_candidates": false,
      "selection_num_starting_points": 600,
      "cold_start_num": 10,
      "exploration_probability": 0.9
    }
  }
}

GPTuner

GPT 是一种能够极大减少超参数优化步骤的贝叶斯优化算法。算法的详细介绍请参阅 NNI GPTuner 文档

算法支持使用的搜索方法有:randintuniformquniformloguniformqloguniform 和数字形式的 choice

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "tuner": {
    "builtinTunerName": "GPTuner",
    "classArgs": {
      "optimize_mode": "maximize",
      "utility": "ei",
      "kappa": 5,
      "xi": 0,
      "nu": 2.5,
      "alpha": 1e-6,
      "cold_start_num": 10,
      "selection_num_warm_up": 100000,
      "selection_num_starting_points": 250
    }
  }
}

PPOTuner

PPO 算法继承了 OpenAI 中 ppo2 的主要逻辑,并适应 NAS 场景。

算法支持使用的搜索方法有:layer_choiceinput_choice。下面是一个搜索空间设置的示例:

{
  "first_conv": {"_type": "layer_choice", "_value": ["conv5x5", "conv3x3"]},
  "mid_conv": {"_type": "layer_choice", "_value": ["0", "1"]},
  "skip": {
    "_type": "input_choice",
    "_value": {"candidates": ["", ""], "n_chosen": 1}
  }
}

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "tuner": {
    "builtinTunerName": "PPOTuner",
    "classArgs": {
      "optimize_mode": "maximize",
      "trials_per_update": 20,
      "epochs_per_update": 4,
      "minibatch_size": 4,
      "ent_coef": 0.0,
      "lr": 3e-4,
      "vf_coef": 0.5,
      "max_grad_norm": 0.5,
      "gamma": 0.99,
      "lam": 0.95,
      "cliprange": 0.2
    }
  }
}

PBTTuner

PBT 算法得自 Population Based Training of Neural Networks

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "tuner": {
    "builtinTunerName": "PBTTuner",
    "classArgs": {
      "optimize_mode": "maximize",
      "population_size": 10,
      "factor": 0.2,
      "resample_probability": 0.25,
      "fraction": 0.2
    }
  }
}

Assessor 算法

Medianstop

Medianstop 算法的逻辑是:如果在某一步 S,当前运行的实验的最佳观测值比所有已经完成的训练的第 S 步前的观测值的中位数差,则停止此次训练。此策略出自论文 Google Vizier: A Service for Black-Box Optimization

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "assessor": {
    "builtinAssessorName": "Medianstop",
    "classArgs": {
      "optimize_mode": "maximize",
      "start_step": 0
    }
  }
}

在上述示例中,start_step 表示从第几步开始上传观测值(过早上传观测值,可能会错误的停止一些刚开始表现较差的训练)。

Curvefitting

Curvefitting 算法使用学习曲线拟合算法来预测未来的学习曲线性能。其逻辑是:如果在某一步,当前训练的预测结果是收敛的并且比历史上的最佳结果差,则停止此次训练。Curvefitting 算法的详细介绍请参阅 NNI Curvefitting 文档

下面是 AutoTuneExperiment 使用此算法的一个示例(示例中的 classArgs 字段包含当前算法所有参数,有些参数在实际使用中可以选择不指定):

{
  "assessor": {
    "builtinAssessorName": "Curvefitting",
    "classArgs": {
      "optimize_mode": "minimize",
      "epoch_num": 20,
      "start_step": 6,
      "threshold": 0.95,
      "gap": 1
    }
  }
}

模型部署

TensorStack AI 平台的模型部署模块可以帮助你快速地将训练完成的 AI 模型部署为推理服务。

针对不同的应用场景,有以下两种 TensorStack API可供使用:

  • MLService 是完善的模型推理服务,可用于生产环境,具有以下特性:
    • 基于 Serverless 架构,服务容量(serving capacity)可根据负载自动伸缩;
    • 自动暴露服务到集群外部,快速上线。
  • SimpleMLService 是精简的模型推理服务,可用于快速测试、固定容量部署等场景。具有以下特性:
    • 服务副本数目(replica)固定;
    • 集群外部访问需要额外配置 Ingress 等资源。

同时,TensorStack AI 平台对模型部署提供自动化的运维支持,包括性能和资源的监控告警以及故障检测,以保障推理服务长期可靠运行。

架构

模型部署模块的架构如下图:

architecture

根据用户提供的模型存储位置和 AI 框架等设置,模型部署模块的控制器(controller)协调模型下载并启动模型推理服务。

下一步

SimpleMLService

SimpleMLService 用于在 TensorStack AI 平台上简单、快捷地部署 AI 模型推理服务,可用于小规模模型部署,快速测试等场景。

SimpleMLService 具有以下特性:

  • 直接支持 TensorFlow、PyTorch 框架,并允许用户自定义框架,具有良好的可扩展性。
  • 支持 PVC、S3 模型存储方式。
  • 直接支持从集群内部访问推理服务;集群外访问需要用户进行额外配置。
  • 服务容量固定,不支持自动伸缩。

创建 SimpleMLService

下面是一个基本的 SimpleMLService 示例:

apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
  name: mnist
spec:
  replicas: 1
  storage:
    s3:
      secretRef:
        name: s3-secret
      uri: s3://models/mnist/
      mountPath: /var/lib/t9k/model
  tensorflow:
    image: t9kpublic/tensorflow-serving:2.6.0
    resources: 
      requests:
        cpu: 1
        memory: 1Gi

本示例的 spec 字段的子字段释义如下:

  • replicas: 定义运行推理服务的副本数量是 1。
  • storage.s3: 设定使用 S3 存储模型,子字段的释义如下:
    • secretRef.name: Secret s3-secret 中存储 S3 配置信息,其详情参见:创建 S3 Secret
    • uri: 模型在 S3 中的存储标识是 s3://models/mnist/
    • mountPath: 模型被加载后,在容器中存储模型的文件系统路径是 /var/lib/t9k/model
  • tensorflow: 设定使用 tensorflow 推理框架,子字段释义如下:
    • image: 指定推理服务容器镜像 t9kpublic/tensorflow-serving:2.6.0
    • resources: 这顶一个副本 Pod 使用的资源量。

直接支持的 AI 框架

SimpleMLService 目前直接支持 TensorFlow、PyTorch 两种框架。

TensorFlow

可以通过设置 spec.tensorflow 字段来部署 TensorFlow 框架,参考示例:创建 SimpleMLService

当使用 TensorFlow 时,控制器会在容器中设置下列启动命令:

/usr/bin/tensorflow_model_server \
  --port=9090 \
  --rest_api_port=8080 \
  --model_name=<SimpleMLService name> \
  --model_base_path=<model-dir-in-container>

PyTorch

可以通过设置 spec.pytorch 字段来部署 PyTorch 框架,示例如下:

spec:
  pytroch:
    image: <pytorch-image>
    modelsFlag: "resnet-18=resnet-18.mar"
    resources: 
      requests:
        cpu: 1
        memory: 1Gi

当使用 PyTorch 时,控制器会在容器中设置下列启动命令:

torchserve \
  --start \
  --model-store=<mode-dir> \
  --models <spec.pytorch.modelsFlag>

自定义框架

如果需要使用 PyTorch, TensorFlow 之外的框架,可以通过设置 spec.custom 字段来自定义框架。

用户可在 spec.custom.spec 字段中定义一个完整的 PodSpec,并需要满足下列要求:

  1. 至少设置一个 containers 成员。
  2. 启动推理服务运行命令时,指定正确的模型路径。
  3. 未设置 spec.service 时,推理服务的服务端口应该使用 8080。

示例如下:

apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
  name: pvc-custom
spec:
  replicas: 1
  storage:
    s3:
      secretRef:
        name: s3-secret
      uri: s3://models/mnist/
      mountPath: /custom/path
  custom:
    spec:
      containers:
      - name: user-container
        args:
        - --port=9000
        - --rest_api_port=8080
        - --model_name=mnist
        - --model_base_path=/custom/path
        command:
        - /usr/bin/tensorflow_model_server
        image: "t9kpublic/tensorflow-serving:2.6.0"

副本数量

副本数量通过字段 spec.replicas 设置,用于定义 SimpleMLService 的 Pod 数量,默认值是 1。

暴露服务

通过设置 spec.service 字段来选择将服务的哪个端口暴露出来。未设置时,默认将 Pod 的 8080 端口映射到 Service 的 80 端口。

下面是一个示例:

spec:
  service:
    ports:
    - name: http
      port: 80
      targetPort: 8080
      protocol: TCP
    type: ClusterIP

在该例中:

  • 将 Pod 的 8080 端口映射到 Service 的 80 端口,协议是 TCP。
  • Service 的 Type 是 ClusterIP

调度器

SimpleMLService 支持使用两种调度器:

通过 spec.scheduler 字段可以设置欲使用的调度器:

  • 不设置 spec.scheduler 字段,默认使用 Kubernetes 调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,使用 T9k Scheduler 调度器。

在下面的示例中,SimpleMLService 使用 T9k Scheduler 调度器,并申请使用 队列 default 中的资源。

spec:
  scheduler:
    t9kScheduler:
      queue: default

模型存储

通过 spec.storage 字段可以设置 SimpleMLService 的模型存储信息,详情请见模型存储

服务状态

SimpleMLService 的状态记录在 status 字段中。

status.address 字段记录了推理服务在集群内的访问地址,子字段如下:

  • url: 推理服务在集群内的访问地址
  • ports: 推理服务可供访问的服务端口

status.conditions 字段表明了当前 SimpleMLService 的状态,包括下列 2 种类型:

  • ModelDownloaded: 模型是否成功地被下载到本地。
  • Ready: 推理服务是否就绪。

在下面的示例中:

  • 访问推理服务的地址是 sample.demo.svc.cluster.local
  • 模型已经下载到容器本地
  • 推理服务处于就绪状态
status:
  address:
    url: sample.demo.svc.cluster.local
    ports:
    - port: 80
      protocol: TCP
  conditions:
  - lastTransitionTime: "2023-12-27T06:52:39Z"
    status: "True"
    type: ModelDownloaded
  - lastTransitionTime: "2023-12-27T06:52:41Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Ready

下一步

MLService

MLService 用于在 TensorStack AI 平台上部署 AI 推理服务,其功能全面,可用于生产环境。

概述

MLService 是推理服务的核心 API,由 releasestransformer 两部分构成:

  • spec.releases 定义一个或多个 releases,以提供多版本模型推理服务的支持。
  • 可选的 transformer 定义前处理(pre-processing)和后处理(post-processing)计算。
mlservice-architecture
图 1: MLService 的组成。一个 MLService 由一个或多个模型服务版本(releases) 及前后处理模块(transformer,非必需)构成;不同的 release 和 transformer 可独立进行规模伸缩。

MLService 的主要特性包括:

  • 支持定义多个版本(release)的推理服务,每个 release 包含一个 predictor,其定义了:
    • 模型存储(storage
    • 模型规约(model),包括 parametersruntime(引用 MLServiceRuntime 定义运行推理服务 Pod 的模板)
    • 计算资源(containersResources
    • 其他部署参数(minReplicas, maxRelicas, logger ...
  • 每个 release 服务的容量可独立自动伸缩,可通过 minReplicasmaxReplicas 设置容量的上下限。
  • 支持金丝雀(canary release)发布模式。
  • 用户可定制 transformer 组件,以在调用推理服务时进行前处理(pre-processing),以及获得推理结果后进行后处理(post-processing)。
  • transformer 的容量也可独立自动伸缩,可通过 minReplicasmaxReplicas 设置容量的上下限。

示例

下面是一个基本的 MLService 示例:

apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
  name: torch-mnist
spec:
  default: version1
  releases:
    - name: version1
      predictor:
        minReplicas: 1
        maxReplicas: 3
        model:
          parameters:
            "MODEL_PATH": "mnist=model.mar"
          runtime: torchserve
        storage:
          pvc:
            name: tutorial
            subPath: tutorial-examples/deployment/pvc/mlservice-torch/
        containersResources:
        - name: user-container
          resources:
            limits:
              cpu: "500m"
              memory: 1Gi

MLServiceRuntime

示例中,我们使用了 MLServiceRuntime torchserve。MLServiceRuntime 定义了推理服务的模板,包含了推理服务的关键信息,例如镜像、启动命令、资源需求等,能够方便地帮助用户快速部署多种模型推理服务程序。

一个 MLServiceRuntime 可以被多个 MLService 使用。

定义

一个基本的 MLServiceRuntime 的示例:

apiVersion: tensorstack.dev/v1beta1
kind: MLServiceRuntime
metadata:
  name: torchserve
spec:
  enabled: true
  template:
    spec:
      containers:
      - name: user-container
        image: torchserve:0.9.0-cpu
        args:
          - torchserve
          - --start
          - --model-store=/var/lib/t9k/model
          - --models {{if .MODEL_PATH}}{{.MODEL_PATH}}{{else}}all{{end}}
        resources:
          limits:
            cpu: "200m"
            memory: 200Mi
        ports:
        - containerPort: 8080
          protocol: TCP

该 MLServiceRuntime 在 spec.template 中定义了推理服务的副本(Pod)的模板,以指定容器镜像 torchserve:0.9.0-cpu、启动命令 torchserve 及其他命令行参数等。

使用

用户可以在 MLService 的 predictor 定义中指定要使用的 MLServiceRuntime 名称,例如:

apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
  name: demo
spec:
  default: version1
  releases:
  - name: version1
    predictor:
      model:
        runtime: torchserve
      storage:
        pvc:
          name: <pvc-name>
          subPath: <model-path>

用户在 release version1.predictor.model.runtime 中指定了 torchserve,系统在创建推理服务器副本(Pod)时,将会使用名称为 torchserve 的 MLServiceRuntime。

进一步的配置

除了直接使用 MLServiceRuntime 定义好的 Pod 模板,MLService 还支持对其进行进一步的配置和修改。

Parameters

MLService 支持在 predictor.model.parameters 设置参数,该字段是一个 map 类型,key 为参数名,value 为参数值。

在之前的 MLServiceRuntime 示例 中包含了 --models {{if .MODEL_PATH}}{{.MODEL_PATH}}{{else}}all{{end}} 的内容。这里使用了 golang template 的语法,含义为:

  • 如果使用此 MLServiceRuntime 的 MLService 指定了 MODEL_PATH,这一行会被设置为 --model <用户指定的 MODEL_PATH>
  • 如果没有指定 MODEL_PATH,这一行会被设置为 --model all

如下所示,在 MLService 中设置 MODEL_PATH

apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
  name: demo
spec:
  default: version1
  releases:
  - name: version1
    predictor:
      model:
        parameters:
          "MODEL_PATH": "mnist=model.mar"
        runtime: torchserve
      storage:
        pvc:
          name: <pvc-name>
          subPath: <model-path>

由上述 MLService 最终产生的副本(Pod)的 args 中会包含 --model mnist=model.mar,指定了使用模型的名称和文件。

StrategicMergePatch

MLServiceRuntime 定义了 Pod 模板,但不一定能适用于所有场景。MLService 支持用户在 MLServiceRuntime 的基础上,进行进一步的叠加修改,例如:

apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
  name: demo
spec:
  default: version1
  releases:
  - name: version1
    predictor:
      model:
        parameters:
          "MODEL_PATH": "mnist=model.mar"
        runtime: torchserve
      storage:
        pvc:
          name: <pvc-name>
          subPath: <model-path>
      template:
        spec:
          containers:
            - name: user-container
              image: self-torchserve:latest

将上面 MLService 中 predictor version1template.spec 和之前的 Runtime 定义示例 相比, 可以发现他们都定义了一个名为 user-container 的 container,但是 image 不同。 于是最终生成的 Pod 中,MLService 中定义的 image 会覆盖 MLServiceRuntime 中的 image,但是 MLServiceRuntime 中 args 等其余设置都会被保留。

计算资源

MLServiceRuntime 定义了 Pod 模板,但对于容器的资源要求,不同场景之间存在差异。因此, MLServiceRuntime 中定义的容器资源要求只是一个缺省时的默认值。

用户可以直接在 MLService predictor 中的 containersResources 定义容器的资源要求,例如:

apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
  name: demo
spec:
  default: version1
  releases:
  - name: version1
    predictor:
      model:
        modelFormat:
          name: pytorch
      storage:
        pvc:
          name: <pvc-name>
          subPath: <model-path>
      containersResources:
      - name: user-container
        resources:
          limits:
            cpu: "500m"
            memory: 1Gi

模型存储

你可以为 Release 或 Transformer 定义模型存储:

  1. 通过 spec.releases[*].predictor.storage 可以设置当前 Release 的模型存储信息。
  2. 通过 spec.transformer.storage 可以设置 Transformer 的模型存储信息。

详情请见 模型存储

更多配置

发布策略

多版本支持

一个 MLService 可以同时部署多个版本(release)的推理服务,以使用不同的模型文件,或者其他配置等。

在下面的示例中,MLService 同时部署了 nov-02(设置为默认)、nov-05nov-11 三个版本的服务,这三个版本都使用同一个 MLServiceRuntime,但是使用了不同的模型:

apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
  name: multi-releases
spec:
  default: nov-02
  releases:
  - name: nov-02
    predictor:
      model:
        runtime: torchserve
      storage:
        pvc:
          name: tutorial
          subPath: model-11-02
  - name: nov-05
    predictor:
      model:
        runtime: torchserve
      storage:
        pvc:
          name: tutorial
          subPath: model-11-05
  - name: nov-11
    predictor:
      model:
        runtime: torchserve
      storage:
        pvc:
          name: tutorial
          subPath: model-11-11

金丝雀发布

MLService 支持金丝雀(canary release)发布策略。用户可以通过 spec.canary 字段设置金丝雀发布对应的模型版本(release),spec.canaryTrafficPercent 字段设置金丝雀发布的路由权重。spec.default 是必需字段,用于设置默认发布。

例如上一节中我们部署了 3 个版本的模型,我们想主要(80% 流量)使用 nov-02 这个版本,并且将刚刚训练好的 nov-11 作为金丝雀版本:

  • 默认发布:nov-02,路由权重为 80%。
  • 金丝雀发布:nov-11,路由权重为 20%。
...
spec:
  default: nov-02
  canary: nov-11
  canaryTrafficPercent: 20
...

日志收集

MLService 支持对预测请求进行日志收集,详情见2.2.2.1日志收集

前处理及后处理

MLService 支持部署含有 transformer 模块的前处理(pre-processing)及后处理(post-processing)的推理服务:

  • 预处理:用户发向推理服务的原始数据,先经过 transformer 预处理,然后再被发送到推理服务。
  • 后处理:推理服务返回的预测结果,先经过 transformer 后处理,然后再返回给用户。

用户可以使用 Tensorstack SDK 编写 transformer 代码,制作镜像,并基于该镜像创建含有 transformer 的推理服务。详细示例请参阅制作并部署含有 Transformer 的模型推理服务

下文展示了一个使用 transformer 的推理服务:

apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
  name: pic-mnist
spec:
  default: origin
  transformer:
    minReplicas: 1
    minReplicas: 5
    template:
      spec:
        containers:
        - name: user-container
          image: t9kpublic/transformer-example:0.1.0
          resources:
            limits:
              cpu: "500m"
              memory: 500Mi

容量伸缩

MLService 支持自动伸缩服务容量:即根据服务负载的变化,自动调节推理服务的部署规模(副本数量)。具体原理可以查看 Knative Autoscaling

用户可以通过设置 spec.releases[*].predictor.minReplicas 字段和 spec.releases[*].predictor.maxReplicas 字段来指定 Predictor 工作负载数量的下限和上限。

同样的,如果用户启用了 Transformer,可以通过 spec.transformer.minReplicas 字段和 spec.transformer.maxReplicas 字段来指定 Transformer 工作负载数量的下限和上限。

以下是一些特殊情况:

  • minReplicas 不填时,工作负载数量的默认最小值为 1。
  • minReplicas 等于 0 时,当没有流量请求时,MLService 会缩容到 0,不再占用系统资源。
  • maxReplicas 不填或设为 0 时,工作负载数量没有上限。

除了负载数量的限制,用户还可以在具体的 Runtime 或者组件(Predictor 或者 Transformer)的 Pod 定义中设置 Knative Autoscaling 相关的 Annotation,例如:

...
spec:
  releases:
    - name: version1
      minReplicas: 1
      maxReplicas: 3
      predictor:
        template:
          metadata:
            annotations: 
              autoscaling.knative.dev/metric: "rps"
              autoscaling.knative.dev/target: "100"
...

在上面的示例中,我们设置了工作负载数量的范围为 [1,3],自动伸缩指标(metric)为 rps,自动伸缩目标(target)为 100。这意味着当每个工作负载每秒处理的请求数量(requests-per-second)达到 100 时,负载会开始扩容,且扩容最大数量为 3,最小数量为 1。

调度器

MLService 支持使用两种调度器:Kubernetes 默认调度器(默认)和 T9k Scheduler。MLService 通过 spec.scheduler 字段设置调度器:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,使用了 T9k Scheduler 调度器,且工作负载处于队列 default 中。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
...

服务状态

通过 MLService 的状态字段可以获取如下信息:

  • 推理服务的全局状态及服务地址:status.ready 表明推理服务是否准备就绪,status.address.url 表明全局推理服务地址。
  • 每个部署的模型的状态及服务地址:status.releases[*].ready 表明该版本推理服务是否准备就绪,status.releases[*].url 表明该版本的推理服务地址。
  • Transformer 的状态及服务地址:status.ready 表明 Transformer 服务是否准备就绪,status.transformer.url 表明 Transformer 服务地址。
  • 推理服务没有就绪的原因:status.conditions 以及 status.releases[*].message 等字段中会记录相关报错信息。

多版本支持的示例的状态为例,其 MLService 状态字段如下。从状态字段可以看出,该推理服务处于就绪状态,外部访问地址为 http://multi-releases.<project>.<domain>,某个 release 的访问地址为 http://multi-releases-predict-<release>.<project>.<domain>

status:
  address:
    url: http://multi-releases.<project>.<domain>
  canaryRelease: nov-02
  conditions:
  - lastTransitionTime: "2023-11-27T10:44:27Z"
    status: "False"
    type: Paused
  - lastTransitionTime: "2023-11-27T10:50:04Z"
    status: "True"
    type: Ready
  defaultRelease: nov-05
  releases:
  - name: nov-02
    ready: true
    readyReplicas: 1
    totalReplicas: 1
    trafficPercent: 80
    url: http://multi-releases-predict-nov-02.<project>.<domain>
  - name: nov-05
    ready: true
    readyReplicas: 1
    totalReplicas: 1
    trafficPercent: 20
    url: http://multi-releases-predict-nov-05.<project>.<domain>
  - name: nov-11
    ready: true
    readyReplicas: 1
    totalReplicas: 1
    trafficPercent: 0
    url: http://multi-releases-predict-nov-11.<project>.<domain>

如果推理服务没有就绪,你可以通过查看 status.conditions 中 type 为 Ready 的 reason 以及 message 来查看具体信息,同时 Event 中也会有相关的错误信息。

访问推理服务

MLService 部署成功后,通过状态字段 status.address.url 可以查询到全局推理服务的 Base URL,再加上部署模型对应的路径即可得到访问推理服务的地址。

示例中的服务为例,推理服务地址的状态字段如下:

...
status:
  address:
    url: http://torch-mnist.<project>.<domain>
...

由于服务使用的是 TorchServe 框架,按照其 API 规范,用户可以通过下述命令查看服务状态:

$ curl http://torch-mnist.<project-name>.<domain-name>/v1/models/mnist
{
    "model_version_status": <model-status>
}

并调用推理服务:

# 数据在 https://github.com/t9k/tutorial-examples/blob/master/deployment/pvc/mlservice-torch/test_data/0.png
$ curl -T test_data/0.png http://torch-mnist.<project-name>.<domain-name>/v1/models/mnist:predict
{
    "predictions": <predict-result>
}

下一步

参考

日志收集

MLService 支持对 predictor 和 transformer 服务进行日志收集,包括接收到的 request 和返回的 response 消息。开启日志收集后,系统会为 MLService 添加日志发送能力,其根据配置的接收 URL,将日志发送到 URL 指定的服务。

设置 MLService

用户可以为每个 predictor 和 transformer 设置日志收集功能:

  1. predictor: MLService 的 spec.releases[*].predictor.logger 字段来启用 predictor 的日志收集功能。
  2. transformer:通过设置 MLService 的 spec.transformer.logger 字段启用 transformer 的日志收集功能。

用户可以通过日志收集的下列字段,来设置日志收集配置:

  • urls:url 数组,系统会将收集到的日志发送到 url 对应的服务。
  • mode:表示对哪些内容进行收集记录。可选值是 all, response, request,默认值是 all。
    • all:requests 和 response 都会被收集记录。
    • response:只记录收集 response。
    • request:只记录收集 requests。

接收日志

日志数据通过 HTTP 协议被发送(HTTP POST)到用户提供的 URL。

日志数据格式是 CloudEvent,如下例所示:

Context Attributes,
  specversion: 1.0
  type: tensorstack.dev.mlservice.response
  source: torch-mnist-logger-predict-origin
  id: 0009174a-24a8-4603-b098-09c8799950e9
  time: 2021-04-10T00:23:26.080736102Z
  datacontenttype: application/json
Extensions,
  component: predict
  inferenceurl: /v1/models/mnist
  mlservicename: torch-mnist-logger
  namespace: example
  traceparent: 00-6d69e2d3917689ee301610780af06de8-be01c3cfdf8e446e-00
Data,
{
  "0": 1.0,
  "2": 1.3369853835154544e-10,
  "6": 7.10219507987428e-14,
  "5": 5.859705488843112e-14,
  "9": 3.2580891499658536e-15
}

在上述示例中:

  • type:表明当前 CloudEvent 数据记录 response 内容。
  • source:release 名称是 origin(source 命名规则是 <mlservice-name>-<component>-<release-name>
  • component:组件是 predict
  • inferenceurl:URL path 是 /v1/models/mnist
  • mlservicename:MLService 的名称是 torch-mnist-logger
  • namespace:MLService 所在的 namespace 是 example
  • Data:MLService 向用户返回的 response 内容是 {"0": 1.0,"2": 1.3369...}

在 HTTP Request 中:

  1. CloudEvent 的 Data 内容存在 Request Body 中
  2. CloudEvent 的其他内容存在 Request Header 中

可使用 CloudEvent 库来实现接收日志数据的 HTTP Server,具体实现可参考 CloudEvent Sample

示例

部署日志接收服务

我们在集群内部署 event-display 服务来接受日志,注意:

  1. event-display 仅简单地将接收到的 CloudEvents 打印出来;
  2. event-display 作为演示的目的。
event-display.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 name: event-display
spec:
 replicas: 1
 selector:
   matchLabels:
     app: event-display
 template:
   metadata:
     labels:
       app: event-display
   spec:
     containers:
       - name: event-display
         image: t9kpublic/knative_event_display:1.0.0
         resources:
           limits:
             cpu: 100m
             memory: 100Mi
---
kind: Service
apiVersion: v1
metadata:
 name: event-display
spec:
 selector:
   app: event-display
 ports:
 - protocol: TCP
   port: 80
   targetPort: 8080

部署命令

kubectl create -f event-display.yaml

部署 MLService

请按照使用方法准备环境,基于部署用于生产环境的模型推理服务示例来部署 MLService logger-example。

首先将 mlservice.yaml 修改为下列内容,注意:

  1. event-display 和 MLService 需要部署在同一个 namespace/project 中。
  2. 这个 MLService 仅对 predictor 设置了 logger 服务。
mlservice.yaml
apiVersion: tensorstack.dev/v1beta1
kind: MLService
metadata:
 name: logger-example
spec:
 default: origin
 releases:
   - name: origin
     predictor:
       logger:
         mode: all
         resources:
           limits:
             cpu: "1"
             memory: 2Gi
           requests:
             cpu: "0.5"
             memory: 1Gi
         urls:
         - http://event-display
       minReplicas: 1
       model:
         parameters:
           "MODEL_PATH": "mnist=model.mar"
         runtime: t9k-torchserve
       containersResources:
       - name: user-container
         resources:
           limits:
             cpu: "500m"
             memory: 1Gi
        storage:
          pvc:
            name: tutorial
            subPath: tutorial-examples/deployment/mlservice/torch-pvc

然后按照 README 文档的操作步骤进行操作。

查看日志

查看 event-display 容器的日志,可看到日志中打印的 CloudEvent 记录了预测请求的详细信息:

terminal.log
$ k get pod -l app=event-display
NAME                             READY   STATUS    RESTARTS   AGE
event-display-7d8d9f97db-lpgg2   1/1     Running   0          14m


$ k logs event-display-7d8d9f97db-lpgg2 
Context Attributes,
  specversion: 1.0
  type: tensorstack.dev.mlservice.request
  source: logger-example-predict-origin
  id: ff726d6b-7fd8-471e-9ddc-de03b201d882
  time: 2024-02-29T08:07:00.849119273Z
Extensions,
  component: predict
  inferenceurl: /v1/models/mnist:predict
  mlservicename: logger-example
  namespace: demo
Data,
  PNG
IHDWfHIDATxc`X`ˬUvo>C0$ůشi˿_{ ZATI̶_Q%̓*y_:=U9;4ɺpJ^{oG8NIx$!K.w;@@4^0
                                                                                                                                     G$Qp֛q?{4g^B
                                                                                                                                                                      <`Rr330
ztB?IENDB`
☁️  cloudevents.Event
Context Attributes,
  specversion: 1.0
  type: tensorstack.dev.mlservice.response
  source: logger-example-predict-origin
  id: ff726d6b-7fd8-471e-9ddc-de03b201d882
  time: 2024-02-29T08:07:01.468872477Z
Extensions,
  component: predict
  inferenceurl: /v1/models/mnist:predict
  mlservicename: logger-example
  namespace: demo
Data,
  {
  "0": 1.0,
  "2": 1.3369905182969433e-10,
  "6": 7.102208632401436e-14,
  "5": 5.859716330864836e-14,
  "9": 3.2580891499658536e-15
}

参考

模型存储

AI 模型可以存储在集群的文件系统里,或者 S3 对象存储服务中。

SimpleMLService 和 MLService 采用相同的方式指定模型的存储细节,用户可以明确、方便地指定模型在集群文件系统或者 S3 对象存储服务中的位置,并设置模型在容器中的挂载路径。

文件系统

通过配置 storage.pvc 字段可以通过 PVC 使用集群文件系统中的模型。storage.pvc 字段包含下列子字段:

  • name: 存储模型数据的 PVC 的名称。
  • subPath: 模型在 PVC 中的路径,不可以是绝对路径(即开头不能是 /)。
  • mountPath: 模型在容器中的挂载路径,必须是绝对路径。未设置时,默认值是 /var/lib/t9k/model

示例如下:

storage:
  pvc:
    name: demo
    subPath: path/mnist
    mountPath: /var/lib/custom

在上述示例中:

  • PVC 名称是 demo
  • 模型在 PVC 中的路径是 path/mnist
  • 模型会被挂载到容器的路径 /var/lib/custom 下。

S3

当使用 S3 服务存储的模型数据时:

  • SimpleMLService/MLService 需要先通过 initContainer 下载模型数据到容器本地,然后才能供给推理服务使用。如果下载失败,则推理服务无法启动。
  • 当 SimpleMLService/MLService 设置了多个副本时,每个副本都需要单独下载模型数据,副本间无法共享模型数据。

如果用户想使用存储在 S3 服务中的模型数据,需要:

  1. 创建存储 S3 服务信息的 Secret
  2. 设置 storage.s3 字段

创建 S3 Secret

存储 S3 信息的 Secret 需要满足下列条件:

  1. 设置 label tensorstack.dev/resource: s3
  2. 设置 data[.s3cfg] 字段,内容是 Base64 编码的 s3cmd config。

YAML 示例如下:

apiVersion: v1
kind: Secret
metadata:
  name: s3-sample
  labels:
    tensorstack.dev/resource: s3
type: Opaque
data:
  .s3cfg: aG9zdF9iYXNlID0gczMuYXAtZWFzdC0xLmFtYXpvbmF3cy5jb20KaG9zdF9idWNrZXQgPSBleGFtcGxlLnMzLmFwLWVhc3QtMS5hbWF6b25hd3MuY29tCmJ1Y2tldF9sb2NhdGlvbiA9IGFwLWVhc3QtMQp1c2VfaHR0cHMgPSBGYWxzZQphY2Nlc3Nfa2V5ID0gdXNlcgpzZWNyZXRfa2V5ID0gcGFzc3dvcmQKc2lnbmF0dXJlX3YyID0gRmFsc2U=

其中 data[.s3cfg] 字段 Base64 解码后如下:

host_base = s3.ap-east-1.amazonaws.com
host_bucket = example.s3.ap-east-1.amazonaws.com
bucket_location = ap-east-1
use_https = False
access_key = user
secret_key = password
signature_v2 = False

设置 storage.s3

设置 storage.s3 字段来使用存储在 S3 中的模型数据。storage.s3 字段包含下列子字段:

  • secretRef: 记录存储 S3 配置信息的 Secret。该字段有下列子字段:
    • name:Secret 名称。
  • uri: 模型在 S3 中的存储标识。
  • mountPath: 模型在容器中的挂载路径,必须是绝对路径。未设置时,默认值是 /var/lib/t9k/model

示例如下:

storage:
  s3:
    secretRef:
      name: s3-secret
    uri: s3://models/mnist/
    mountPath: /var/lib/custom

在上述示例中:

  • Secret s3-secret 存储着 S3 配置信息。
  • 模型在 S3 中的存储标识是 s3://models/mnist/
  • 模型会被挂载到容器的路径 /var/lib/custom 下。

存储类型比较

使用 PVC 存储模型数据:

  • 优点:
    • 挂载速度快
    • 多副本可以共享 PVC 数据
  • 缺点:
    • 需要提前创建 PVC,并在 PVC 中准备好模型数据

使用 S3 存储模型数据:

  • 优点:
    • 只需简单设置,就能 S3 服务存储的模型数据
    • 跨项目共享使用模型很方便
  • 缺点:
    • S3 中的模型需要先被下载才能使用,启动时间一般较长
    • 多副本间无法共享模型数据,每个副本都需要从 S3 下载模型数据

下一步

参考

Job

TensorStack AI 平台定义了一系列 CRD(称为 Job)以支持批处理(Batch Processing)计算任务,特别是 AI 领域的大规模分布式并行训练类型性质的计算。

t9k-job
图 1:Job 系统的基本原理。用户提交 Job 的定义;Job Controller 1)分析 Job 定义;2)请求计算资源(CPU、RAM、GPU、高速网络、存储...);3)启动、监控、暂停、继续 、终止、调试 Job。

Job 类型

为了支持不同框架的计算任务,TensorStack 提供了一系列 Job:

  • TrainingJob:一类使用分布式计算框架进行机器学习的 T9k Job。
  • MPIJob:MPIJob 使用户能够方便地在集群环境中使用 OpenMPI 进行并行计算。
  • BeamJob:用于在集群中通过 Apache Beam Python SDK 运行分布式计算任务,并支持多种底层计算引擎(例如 Apache Spark, Apache Flink)。
  • GenericJob:一个通用的 T9k Job 资源,支持各种并行计算场景及 T9k 高级调度策略。
    • GenericJob 十分灵活,用户可以使用 GenericJob 实现 MPIJob、PyTorchTrainingJob 等特定功能的 T9k Job;但其自动化程度低,需要手工设置很多参数。
    • GenericJob 的目的是提供一个总是可行的 “通用” 机制,以支持一些其他特定功能 T9k Job 还未支持的新的计算场景。

运行模式

T9k Job 支持多种运行模式(spec.runMode):

  • 立即(Immediate)模式:默认、基本模式。Job 被分配资源后,将会立即开始运行。
  • 调试(Debug)模式:帮助用户创建 Job 环境,但不立即执行,用户可以在训练环境中手动启动 Job 或者运行调试代码。
  • 暂停(Pause)模式:暂停执行 Job;在一些场合下(如集群资源不足),用户可随时暂停 Job,待条件允许再继续执行 Job。
  • 弹性(Elastic)伸缩模式:可以动态调整 Job 规模。

以下是各类型 Job 支持的模式列表:

Job 类型立即模式调试模式暂停模式弹性伸缩模式
GenricJob***
PyTorchTrainingJob****
TensorFlowTrainingJob***
XGBoostTrainingJob***
MPIJob***
ColossalAIJob***
DeepSpeedJob****
BeamJob*

各种模式的具体使用方式,请参考对应 Job 类型的文档。

GenericJob

GenericJob 是最基本的 T9k Job 资源,支持使用 T9k 高级调度策略。GenericJob 的使用十分灵活,一个熟练的使用者可以通过 GenericJob 实现 MPIJob、PyTorchTrainingJob 等特定功能的 T9k Job。

创建 GenericJob

下面是一个基本的 GenericJob 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
  name: generic-example
spec:
  successRules:
    - { "worker": [0] }
  failureRules:
    - { "worker": [0] }
    - { "worker": [1] }
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
            - command:
                - sleep
                - '365'
              image: nginx:latest
              name: sleep

在该例中:

  • 创建 4 个副本(由 spec.replicaSpecs[0].replicas 字段指定),这些副本的类型为 worker(由 spec.replicaSpecs[0].type 字段指定)。每个副本执行命令 sleep 365(由 spec.replicaSpecs[0].template 字段指定)。
  • GenericJob 的成功条件为序号为 0 且类型为 worker 的副本执行完成(由 spec.successRules 字段指定)。
  • GenericJob 的失败条件有两个,任意一个条件达成都会导致 GenericJob 失败(由 spec.failureRules 字段指定):
    • 序号为 0 且类型为 worker 的副本执行失败。
    • 序号为 1 且类型为 worker 的副本执行失败。

副本设置

GenericJob 副本运行环境和命令可以通过 spec.replicaSpecs[*].template 进行配置,可配置内容包括镜像、运行命令、资源配置、环境变量等。

资源配置

副本资源配置通过 spec.replicaSpecs[*].template.spec.containers[*].resources 字段指定。

GenericJob 的资源配置包括两部分:

  • 资源请求量(requests):创建该副本时,节点上至少应具有这些数量的资源。如果集群中所有节点都不满足副本的资源请求量,则副本的创建可能会被阻塞;或者如果副本的优先级较高,则有可能驱逐节点上其他工作负载来为副本空出可用的资源。
  • 资源上限(limits):该副本在运行期间,最多可以使用的资源数量。比如:如果副本在运行时申请分配超过上限的内存,则有可能出现 OOMKILLED 错误。(注:资源上限不能小于资源请求量)

在下面的示例中,GenericJob 中每个 worker 副本设置了以下资源配置:

  • 资源请求量:2 个 cpu 核心、2Gi 内存;
  • 资源上限:4 个 cpu 核心、4Gi 内存。
apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
  name: generic-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - resources:
              limits:
                cpu: 4
                memory: 4Gi
              requests:
                cpu: 2
                memory: 2Gi

共享内存

在进行多节点任务时,可以按照如下方式修改 GenericJob 来使用共享内存:

apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
  name: generic-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - ...
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
              sizeLimit: "1Gi"

在该例中:

  • spec.replicaSpecs[*].template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.replicaSpecs[*].template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

环境变量

副本环境变量通过 spec.replicaSpecs[*].template.spec.containers[*].env 字段指定。GenericJob 支持直接设置环境变量内容和引用其他资源字段作为环境变量两种方式。

在下面的示例中,GenericJob 给 worker 副本设置了两个环境变量:ENV_DIRECTENV_REFERENCED。其中 ENV_DIRECT 环境变量被直接设置为 env-valueENV_REFERENCED 环境变量引用了 secret-name Secret 的 key-in-secret 字段的内容。

apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
  name: generic-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
            - env:
              - name: ENV_DIRECT
                value: env-value
              - name: ENV_REFERENCED
                valueFrom:
                  secretKeyRef:
                    name: secret-name
                    key: key-in-secret

变量替换

在副本的配置信息中有时需要传入副本自身或其他副本的信息,包括序号、类型和副本的服务地址等。GenericJob 通过变量替换的方式提供这些信息,主要有以下 5 种变量:

  • $(type):当前副本的类型。
  • $(rank):当前副本在同类副本中的序号。
  • $(replicas[_type_]):扮演此类型的副本的数量。
  • $(service._type_[_rank_].host):各个副本的域名(当且仅当副本的服务被暴露出来,此变量可用)。
  • $(service.port[_port-name_])spec.service.ports 字段中定义的服务端口号(当且仅当副本的服务被暴露出来,此变量可用)。

上述变量中 _type__rank__port-name_ 需填入具体的类型序号端口名称(由 spec.service.ports[*].name 字段指定)。

变量替换可以被使用在下列字段中:

  • spec.replicaSpecs[*].template.command
  • spec.replicaSpecs[*].template.args
  • spec.replicaSpecs[*].template.env

以下是用 GenericJob 实现的 TensorFlow 分布式框架使用示例,其中 TF_CONFIG 环境变量需要填写所有副本的地址和当前副本的序号等信息,我们使用变量替换的方式添加:

apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
  name: generic-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
            - command:
                - python
                - /mnt/training.py
              image: tensorflow/tensorflow:2.11.0
              name: tensorflow
              env:
                - name: TF_CONFIG
                  value: '{"task":{"type":"$(type)","index":$(rank)},"cluster":{"worker":["$(service.worker[0].host):$(service.port[http])","$(service.worker[1].host):$(service.port[http])","$(service.worker[2].host):$(service.port[http])","$(service.worker[3].host):$(service.port[http])"]}}'

重启机制

GenericJob 为副本提供以下重启机制:

  1. Never:不重启
  2. OnFailure:错误即重启
  3. Always:总是重启(谨慎使用此策略,此策略可能导致 GenericJob 无法停止)

GenericJob 重启机制通过 spec.replicaSpecs[*].restartPolicy 字段指定:

  • spec.replicaSpecs[*].restartPolicy.policy 表示当前副本所使用的重启策略,可以设置为 NeverOnFailureAlways
  • spec.replicaSpecs[*].restartPolicy.limit 表示当前副本的最大重启次数。

不同的类型可以使用不同的重启策略,比如 master 使用 Alwaysworker 使用 OnFailure

成功和失败

GenericJob 的成功和失败条件是通过 spec.successRulesspec.failureRules 字段指定的,其规则如下:

  • spec.successRules 数组包含 GenericJob 的所有成功条件,其中:
    • 任意一个条件达成则 GenericJob 成功。
    • 每个条件是一个由若干副本组成的集合,如果这些副本都执行完成,则该条件达成。
  • spec.failureRules 数组包含 GenericJob 的所有失败条件,其中
    • 任意一个条件达成则 GenericJob 失败。
    • 每个条件是一个由若干副本组成的集合,如果这些副本都失败或者重启次数耗尽,则该条件达成。

在下面的示例中,记录了 3 种 GenericJob 成功的判定条件:

  • 类型为 master 且序号为 0 的副本执行完成。
  • 类型为 worker 且序号为 0、1、2 的三个副本全部执行完成。
  • 类型为 master 且序号为 2 和类型为 worker 且序号为 0、1 的三个副本全部执行完成。

和 1 种 GenericJob 失败的判定:

  • 类型为 master 且序号为 0 的副本执行失败。
...
spec:
  successRules:
  - {"master": [0]}
  - {"worker": [0, 1, 2]}
  - {"master": [2], "worker": [0, 1]}
  failureRules:
  - {"master": [0]}

暴露副本的服务

在分布式计算中,有时需要不同的副本之间进行通信和数据交换。使用者可以通过设置 spec.service 字段来暴露副本的端口。

在下面的示例中,GenericJob 暴露出每一个副本的服务:端口为 2222,域名的格式为 [job-name]-[type]-[rank],例如下例中类型为 worker 且序号为 0 的副本的域名为 generic-example-worker-0

apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
  name: generic-example
spec:
  service:
    ports:
      - name: http
        port: 2222
  replicaSpecs:
    - type: worker
      replicas: 1
...

清除策略

在 GenericJob 成功或失败后,控制器清理所创建的 Kubernetes 资源,使 GenericJob 不再浪费集群资源(内存、CPU 等)。GenericJob 提供三种策略,通过 spec.cleanUpPolicy 字段指定:

  • All:清除全部副本
  • None:不清除副本
  • Unfinished:清除未结束(处于 PendingRunningUnknown 阶段)的副本

调度器

目前 GenericJob 支持两种调度器:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler 调度器

调度器通过 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 的默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,GenericJob 启用 T9k Scheduler 调度器,将副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50

调试模式

GenericJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。

该模式可以通过 spec.runMode.debug 字段来设置:

  • spec.runMode.debug.enabled 表示是否启用调试模式。
  • spec.runMode.debug.replicaSpecs 表示如何配置各个副本的调试模式:
    • spec.runMode.debug.replicaSpecs.type 表示作用于的副本类型。
    • spec.runMode.debug.replicaSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.debug.replicaSpecs.command 表示副本在等待调试的时候执行的命令,默认为 sleep inf
    • 如果不填写 spec.runMode.debug.replicaSpecs 字段,则表示所有副本都使用默认设置。

在下面的示例中:

  • 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行 sleep inf
# 示例一
...
spec:
  runMode:
    debug:
      enabled: true
      replicaSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    debug:
      enabled: true

暂停模式

GenericJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。

该模式可以通过 spec.runMode.pause 字段来设置:

  • spec.runMode.pause.enabled 表示是否启用暂停模式。
  • spec.runMode.pause.resumeSpecs 表示结束暂停后,如何恢复各个副本:
    • spec.runMode.pause.resumeSpecs.type 表示作用于的副本类型。
    • spec.runMode.pause.resumeSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.pause.resumeSpecs.commandspec.runMode.pause.resumeSpecs.args 表示副本在恢复运行时候执行的命令,默认使用 spec.replicaSpecs[0].template 中的命令。
    • 如果不填写 spec.runMode.pause.resumeSpecs 字段,则表示所有副本都使用默认设置。

用户可以随时修改 spec.runMode.pause.enabled 来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs,所以如果有暂停 GenericJob 的需求,请提前设置好恢复设置。

在下面的示例中:

  • 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行 spec.replicaSpecs[0].template 中设置的命令。
# 示例一
...
spec:
  runMode:
    pause:
      enabled: true
      resumeSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    pause:
      enabled: true

GenericJob 状态

GenericJob 的状态和阶段

status.conditions 字段用于描述当前 GenericJob 的状态,包括以下 6 种类型:

  1. Initialized:GenericJob 已经成功创建各子资源,完成初始化。
  2. Running:开始执行任务。
  3. ReplicaFailure:有一个或多个副本出现错误。
  4. Completed:GenericJob 成功。
  5. Failed:GenericJob 失败。
  6. Paused:GenericJob 进入暂停模式,所有副本都已删除或正在删除。

status.phase 字段用于描述当前 GenericJob 所处的阶段,GenericJob 的整个生命周期主要有以下7个阶段:

  1. Pending:GenericJob 刚刚创建,等待副本启动。
  2. Running:副本创建成功,开始执行任务。
  3. Paused:GenericJob 进入暂停模式。
  4. Resuming:GenericJob 正从暂停模式中恢复运行。恢复运行后,切换为 Running 阶段。
  5. Succeeded:GenericJob 成功。
  6. Failed:GenericJob 失败。
  7. Unknown:控制器无法获得 GenericJob 的阶段。

在下面的示例中,GenericJob 所有子资源创建成功,所以类型为 Initalizedcondition 被设为 True;GenericJob 运行结束,所以类型为 Completedcondition 被设置为 True;但是 GenericJob 的训练结果是失败的,所以类型为 Failedcondition 被设置为 True(原因是 The job is failed with rule: { "worker": [0] })。当前 GenericJob 运行阶段为 Failed

...
status:
  conditions:
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "The job has been initialized successfully."
      reason: "-"
      type: Initializing
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "All pods are running normally."
      reason: "-"
      type: Running
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "False"
      message: "All pods are running normally."
      reason: "-"
      type: ReplicaFailure
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "False"
      message: 'The job is failed with rule: { "worker": [0] }'
      reason: "Failed"
      type: Completed
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "True"
      message: 'The job is failed with rule: { "worker": [0] }'
      reason: "Failed"
      type: Failed
  phase: Failed

副本的状态

status.tasks 字段用来记录副本的状态,记录的内容主要包括:

  • 副本的重启次数(同一种类型的副本的重启次数之和);
  • 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了 CreatingDeleted 分别表示正在创建和已删除;
  • 副本在集群中对应的 Pod 的索引信息。

在下面的示例中,GenericJob 创建了 2 个类型为 worker 的副本,这 2 个副本的重启次数之和为 3,当前均处于 Running 阶段,分别运行在 generic-example-worker-0generic-example-worker-1 这 2 个 Pod 上。

...
status:
  tasks:
  - type: worker
    restartCount: 3
    status:
    - phase: Running
      name: generic-example-worker-0
      uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
      containers: []
    - phase: Running
      name: generic-example-worker-1
      uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
      containers: []

副本状态统计

status.aggregate 字段统计了各个阶段的副本数量。

在下面示例中,GenericJob 创建了 3 个副本,其中 1 个处于 Pending 阶段,另外两个处于 Running 阶段。

...
status:
  aggregate:
    creating: 0
    deleted: 0
    failed: 0
    pending: 1
    running: 2
    succeeded: 0
    unknown: 0
...

PyTorchTrainingJob

PyTorchTrainingJob 是服务于 PyTorch 分布式训练框架的 T9k Job。

你可以较为方便地使用 PyTorchTrainingJob 为 PyTorch 训练脚本提供训练环境,并监控训练进程。

创建 PyTorchTrainingJob

下面是一个基本的 PyTorchTrainingJob 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: pytorch-example
spec:
  replicaSpecs:
  - replicas: 4
    restartPolicy: OnFailure
    template:
      spec:
        containers:
        - command:
          - python
          - dist_mnist.py
          image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
          name: pytorch
    type: worker

在该例中:

  • 创建 4 个副本(由 spec.replicaSpecs[*].replicas 字段指定),副本的角色为 worker(由 spec.replicaSpecs[*].type 字段指定)。
  • 每个副本使用 pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel 镜像,执行命令 python dist_mnist.py(由 template 字段指定,此处的填写方式参考 PodTemplate)。
  • 当副本失败后,会自动重启(由 spec.replicaSpecs[*].restartPolicy 字段指定)。

副本设置

PyTorchTrainingJob 副本运行环境和命令可以通过 spec.replicaSpecs[*].template 进行配置,可配置内容包括镜像、运行命令、资源配置、环境变量等。

资源配置

副本资源配置通过 spec.replicaSpecs[*].template.spec.containers[*].resources 字段指定。

PyTorchTrainingJob 的资源配置包括两部分:

  • 资源请求量(requests):创建该副本时,节点上至少应具有这些数量的资源。如果集群中所有节点都不满足副本的资源请求量,则副本的创建可能会被阻塞;或者如果副本的优先级较高,则有可能驱逐节点上其他工作负载来为副本空出可用的资源。
  • 资源上限(limits):该副本在运行期间,最多可以使用的资源数量。比如:如果副本在运行时申请分配超过上限的内存,则有可能出现 OOMKILLED 错误。(注:资源上限不能小于资源请求量)

在下面的示例中,PyTorchTrainingJob 中每个 worker 副本设置了以下资源配置:

  • 资源请求量:2 个 cpu 核心、2Gi 内存;
  • 资源上限:4 个 cpu 核心、4Gi 内存。
apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: pytorch-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - resources:
              limits:
                cpu: 4
                memory: 4Gi
              requests:
                cpu: 2
                memory: 2Gi

共享内存

在进行多节点任务时,可以按照如下方式修改 PyTorchTrainingJob 来使用共享内存:

apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: pytorch-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - ...
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
              sizeLimit: "1Gi"

在该例中:

  • spec.replicaSpecs[*].template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.replicaSpecs[*].template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

环境变量

副本环境变量通过 spec.replicaSpecs[*].template.spec.containers[*].env 字段指定。PyTorchTrainingJob 支持直接设置环境变量内容和引用其他资源字段作为环境变量两种方式。

在下面的示例中,PyTorchTrainingJob 给 worker 副本设置了两个环境变量:ENV_DIRECTENV_REFERENCED。其中 ENV_DIRECT 环境变量被直接设置为 env-valueENV_REFERENCED 环境变量引用了 secret-name Secret 的 key-in-secret 字段的内容。

apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: pytorch-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
            - env:
              - name: ENV_DIRECT
                value: env-value
              - name: ENV_REFERENCED
                valueFrom:
                  secretKeyRef:
                    name: secret-name
                    key: key-in-secret

重启机制

PyTorchTrainingJob 的 spec.replicaSpec[*].template 字段使用 PodTemplate 的规范填写,但是 Pod 的重启策略并不能满足 PyTorchTrainingJob 的需求,所以 PyTorchTrainingJob 会给副本的重启策略都设置为 Never,并由控制器根据 spec.replicaSpec[*].restartPolicy 字段处理副本的重启。

可选的重启策略有以下四种:

  • Never:不重启
  • OnFailure:失败后重启
  • Always:总是重启
  • ExitCode:特殊退出码重启

使用 Never 重启策略时,Job 的副本失败后不会重启。如果需要调试代码错误,可以选择此策略,便于从副本中读取训练日志。

ExitCode 是一种比较特殊的重启策略,它将失败进程的返回值分为两类:一类是由于系统环境原因或用户操作导致的错误,此类错误可以通过重启解决;另一类是代码错误或者其他不可自动恢复的错误。可重启的退出码包括:

  • 130(128+2):使用 Control+C 终止容器运行。
  • 137(128+9):容器接收到 SIGKILL 信号。
  • 143(128+15):容器接收到 SIGTERM 信号。
  • 138:用户可以自定义这个返回值的含义。如果用户希望程序在某处退出并重启,可以在代码中写入这个返回值。

如果因为某种原因(例如代码错误或者环境错误并且长时间没有修复),PyTorchTrainingJob 不断地失败重启却无法解决问题,这会导致集群资源的浪费。用户可以通过设置 spec.runPolicy.backoffLimit 字段(默认为 3)来设置副本的最大重启次数。重启次数为所有副本共享,即所有副本重启次数累计达到此数值后,副本将不能再次重启。

使用 torchrun 启动训练

前面的示例中所使用的训练方法比较原始,即直接用 python 启动训练脚本,执行训练。

PyTorch 在后续提供了 torch.distributed.launch 包和 torchrun 工具来更好地启动和管理训练,具体优点包括:支持一机多进程高容错弹性伸缩训练规模等。PyTorchTrainingJob 也支持使用 torchrun 启动训练来继承这些优点。

spec:
  torchrunConfig:
    enabled: true
    maxRestarts: 10
    procPerNode: "1"
    rdzvBackend: c10d
    extraOptions: []

在 PyTorchTrainingJob 的定义中加入上述片段,来使用 torchrun 启动训练,其中:

  • enabled:是否启用 torchrun
  • maxRestarts:训练进程的最多重启次数。
  • procPerNode:一个副本中启动多少个训练进程。除了可以指定一个数字字符串之外,还可以设置为 gpu,表示启动等同于副本所使用的 GPU 数量的训练进程。
  • rdzvBackendtorchrun 所使用的汇合通信方式,可以设置为 c10detcdetcd-v2,但是只有 c10dtorch 内置的。如果用户希望使用 etcd 需要自行搭建 etcd 服务器。
  • extraOptionstorchrun 的其他参数,上面的参数是 torchrun 比较常用的设置,用户也可以通过 extraOptions 字段提供更多 torchrun 的其他设置。

弹性训练

使用 torchrun 启动的 PyTorchTrainingJob 支持弹性伸缩训练规模,通过 spec.elastic 设置伸缩范围和当前期望训练规模。

在下面的示例中,PyTorchTrainingJob 启用弹性训练功能,训练规模的伸缩范围是 [4,10],当前期望训练规模为 7。

spec:
  elastic:
    enabled: true
    minReplicas: 4
    maxReplicas: 10
    expectedReplicas: 7

注:期望训练规模(spec.elastic.expectedReplicas)并不代表实际训练规模,当集群资源数量不足时,控制器可能无法创建足够的副本。

最佳实践

...
spec:
  torchrunConfig:
    enabled: false
    minNodes: 1
    maxRestarts: 10
    procPerNode: "1"
    rdzvBackend: c10d
    extraOptions: []
  replicaSpecs:
  - replicas: 4
    restartPolicy: OnFailure
    template:
      spec:
        containers:
        - command:
          - python
          args:
          - dist_mnist.py
          image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
          name: pytorch
    type: worker
...

在上面的示例中:spec.replicaSpecs[*].template.spec.containers[0].command 只填写 python,其他参数填写在 spec.replicaSpecs[*].template.spec.containers[0].args 中。这样可以实现以下效果:

  • spec.torchrunConfig.enabled 设置为 false 时,控制器会为训练副本设置正确的环境变量,并通过 python dist_mnist.py 命令启动训练脚本。
  • spec.torchrunConfig.enabled 设置为 true 时,控制器会忽略 python 命令,而是改用 torchrun 命令,其格式为:torchrun <torchrun_args> dist_mnist.py

这样做的优点就是,在切换 torchrun 模式时,不需要对其他字段进行改动。

另外,如果用户使用 Python Module 作为训练脚本,可以参考以下配置:

...
spec:
  torchrunConfig:
    enabled: false
    ...
  replicaSpecs:
  - replicas: 4
    restartPolicy: OnFailure
    template:
      spec:
        containers:
        - command:
          - python
          args:
          - -m
          - training.module
          image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
          name: pytorch
    type: worker
...

在上面的示例中,当 spec.torchrunConfig.enabled 设置为 true 时,-m 参数同样可以被 torchrun 使用。

成功和失败

在 PyTorch 分布式训练框架中,需要设置 MASTER_ADDRMASTER_PORT,PyTorchTrainingJob 会将第一个训练副本作为 master(主节点)。当分布式训练的主节点成功结束,PyTorch 分布式训练成功;反之,当分布式训练的主节点执行失败,PyTorch 分布式训练失败。

但是 master 的失败有时可能是因为环境因素导致的,比如集群网络断连、集群节点崩溃等等,此类原因导致的失败应该被允许自动恢复。针对这一情况,PyTorchTrainingJob 支持副本重启(请参阅重启机制),并设定了重启次数限制(由 spec.runPolicy.backoffLimit 字段指定),当副本重启次数达到上限后,如果主节点再次失败,则训练失败。此外,PyTorchTrainingJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds 字段指定),当超过这个执行时间后,训练失败。

如果 PyTorchTrainingJob 在没有超过重启次数和没有超过最长执行时间的情况下成功完成了主节点的运行,则训练成功。

清除策略

在训练结束后,可能有些副本仍处于运行状态。这些运行的副本仍然会占用集群资源,PyTorchTrainingJob 提供清除策略,在训练结束后删除这些副本。

PyTorchTrainingJob 提供以下三种策略:

  • None:不删除副本。
  • All:删除所有副本。
  • Unfinished:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议用户在调试完毕后手动删除这些副本或删除整个 PyTorchTrainingJob。

调度器

目前 PyTorchTrainingJob 支持使用以下两种调度器:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler 调度器

调度器通过 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 的默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,PyTorchTrainingJob 启用 T9k Scheduler 调度器,将副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50

TensorBoard 的使用

PyTorchTrainingJob 支持使用 TensorBoard 对训练过程和结果进行实时可视化(由 spec.tensorboardSpec 字段设置)。

在下面的示例中,PyTorchTrainingJob 使用 t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2 镜像创建一个 TensorBoard,可视化名为 torch-tensorboard-pvc 的 PVC 中 /log 路径下的模型数据。

...
spec:
  tensorboardSpec:
    image: t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2
    trainingLogFilesets:
    - t9k://pvc/torch-tensorboard-pvc/log

调试模式

PyTorchTrainingJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。

该模式可以通过 spec.runMode.debug 字段来设置:

  • spec.runMode.debug.enabled 表示是否启用调试模式。
  • spec.runMode.debug.replicaSpecs 表示如何配置各个副本的调试模式:
    • spec.runMode.debug.replicaSpecs.type 表示作用于的副本类型。
    • spec.runMode.debug.replicaSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.debug.replicaSpecs.command 表示副本在等待调试的时候执行的命令,默认为 sleep inf
    • 如果不填写 spec.runMode.debug.replicaSpecs 字段,则表示所有副本都使用默认设置。

在下面的示例中:

  • 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行 sleep inf
# 示例一
...
spec:
  runMode:
    debug:
      enabled: true
      replicaSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    debug:
      enabled: true

暂停模式

PyTorchTrainingJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。

该模式可以通过 spec.runMode.pause 字段来设置:

  • spec.runMode.pause.enabled 表示是否启用暂停模式。
  • spec.runMode.pause.resumeSpecs 表示结束暂停后,如何恢复各个副本:
    • spec.runMode.pause.resumeSpecs.type 表示作用于的副本类型。
    • spec.runMode.pause.resumeSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.pause.resumeSpecs.commandspec.runMode.pause.resumeSpecs.args 表示副本在恢复运行时候执行的命令,默认使用 spec.replicaSpecs[0].template 中的命令。
    • 如果不填写 spec.runMode.pause.resumeSpecs 字段,则表示所有副本都使用默认设置。

用户可以随时修改 spec.runMode.pause.enabled 来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs,所以如果有暂停 PyTorchTrainingJob 的需求,请提前设置好恢复设置。

在下面的示例中:

  • 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行 spec.replicaSpecs[0].template 中设置的命令。
# 示例一
...
spec:
  runMode:
    pause:
      enabled: true
      resumeSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    pause:
      enabled: true

PyTorchTrainingJob 状态

PyTorchTrainingJob 的状态和阶段

status.conditions 字段用于描述当前 PyTorchTrainingJob 的状态,包括以下 6 种类型:

  1. Initialized:PyTorchTrainingJob 已经成功创建各子资源,完成初始化。
  2. Running:开始执行任务。
  3. ReplicaFailure:有一个或多个副本出现错误。
  4. Completed:PyTorchTrainingJob 成功。
  5. Failed:PyTorchTrainingJob 失败。
  6. Paused:PyTorchTrainingJob 进入暂停模式,所有副本都已删除或正在删除。

status.phase 字段用于描述当前 PyTorchTrainingJob 所处的阶段,PyTorchTrainingJob 的整个生命周期主要有以下7个阶段:

  1. Pending:PyTorchTrainingJob 刚刚创建,等待副本启动。
  2. Running:副本创建成功,开始执行任务。
  3. Paused:PyTorchTrainingJob 进入暂停模式。
  4. Resuming:PyTorchTrainingJob 正从暂停模式中恢复运行。恢复运行后,切换为 Running 阶段。
  5. Succeeded:PyTorchTrainingJob 成功。
  6. Failed:PyTorchTrainingJob 失败。
  7. Unknown:控制器无法获得 PyTorchTrainingJob 的阶段。

在下面的示例中,PyTorchTrainingJob 所有子资源创建成功,所以类型为 Initalizedcondition 被设为 True;PyTorchTrainingJob 运行结束,所以类型为 Completedcondition 被设置为 True;PyTorchTrainingJob 的训练成功结束,所以类型为 Completedcondition 被设置为 True(原因是 The job has finished successfully.)。当前 PyTorchTrainingJob 运行阶段为 Succeeded

...
status:
  conditions:
    - lastTransitionTime: "2023-12-19T02:40:25Z"
      message: The job has been initialized successfully.
      reason: '-'
      status: "True"
      type: Initialized
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "False"
      type: Running
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "False"
      type: Failed
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "True"
      type: Completed
    - lastTransitionTime: "2023-12-19T02:40:25Z"
      message: All pods are running normally.
      reason: '-'
      status: "False"
      type: ReplicaFailure
  phase: Succeeded

副本的状态

status.tasks 字段用来记录副本的状态,记录的内容主要包括:

  • 副本的重启次数(同一种角色的副本的重启次数之和);
  • 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了 CreatingDeleted 分别表示正在创建和已删除;
  • 副本在集群中对应的 Pod 的索引信息。

在下面的示例中,PyTorchTrainingJob 创建了 1 个角色为 worker 的副本,当前均处于 Succeeded 阶段,运行在 torch-mnist-trainingjob-5b373-worker-0 这个 Pod 上。

...
status:
  tasks:
  - replicas:
    - containers:
      - exitCode: 0
        name: pytorch
        state: Terminated
      name: torch-mnist-trainingjob-5b373-worker-0
      phase: Succeeded
      uid: d39f91d6-9c48-4c57-bb71-4131226395b6
    type: worker

副本状态统计

status.aggregate 字段统计了各个阶段的副本数量。

在下面示例中,PyTorchTrainingJob 创建了 3 个副本,其中 1 个处于 Pending 阶段,另外两个处于 Running 阶段。

...
status:
  aggregate:
    creating: 0
    deleted: 0
    failed: 0
    pending: 1
    running: 2
    succeeded: 0
    unknown: 0
...

TensorBoard 状态

status.tensorboard 字段用来记录 TensorBoard 的状态。

在下面的示例中,PyTorchTrainingJob 创建了名为 torch-mnist-trainingjob-5b373 的 TensorBoard,TensorBoard 目前运行正常。

status:
  tensorboard:
    action: NOP
    dependent:
      apiVersion: tensorstack.dev/v1beta1
      kind: TensorBoard
      name: torch-mnist-trainingjob-5b373
      namespace: demo
      uid: b09378f3-2164-4f14-a425-a1340fa32d7d
    note: TensorBoard [torch-mnist-trainingjob-5b373] is ready
    ready: true
    reason: DependentReady
    type: Normal

下一步

TensorFlowTrainingJob

TensorFlowTrainingJob 是服务于 TensorFlow 分布式训练框架的 T9k Job。

你可以较为方便地使用 TensorFlowTrainingJob 为 TensorFlow 训练脚本提供训练环境,并监控训练进程。

创建 TensorFlowTrainingJob

下面是一个基本的 TensorFlowTrainingJob 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
  name: tensorflow-example
spec:
  replicaSpecs:
  - replicas: 4
    restartPolicy: OnFailure
    template:
      spec:
        containers:
        - command:
          - python
          - dist_mnist.py
          image: tensorflow/tensorflow:2.11.0
          name: tensorflow
          resources:
            limits:
              cpu: 1
              memory: 2Gi
            requests:
              cpu: 500m
              memory: 1Gi
    type: worker

在该例中:

  • 创建 4 个副本(由 spec.replicaSpecs[*].replicas 字段指定),副本的角色为 worker(由 spec.replicaSpecs[*].type 字段指定)。
  • 每个副本使用 tensorflow/tensorflow:2.11.0 镜像,执行命令 python dist_mnist.py(由 spec.replicaSpecs<a target="_blank" rel="noopener noreferrer" href="https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates">*].template 字段指定,此处的填写方式参考 [PodTemplate)。
  • 当副本失败后,会自动重启(由 spec.replicaSpecs[*].restartPolicy 字段指定)。

副本的类型

在 TensorFlow 分布式训练框架中,副本有 4 种类型:Chief、Worker、PS 和 Evaluator。

在 TensorFlowTrainingJob 中,副本的类型由 spec.replicaSpecs[*].type 字段指定,分别是 chiefworkerpsevaluator

副本设置

TensorFlowTrainingJob 副本运行环境和命令可以通过 spec.replicaSpecs[*].template 进行配置,可配置内容包括镜像、运行命令、资源配置、环境变量等。

资源配置

副本资源配置通过 spec.replicaSpecs[*].template.spec.containers[*].resources 字段指定。

TensorFlowTrainingJob 的资源配置包括两部分:

  • 资源请求量(requests):创建该副本时,节点上至少应具有这些数量的资源。如果集群中所有节点都不满足副本的资源请求量,则副本的创建可能会被阻塞;或者如果副本的优先级较高,则有可能驱逐节点上其他工作负载来为副本空出可用的资源。
  • 资源上限(limits):该副本在运行期间,最多可以使用的资源数量。比如:如果副本在运行时申请分配超过上限的内存,则有可能出现 OOMKILLED 错误。(注:资源上限不能小于资源请求量)

在下面的示例中,TensorFlowTrainingJob 中每个 worker 副本设置了以下资源配置:

  • 资源请求量:2 个 cpu 核心、2Gi 内存;
  • 资源上限:4 个 cpu 核心、4Gi 内存。
apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
  name: tensorflow-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - resources:
              limits:
                cpu: 4
                memory: 4Gi
              requests:
                cpu: 2
                memory: 2Gi

共享内存

在进行多节点任务时,可以按照如下方式修改 TensorFlowTrainingJob 来使用共享内存:

apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
  name: tensorflow-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - ...
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
              sizeLimit: "1Gi"

在该例中:

  • spec.replicaSpecs[*].template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.replicaSpecs[*].template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

环境变量

副本环境变量通过 spec.replicaSpecs[*].template.spec.containers[*].env 字段指定。TensorFlowTrainingJob 支持直接设置环境变量内容和引用其他资源字段作为环境变量两种方式。

在下面的示例中,TensorFlowTrainingJob 给 worker 副本设置了两个环境变量:ENV_DIRECTENV_REFERENCED。其中 ENV_DIRECT 环境变量被直接设置为 env-valueENV_REFERENCED 环境变量引用了 secret-name Secret 的 key-in-secret 字段的内容。

apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
  name: tensorflow-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
            - env:
              - name: ENV_DIRECT
                value: env-value
              - name: ENV_REFERENCED
                valueFrom:
                  secretKeyRef:
                    name: secret-name
                    key: key-in-secret

重启机制

TensorFlowTrainingJob 的 spec.replicaSpec[*].template 字段使用 PodTemplate 的规范填写,但是 Pod 的重启策略并不能完全满足 TensorFlowTrainingJob 的需求,所以 TensorFlowTrainingJob 使用 spec.replicaSpec[*].restartPolicy 字段覆盖 spec.replicaSpec[*].template 中指定的重启策略。

可选的重启策略有以下四种:

  • Never:不重启
  • OnFailure:失败后重启
  • Always:总是重启
  • ExitCode:特殊退出码重启

使用 Never 重启策略时,Job 的副本失败后不会重启。如果需要调试代码错误,可以选择此策略,便于从副本中读取训练日志。

ExitCode 是一种比较特殊的重启策略,它将失败进程的返回值分为两类:一类是由于系统环境原因或用户操作导致的错误,此类错误可以通过重启解决;另一类是代码错误或者其他不可自动恢复的错误。可重启的退出码包括:

  • 130(128+2):使用 Control+C 终止容器运行。
  • 137(128+9):容器接收到 SIGKILL 信号。
  • 143(128+15):容器接收到 SIGTERM 信号。
  • 138:用户可以自定义这个返回值的含义。如果用户希望程序在某处退出并重启,可以在代码中写入这个返回值。

如果因为某种原因(例如代码错误或者环境错误并且长时间没有修复),TensorFlowTrainingJob 不断地失败重启却无法解决问题,这会导致集群资源的浪费。用户可以通过设置 spec.runPolicy.backoffLimit 字段来设置副本的最大重启次数。重启次数为所有副本共享,即所有副本重启次数累计达到此数值后,副本将不能再次重启。

成功和失败

在 TensorFlow 分布式训练框架中,Chief 是主节点。如果没有指定 Chief,则会选择第一个 Worker 作为主节点。当分布式训练的主节点执行完成时,TensorFlow 分布式训练成功;反之,当分布式训练的主节点执行失败时,TensorFlow 分布式训练失败。

在 TensorFlowTrainingJob 中,如果没有 Chief 副本,则选取序号为 0 的 Worker 节点作为主节点。主节点的失败有时可能是因为环境因素导致的,比如集群网络断连、集群节点崩溃等等,此类原因导致的失败应该被允许自动恢复。针对这一情况,TensorFlowTrainingJob 允许副本重启(请参阅重启机制),并设定了重启次数限制(由 spec.runPolicy.backoffLimit 字段指定),当副本重启次数达到上限后,如果主节点再次失败,则 TensorFlowTrainingJob 失败。此外,TensorFlowTrainingJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds 字段指定),当超过这个执行时间后,TensorFlowTrainingJob 失败。

如果 TensorFlowTrainingJob 在没有超过重启次数和没有超过最长执行时间的情况下成功完成了主节点的运行,则 TensorFlowTrainingJob 成功。

清除策略

在训练结束后,可能有些副本仍处于运行状态,比如 TensorFlow 训练框架中的 PS 经常在训练完成后仍然保持运行。这些运行的副本仍然会占用集群资源,TensorFlowTrainingJob 提供清除策略,在训练结束后删除这些副本。

TensorFlowTrainingJob 提供以下三种策略:

  • None:不删除副本。
  • All:删除所有副本。
  • Unfinished:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议你在调试完毕后手动删除这些副本或删除整个 TensorFlowTrainingJob。

调度器

目前 TensorFlowTrainingJob 支持使用以下两种调度器:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler 调度器

调度器通过 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 的默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,TensorFlowTrainingJob 启用 T9k Scheduler 调度器,将副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50

TensorBoard 的使用

TensorFlowTrainingJob 支持使用 TensorBoard 对训练过程和结果进行实时可视化(由 spec.tensorboardSpec 字段设置)。

在下面的示例中,TensorFlowTrainingJob 使用 t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2 镜像创建一个 TensorBoard,可视化名为 tensorflow-tensorboard-pvc 的 PVC 中 /log 路径下的模型数据。

...
spec:
  tensorboardSpec:
    image: t9kpublic/tensorflow-2.11.0:cpu-sdk-0.5.2
    trainingLogFilesets:
    - t9k://pvc/tensorflow-tensorboard-pvc/log
...

调试模式

TensorFlowTrainingJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。

该模式可以通过 spec.runMode.debug 字段来设置:

  • spec.runMode.debug.enabled 表示是否启用调试模式。
  • spec.runMode.debug.replicaSpecs 表示如何配置各个副本的调试模式:
    • spec.runMode.debug.replicaSpecs.type 表示作用于的副本类型。
    • spec.runMode.debug.replicaSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.debug.replicaSpecs.command 表示副本在等待调试的时候执行的命令,默认为 sleep inf
    • 如果不填写 spec.runMode.debug.replicaSpecs 字段,则表示所有副本都使用默认设置。

在下面的示例中:

  • 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行 sleep inf
# 示例一
...
spec:
  runMode:
    debug:
      enabled: true
      replicaSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    debug:
      enabled: true

暂停模式

TensorFlowTrainingJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。

该模式可以通过 spec.runMode.pause 字段来设置:

  • spec.runMode.pause.enabled 表示是否启用暂停模式。
  • spec.runMode.pause.resumeSpecs 表示结束暂停后,如何恢复各个副本:
    • spec.runMode.pause.resumeSpecs.type 表示作用于的副本类型。
    • spec.runMode.pause.resumeSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.pause.resumeSpecs.commandspec.runMode.pause.resumeSpecs.args 表示副本在恢复运行时候执行的命令,默认使用 spec.replicaSpecs[0].template 中的命令。
    • 如果不填写 spec.runMode.pause.resumeSpecs 字段,则表示所有副本都使用默认设置。

用户可以随时修改 spec.runMode.pause.enabled 来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs,所以如果有暂停 TensorFlowTrainingJob 的需求,请提前设置好恢复设置。

在下面的示例中:

  • 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行 spec.replicaSpecs[0].template 中设置的命令。
# 示例一
...
spec:
  runMode:
    pause:
      enabled: true
      resumeSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    pause:
      enabled: true

TensorFlowTrainingJob 状态

TensorFlowTrainingJob 的状态和阶段

status.conditions 字段用于描述当前 TensorFlowTrainingJob 的状态,包括以下 6 种类型:

  1. Initialized:TensorFlowTrainingJob 已经成功创建各子资源,完成初始化。
  2. Running:开始执行任务。
  3. ReplicaFailure:有一个或多个副本出现错误。
  4. Completed:TensorFlowTrainingJob 成功。
  5. Failed:TensorFlowTrainingJob 失败。
  6. Paused:TensorFlowTrainingJob 进入暂停模式,所有副本都已删除或正在删除。

status.phase 字段用于描述当前 TensorFlowTrainingJob 所处的阶段,TensorFlowTrainingJob 的整个生命周期主要有以下7个阶段:

  1. Pending:TensorFlowTrainingJob 刚刚创建,等待副本启动。
  2. Running:副本创建成功,开始执行任务。
  3. Paused:TensorFlowTrainingJob 进入暂停模式。
  4. Resuming:TensorFlowTrainingJob 正从暂停模式中恢复运行。恢复运行后,切换为 Running 阶段。
  5. Succeeded:TensorFlowTrainingJob 成功。
  6. Failed:TensorFlowTrainingJob 失败。
  7. Unknown:控制器无法获得 TensorFlowTrainingJob 的阶段。

在下面的示例中,TensorFlowTrainingJob 所有子资源创建成功,所以类型为 Initalizedcondition 被设为 True;TensorFlowTrainingJob 运行结束,所以类型为 Completedcondition 被设置为 True;TensorFlowTrainingJob 的训练成功结束,所以类型为 Completedcondition 被设置为 True(原因是 The job has finished successfully.)。当前 TensorFlowTrainingJob 运行阶段为 Succeeded

...
status:
  conditions:
    - lastTransitionTime: "2023-12-19T02:40:25Z"
      message: The job has been initialized successfully.
      reason: '-'
      status: "True"
      type: Initialized
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "False"
      type: Running
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "False"
      type: Failed
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "True"
      type: Completed
    - lastTransitionTime: "2023-12-19T02:40:25Z"
      message: All pods are running normally.
      reason: '-'
      status: "False"
      type: ReplicaFailure
  phase: Succeeded

副本的状态

status.tasks 字段用来记录副本的状态,记录的内容主要包括:

  • 副本的重启次数(同一类型的副本的重启次数之和);
  • 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了 CreatingDeleted 分别表示正在创建和已删除;
  • 副本在集群中对应的 Pod 的索引信息。

在下面的示例中,TensorFlowTrainingJob 创建了 1 个类型为 worker 的副本,当前均处于 Succeeded 阶段,运行在 mnist-trainingjob-5b373-worker-0 这个 Pod 上。

...
status:
  tasks:
  - replicas:
    - containers:
      - exitCode: 0
        name: pytorch
        state: Terminated
      name: mnist-trainingjob-5b373-worker-0
      phase: Succeeded
      uid: d39f91d6-9c48-4c57-bb71-4131226395b6
    type: worker

副本状态统计

status.aggregate 字段统计了各个阶段的副本数量。

在下面示例中,TensorFlowTrainingJob 创建了 3 个副本,其中 1 个处于 Pending 阶段,另外两个处于 Running 阶段。

...
status:
  aggregate:
    creating: 0
    deleted: 0
    failed: 0
    pending: 1
    running: 2
    succeeded: 0
    unknown: 0
...

TensorBoard 状态

status.tensorboard 字段用来记录 TensorBoard 的状态。

在下面的示例中,TensorFlowTrainingJob 创建了名为 mnist-trainingjob-5b373 的 TensorBoard,TensorBoard 目前运行正常。

status:
  tensorboard:
    action: NOP
    dependent:
      apiVersion: tensorstack.dev/v1beta1
      kind: TensorBoard
      name: mnist-trainingjob-5b373
      namespace: demo
      uid: b09378f3-2164-4f14-a425-a1340fa32d7d
    note: TensorBoard [mnist-trainingjob-5b373] is ready
    ready: true
    reason: DependentReady
    type: Normal

下一步

DeepSpeedJob

DeepSpeedJob 是服务于 DeepSpeed 分布式训练框架的 T9k Job。

你可以较为方便地使用 DeepSpeedJob 为 DeepSpeed 训练脚本提供训练环境,并监控训练进程。

创建 DeepSpeedJob

下面是一个基本的 DeepSpeedJob 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: DeepspeedJob
metadata:
  name: deepspeed-example
spec:
  config:
    slotPerWorker: 1
    run:
      python: /t9k/mnt/train.py
  worker:
    replicas: 4
    template:
      spec:
        restartPolicy: OnFailure
        containers:
        - image: deepspeed/deepspeed:v072_torch112_cu117
          imagePullPolicy: IfNotPresent
          name: worker
          resources:
            limits:
              cpu: 4
              memory: 4Gi
            requests:
              cpu: 2
              memory: 2Gi
          volumeMounts:
          - mountPath: /t9k/mnt
            name: code
        volumes:
        - name: code
          persistentVolumeClaim:
            claimName: deepspeed

在该例中:

  • 创建 4 个训练副本,这些副本会启动 sshd 服务。
  • 第一个副本会启动 deepspeed 程序,该程序会通过 pdsh(或其他方式)访问 4 个副本,并在每个副本上运行 /t9k/mnt/train.py 脚本。

副本设置

DeepSpeedJob 副本运行环境和命令可以通过 spec.worker.template 进行配置,可配置内容包括镜像、运行命令、资源配置、环境变量等。

资源配置

副本资源配置通过 spec.worker.template.spec.containers[*].resources 字段指定。

DeepSpeedJob 的资源配置包括两部分:

  • 资源请求量(requests):创建该副本时,节点上至少应具有这些数量的资源。如果集群中所有节点都不满足副本的资源请求量,则副本的创建可能会被阻塞;或者如果副本的优先级较高,则有可能驱逐节点上其他工作负载来为副本空出可用的资源。
  • 资源上限(limits):该副本在运行期间,最多可以使用的资源数量。比如:如果副本在运行时申请分配超过上限的内存,则有可能出现 OOMKILLED 错误。(注:资源上限不能小于资源请求量)

在下面的示例中,DeepSpeedJob 中每个副本设置了以下资源配置:

  • 资源请求量:2 个 cpu 核心、2Gi 内存;
  • 资源上限:4 个 cpu 核心、4Gi 内存。
apiVersion: batch.tensorstack.dev/v1beta1
kind: DeepSpeedJob
metadata:
  name: deepspeed-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
        - resources:
            limits:
              cpu: 4
              memory: 4Gi
            requests:
              cpu: 2
              memory: 2Gi

共享内存

在进行多节点任务时,可以按照如下方式修改 DeepSpeedJob 来使用共享内存:

apiVersion: batch.tensorstack.dev/v1beta1
kind: DeepSpeedJob
metadata:
  name: deepspeed-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
        - ...
          volumeMounts:
            - mountPath: /dev/shm
              name: dshm
        volumes:
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: "1Gi"

在该例中:

  • spec.worker.template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.worker.template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

环境变量

副本环境变量通过 spec.worker.template.spec.containers[*].env 字段指定。DeepSpeedJob 支持直接设置环境变量内容和引用其他资源字段作为环境变量两种方式。

在下面的示例中,DeepSpeedJob 给副本设置了两个环境变量:ENV_DIRECTENV_REFERENCED。其中 ENV_DIRECT 环境变量被直接设置为 env-valueENV_REFERENCED 环境变量引用了 secret-name Secret 的 key-in-secret 字段的内容。

apiVersion: batch.tensorstack.dev/v1beta1
kind: DeepSpeedJob
metadata:
  name: deepspeed-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
          - env:
            - name: ENV_DIRECT
              value: env-value
            - name: ENV_REFERENCED
              valueFrom:
                secretKeyRef:
                  name: secret-name
                  key: key-in-secret

训练配置

DeepSpeedJob 在 spec.config 中配置如何执行训练。有以下参数可以设置:

  • run:如何启动训练,以下三个参数只能填写一个,否则报错:
    • python:使用 Python 脚本进行训练。指定 Python 文件以及启动参数。
    • module:使用 Python module 进行训练。指定 Python module 以及启动参数。
    • exec:使用可执行文件/命令进行训练。指定可执行文件以及启动参数。
  • slotsPerWorker:每一个副本上设置多少个“插槽”。“插槽”是继承自 MPI 中的概念,表示一个副本上可以运行多少个训练进程。一般来说该值被设为每个副本分配的 GPU 数量。例如当创建了一个 replica 为 4 的任务,并且给每个副本分配了 2 个 nvidia.com/gpu,则应该将 slotsPerWorker 设为 2,这样最后一共会运行 4 * 2 = 8 个训练进程。
  • localRank:是否传递 LOCAL_RANK 环境变量,默认为 true
  • autotune:启用超参数调优,可以设置为 noneruntune,默认为 nonenone 为不启动超参数调优;tune 只查找最合适的超参数组合,但是不执行训练;run 查找最合适的超参数组合,并用该超参数执行训练。
  • otherArgs:设置其他 DeepSpeed 参数,详见下文。

otherArgs

DeepSpeedJob 希望提供用户足够的灵活性,所以支持用户通过 otherArgs 字段设置传入 DeepSpeed 的参数。config 中的配置实际上也是通过 DeepSpeed 参数实现的,以下列出除了在配置文件中指定的参数之外的其他可用参数:

  • --launcher: 多节点训练使用的启动器后端,目前的选项包括 PDSH、OpenMPI、MVAPICH、SLURM、MPICH。(默认:pdsh)。目前 DeepSpeedJob 只支持 pdsh
  • --no_ssh_check:多节点训练时不执行 ssh 检查。
  • --save_pid: 在 /tmp/<main-pid>.ds 处保存包含启动器进程 ID(pid),其中 <main-pid> 是第一个调用 DeepSpeed 的进程的 pid。PDSH 模式下不支持。
  • --enable_each_rank_log: 将每个 Rank 的 stdout 和 stderr 重定向到不同的日志文件。PDSH 模式下不支持。
  • --bind_cores_to_rank:将每个 Rank 绑定到主机的不同核心。PDSH 模式下不支持。
  • --bind_core_list:要绑定的核心列表,以逗号分隔。例如 1,3-5,7 => [1,3,4,5,7]。 未指定时,系统上的所有核心都将被绑定。PDSH 模式下不支持。

训练的成功和失败判定

DeepSpeedJob 分布式训练框架中,第一个训练副本(下文记为 worker-0)是分布式任务的主节点。当 worker-0 成功结束,则 DeepSpeedJob 训练成功;反之,当 worker-0 执行失败,DeepSpeedJob 训练失败。

如果一次训练执行时间过长,用户可能需要考虑代码是否需要优化、是否需要分配更多资源等问题。DeepSpeedJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds 字段指定),当超过这个执行时间后,训练失败。

清除策略

在训练完毕后,可能有些副本仍处于运行状态。这些运行的副本仍然会占用集群资源,DeepSpeedJob 提供清除策略,可以在训练结束后删除这些训练副本。

DeepSpeedJob 提供以下三种策略:

  • None:不删除副本。
  • All:删除所有副本。
  • Unfinished:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议你在调试完毕后手动删除这些副本或删除整个 DeepSpeedJob。

调度策略

目前 DeepSpeedJob 支持两种调度策略:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler

调度策略通过 CRD 的 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 的默认调度策略。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,MPIJob 启用 T9k Scheduler 调度器,将副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50

调试模式

DeepSpeedJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。

该模式可以通过 spec.runMode.debug 字段来设置:

  • spec.runMode.debug.enabled 表示是否启用调试模式。
  • spec.runMode.debug.replicaSpecs 表示如何配置各个副本的调试模式:
    • spec.runMode.debug.replicaSpecs.type 表示作用于的副本类型。
    • spec.runMode.debug.replicaSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.debug.replicaSpecs.command 表示副本在等待调试的时候执行的命令,默认为 /usr/sbin/sshd -D
    • 如果不填写 spec.runMode.debug.replicaSpecs 字段,则表示所有副本都使用默认设置。

在下面的示例中:

  • 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行 sleep inf
  • 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行 /usr/sbin/sshd -D
# 示例一
...
spec:
  runMode:
    debug:
      enabled: true
      replicaSpecs:
        - type: worker
          skipInitContainer: true
          command: ["sleep", "inf"]

---
# 示例二
...
spec:
  runMode:
    debug:
      enabled: true

暂停模式

DeepSpeedJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。

该模式可以通过 spec.runMode.pause 字段来设置:

  • spec.runMode.pause.enabled 表示是否启用暂停模式。
  • spec.runMode.pause.resumeSpecs 表示结束暂停后,如何恢复各个副本:
    • spec.runMode.pause.resumeSpecs.type 表示作用于的副本类型。
    • spec.runMode.pause.resumeSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.pause.resumeSpecs.commandspec.runMode.pause.resumeSpecs.args 表示副本在恢复运行时候执行的命令,默认使用 spec.replicaSpecs[0].template 中的命令。
    • 如果不填写 spec.runMode.pause.resumeSpecs 字段,则表示所有副本都使用默认设置。

用户可以随时修改 spec.runMode.pause.enabled 来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs,所以如果有暂停 DeepSpeedJob 的需求,请提前设置好恢复设置。

在下面的示例中:

  • 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行 spec.replicaSpecs[0].template 中设置的命令。
# 示例一
...
spec:
  runMode:
    pause:
      enabled: true
      resumeSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    pause:
      enabled: true

DeepSpeedJob 状态

DeepSpeedJob 的状态和阶段

status.conditions 字段用于描述当前 DeepSpeedJob 的状态,包括以下 5 种类型:

  1. Initialized:DeepSpeedJob 已经成功创建各子资源,完成初始化。
  2. Running:开始执行任务。
  3. ReplicaFailure:有一个或多个副本出现错误。
  4. Completed:DeepSpeedJob 成功。
  5. Failed:DeepSpeedJob 失败。

status.phase 字段用于描述当前 DeepSpeedJob 所处的阶段,DeepSpeedJob 的整个生命周期主要有以下几个阶段:

  1. Pending:DeepSpeedJob 刚刚创建,等待副本启动。
  2. Running:副本创建成功,开始执行任务。
  3. Succeeded:DeepSpeedJob 成功。
  4. Failed:DeepSpeedJob 失败。
  5. Unknown:控制器无法获得 DeepSpeedJob 的阶段。

在下面的示例中,DeepSpeedJob 所有子资源创建成功,所以类型为 Initalizedcondition 被设为 True;DeepSpeedJob 运行结束,所以类型为 Completedcondition 被设置为 True;但是 DeepSpeedJob 的训练结果是失败的,所以类型为 Failedcondition 被设置为 True。当前 DeepSpeedJob 运行阶段为 Failed

...
status:
  conditions:
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "The job has been initialized successfully."
      reason: "-"
      type: Initializing
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "All pods are running normally."
      reason: "-"
      type: Running
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "False"
      message: "All pods are running normally."
      reason: "-"
      type: ReplicaFailure
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "False"
      message: "The job exited with an error code."
      reason: "Failed"
      type: Completed
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "True"
      message: "The job exited with an error code."
      reason: "Failed"
      type: Failed
  phase: Failed

副本的状态

status.tasks 字段用来记录副本的状态,记录的内容主要包括:

  • 副本的重启次数(同一种角色的副本的重启次数之和)
  • 副本当前的运行阶段
  • 副本在集群中对应的 Pod 的索引信息

在下面的示例中,DeepSpeedJob 创建了 2 个训练副本,当前均处于 Running 阶段,分别运行在 deepspeed-example-worker-0deepspeed-example-worker-1 这 2 个 Pod 上。

...
status:
  tasks:
  - type: worker
    restartCount: 0
    status:
    - phase: Running
      name: deepspeed-example-worker-0
      uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
      containers: []
    - phase: Running
      name: deepspeed-example-worker-1
      uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
      containers: []

副本状态统计

status.aggregate 字段统计了各个阶段的副本数量。

在下面的示例中,DeepSpeedJob 创建了 3 个副本,其中 1 个处于 Pending 阶段,另外两个处于 Running 阶段。

...
status:
  aggregate:
    creating: 0
    deleted: 0
    failed: 0
    pending: 1
    running: 2
    succeeded: 0
    unknown: 0
...

ColossalAIJob

ColossalAIJob 是服务于 ColossalAI 分布式训练框架的 T9k Job。

你可以较为方便地使用 ColossalAIJob 为 ColossalAI 训练脚本提供训练环境,并监控训练进程。

创建 ColossalAIJob

下面是一个基本的 ColossalAIJob 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: ColossalAIJob
metadata:
  name: colossalai-example
spec:
  ssh:
    authMountPath: /root/.ssh
    sshdPath: /usr/sbin/sshd
  launcher:
    image: hpcaitech/colossalai:0.3.0
    workingDir: /workspace
    env: []
    resources: 
      limits:
        cpu: 1
        memory: 2Gi
      requests:
        cpu: 500m
        memory: 1Gi
  worker:
    replicas: 2
    procPerWorker: 1
    command:
      - train.py
      - arg1
    torchArgs: []
    template:
      spec:
        restartPolicy: OnFailure
        containers:
          - image: hpcaitech/colossalai:0.3.0
            imagePullPolicy: IfNotPresent
            name: worker
            resources:
              limits:
                cpu: 2
                memory: 8Gi
                nvidia.com/gpu: 1
              requests:
                cpu: 1
                memory: 4Gi
                nvidia.com/gpu: 1
            volumeMounts:
              - mountPath: /workspace
                name: code
        volumes:
          - name: code
            persistentVolumeClaim:
              claimName: colossalai

在该例中:

  • 创建 1 个启动副本,该启动副本是 ColossalAI 在训练中所必须的,启动副本的配置参考 PodTemplate,这里不再赘述(启动副本的配置由 spec.launcher 字段指定)。
  • 创建 2 个执行副本(由 spec.worker.replicas 字段指定),每个执行副本上启动 1 个训练进程(由 spec.worker.procPerWorker 字段指定),训练脚本和参数为 train.py arg1(由 spec.worker.command 字段指定),执行副本的其他配置参考 PodTemplate,这里不再赘述(这些配置由 spec.worker.template 字段指定)。
  • 执行副本需要执行 sshd 程序,等待启动副本发来训练指令。sshd 的路径为 /user/sbin/sshd(由 spec.ssh.sshdPath 字段指定,使用该字段的原因是 sshd 程序必须使用绝对路径调用,所以需要其具体路径)。

副本设置

ColossalAIJob 副本运行环境和命令可以通过 spec.worker.template 进行配置,可配置内容包括镜像、运行命令、资源配置、环境变量等。

资源配置

副本资源配置通过 spec.worker.template.spec.containers[*].resources 字段指定。

ColossalAIJob 的资源配置包括两部分:

  • 资源请求量(requests):创建该副本时,节点上至少应具有这些数量的资源。如果集群中所有节点都不满足副本的资源请求量,则副本的创建可能会被阻塞;或者如果副本的优先级较高,则有可能驱逐节点上其他工作负载来为副本空出可用的资源。
  • 资源上限(limits):该副本在运行期间,最多可以使用的资源数量。比如:如果副本在运行时申请分配超过上限的内存,则有可能出现 OOMKILLED 错误。(注:资源上限不能小于资源请求量)

在下面的示例中,ColossalAIJob 中每个副本设置了以下资源配置:

  • 资源请求量:2 个 cpu 核心、2Gi 内存;
  • 资源上限:4 个 cpu 核心、4Gi 内存。
apiVersion: batch.tensorstack.dev/v1beta1
kind: ColossalAIJob
metadata:
  name: colossalai-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
        - resources:
            limits:
              cpu: 4
              memory: 4Gi
            requests:
              cpu: 2
              memory: 2Gi

共享内存

在进行多节点任务时,可以按照如下方式修改 ColossalAIJob 来使用共享内存:

apiVersion: batch.tensorstack.dev/v1beta1
kind: ColossalAIJob
metadata:
  name: colossalai-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
        - ...
          volumeMounts:
            - mountPath: /dev/shm
              name: dshm
        volumes:
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: "1Gi"

在该例中:

  • spec.worker.template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.worker.template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

环境变量

副本环境变量通过 spec.worker.template.spec.containers[*].env 字段指定。ColossalAIJob 支持直接设置环境变量内容和引用其他资源字段作为环境变量两种方式。

在下面的示例中,ColossalAIJob 给副本设置了两个环境变量:ENV_DIRECTENV_REFERENCED。其中 ENV_DIRECT 环境变量被直接设置为 env-valueENV_REFERENCED 环境变量引用了 secret-name Secret 的 key-in-secret 字段的内容。

apiVersion: batch.tensorstack.dev/v1beta1
kind: ColossalAIJob
metadata:
  name: colossalai-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
          - env:
            - name: ENV_DIRECT
              value: env-value
            - name: ENV_REFERENCED
              valueFrom:
                secretKeyRef:
                  name: secret-name
                  key: key-in-secret

重启机制

与其他 TrainingJob 不同,ColossalAIJob 使用 colossalairun 作为启动命令,在这种情况下,Pod 失败重启后不会再加入到训练中。所以 ColossalAIJob 无法像其他 TrainingJob 那样支持 Pod 失败重启。

成功和失败

在 ColossalAIJob 分布式训练框架中:

  • 如果启动副本执行失败,ColossalAIJob 训练失败。
  • 如果启动副本执行成功,ColossalAIJob 并不一定成功:启动副本的作用是启动训练和监测,无论是训练成功还是失败,启动副本都会正常结束,而不是报错。因此,如要确定 ColossalAIJob 是否成功结束,需要检查启动副本的日志。

清除策略

在 ColossalAIJob 训练结束后,ColossalAIJob 控制器可以清理所创建的 Kubernetes 资源,使 ColossalAIJob 不再浪费集群资源(内存、CPU 等)。一般来说,你需要查看启动副本的日志来确定训练结果,所以启动副本不在清理范围之内,ColossalAIJob 控制器只清理执行副本(通过 spec.runPolicy.cleanUpWorkers 字段设置)。

在下面的示例中,ColossalAIJob 在训练结束后会自动删除所有执行副本:

...
spec:
  runPolicy:
    cleanUpWorkers: true

调度器

目前 ColossalAIJob 支持两种调度器:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler 调度器

调度器通过 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 的默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,ColossalAIJob 启用 T9k Scheduler 调度器,将执行副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50

调试模式

ColossalAIJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。

该模式可以通过 spec.runMode.debug 字段来设置:

  • spec.runMode.debug.enabled 表示是否启用调试模式。
  • spec.runMode.debug.replicaSpecs 表示如何配置各个副本的调试模式:
    • spec.runMode.debug.replicaSpecs.type 表示作用于的副本类型。
    • spec.runMode.debug.replicaSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.debug.replicaSpecs.command 表示副本在等待调试的时候执行的命令,默认为 sleep inf
    • 如果不填写 spec.runMode.debug.replicaSpecs 字段,则表示所有副本都使用默认设置。

在下面的示例中:

  • 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行 sleep inf
# 示例一
...
spec:
  runMode:
    debug:
      enabled: true
      replicaSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    debug:
      enabled: true

暂停模式

ColossalAIJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。

该模式可以通过 spec.runMode.pause 字段来设置:

  • spec.runMode.pause.enabled 表示是否启用暂停模式。
  • spec.runMode.pause.resumeSpecs 表示结束暂停后,如何恢复各个副本:
    • spec.runMode.pause.resumeSpecs.type 表示作用于的副本类型。
    • spec.runMode.pause.resumeSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.pause.resumeSpecs.commandspec.runMode.pause.resumeSpecs.args 表示副本在恢复运行时候执行的命令,默认使用 spec.replicaSpecs[0].template 中的命令。
    • 如果不填写 spec.runMode.pause.resumeSpecs 字段,则表示所有副本都使用默认设置。

用户可以随时修改 spec.runMode.pause.enabled 来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs,所以如果有暂停 ColossalAIJob 的需求,请提前设置好恢复设置。

在下面的示例中:

  • 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行 spec.replicaSpecs[0].template 中设置的命令。
# 示例一
...
spec:
  runMode:
    pause:
      enabled: true
      resumeSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    pause:
      enabled: true

ColossalAIJob 状态

ColossalAIJob 的状态和阶段

status.conditions 字段用于描述当前 ColossalAIJob 的状态,包括以下 5 种类型:

  1. Initialized:ColossalAIJob 已经成功创建各子资源,完成初始化。
  2. Running:开始执行任务。
  3. ReplicaFailure:有一个或多个副本出现错误。
  4. Completed:ColossalAIJob 成功。
  5. Failed:ColossalAIJob 失败。
  6. Paused:ColossalAIJob 进入暂停模式,所有副本都已删除或正在删除。

status.phase 字段用于描述当前 ColossalAIJob 所处的阶段,ColossalAIJob 的整个生命周期主要有以下几个阶段:

  1. Pending:ColossalAIJob 刚刚创建,等待副本启动。
  2. Running:副本创建成功,开始执行任务。
  3. Paused:ColossalAIJob 进入暂停模式。
  4. Resuming:ColossalAIJob 正从暂停模式中恢复运行。恢复运行后,切换为 Running 阶段。
  5. Succeeded:ColossalAIJob 成功。
  6. Failed:ColossalAIJob 失败。
  7. Unknown:控制器无法获得 ColossalAIJob 的阶段。

在下面的示例中,ColossalAIJob 所有子资源创建成功,所以类型为 Initalizedcondition 被设为 True;ColossalAIJob 运行结束,所以类型为 Completedcondition 被设置为 True;但是 ColossalAIJob 的训练结果是失败的,所以类型为 Failedcondition 被设置为 True。当前 ColossalAIJob 运行阶段为 Failed

...
status:
  conditions:
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "The job has been initialized successfully."
      reason: "-"
      type: Initializing
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "All pods are running normally."
      reason: "-"
      type: Running
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "False"
      message: "All pods are running normally."
      reason: "-"
      type: ReplicaFailure
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "False"
      message: "The job exited with an error code."
      reason: "Failed"
      type: Completed
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "True"
      message: "The job exited with an error code."
      reason: "Failed"
      type: Failed
  phase: Failed

副本的状态

status.tasks 字段用来记录副本的状态,记录的内容主要包括:

  • 副本的重启次数(同一类型的副本的重启次数之和)
  • 副本当前的运行阶段
  • 副本在集群中对应的 Pod 的索引信息

在下面的示例中,ColossalAIJob 创建了 1 个启动副本和 2 个执行副本。执行副本当前均处于 Running 阶段,分别运行在 colossalai-example-worker-0colossalai-example-worker-1 这 2 个 Pod 上;启动副本当前处于 Running 阶段,运行在 colossalai-example-launcher Pod 上。

...
status:
  tasks:
  - type: launcher
    restartCount: 0
    status:
    - phase: Running
      name: colossalai-example-launcher
      uid: 66634db2-35e7-4641-a4dc-adbd5479734e
      containers: []
  - type: worker
    restartCount: 0
    status:
    - phase: Running
      name: colossalai-example-worker-0
      uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
      containers: []
    - phase: Running
      name: colossalai-example-worker-1
      uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
      containers: []

副本状态统计

status.aggregate 字段统计了各个阶段的副本数量。

在下面的示例中,ColossalAIJob 创建了 3 个副本,其中 1 个处于 Pending 阶段,另外两个处于 Running 阶段。

...
status:
  aggregate:
    creating: 0
    deleted: 0
    failed: 0
    pending: 1
    running: 2
    succeeded: 0
    unknown: 0
...

XGBoostTrainingJob

XGBoostTrainingJob 是服务于 XGBoost 分布式计算框架的 T9k Job。

你可以较为方便地使用 XGBoostTrainingJob 为 XGBoost 计算程序提供训练环境,并监控训练进程。

创建 XGBoostTrainingJob

下面是一个基本的 XGBoostTrainingJob 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: XGBoostTrainingJob
metadata:
  name: training-iris-xgb
spec:
  replicaSpecs:
    - type: master
      replicas: 1
      restartPolicy: OnFailure
      template:
        spec:
          containers:
            - name: xgboost
              image: t9kpublic/xgboost-dist-iris:3.7
              command:
                - python3
                - /mnt/main.py
                - --job_type=Train
                - --xgboost_parameter=objective:multi:softprob,num_class:3
                - --n_estimators=10
                - --learning_rate=0.1
                - --model_path=/mnt/xgboost_model/
                - --model_storage_type=local
    - type: worker
      replicas: 2
      restartPolicy: OnFailure
      template:
          containers:
            - name: xgboost
              image: t9kpublic/xgboost-dist-iris:3.7
              command:
                - python3
                - /mnt/main.py
                - --job_type=Train
                - --xgboost_parameter=objective:multi:softprob,num_class:3
                - --n_estimators=10
                - --learning_rate=0.1
                - --model_path=/mnt/xgboost_model/
                - --model_storage_type=local

在该例中:

  • 创建 1 个 master 副本和 2 个 worker 副本(由 spec.replicaSpecs[*].replicas 字段和 spec.replicaSpecs[*].type 字段指定)。
  • 每个副本使用 registry.tensorstack.cn/t9kmirror/xgboost-dist-iris:1.1 镜像,执行命令 python3 /mnt/main.py --job_type=Train --xgboost_parameter=objective:multi:softprob,num_class:3 --n_estimators=10 --learning_rate=0.1 --model_path=/mnt/xgboost_model/ --model_storage_type=local(由 spec.replicaSpecs<a target="_blank" rel="noopener noreferrer" href="https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates">*].template 字段指定,此处的填写方式参考 [PodTemplate)。
  • 当副本失败后,会自动重启(由 spec.replicaSpecs[*].restartPolicy 字段指定)。

副本设置

XGBoostTrainingJob 副本运行环境和命令可以通过 spec.replicaSpecs[*].template 进行配置,可配置内容包括镜像、运行命令、资源配置、环境变量等。

资源配置

副本资源配置通过 spec.replicaSpecs[*].template.spec.containers[*].resources 字段指定。

XGBoostTrainingJob 的资源配置包括两部分:

  • 资源请求量(requests):创建该副本时,节点上至少应具有这些数量的资源。如果集群中所有节点都不满足副本的资源请求量,则副本的创建可能会被阻塞;或者如果副本的优先级较高,则有可能驱逐节点上其他工作负载来为副本空出可用的资源。
  • 资源上限(limits):该副本在运行期间,最多可以使用的资源数量。比如:如果副本在运行时申请分配超过上限的内存,则有可能出现 OOMKILLED 错误。(注:资源上限不能小于资源请求量)

在下面的示例中,XGBoostTrainingJob 中每个 worker 副本设置了以下资源配置:

  • 资源请求量:2 个 cpu 核心、2Gi 内存;
  • 资源上限:4 个 cpu 核心、4Gi 内存。
apiVersion: batch.tensorstack.dev/v1beta1
kind: XGBoostTrainingJob
metadata:
  name: xgboost-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - resources:
              limits:
                cpu: 4
                memory: 4Gi
              requests:
                cpu: 2
                memory: 2Gi

共享内存

在进行多节点任务时,可以按照如下方式修改 XGBoostTrainingJob 来使用共享内存:

apiVersion: batch.tensorstack.dev/v1beta1
kind: XGBoostTrainingJob
metadata:
  name: xgboost-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
          - ...
            volumeMounts:
              - mountPath: /dev/shm
                name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
              sizeLimit: "1Gi"

在该例中:

  • spec.replicaSpecs[*].template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.replicaSpecs[*].template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

环境变量

副本环境变量通过 spec.replicaSpecs[*].template.spec.containers[*].env 字段指定。XGBoostTrainingJob 支持直接设置环境变量内容和引用其他资源字段作为环境变量两种方式。

在下面的示例中,XGBoostTrainingJob 给 worker 副本设置了两个环境变量:ENV_DIRECTENV_REFERENCED。其中 ENV_DIRECT 环境变量被直接设置为 env-valueENV_REFERENCED 环境变量引用了 secret-name Secret 的 key-in-secret 字段的内容。

apiVersion: batch.tensorstack.dev/v1beta1
kind: XGBoostTrainingJob
metadata:
  name: xgboost-example
spec:
  replicaSpecs:
    - type: worker
      replicas: 4
      template:
        spec:
          containers:
            - env:
              - name: ENV_DIRECT
                value: env-value
              - name: ENV_REFERENCED
                valueFrom:
                  secretKeyRef:
                    name: secret-name
                    key: key-in-secret

重启机制

XGBoostTrainingJob 的 spec.replicaSpec[*].template 字段使用 PodTemplate 的规范填写,但是 Pod 的重启策略并不能满足 XGBoostTrainingJob 的需求,所以 XGBoostTrainingJob 使用 spec.replicaSpec[*].restartPolicy 字段覆盖 spec.replicaSpec[*].template 中指定的重启策略。

可选的重启策略有以下四种:

  • Never:不重启
  • OnFailure:失败后重启
  • Always:总是重启
  • ExitCode:特殊退出码重启

使用 Never 重启策略时,Job 的副本失败后不会重启。如果需要调试代码错误,可以选择此策略,便于从副本中读取训练日志。

ExitCode 是一种比较特殊的重启策略,它将失败进程的返回值分为两类:一类是由于系统环境原因或用户操作导致的错误,此类错误可以通过重启解决;另一类是代码错误或者其他不可自动恢复的错误。可重启的退出码包括:

  • 130(128+2):使用 Control+C 终止容器运行。
  • 137(128+9):容器接收到 SIGKILL 信号。
  • 143(128+15):容器接收到 SIGTERM 信号。
  • 138:用户可以自定义这个返回值的含义。如果用户希望程序在某处退出并重启,可以在代码中写入这个返回值。

如果因为某种原因(例如代码错误或者环境错误并且长时间没有修复),XGBoostTrainingJob 不断地失败重启却无法解决问题,这会导致集群资源的浪费。用户可以通过设置 spec.runPolicy.backoffLimit 字段来设置副本的最大重启次数。重启次数为所有副本共享,即所有副本重启次数累计达到此数值后,副本将不能再次重启。

成功和失败

在 XGBoost 分布式训练框架中,副本有 2 种类型:Master 和 Worker,其中 Master 是主节点。当分布式训练的主节点成功结束时,XGBoost 分布式训练成功;反之,当分布式训练的主节点执行失败时,XGBoost 分布式训练失败。

但是主节点的失败有时可能是因为环境因素导致的,比如集群网络断连、集群节点崩溃等等,此类原因导致的失败应该被允许自动恢复。针对这一情况,XGBoostTrainingJob 允许副本重启(请参阅重启机制),并设定了重启次数限制(由 spec.runPolicy.backoffLimit 字段指定),当副本重启次数达到上限后,如果主节点再次失败,则训练失败。此外,XGBoostTrainingJob 可以设置最长执行时间(由 spec.runPolicy.activeDeadlineSeconds 字段指定),当超过这个执行时间后,训练失败。

如果 XGBoostTrainingJob 在没有超过重启次数和没有超过最长执行时间的情况下成功完成了主节点的运行,则训练成功。

清除策略

在训练结束后,可能有些副本仍处于运行状态。这些运行的副本仍然会占用集群资源,XGBoostTrainingJob 提供清除策略,在训练结束后删除这些训练节点。

XGBoostTrainingJob 提供以下三种策略:

  • None:不删除副本。
  • All:删除所有副本。
  • Unfinished:只删除未结束的副本。
`None` 策略主要用于训练脚本调试阶段。如果需要从副本中读取训练日志,则可以选用此策略。但由于这些副本可能占用资源并影响后续训练,建议你在调试完毕后手动删除这些副本或删除整个 XGBoostTrainingJob。

调度器

目前 XGBoostTrainingJob 支持使用以下两种调度器:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler 调度器

调度器通过 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 的默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,XGBoostTrainingJob 启用 T9k Scheduler 调度器,将副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50

调试模式

XGBoostTrainingJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。

该模式可以通过 spec.runMode.debug 字段来设置:

  • spec.runMode.debug.enabled 表示是否启用调试模式。
  • spec.runMode.debug.replicaSpecs 表示如何配置各个副本的调试模式:
    • spec.runMode.debug.replicaSpecs.type 表示作用于的副本类型。
    • spec.runMode.debug.replicaSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.debug.replicaSpecs.command 表示副本在等待调试的时候执行的命令,默认为 sleep inf
    • 如果不填写 spec.runMode.debug.replicaSpecs 字段,则表示所有副本都使用默认设置。

在下面的示例中:

  • 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了调试模式,副本使用默认调试设置,即不跳过 InitContainer,并执行 sleep inf
# 示例一
...
spec:
  runMode:
    debug:
      enabled: true
      replicaSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    debug:
      enabled: true

暂停模式

XGBoostTrainingJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。

该模式可以通过 spec.runMode.pause 字段来设置:

  • spec.runMode.pause.enabled 表示是否启用暂停模式。
  • spec.runMode.pause.resumeSpecs 表示结束暂停后,如何恢复各个副本:
    • spec.runMode.pause.resumeSpecs.type 表示作用于的副本类型。
    • spec.runMode.pause.resumeSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.pause.resumeSpecs.commandspec.runMode.pause.resumeSpecs.args 表示副本在恢复运行时候执行的命令,默认使用 spec.replicaSpecs[0].template 中的命令。
    • 如果不填写 spec.runMode.pause.resumeSpecs 字段,则表示所有副本都使用默认设置。

用户可以随时修改 spec.runMode.pause.enabled 来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs,所以如果有暂停 XGBoostTrainingJob 的需求,请提前设置好恢复设置。

在下面的示例中:

  • 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行 spec.replicaSpecs[0].template 中设置的命令。
# 示例一
...
spec:
  runMode:
    pause:
      enabled: true
      resumeSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    pause:
      enabled: true

XGBoostTrainingJob 状态

XGBoostTrainingJob 的状态和阶段

status.conditions 字段用于描述当前 XGBoostTrainingJob 的状态,包括以下 6 种类型:

  1. Initialized:XGBoostTrainingJob 已经成功创建各子资源,完成初始化。
  2. Running:开始执行任务。
  3. ReplicaFailure:有一个或多个副本出现错误。
  4. Completed:XGBoostTrainingJob 成功。
  5. Failed:XGBoostTrainingJob 失败。
  6. Paused:XGBoostTrainingJob 进入暂停模式,所有副本都已删除或正在删除。

status.phase 字段用于描述当前 XGBoostTrainingJob 所处的阶段,XGBoostTrainingJob 的整个生命周期主要有以下7个阶段:

  1. Pending:XGBoostTrainingJob 刚刚创建,等待副本启动。
  2. Running:副本创建成功,开始执行任务。
  3. Paused:XGBoostTrainingJob 进入暂停模式。
  4. Resuming:XGBoostTrainingJob 正从暂停模式中恢复运行。恢复运行后,切换为 Running 阶段。
  5. Succeeded:XGBoostTrainingJob 成功。
  6. Failed:XGBoostTrainingJob 失败。
  7. Unknown:控制器无法获得 XGBoostTrainingJob 的阶段。

在下面的示例中,XGBoostTrainingJob 所有子资源创建成功,所以类型为 Initalizedcondition 被设为 True;XGBoostTrainingJob 运行结束,所以类型为 Completedcondition 被设置为 True;XGBoostTrainingJob 的训练成功结束,所以类型为 Completedcondition 被设置为 True(原因是 The job has finished successfully.)。当前 XGBoostTrainingJob 运行阶段为 Succeeded

...
status:
  conditions:
    - lastTransitionTime: "2023-12-19T02:40:25Z"
      message: The job has been initialized successfully.
      reason: '-'
      status: "True"
      type: Initialized
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "False"
      type: Running
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "False"
      type: Failed
    - lastTransitionTime: "2023-12-19T02:53:14Z"
      message: The job has finished successfully.
      reason: Succeeded
      status: "True"
      type: Completed
    - lastTransitionTime: "2023-12-19T02:40:25Z"
      message: All pods are running normally.
      reason: '-'
      status: "False"
      type: ReplicaFailure
  phase: Succeeded

副本的状态

status.tasks 字段用来记录副本的状态,记录的内容主要包括:

  • 副本的重启次数(同一种角色的副本的重启次数之和);
  • 副本当前的运行阶段,此处的“运行阶段”在 K8s Pod 的 5 个阶段的基础上,添加了 CreatingDeleted 分别表示正在创建和已删除;
  • 副本在集群中对应的 Pod 的索引信息。

在下面的示例中,XGBoostTrainingJob 创建了 1 个角色为 worker 的副本,当前均处于 Succeeded 阶段,运行在 mnist-trainingjob-5b373-worker-0 这个 Pod 上。

...
status:
  tasks:
  - replicas:
    - containers:
      - exitCode: 0
        name: pytorch
        state: Terminated
      name: mnist-trainingjob-5b373-worker-0
      phase: Succeeded
      uid: d39f91d6-9c48-4c57-bb71-4131226395b6
    type: worker

副本状态统计

status.aggregate 字段统计了各个阶段的副本数量。

在下面示例中,XGBoostTrainingJob 创建了 3 个副本,其中 1 个处于 Pending 阶段,另外两个处于 Running 阶段。

...
status:
  aggregate:
    creating: 0
    deleted: 0
    failed: 0
    pending: 1
    running: 2
    succeeded: 0
    unknown: 0
...

MPIJob

OpenMPI 是一个开源的 MPI(Message Passing Interface)协议的实现项目。

MPIJob 是一种使用 OpenMPI 进行分布式计算的 T9k Job,此资源让你能够方便地在集群环境中使用 OpenMPI 进行训练。

创建 MPIJob

下面的 MPIJob 示例创建了 5 个执行副本,每个执行副本启动 3 个进程,运行随机游走程序:

apiVersion: batch.tensorstack.dev/v1beta1
kind: MPIJob
metadata:
  name: mpi-example
spec:
  worker:
    replicas: 5
    extraMPIArgs:
      - -N
      - "3"
      - --enable-recovery
      - --max-restarts
      - "100"
      - --allow-run-as-root
      - -bind-to
      - none
    cmd:
      - ./random_walk
      - "20"
      - "40"
      - "2"
    template:
      spec:
        containers:
          - name: mpi-worker
            image: t9kpublic/mpi-tutorial:2021022-2
            resources:
              limits:
                cpu: 100m
              requests:
                cpu: 50m
            workingDir: /usr/local/code
  mca:
    btl: ^openib
  runPolicy:
    cleanUpWorkers: true
  ssh:
    sshdPath: /usr/sbin/sshd
  mpiHome: /usr/local

在该例中:

  • 创建 5 个执行副本(由 spec.worker.replicas 字段指定)。
  • spec.worker.template 字段沿用 PodTemplate 的规约,配置执行副本和启动副本的环境。每个执行副本包含一个名为 mpi-worker 的容器(为了确定用于执行 MPI 进程的容器,执行副本定义中必须有一个名为 mpi-worker 的容器)。mpi-worker 容器创建后执行 sshd 命令并等待启动副本连接,所以此容器会忽略 PodTemplate 定义中的 commandargs 字段(因此该例中没有填写这两个字段)。
  • 在执行副本准备完毕后,启动副本向执行副本发送启动命令,令执行副本创建 3 个 MPI 进程,这些进程分别执行 ./random_walk 20 40 2(由 spec.worker.cmd 字段指定)命令。
  • 在训练过程中不使用 Infiniband 进行通信(由 spec.mca.btl 字段指定)。
  • 在训练结束后自动清除副本(由 spec.runPolicy.cleanUpWorkers 字段指定)来释放集群资源。
  • sshd 的路径为 /user/sbin/sshd(由 spec.ssh.sshdPath 字段指定,使用该字段的原因是 sshd 程序必须使用绝对路径调用,所以需要其具体路径)。
  • MPI 安装在 /usr/local 处(由 spec.mpiHome 字段指定,使用该字段的原因是 mpirun 的有些功能需要知道 MPI 的根目录地址才能正确运行)。

运行 Horovod 训练脚本

使用 Horovod 框架的分布式训练脚本也可以使用 MPIJob 进行训练。

在 MPIJob 中需要执行以下操作:

  1. spec.worker.template.spec.containers[mpi-worker].env 字段中添加 NCCL_DEBUG
  2. spec.mca 字段中添加 pml:ob1btl:^openib

下面是使用 MPIJob 执行 Horovod 框架的分布式训练脚本的示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: MPIJob
metadata:
  name: mpi-example
spec:
  mca:
    btl: ^openib
    pml: ob1
  worker:
    template:
      spec:
        containers:
          - name: mpi-worker
            env: 
            - name: "NCCL_DEBUG"
              value: "INFO"
...

副本设置

MPIJob 副本运行环境和命令可以通过 spec.worker.template 进行配置,可配置内容包括镜像、运行命令、资源配置、环境变量等。

资源配置

副本资源配置通过 spec.worker.template.spec.containers[*].resources 字段指定。

MPIJob 的资源配置包括两部分:

  • 资源请求量(requests):创建该副本时,节点上至少应具有这些数量的资源。如果集群中所有节点都不满足副本的资源请求量,则副本的创建可能会被阻塞;或者如果副本的优先级较高,则有可能驱逐节点上其他工作负载来为副本空出可用的资源。
  • 资源上限(limits):该副本在运行期间,最多可以使用的资源数量。比如:如果副本在运行时申请分配超过上限的内存,则有可能出现 OOMKILLED 错误。(注:资源上限不能小于资源请求量)

在下面的示例中,MPIJob 中每个副本设置了以下资源配置:

  • 资源请求量:2 个 cpu 核心、2Gi 内存;
  • 资源上限:4 个 cpu 核心、4Gi 内存。
apiVersion: batch.tensorstack.dev/v1beta1
kind: MPIJob
metadata:
  name: mpi-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
        - resources:
            limits:
              cpu: 4
              memory: 4Gi
            requests:
              cpu: 2
              memory: 2Gi

共享内存

在进行多节点任务时,可以按照如下方式修改 MPIJob 来使用共享内存:

apiVersion: batch.tensorstack.dev/v1beta1
kind: MPIJob
metadata:
  name: mpi-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
        - ...
          volumeMounts:
            - mountPath: /dev/shm
              name: dshm
        volumes:
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: "1Gi"

在该例中:

  • spec.worker.template.spec.volumes 中增加一项,名称为 dshm,其中限制共享内存最大为 1Gi
  • spec.worker.template.spec.containers[*].volumeMounts 中增加一项,将上述 dshm 绑定到 /dev/shm 路径。

环境变量

副本环境变量通过 spec.worker.template.spec.containers[*].env 字段指定。MPIJob 支持直接设置环境变量内容和引用其他资源字段作为环境变量两种方式。

在下面的示例中,MPIJob 给副本设置了两个环境变量:ENV_DIRECTENV_REFERENCED。其中 ENV_DIRECT 环境变量被直接设置为 env-valueENV_REFERENCED 环境变量引用了 secret-name Secret 的 key-in-secret 字段的内容。

apiVersion: batch.tensorstack.dev/v1beta1
kind: MPIJob
metadata:
  name: mpi-example
spec:
  worker:
    replicas: 4
    template:
      spec:
        containers:
          - env:
            - name: ENV_DIRECT
              value: env-value
            - name: ENV_REFERENCED
              valueFrom:
                secretKeyRef:
                  name: secret-name
                  key: key-in-secret

调度器

目前 MPIJob 支持使用以下两种调度器:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler

调度策略通过 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则使用 Kubernetes 的默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,MPIJob 启用 T9k Scheduler 调度器,将执行副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50

调试模式

MPIJob 支持调试模式。在该模式下,训练环境会被部署好,但不会启动训练,用户可以连入副本测试环境或脚本。

该模式可以通过 spec.runMode.debug 字段来设置:

  • spec.runMode.debug.enabled 表示是否启用调试模式。
  • spec.runMode.debug.replicaSpecs 表示如何配置各个副本的调试模式:
    • spec.runMode.debug.replicaSpecs.type 表示作用于的副本类型。
    • spec.runMode.debug.replicaSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.debug.replicaSpecs.command 表示副本在等待调试的时候执行的命令,launcher 的默认命令为 sleep infworker 的默认命令为 /usr/bin/sshd -D
    • 如果不填写 spec.runMode.debug.replicaSpecs 字段,则表示所有副本都使用默认设置。

在下面的示例中:

  • 示例一:开启了调试模式,并配置 worker 跳过 InitContainer,并执行 sleep inf
  • 示例二:开启了调试模式,副本使用默认调试设置,即 worker 不跳过 InitContainer,并执行 /usr/bin/sshd -D
# 示例一
...
spec:
  runMode:
    debug:
      enabled: true
      replicaSpecs:
        - type: worker
          skipInitContainer: true
          command: ["sleep", "inf"]

---
# 示例二
...
spec:
  runMode:
    debug:
      enabled: true

暂停模式

MPIJob 支持暂停模式。在该模式下,删除(或不创建)副本,停止训练。

该模式可以通过 spec.runMode.pause 字段来设置:

  • spec.runMode.pause.enabled 表示是否启用暂停模式。
  • spec.runMode.pause.resumeSpecs 表示结束暂停后,如何恢复各个副本:
    • spec.runMode.pause.resumeSpecs.type 表示作用于的副本类型。
    • spec.runMode.pause.resumeSpecs.skipInitContainer 表示让副本的 InitContainer 失效,默认为 false
    • spec.runMode.pause.resumeSpecs.commandspec.runMode.pause.resumeSpecs.args 表示副本在恢复运行时候执行的命令,默认使用 spec.replicaSpecs[0].template 中的命令。
    • 如果不填写 spec.runMode.pause.resumeSpecs 字段,则表示所有副本都使用默认设置。

用户可以随时修改 spec.runMode.pause.enabled 来控制任务暂停,但是不可以更改 spec.runMode.pause.resumeSpecs,所以如果有暂停 MPIJob 的需求,请提前设置好恢复设置。

在下面的示例中:

  • 示例一:开启了暂停模式,并配置 worker 跳过 InitContainer,并执行 /usr/bin/sshd
  • 示例二:开启了暂停模式,副本使用默认恢复设置,即不跳过 InitContainer,并执行 spec.replicaSpecs[0].template 中设置的命令。
# 示例一
...
spec:
  runMode:
    pause:
      enabled: true
      resumeSpecs:
        - type: worker
          skipInitContainer: true
          command: ["/usr/bin/sshd"]

---
# 示例二
...
spec:
  runMode:
    pause:
      enabled: true

MPIJob 状态

MPIJob 的状态和阶段

status.conditions 字段用于描述当前 MPIJob 的状态,包括以下 5 种类型:

  1. Initialized:MPIJob 已经成功创建各子资源,完成初始化。
  2. Running:开始执行任务。
  3. ReplicaFailure:有一个或多个副本出现错误。
  4. Completed:MPIJob 结束
  5. Failed:MPIJob 失败。
  6. Paused:MPIJob 进入暂停模式,所有副本都已删除或正在删除。

status.phase 字段用于描述当前 MPIJob 所处的阶段,MPIJob 的整个生命周期主要有以下几个阶段:

  1. Pending:MPIJob 刚刚创建,等待副本启动。
  2. Running:副本创建成功,开始执行任务。
  3. Paused:MPIJob 进入暂停模式。
  4. Resuming:MPIJob 正从暂停模式中恢复运行。恢复运行后,切换为 Running 阶段。
  5. Succeeded:MPIJob 结束
  6. Failed:MPIJob 失败。
  7. Unknown:控制器无法获得 MPIJob 的阶段。

在下面的示例中,MPIJob 所有子资源创建成功,所以类型为 Initalizedcondition 被设为 True;MPIJob 运行结束,所以类型为 Completedcondition 被设置为 True;但是 MPIJob 的训练结果是失败的,所以类型为 Failedcondition 被设置为 True。当前 MPIJob 运行阶段为 Failed

...
status:
  conditions:
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "The job has been initialized successfully."
      reason: "-"
      type: Initializing
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      message: "All pods are running normally."
      reason: "-"
      type: Running
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "False"
      message: "All pods are running normally."
      reason: "-"
      type: ReplicaFailure
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "False"
      message: "The job exited with an error code."
      reason: "Failed"
      type: Completed
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "True"
      message: "The job exited with an error code."
      reason: "Failed"
      type: Failed
  phase: Failed

副本的状态

status.tasks 字段用来记录副本的状态,记录的内容主要包括:

  • 副本的重启次数(同一种角色的副本的重启次数之和)
  • 副本当前的运行阶段
  • 副本在集群中对应的 Pod 的索引信息

在下面的示例中,MPIJob 创建了 1 个启动副本和 2 个执行副本。当前均处于 Running 阶段,分别运行在 mpi-example-worker-0mpi-example-worker-1 这 2 个 Pod 上;启动副本当前处于 Running 阶段,运行在 mpi-example-launcher Pod 上。

...
status:
  tasks:
  - type: launcher
    restartCount: 0
    status:
    - phase: Running
      name: mpi-example-launcher
      uid: 66634db2-35e7-4641-a4dc-adbd5479734e
      containers: []
  - type: worker
    restartCount: 0
    status:
    - phase: Running
      name: mpi-example-worker-0
      uid: e3ec2ee3-6645-4e21-993f-1e472b94e0ae
      containers: []
    - phase: Running
      name: mpi-example-worker-1
      uid: 908a93f0-7b8b-491e-85d5-3da0abcb4ca4
      containers: []

副本状态统计

status.aggregate 字段统计了各个阶段的副本数量。

在下面示例中,MPIJob 创建了 3 个副本,其中 1 个处于 Pending 阶段,另外两个处于 Running 阶段。

...
status:
  aggregate:
    creating: 0
    deleted: 0
    failed: 0
    pending: 1
    running: 2
    succeeded: 0
    unknown: 0
...

下一步

BeamJob

BeamJob 用于在集群中通过 Apache Beam Python SDK 运行分布式计算任务,并提供多种底层计算引擎,目前支持 Apache Flink,未来会支持 Apache Spark

创建 BeamJob

下面是一个基本的 BeamJob 配置示例,负责统计输入文件中的英文单词出现次数,并将结果存储在输出文件中:

apiVersion: batch.tensorstack.dev/v1beta1
kind: BeamJob
metadata:
  name: beamjob-example
spec:
  flinkClusterTemplate:
    spec:
      flinkVersion: 1.10.1
      image:
        name: t9kpublic/flink:1.10.1
      jobManager:
        accessScope: Cluster
        resources:
          limits:
            cpu: "100m"
            memory: "1Gi"
      taskManager:
        replicas: 2
        resources:
          limits:
            cpu: "100m"
            memory: "2Gi"
      flinkProperties:
        taskmanager.numberOfTaskSlots: "1"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - image: t9kpublic/apache_beam_python3.7_sdk:2.22.0
            name: submit-job
            command:
              - "python3"
            args:
              - "-m"
              - "apache_beam.examples.wordcount"
              - "--input"
              - "/mypvc/input.txt"
              - "--output"
              - "/mypvc/output.txt"
            volumeMounts:
              - mountPath: "/mypvc"
                name: mypvc
          volumes:
            - name: mypvc
              persistentVolumeClaim:
                claimName: mypvc
          restartPolicy: OnFailure

在该例中:

  • 你需要准备好一个名为 mypvc 的 PVC,并将名为 input.txt 的输入文件存放在 PVC 的根路径下。
  • flinkClusterTemplate 字段描述了所要创建的 Flink 集群,其中包含 1 个 Job Manager{target=_blank},所使用的 Flink 版本为 1.10.1。
  • jobTemplate 字段描述了用户如何将所要运行的任务提交给 Flink 集群,其中所使用的 Apache Beam Python SDK 版本为 2.22.0,所运行的程序为 Apache Beam Python SDK 自带的单词统计程序 apache_beam.examples.wordcount

BeamJob 状态

BeamJob 的状态和阶段

status.conditions 字段用于描述当前 BeamJob 的状态,包括以下 2 种类型:

  • ClusterRunning:Flink 集群正在运行
  • JobRunning:用户提交的任务正在运行

status.phase 字段用于描述当前 BeamJob 所处的阶段,BeamJob 的整个生命周期主要有以下几个阶段:

  1. Initializing:BeamJob 刚刚创建,等待 Flink 集群启动。
  2. Running:Flink 集群已启动,用户提交的任务正在运行。
  3. Succeeded:BeamJob 成功。
  4. Failed:BeamJob 失败。
  5. Unknown:控制器执行错误,导致未能获取 BeamJob 当前运行阶段。

status.jobURL 字段是 Flink 集群的 Web UI 中用户提交的此次任务对应的详细信息页面。

在下面的示例中,Flink 集群已启动,所以类型为 ClusterRunningcondition 被设置为 True;用户所提交的任务正在运行,所以类型为 JobRunningcondition 被设置为 True。当前 BeamJob 运行阶段为 Running,如需在 Flink 集群的 Web UI 中查看任务的详细信息,请跳转至 jobURL

...
status:
  conditions:
    - lastTransitionTime: "2021-01-18T02:36:09Z"
      status: "True"
      type: ClusterRunning
    - lastTransitionTime: "2021-01-18T02:36:31Z"
      status: "True"
      type: JobRunning
  phase: Running
  jobURL: /t9k/flink-cluster/beamjob-example-flinkcluster/namespace/t9k-example/#/job/c9f62e4d61d089f351ab1f8b29e1df32/overview/

status.flinkClusterStatus 字段用来记录 Flink 集群的状态,包括所有 Job Manager 和 Task Manager 的运行阶段以及对应的 Pod 索引。

在下面的示例中,BeamJob 创建的 Flink 集群包括 1 个 Job Manager 和 2 个 Task Manager,均处于 Running 阶段(记录在 phase 字段中),对应的 Pod 的索引信息记录在 reference 字段中(包括 Pod 的名称和 UID)。

...
status:
  flinkClusterStatus:
    jobManagerStatus:
    - phase: Running
      reference:
        name: beamjob-example-flinkcluster-jobmanager-0
        uid: 21c67b2d-88d4-4b0a-9044-2311edee5e83
    taskManagerStatus:
    - phase: Running
      reference:
        name: beamjob-example-flinkcluster-taskmanager-0
        uid: c120c704-0730-49c8-8995-5fb719840af7
    - phase: Running
      reference:
        name: beamjob-example-flinkcluster-taskmanager-1
        uid: f1326d53-c5b6-4869-b5e9-8c35b7a7637d

用户提交任务的状态

status.jobStatus 字段用来记录用户所提交的任务的状态,包括运行阶段以及对应的 Pod 索引。

在下面的示例中,BeamJob 创建的用户任务仅包含 1 个 Pod,处于 Succeeded 阶段(记录在 phase 字段中),对应的 Pod 的索引信息记录在 reference 字段中(包括 Pod 的名称和 UID)。用户所提交的任务运行可能出现错误并多次重试,因此 status.jobStatus 字段可能包含多个 Pod。

...
status:
  jobStatus:
  - phase: Succeeded
    reference:
      name: beamjob-example-batchjob-szsn8
      uid: 9aed0159-fe2a-4096-99a7-1c89af5a6f0e

清除策略

在 BeamJob 成功或失败后,所创建的 Flink 集群仍然在运行,占据较多的计算资源。在下面的示例中,你可以在 spec.runPolicy 字段中将 cleanUpCluster 设置为 true,在 BeamJob 运行完毕(无论成功还是失败)之后删除 Flink 集群。

...
spec:
  runPolicy:
    cleanUpCluster: true
...

调度器

目前 BeamJob 支持两种调度器:

  1. Kubernetes 的默认调度器
  2. T9k Scheduler 调度器

调度器通过 spec.scheduler 字段设置:

  • 不设置 spec.scheduler 字段,则默认使用 Kubernetes 的默认调度器。
  • 设置 spec.scheduler.t9kScheduler 字段,则使用 T9k Scheduler 调度器。

在下面的示例中,BeamJob 启用 T9k Scheduler 调度器,将副本插入 default 队列中等待调度,其优先级为 50。

...
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50
...

账户和安全

TensorStack AI 平台提供全面、系统性的安全支持,以保障平台本身、平台提供的各种工具(例如模型构建控制台)和用户的各种工作负载(例如训练任务)的安全。

账户

账户是用户在 TensorStack AI 平台身份和权限的代表。

在使用 TensorStack AI 平台前,用户需要先联系集群管理员为其创建一个平台账户。

API Key

在使用浏览器场景下(例如使用模型构建控制台),用户能够直接、同步地参与到身份认证和授权流程。用户可以方便地通过交互式的方式提供安全凭证(用户名 + 密码)来完成认证和授权,并随后通过 Cookie + Access Token 建立安全的交互过程。

但是,还有其他环境或者场景不适合采用前述方式。例如,用户通过命令行(环境受限,无法使用浏览器)或者在自动化脚本中向服务器发送请求,此时要求“用户同步进行交互”来获得访问令牌是非常不便捷的;或者,在此过程中需要通过客户程序输入密码,可能造成密码泄漏。同时,有些场景下,我们希望能够只授予客户端部分权限,但直接使用前述 access token 或者 Cookie 并不能更进一步缩小权限。

API Key 是 TensorStack AI 平台应对上述问题的解决方案。它是一种可撤销的、异步的、持久的安全授权方式,具有以下特点:

  • 可以长期持有(适合在脚本中使用)
  • 不会泄漏账户信息(无需使用用户名和密码)
  • 可以选择性地包含账户的部分权限
  • 方便在脚本程序、命令行工具等“非交互场景”进行集成使用
  • 可以随时方便地取消该授权

下一步

项目

项目(Project)是 TensorStack AI 平台为了有效使用集群资源,实现多用户、多项目同时、安全、共享使用集群而提供的机制;它是一个 CRD。

它具有以下特征:

  • 每个项目有一个项目管理员,他可以管理项目的成员
  • 只有项目的管理员和成员可以在项目中执行操作。
  • 每个项目对应一个同名的 Kubernetes 命名空间(Namespace),项目的成员拥有当前命名空间中几乎所有 K8s 资源的操作权限。

项目定义

以下是一个项目的定义(Custom Resource)示例:

apiVersion: tensorstack.dev/v1beta1
kind: Project
metadata:
spec:
  networkPolicy:
    template:
      spec:
        egress:
          - to:
              - namespaceSelector:
                  matchLabels:
                    kubernetes.io/metadata.name: t9k-system
                podSelector:
                  matchLabels:
                    app: security-console-server
        ingress:
          - from:
              - namespaceSelector:
                  matchLabels:
                    kubernetes.io/metadata.name: t9k-system
        policyTypes:
          - Ingress
          - Egress
    useDefaultTemplate: false
  quotaProfile: demo
  resourceQuota:
    template:
      spec:
        hard:
          cpu: '200'
          memory: 1280Gi
          nvidia.com/gpu: '18'
          persistentvolumeclaims: 200Gi
          pods: 1k

注:普通用户(包括项目管理员)不可修改上述项目配置,这里仅用该配置进行演示和讲解。

在上述示例中:

  • 该项目中设置以下网络策略:
    • 该项目中的工作负载可以访问 t9k-system 命名空间中的 security-console-server 服务(由字段 spec.networkPolicy.template.spec.egress 字段指定)。
    • 该项目中的服务可以被 t9k-system 命名空间的任一工作负载访问(由字段 spec.networkPolicy.template.spec.ingress 字段指定)。
  • 该项目使用 demo 资源配额模板。

资源配额与配额模板

一个项目的资源配额(由 spec.resourceQuota 字段指定)表示:当前项目中所能使用的资源上限,包括但不限于 CPU、内存、GPU 和 Pod 数量。

值得说明的一点:项目的资源配额中关于 CPU、内存、GPU、Pod 等资源数量的限制都直接作用于 Pod。即如果你创建一个 T9k Job,它即将创建的 pod 需要申请超过项目资源配额的资源数量,则 T9k Job 会被成功创建,但是 T9k Job 创建 Pod 的请求会被拒绝。

管理员可以使用配额模板批量设置或修改项目的资源配额。项目控制器会自动查找配额模板(由 spec.quotaProfile 字段指定)的内容,据此同步项目的资源配额。

网络策略

管理员可以通过项目的网络策略(由字段 spec.networkPolicy 字段指定)实现以下功能:

  1. 禁止普通用户访问系统级应用,避免保密信息泄漏和系统遭到恶意攻击。
  2. 阻断项目间通信,避免项目之间的互相干扰。
  3. 限定项目的访客 IP,构建安全的项目环境。

项目授权

项目授权信息存储在特定的授权服务器而非项目定义中。

普通用户(包括项目管理员)可以在安全控制台(Security Console)查看自己所在和所管理的项目以及项目的成员。

项目管理员可以通过安全控制台编辑项目成员。

项目的使用范围

项目可以被应用到 TensorStack AI 平台的模型构建、模型部署和工作流三个模块,集群管理员可以设置一个项目的使用范围。

目前项目可选的使用范围包括:

  • build:用户可以在模型构建和工作流模块中使用此项目。
  • deploy:用户可以在模型部署模块中使用此项目。

一个项目可以同时设置上述两个使用范围。

项目成员管理

项目管理员可以在安全控制台设置项目成员:

  • 项目成员可以是用户或用户组,一个用户组被设置为项目成员表示该组中的所有用户都可以使用该项目。
  • 设置项目成员时,可以对每一个成员单独设置项目的使用范围,对成员设置的项目使用范围应为项目所有使用范围的子集。

下一步

告警通知

当集群或者用户的工作负载出现异常情况时,Tensorstack AI 平台会产生告警信息。通过告警信息,用户可以及时发现、处理问题。

有两种查看告警信息的方法:

  • 在 Tensorstack Web UI 查看告警信息
  • 通过邮件接收告警信息:提前在 Tensorstack Web UI 订阅某些告警信息,当产生这些告警信息时,系统会将告警信息发送到你的订阅邮件

下面是查看告警信息的页面:

check-alerts-main-page

下面是订阅告警信息的页面:

subscribe-alert-main-page

告警信息列表

系统可以产生下列告警信息

Pod 相关

  • KubePodCrashLooping:Pod container 处于 CrashLooping 状态。
  • KubeImagePullError:Pod 容器无法拉取镜像(错误原因是 ImagePullError 或 ErrImagePull)
  • KubeContainerOOM:容器的内存溢出,原因可能是超出容器的资源限制或节点的内存上限

资源配额相关

  • KubeQuotaAlmostFull:资源配额几乎耗尽了,需要减少资源使用或增加资源配额
  • KubeQuotaFullyUsed:资源配额已耗尽,需要减少使用或增加配额。在资源配额耗尽期间,系统拒绝创建 Pod 的行为
  • KubeQuotaExceeded:资源请求总量超过了资源配额

存储相关

KubePersistentVolumeFillingUp:PersistentVolume 存储空间已使用 97%。

T9k 工作负载相关

  • T9kMLServiceNotReady:未处于暂停状态的 MLService 超过 15 分钟还未就绪
  • T9kSimpleMLServiceNotReady:SimpleMLService 超过 15 分钟还未就绪
  • T9kJobFailed:Job 运行失败。
  • T9kNotebookNotReady:未处于暂停状态的 Notebook 超过 15 分钟还未就绪
  • T9kTensorBoardNotReady:未处于暂停状态的 TensorBoard 超过 15 分钟还未就绪

项目权限

用户只能查看、订阅他有权访问的项目中的告警信息。

下一步

计算资源

运行集群中的工作负载需要使用计算资源。TensorStack AI 平台提供了完善的计算资源分配和管理机制,支持使用 GPU、高速网卡等扩展设备资源,并提供资源使用监控、统计功能帮助用户随时获得工作负载的资源使用情况。

资源请求和限制

资源请求(requests)和限制(limits)是一种管理资源的重要机制,用于确保集群中的工作负载可以按照预期方式使用计算资源。资源请求(spec.containers[].resources.requests 字段)定义了工作负载的一个容器所需的最小资源量,资源限制(spec.containers[].resources.limits 字段)则定义了该容器所允许使用的最大资源量。集群的调度器根据这些参数进行资源分配,确保各个容器在共享主机资源时不会相互干扰或过度使用资源。

容器会被分配请求(requests)的资源量;如果容器所在的节点有足够的可用资源,容器可以使用超出请求(requests)的资源量,但不可使用超出限制(limits)的资源量。例如,当容器中的进程尝试使用超出限制的内存(memory)资源量时,系统会将尝试申请内存的进程终止,并触发内存不足(OOM)错误。

资源类型

资源类型包括 CPU、内存(memory)和扩展资源(extended resources):

  • CPU 的请求和限制以 Kubernetes CPU 为单位,1 个 Kubernetes CPU 等于 1 个物理 CPU 核心或 1 个虚拟核心,取决于节点是一台物理主机还是运行在某物理主机上的虚拟机。可以指定小数,例如 0.1100m1m = 1/1000),来使用核心的部分处理能力。

  • 内存的请求和限制以字节为单位。可以使用科学计数法、定点后缀(k、M、G、T、P 和 E)和 2 的幂后缀(Ki、Mi、Gi、Ti、Pi 和 Ei),例如以下表达式代表大致相同的值:

    128974848 129e6 129M 128974848000m 123Mi

  • 除了 CPU 和内存之外,Kubernetes 还支持扩展资源。扩展资源由管理员颁布(advertise),然后用户可以像使用 CPU 和内存一样使用扩展资源。GPU 是最重要的扩展资源类型之一,请参阅 GPU 使用

资源配额

资源配额是对于资源使用量的限制,旨在确保集群中有限的计算资源被公平、有效地分配和利用,以提高集群的整体效率。平台引入了以下两种资源配额:

  1. 项目配额:一个项目中的工作负载可以使用的资源总量。
  2. 队列配额:一个队列中的工作负载可以使用的资源总量。

当用户创建工作负载(如 Notebook、T9k Job 等)时,系统会检查项目和队列的资源使用量是否将超过各自的资源配额。如果超过配额,系统将拒绝该工作负载的创建。

请参阅项目资源配额队列资源配额

调度

调度(scheduling)是指将 Pod 分配给集群中的节点的过程。当用户创建一个工作负载时,由调度器决定将工作负载的 Pod 放置在哪些节点上运行。调度器会根据一系列的策略和条件来选择最合适的节点,并确保集群中的工作负载被有效地分配和管理。

节点上的每种资源类型都有特定的容量,调度器会确保对于每种资源类型,所有调度到某个节点上的 Pod 的资源请求量之和都小于该节点的可用容量。只有当所有资源请求(包括 CPU、内存和任何扩展资源)都被某个节点满足时,Pod 才能被调度到这个节点上。当资源请求无法被任何节点满足时,Pod 将保持 PENDING 状态。

除了资源需求,调度器还会根据自身的调度策略,以及节点的约束、亲和性、健康状态等来选择节点。

关于调度的更多细节,请参阅调度器

参考

下一步

调度器

调度器负责将工作负载的 Pod 放置在合适的节点上运行。平台支持 Kubernetes 的默认调度器 kube-scheduler,同时提供了功能更加强大的 T9k Scheduler。

这一部分将分别介绍这两种调度器的特性。

kube-scheduler

kube-scheduler 是 Kubernetes 集群的默认调度器,也是平台的默认调度器。

下面将介绍 kube-scheduler 的一些常见的特性。如果想要更全面地了解 kube-scheduler,请参阅官方文档 调度、抢占和驱逐

指定调度偏好

在创建 Pod 时,用户可以主动设置一些调度偏好,从而影响调度行为,约束 Pod 只能运行在指定的节点上。下面是一些可以设置的调度偏好。

NodeSelector

nodeSelector 用于约束 Pod 只能运行在指定的节点上,用户通过设置 nodeSelector 来表明用户希望目标节点所具有的节点标签。Pod 只会被调度到拥有用户所指定的每个标签的节点上。

设置方式:通过 Pod 的 spec.nodeSelector 字段来设置 nodeSelector。字段类型是 map,定义了节点标签。

示例:当 Pod YAML 设置了下列 nodeSelector 时,节点需要同时有标签 kubernetes.io/os: linuxkubernetes.io/arch: amd64

spec:
 nodeSelector:
   kubernetes.io/os: linux
   kubernetes.io/arch: amd64

亲和性

亲和性(affinity)用于影响 Pod 可以被调度到哪些节点上,亲和性分为两种类型:

  • 节点亲和性:功能类似于 nodeSelector,但它的表达能力更强,并且允许用户指定软规则。
  • Pod 间亲和性与反亲和性:使用户可以基于已经在节点上运行的 Pod 的标签来约束 Pod 可以调度到的节点,而不是基于节点上的标签。

节点亲和性

节点亲和性使用户可以基于节点标签来约束 Pod 可以调度到的节点。节点亲和性有两种类型:

  • requiredDuringSchedulingIgnoredDuringExecution: 调度器只有在规则被满足的时候才能执行调度。此功能类似于 nodeSelector, 但其语法表达能力更强。
  • preferredDuringSchedulingIgnoredDuringExecution: 调度器会尝试寻找满足对应规则的节点。如果找不到匹配的节点,调度器仍然会调度该 Pod。

设置方式:

  • 通过 Pod 的 spec.affinity.nodeAffinity 字段来设置节点亲和性。
  • 字段 API 参考

示例:

spec:
 affinity:
   nodeAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
       nodeSelectorTerms:
       - matchExpressions:
         - key: topology.kubernetes.io/zone
           operator: In
           values:
           - antarctica-east1
           - antarctica-west1
     preferredDuringSchedulingIgnoredDuringExecution:
     - weight: 1
       preference:
         matchExpressions:
         - key: node-role.kubernetes.io/compute
           operator: Exists

Pod 设置的上述 affinity 表明:

  1. 可调度的节点上必须有标签 topology.kubernetes.io/zone:antarctica-east1topology.kubernetes.io/zone:antarctica-west1
  2. 倾向于将 Pod 调度到含有标签键 node-role.kubernetes.io/compute 的节点上

Pod 间亲和性与反亲和性

Pod 间亲和性与反亲和性使用户可以基于已经在节点上运行的 Pod 的标签来约束 Pod 可以调度到的节点,而不是基于节点上的标签。与节点亲和性类似,Pod 间亲和性与反亲和性也分为 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 两种类型。

Pod 间亲和性与反亲和性的规则格式为“如果 X 上已经运行了一个或多个满足规则 Y 的 Pod, 则这个 Pod 应该(或者在反亲和性的情况下不应该)运行在 X 上”。 这里的 X 可以是节点、机架、云提供商可用区或地理区域或类似的拓扑域, Y 则是 Kubernetes 尝试满足的规则。

  • 拓扑域(X):用户会通过 topologyKey 来表达拓扑域(X)的概念,其值是系统用来标示域的节点标签键。以 topologyKey topology.kubernetes.io/zone 为例,标签键 topology.kubernetes.io/zone 对应的值相同的节点会被认为是同一拓扑域。
  • 规则(Y):通过 Pod affinity 字段定义的标签筛选规则。

设置方式:

  • 通过 spec.affinity.podAffinity 字段来设置 Pod 间亲和性,通过 spec.affinity.podAntiAffinity 字段来设置 Pod 间反亲和性。
  • 必须设置 topologyKey 字段,以表达拓扑域(X)
  • 字段 API 参考

示例:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: application-server
...
spec:
 template:
   metadata:
     labels:
       app: database
   spec:
     affinity:
       podAntiAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
             matchExpressions:
             - key: app
               operator: In
               values:
               - database
           topologyKey: topology.kubernetes.io/zone

上述 Deployment 为他的 Pod 设置了:

  • Pod 标签: app: database
  • Pod 间亲和性:保证所有 Pod 可以运行在相同拓扑域(标签键是 topology.kubernetes.io/zone)的节点上。

nodeName

Pod 含有 spec.nodeName 字段,用于表明 Pod 运行在哪个节点上。在创建 Pod 时:

  • 未设置 nodeName 字段:调度器会根据调度规则自动为 Pod 设置 nodeName。
  • 设置了 nodeName 字段:Pod 会绕过调度器的调度规则,直接被分配到指定的节点上运行。

下面是设置 nodeName 的 Pod 示例:

apiVersion: v1
kind: Pod
metadata:
 name: nginx
spec:
 containers:
 - name: nginx
   image: nginx
 nodeName: kube-01

上面的 Pod 只能运行在节点 kube-01 上。

污点与容忍度

污点(taint)是节点的一种属性,它可被用来使得某些类型的 Pod 不能被调度到该节点上(除非 Pod 明确说明其容忍该污点)。例如,当节点存在出现软硬件故障、网络不可用、磁盘空间不足等问题时,系统会自动为该节点添加一个污点。此外,当管理员发现节点存在问题或正在测试节点时,也可能为该节点添加污点。

容忍度(tolerations)是添加在一个 Pod 上的,如果 Pod 的容忍度与节点污点匹配,那么 Pod 可以被分配到含有污点的节点上。

节点污点示例

如果用户有查看节点的权限,用户可以使用 kubectl get node <nodeName> -o yaml 查看节点的污点。否则用户需要向管理员咨询节点的污点信息。

下面是一个示例,节点的 spec.taints 字段定义了污点信息:

spec:
  taints:
  - effect: NoSchedule
    key: key1
    value: value1

容忍度

创建 Pod 时,通过 spec.tolerations (API 参考) 字段来设置容忍度。

下面的容忍度设置可以忍受上述节点污点,从而 Pod 可以被调度到上述节点上:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"

Pod 拓扑分布约束

拓扑分布约束(topology spread constraints)用于控制 Pod 在集群内的拓扑分布,通过 Pod 的 spec.topologySpreadConstraints 字段进行设置。详情请见 Kubernetes 文档

下面是一个帮助用户理解拓扑分布约束的基本示例:

集群状态如下

  • 集群内有四个节点,通过节点标签 zone: <区域名> 划分为两个区域 zoneA 和 zoneB。
  • 含有标签 foo: bar 的 3 个 Pod 分别运行在 node1、node2、node3 中。

cluster-status

用户若想创建一个新的 Pod,并且希望新来的 Pod 均匀分布在现有的可用区域,则可以按如下设置其清单:

kind: Pod
apiVersion: v1
metadata:
 name: mypod
 labels:
   foo: bar
spec:
 topologySpreadConstraints:
 - maxSkew: 1
   topologyKey: zone
   whenUnsatisfiable: DoNotSchedule
   labelSelector:
     matchLabels:
       foo: bar
 containers:
 - name: pause
   image: registry.k8s.io/pause:3.1

spec.topologySpreadConstraints 下的子字段说明:

  • maxSkew:值是 1,表明不同节点区域之间 Pod 数量的最大差值为 1。
  • topologyKey:用于划分节点区域的节点标签的键值。
  • whenUnsatisfiable:值是 DoNotSchedule,表明调度器无法找到满足拓扑约束的方式时,将 Pod 保持在 pending 状态。
  • labelSelector:表明含有标签 foo: bar 的 Pod 会被统计,以确定相应拓扑域中 Pod 的数量。

综上,zoneA 上有 2 个 Pod,zoneB 上有 1 个 Pod,如果 mypod 被分配到 zoneA 上会导致 skew 为 2,违背 maxSkew=1,所以 mypod 会被调度器分配到 zoneB 中的 Node3 或 Node4 上。

优先级和抢占

kube-scheduler 和 T9k Scheduler 都有各自的优先级和抢占机制,用户可根据需求选用。

kube-scheduler 的优先级和抢占机制请参阅 Pod 优先级和抢占

参考

T9k Scheduler

T9k Scheduler 专为大规模分布式并行计算及异构资源集群设计,可以更加有效地管理 AI 集群的计算资源和计算任务。相比 kube-scheduler,T9k Scheduler 在对 AI 计算场景的支持方面进行了增强,并增加了额外的机制以对集群进行更加精细化管理,例如划分资源池,并对其设置配额及使用权限等。

这一部分将首先介绍 T9k Scheduler 引入的两个重要的管理计算资源的机制,同时也是 API 资源:队列(Queue)和 PodGroup。然后在它们的基础上说明 T9k Scheduler 的一些调度策略。

队列

队列(Queue)是 T9k Scheduler 引入的一项资源管理机制。如果用户在创建工作负载时使用 T9k Scheduler 调度,就需要通过一个队列申请计算资源。

队列设置

队列由管理员进行创建和设置,但作为用户也需要了解下面的这些设置。

使用权限

队列的使用权限用于控制哪些用户、组和项目可以使用这个队列。队列的使用权限通过两种方式进行设置:

  1. 管理员直接设置拥有队列使用权限的用户和组。
  2. 管理员设置队列的 spec.namespaceSelector(类型是 labelSelector)字段。

当满足下列任一条件时,用户有权限在特定项目下使用特定队列创建工作负载:

  • 用户拥有该队列的使用权限。
  • 该队列设置了 spec.namespaceSelector 字段,并且该项目对应的 namespace 的标签匹配这个 namespaceSelector

节点限制

队列的节点限制用于指定队列可用的集群工作节点(worker node),T9k Scheduler 只会将队列内的工作负载分配到这些特定的节点上。

spec.nodeSelector(类型是 labelSelector)字段用于设置队列的节点限制:

  • 字段未被设置时,队列可以使用集群内所有的节点。
  • 字段被设置时,队列可以使用节点标签匹配 nodeSelector 的节点。

在下面的示例中,队列可以使用节点标签包含 topology.kubernetes.io/zone: pekingtopology.kubernetes.io/zone: tianjin 的节点。

...
spec:
  nodeSelector:
    matchExpressions:
    - key: topology.kubernetes.io/zone
      operator: In
      values:
      - peking
      - tianjin

资源配额

队列的资源配额用于限制队列可以分配的资源量。如果用户创建的工作负载(例如 Notebook、T9k Job 等)会导致队列的资源使用量超出资源配额,那么系统会拒绝该工作负载的创建。

spec.quota 字段定义队列的资源配额,status.allocated 字段表示队列已经分配的资源量。

在下面的示例中,队列的 CPU 资源配额为 40,即队列中所有工作负载的 CPU 请求量(requests)之和不能超过 40,而当前已经分配了 38。如果此时用户使用该队列创建一个请求 {cpu: 4} 资源的 Notebook,则该 Notebook 会被拒绝创建。

...
spec:
  quota:
    requests:
      cpu: 40
status:
  allocated:
    cpu: "38"

优先级

spec.priority 字段定义队列的优先级,值类型是 int,范围是 [0,100],数值越大代表队列的优先级越高。队列的优先级会影响下列事件:

  • 优先级较高的队列会被优先分配资源。
  • 如果 T9k Scheduler 开启了资源抢占,则优先级较高的队列可以抢占低优先级队列使用的资源。

是否可被抢占资源

spec.preemptible 字段定义队列是否可以被其他队列抢占资源,字段值类型是 bool

  • true:队列可以被抢占资源。
  • false:队列不能被抢占资源。

开启/关闭

spec.closed 字段定义队列是否处于关闭状态。如果队列处于关闭状态,用户就不能创建使用该队列的工作负载。字段值类型是 bool

  • 字段未被设置或被设置为 false 时,队列处于开启状态。
  • 字段被设置为 true 时,队列处于关闭状态。

最大运行时长

最大运行时长会限制队列中的 Pod 的运行时长,如果 Pod 的存在时长(存在时长=当前时间 - 创建时间)超过最大运行时长,Pod 会被删除。

spec.maxDuration 字段定义队列的最大运行时长:

  • 值类型是 string,并且需要匹配正则表达式 ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$
  • 支持的时间单位:y, w(周), d, h, m, s, ms。
  • 示例:"3w","2h45m"。
  • 未设置时,队列中的 Pod 不受最大运行时长约束。

资源尺寸

资源尺寸(resource shape)会限制队列中的工作负载的资源请求量。当用户创建资源请求量超过资源尺寸的工作负载时,系统会拒绝该工作负载的创建。

spec.resourceShapeProfile 字段定义队列使用的资源尺寸模板,模板对应的资源尺寸详情存储在 ConfigMap t9k-system/resource-shapes 中。用户可以通过集群管理控制台查看队列的资源尺寸设置。

下一步

PodGroup

PodGroup 是 T9k Scheduler 引入的另一项资源管理机制。PodGroup 关联一组协同工作的 Pod,这些 Pod 共同完成一项计算任务(例如模型分布式训练),因此应作为一个整体被分配资源。PodGroup 是平台支持 coscheduling 机制的关键组成部分,可以为并行计算提供更好的支持,包括避免死锁场景和提高资源利用率。

通常情况下,用户可以通过创建 T9k Job 类型的工作负载来自动化地使用 PodGroup,但也可以手动创建 PodGroup。

规范

下面是一个基本的 PodGroup 示例:

apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
  name: chorus
  namespace: default
spec:
  minMember: 3
  priority: 50
  queue: default

在该例中:

  • 最小 Pod 数量是 3(由 spec.minMember 字段指定)。
  • PodGroup 的优先级是 50(由 spec.priority 字段指定)。
  • PodGroup 通过 default 队列(由 spec.queue 字段指定)申请计算资源。

队列

spec.queue 字段定义 PodGroup 使用的队列,默认值是 default

优先级

spec.priority 字段定义 PodGroup 的优先级,值类型是 int,范围是 [0,100],默认值是 0,值越大表示优先级越高。在同一个队列中,优先级高的 PodGroup 会被优先分配资源。

运行需求

spec.minMember 字段定义 PodGroup 运行需要的最小 Pod 数量,可选的 spec.roles 字段定义 PodGroup 运行需要的角色以及相应角色的最小 Pod 数量。也就是说,只有以下条件同时被满足,调度器才会为 PodGroup 分配资源:

  • PodGroup 中的 Pod 数量达到最小 Pod 数量。
  • 如果设置了 spec.roles 字段,对于每一个角色,PodGroup 中扮演该角色的 Pod 数量都达到相应的最小 Pod 数量。

在下面的示例中,PodGroup 的运行需求是:有 3 个 Pod,并且有 1 个角色为 master 的 Pod 和 1 个角色为 worker 的 Pod。

...
spec:
  minMember: 3
  roles:
  - name: master
    minMember: 1
  - name: worker
    minMember: 1

状态

PodGroup 的状态记录在 status 字段中。

status.conditions 字段记录了当前 PodGroup 的状态,包括以下两种类型:

  • GroupScheduled:PodGroup 是否已经被分配过资源
  • SufficientGroupMember:PodGroup 的 Pod 数量是否满足运行需求

status.allocated 字段记录了当前 PodGroup 被分配的资源量。

下列字段记录了当前 PodGroup 的处于不同阶段的 Pod 数量:

  • status.pending:处于 Pending 阶段的 Pod 数量
  • status.running:处于 Running 阶段的 Pod 数量
  • status.succeeded:处于 Succeeded 阶段的 Pod 数量
  • status.failed:处于 Failed 阶段的 Pod 数量
  • status.unknown:处于 Unknown 阶段的 Pod 数量

下面是一个正常运行中的 PodGroup 的 status 字段的示例:

...
status:
  allocated:
    cpu: 3
    memory: 600M
  conditions:
  - lastTransitionTime: "2023--17T13:54:02Z"
    reason: SufficientMemberPods
    status: "True"
    transitionID: 82ce5bf5-313d-4294-b44b-9b44ffd52213
    type: SufficientGroupMember
  - lastTransitionTime: "2023-12-17T13:48:16Z"
    message: Resources have been allocated to PodGroup
    reason: PodGroupScheduled
    status: "True"
    transitionID: c5a70cac-769c-44c4-a6ba-f4b1227cb135
    type: GroupScheduled
  running: 3

在该例中:

  • condition SufficientGroupMemberTrue,表示 PodGroup 满足最小成员约束,可以被分配资源。
  • condition GroupScheduledTrue,表示整个 PodGroup 已经被分配资源。
  • PodGroup 被分配了 3 个 CPU(核心)和 600MB 内存。
  • 有 3 个 Pod 处于 running 状态。

下一步

调度策略

T9k Scheduler 的一些调度策略介绍如下。

优先级和抢占

当集群资源不足,无法为所有 Pod 分配资源时,T9k Scheduler 会尝试为未被分配资源的 Pod(Pod A)抢占资源。Pod A 只能抢占所属队列的优先级比自己低的 Pod 的资源。资源抢占成功后,被抢占资源的 Pod 会被删除,Pod A 会被分配资源。

尽管被抢占资源的 Pod 会被直接删除,但是 Pod 所属的父资源(例如 Deployment、T9k Job 等)不会被删除,此时父资源会重新创建 Pod 来申请集群资源,从而可能触发新一轮的抢占行为。以此类推,一次抢占行为可能会触发一系列的抢占行为。因此需要通过设置队列的某些属性,来控制集群对队列的资源抢占行为,例如关闭生产级别队列的抢占开关。

假设集群总资源为 {cpu: 300},集群中有 4 个队列,当前状态如下:

队列名称资源配额优先级Pod
A{cpu: 200}1A1 {cpu: 50},A2 {cpu: 50},A3 {cpu: 50}
B{cpu: 100}1B1 {cpu: 50}
C{cpu: 50}2C1 {cpu: 50}
D{cpu: 200}2D1 {cpu: 50}

设想用户接下来进行的操作,并给出相应的结果和原因:

用户操作结果原因
在队列 B 中创建
Pod B2 {cpu: 50}
阻塞集群资源已全部分配且队列 B 优先级低,无法抢占其他队列的资源。
在队列 C 中创建
Pod C2 {cpu: 50}
阻塞超过队列 C 的资源配额。
在队列 D 中创建
Pod D2 {cpu: 50}
成功发生资源抢占行为,抢占队列 A 的资源:删除 Pod A3(优先级低于 A1、A2),创建 Pod D2。

公平排序

当两个队列的优先级相同时,T9k Scheduler 会根据队列的主导资源占比来确定资源分配顺序,主导资源占比较低的队列将优先获得资源分配。这里的主导资源占比指的是队列中资源占比最高的资源类型所占的比例。

假设队列 A 和 B 的优先级相同,资源配额及使用情况如下图所示:

fair-ranking

队列名称资源占比主导资源占比
A{cpu: 3/6, Memory: 5/8}5/8
B{cpu: 3/8, Memory: 1/2}1/2

根据前述公平排序原则,T9k Scheduler 会优先为队列 B 分配资源。

GPU 使用

许多执行深度学习相关任务的工作负载都需要使用 GPU 进行计算,这些任务包括数据集的预处理、模型训练以及模型推理等等。平台支持目前所有主流的 GPU 设备,并且可以轻松扩展以支持更多设备类型。

使用模式

独占模式

独占模式指的是在特定时间段内,GPU 仅供单一工作负载使用。

适用场景:GPU 被满负荷使用,并且计算需要尽快完成。例如训练 AI 模型。

共享模式

共享模式指的是单个物理 GPU 被多个工作负载同时使用。

适用场景:对于有些计算任务,例如交互式的 Notebook,小规模或者低使用量的模型推理服务,经常只需要使用 GPU 的部分计算能力。在这些情况下,让多个计算任务共享使用 GPU,将能极大地提升 GPU 的利用率。

共享 NVIDIA GPU

下面介绍 NVIDIA 提供的多种 GPU 共享和并发使用的机制,以支持不同的场景。

simplemlservice-detail
图 1:NVIDIA GPU 的并发(concurrency)使用机制。包括:1)应用程序级别(需要修改应用代码才能使用)的 CUDA streams API;2)对应用程序透明的系统软件和硬件分区(partitioning)技术,例如 MPS、Time-slicing、MIG、虚拟化。Source: NVIDIA。

MPS

CUDA MPS(Multi-Process Service,多进程服务)是 CUDA API 的客户端-服务器架构的实现,用于提供同一 GPU 同时给多个进程使用。MPS 是一个 “AI 史前”(深度学习尚未在 GPU 上运行)的方案,是 NVIDIA 为了解决在科学计算领域单个 MPI 进程无法有效利用 GPU 的计算能力而推出的技术。

与时间切片(Time Slicing)相比,MPS 通过在多个客户端之间共享一个 CUDA Context 消除了多个 CUDA 应用之间上下文切换的开销,从而带来更好的计算性能。 此外,MPS 为每个 CUDA 程序提供了单独的内存地址空间,因而可以实现对单个 CUDA 程序实施内存大小使用限制,克服了 Time Slicing 机制在这方面的不足。

优点:

  • 可以控制单个应用的内存大小使用限制。
  • 由于消除了多个 CUDA 应用之间 context swtich 的代价,具有更好的性能。
  • 是一个 CUDA 层面的方案,不依赖于 GPU 的特定架构,支持较早的 GPU 硬件。

缺点:

  • CUDA 应用之间隔离不足:单个应用的错误可以导致整个 GPU 重置(reset)。
  • NVIDIA 还未(截止2024/01)正式在 K8s 环境下提供支持。

Time Slicing

时间切片(Time Slicing),也称为时间共享(Temporal Sharing),是指将多个 CUDA 程序分配到同一个 GPU 上运行,即一个简单的超额订阅(oversubscription)策略。NVIDIA 在 Pascal 架构(GP100,2016 年首发)之上提供了对此技术的支持。这些 GPU 卡上的调度器提供了指令粒度(不再需要等待 CUDA kernel 执行完成)的计算抢占(Compute Premption)技术。当抢占发生时, 当前 CUDA 程序的执行上下文(execution context:寄存器、共享内存等)被交换(swapped)到 GPU DRAM,以便另一个 CUDA 程序运行。

优点:

  • 非常容易设置。
  • 对分区数量无限制。
  • 可在众多 GPU 架构上部署。

缺点:

  • 上下文切换引起的效率降低。
  • 共享 GPU 设备导致的的隔离不足、潜在的 GPU OOM 等。
  • 时间片周期恒定,且无法为每个工作负载设置可用资源的优先级或大小。

MIG

MIG 可以把一个 GPU 划分为最多 7 个独立的 GPU 实例,从而为多个 CUDA 程序提供专用的 GPU 资源,包括流式多处理器(Streaming Multiprocessors)和 GPU 引擎。这些 MIG 实例可以为不同的 GPU 客户端(例如进程、容器或 VM)提供更加高级的故障隔离能力和 QoS。

优点:

  • 硬件隔离,并发进程安全运行且互不影响。
  • 在分区级别提供监控和遥测(monitoring & telemetry)数据。
  • 每个分区可以叠加使用其他共享技术,例如 vGPU、time-slicing、MPS。

缺点:

  • 仅在最新的 GPU 架构(Ampere,Hopper)上提供。
  • 重新配置分区布局需在 GPU 空闲(驱逐所有正在运行的进程)时。
  • 一些分区配置会导致部分 SM / DRAM 无法被利用。

vGPU

NVIDIA vGPU 是 NVIDIA 在数据中心提供的 GPU 虚拟化技术,它对具有完整输入输出内存管理单元(IOMMU)保护的 VM 提供支持,使得这些 VM 能够同时、直接地访问单个物理 GPU。

除了安全性之外,NVIDIA vGPU 还有其他优势,例如:

  • 支持实时虚拟机迁移(live VM migration)。
  • 可设置不同的调度策略,包括 best-effort、equal-share 和 fixed-sharez:
    • 当使用 fixed-share 调度器时可提供可预知的性能。
  • 运行混合的 VDI(Virtual Desktop Infrastructure)和计算工作负载的能力。
  • 与业界广泛使用的虚拟机管理程序(hypervisor,如 vmware)的集成能力。

缺点:

  • 部署 vGPU 需要额外的软件授权费用。
  • 分区仍然通过时间片(time-slicing)完成。

扩展资源名称

如果用户想要知道所使用的集群有哪些代表 GPU 的扩展资源名称,请咨询集群管理员。下面列举了一些常见的代表 GPU 的扩展资源名称。

NVIDIA GPU

当集群安装有 NVIDIA GPU 硬件资源时,通常有下列扩展资源名称:

  • nvidia.com/gpu:一个扩展资源对应一个 NVIDIA GPU 硬件资源。可以申请多个 GPU,例如当声明资源 nvidia.com/gpu: 8 时,会有 8 个 NVIDIA GPU 分配给这个工作负载使用。
  • nvidia.com/gpu.shared:通过这个扩展资源,多个工作负载可以共享使用一个 NVIDIA GPU。需要注意的是,当共享机制是通过 Time Slicing 实现时,用户为工作负载设置 nvidia.com/gpu.shared 扩展资源的数量不能超过 1(参考)。

NVIDIA 还有其他形式的设备名称,例如,当部署了 MIG 技术时,常见的资源名称有:

  • nvidia.com/mig-3g.20gb:一个扩展资源对应的计算能力是物理 GPU 的 3/7,显存大小是 20GB。
  • nvidia.com/mig-2g.10gb:一个扩展资源对应的计算能力是物理 GPU 的 2/7,显存大小是 10GB。
  • nvidia.com/mig-1g.5gb:一个扩展资源对应的计算能力是物理 GPU 的 1/7,显存大小是 5GB。

AMD GPU

当集群安装有 AMD GPU 硬件资源时,通常有下列扩展资源名称:

  • amd.com/gpu:一个扩展资源对应一个 AMD GPU 硬件资源。同样地,可以申请多个 GPU,例如 amd.com/gpu: 2

其他

请参考对应厂商的 device plugin 文档。

使用示例

独占 GPU

下面是一个独占使用 GPU 的 PyTorchTrainingJob 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
 name: pytorch-example
spec:
 replicaSpecs:
 - replicas: 4
   restartPolicy: OnFailure
   template:
     spec:
       containers:
       - command:
         - python
         - dist_mnist.py
         image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
         name: pytorch
         resources:
           limits:
             nvidia.com/gpu: 4
           requests:
             cpu: 10
             memory: 5Gi
   type: worker

在该例中,spec.replicaSpecs[0].template.spec.containers[0].resources.limits 字段设置了资源量 nvidia.com/gpu: 4,表示一个 replica 会独占使用 4 个 NVIDIA GPU。同时又设置了 replica 的数量为 4,因此该 PyTorchTrainingJob 总共会占用 16 个 NVIDIA GPU。

共享 GPU

下面是一个以共享方式使用 GPU 的 Notebook 示例:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: tutorial
spec:
  type: jupyter
  template:
    spec:
      containers:
        - name: notebook
          image: t9kpublic/torch-2.1.0-notebook:1.77.1
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
          resources:
            requests:
              cpu: '8'
              memory: 16Gi
              nvidia.com/gpu.shared: 1
            limits:
              cpu: '16'
              memory: 32Gi
              nvidia.com/gpu.shared: 1
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: tutorial

在该例中,spec.template.spec.containers[0].resources.limits 字段设置了资源量 nvidia.com/gpu.shared: 1,表示这个 Notebook 以共享方式使用一个 NVIDIA GPU。

指定 GPU 型号

不同节点上安装的 GPU 型号经常是不同的,而同一厂家的 GPU 对应的扩展资源名称常常是相同的,例如对于 NVIDIA GPU,在不考虑共享 GPU 的情况下,A100 和 A40 型号对应的扩展资源名称都是 nvidia.com/gpu

调度器为工作负载分配资源时会忽略型号信息,如果用户想让工作负载使用特定型号的 GPU,例如 NVIDIA A100-80GBNVIDIA A40,可以参考下列方式设置工作负载,使其能被分配到安装有特定型号 GPU 的节点上。

设置 nodeSelector 字段

安装有 GPU 硬件的节点会通过节点标签来表明其安装的 GPU 型号。如果用户将工作负载的 nodeSelector 字段设置为指定型号 GPU 对应的节点标签,并且为工作负载设置了代表 GPU 的扩展资源,那么工作负载就可以使用指定型号的 GPU。

常见的节点标签

如果用户想要知道所使用的集群有哪些表明 GPU 型号的节点标签,请咨询管理员。下面是一些表明 GPU 型号的节点标签示例:

GPU 型号节点标签
NVIDIA A100-40GBnvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB
NVIDIA A100-80GBnvidia.com/gpu.product: NVIDIA-A100-PCIE-80GB
NVIDIA GTX 1070nvidia.com/gpu.product: NVIDIA-GeForce-GTX-1070
NVIDIA TITAN-Xnvidia.com/gpu.product: NVIDIA-TITAN-X

常见工作负载的 nodeSelector 字段

下面列举了常见的工作负载,以及工作负载用于设置 nodeSelector 的字段:

工作负载字段
GenericJobspec.replicaSpecs[*].template.spec.nodeSelector
PyTorchTrainingJobspec.replicaSpecs[*].template.spec.nodeSelector
TensorFlowTrainingJobspec.replicaSpecs[*].template.spec.nodeSelector
XGBoostTrainingJobspec.replicaSpecs[*].template.spec.nodeSelector
DeepSpeedJobspec.worker.template.spec.nodeSelector
ColossalAIJobspec.worker.template.spec.nodeSelector
MPIJobspec.worker.template.spec.nodeSelector
BeamJobspec.jobTemplate.spec.template.spec.nodeSelector
Notebookspec.template.spec.nodeSelector
SimpleMLService只有使用自定义框架时,才能通过字段 spec.custom.nodeSelector 设置 nodeSelector
MLService predictorspec.releases[*].predictor.template.spec.nodeSelector
MLService transformerspec.transformer.template..spec.nodeSelector
Podspec.nodeSelector

示例

下面是一个设置了 nodeSelector 字段的 Notebook 示例:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
 name: tutorial-nodeselector
spec:
 type: jupyter
 template:
   spec:
     containers:
       - name: notebook
         image: t9kpublic/torch-2.1.0-notebook:1.77.1
         volumeMounts:
           - name: workingdir
             mountPath: /t9k/mnt
         resources:
           limits:
             cpu: '16'
             memory: 32Gi
             nvidia.com/gpu: 1
     nodeSelector:
       nvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB
     volumes:
       - name: workingdir
         persistentVolumeClaim:
           claimName: tutorial

在该例中:

  • Notebook 的资源量设置了 nvidia.com/gpu: 1,表示 Notebook 使用一个 GPU。
  • Notebook 的 nodeSelector 被设置为 nvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB,因此 Notebook 的 Pod 会被分配到含有标签 nvidia.com/gpu.product: NVIDIA-A100-PCIE-40GB 的节点上运行,从而 Notebook 会被分配一个 NVIDIA A100-40GB。

设置队列

通过 nodeSelector 机制指定 GPU 型号的过程繁琐,并且管理员也缺乏对 GPU 使用权限的方便控制。平台提供了更加便捷的队列机制方便用户使用特定类型的资源。

当满足以下条件时,可以通过设置队列来使用特定型号的 GPU:

  1. 管理员创建了队列并为其设置了适当的节点限制。例如,创建了队列 a100,并设置其可以使用安装了 NVIDIA A100 的节点。
  2. 用户有这个队列的使用权限

在创建工作负载时,进行下列操作以使用特定型号的 GPU:

  • 使用 T9k Scheduler。
  • 设置队列名称,例如 a100
  • 设置代表 GPU 的扩展资源,例如 nvidia.com/gpu

示例

假设管理员创建并设置了两个队列,名称分别是:

  • a100:队列可以使用的节点上都安装了 NVIDIA A100-80GB。
  • a40:队列可以使用的节点上都安装了 NVIDIA A40-40GB。

并且用户有它们的使用权限。那么如果用户想要创建一个使用一个 NVIDIA A100-80GB 的 Notebook,则可以使用以下 YAML 配置文件:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
 name: tutorial
spec:
 type: jupyter
 scheduler:
   t9kScheduler:
     queue: a100
 template:
   spec:
     containers:
       - name: notebook
         image: t9kpublic/torch-2.1.0-notebook:1.77.1
         volumeMounts:
           - name: workingdir
             mountPath: /t9k/mnt
         resources:
           limits:
             cpu: '16'
             memory: 32Gi
             nvidia.com/gpu: 1
     volumes:
       - name: workingdir
         persistentVolumeClaim:
           claimName: tutorial

在该例中:

  • Notebook 的资源量设置了 nvidia.com/gpu: 1,表示 Notebook 使用一个 GPU。
  • 字段 spec.scheduler.t9kScheduler.queue 被设置为 a100,表示 Notebook 使用 T9k Scheduler 进行资源调度,并且使用队列 a100

参考

资源回收

一些交互式工作负载(例如 NotebookTensorBoardExplorer)的计算资源经常被闲置。例如在非工作时间,用户创建的 Notebook 服务虽然没有用户使用,但仍占用大量集群计算资源,造成资源浪费。

为充分利用集群资源,平台提供资源回收机制,自动检测并暂停空闲的 Notebook、TensorBoard 和 Explorer 等服务,释放占用的资源。

原理

这里以 Notebook 为例介绍资源回收的原理(TensorBoard、Explorer 或其他工作负载同理)。

structure

如上图所示:

  1. 集群管理员设置 “资源回收配置” 策略(Project 1 没有设置自动回收,Project 2 则设置了自动回收);
  2. 根据配置,Resource Keeper 监听启用回收功能的项目(Project 2)中的 Notebook 状态;
  3. 当 Notebook 空闲时间达到配置中规定的阈值,则 Resource Keeper 对该资源实施暂停操作,以释放资源。

状态检测

很多在平台上运行的服务都使用 PEP Proxy 来处理身份验证和授权。由于其代理所有客户端请求,这些 PEP Proxy 也可以作为检查服务是否空闲的信息来源。

pepproxy

对于 TensorBoard 和 Explorer,对应控制器会向 PEP Proxy 发送请求,检查其上一次请求的时间,如果在给定时间内(比如 1 小时,由管理员配置)没有再次请求,则控制器判定其为空闲状态。

Jupyter Notebook 本身的 server 就提供了状态查询功能。因此,对于 Notebook 类型的工作负载,Notebook 的控制器会先尝试向 Notebook server 发送请求检查空闲状态。如果处于空闲或请求失败(可能 Notebook 使用的不是 Jupyter 内核,这主要发生在自定义 Notebook 上),则继续向 PEP Proxy 发送请求,查询 PEP Proxy 观测到的服务使用情况。如果在给定时间内(比如 1 小时,由管理员配置)没有再次请求,则控制器判定其为空闲状态。

对于 RStudio Notebook,目前没有空闲状态的判定,控制器将其视为一直处于活跃状态。

资源使用监控

在平台创建工作负载后,用户可以通过控制台或命令行工具查看工作负载的资源使用情况。

控制台

用户可以在下列控制台的工作负载的详情页面查看资源监测图表:

  • 模型构建(Build Console):
    • Notebook
    • T9k Job
    • Tensorboard
    • Pod
  • 模型部署(Deploy Console):
    • MLService

当用户定义工作负载时可以选择性地为每个容器设定所需要的资源数量,最常见的可设定资源是 CPU、内存和扩展资源。

以 PyTorchTrainingJob 为例,用户可以查看下面几类资源的使用情况。

CPU / Memory / 扩展资源

CPU(内存)的资源监测图如下所示,图中包含三条折线:

  • 请求量:工作负载声明的 resources.requests.cpuresources.requests.memory
  • 上限:工作负载声明的 resources.limits.cpuresources.limits.memory
  • 使用量:工作负载实际使用的 CPU(内存)资源量
cpu
memory

当工作负载声明扩展资源时,显示扩展资源的资源监测图。

在本例中,PytorchTrainingJob 声明了扩展资源 nvidia.com/gpu: 2,页面显示了工作负载声明的 resources.limits."nvidia.com/gpu" 资源量。

nvidia.com/gpu

NVIDIA GPU

当工作负载声明的扩展资源是 nvidia.com/gpu 时,资源监测图会展示额外的 GPU 相关指标,包括:利用率、温度、功率、显存使用率、已用显存量、SM Clock、TensorCore 利用率。

下面是展示 GPU 利用率和显存使用率的图表:

gpu-utilization
gpu-memory-utilization

网络带宽

网络带宽显示下面两项指标:

  • 接收带宽:所有容器接收数据的网络带宽总计。
  • 发送带宽:所有容器发送数据的网络带宽总计。
network-receive
network-transmit

存储 I/O

存储 I/O 显示下面两项指标:

  • IOPS(读+写):所有容器在节点的物理磁盘上,进行读写的操作次数之和。
  • 吞吐量(读+写):所有容器在节点的物理磁盘上,读写数据的吞吐量。
storage-iops
storage-throughput

命令行工具

用户可以在 Notebook 的终端中,使用 kubectl top 命令查看 Pod 的 CPU、内存使用情况。例如:

(base) [/t9k/mnt t9kuser@managed-notebook-933f6-0]
$ kubectl top pods
NAME                                         CPU(cores)   MEMORY(bytes)   
managed-notebook-933f6-0                     25m          153Mi           
managed-project-event-ctl-854b96f4dd-f6hn8   1m           29Mi 

下一步

存储

TensorStack AI 平台支持多种类型的存储服务:Block Storage Volumes(块存储卷),Shared Filesystem Volumes (共享文件系统卷),以及基于 S3 协议的对象存储。

存储卷(Storage Volumes)

用户可申请使用两种类型的存储卷(Storage Volumes):块存储卷,或者共享文件系统卷

这两种高性能的网络存储卷服务,可为各种类型的工作负载,如 Notebook、T9k Job、推理服务等提供持久化存储卷(Persistent Volumes)服务。

  • 支持在集群中使用不同性能等级的存储服务。例如,管理员可设置集群同时提供高性能的 SSD 和海量的 HDD 两种等级的存储服务。
  • 所有 SSD 和 HDD 等级均可创建为 Block Volumes(块存储卷)或 Shared Filesystem Volumes(共享文件系统存储卷)。
  • 可随时调整 Volume 大小以增加容量。
  • 存储与计算分开管理,并且可以在不同实例和硬件类型之间移动。
  • 支持存储卷的快照、备份及恢复。
  • 可通过 UI 或 命令行工具 kubectl 轻松管理。

块存储卷(Block Storage Volumes)

Block Storage Volumes(块存储卷)可作为高性能虚拟存储盘挂载到各种类型的工作负载上。这些卷被呈现为通用 Block Device (块设备),操作系统将其视为物理连接存储设备,并且独占使用。

如果集群部署了高性能的 NVMe 的存储节点,并使用了足够快的网络,这种类型的存储卷的性能将会超过本地 SATA 接口的 SSD,并且可以扩展到 PB 级别容量。

共享文件系统卷(Shared Filesystem Volumes)

遵守 POSIX 标准的 Filesystem Volumes(文件系统卷)可以挂载到各种工作负载上,以提供原生共享文件系统。

同时,这些卷可以同时附加到多个工作负载实例上,非常适合作在 Notebook、大规模并行计算 Job、推理服务等场景的存储卷。

对象存储

平台提供基于 S3 协议的对象存储服务,支持方便、通用的数据共享机制及低成本的数据归档服务。

使用

TensorStack 的存储卷(Storage Volumes)系统支持建立在 Kubernetes 的 Storage API 基础之上,通过 API Persistent VolumesStorage Class 等提供用户接口。

同时,为了支持一些特定场景的使用,TensorStack 提供 CRD StorageShimExplorer 以提供扩展支持。

例 1:获得集群中的存储类型:

$ kubectl get sc

例 2:创建存储请求:

# 使用 StorageClass `generic-hdd` 的 Filesystem Volumes (文件系统卷)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-example
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 100Gi
  storageClassName: generic-hdd
  volumeMode: Filesystem

CRD 资源

存储系统中普通用户相关的 CRD 资源,列表如下:

来源说明
PVCKubernetes动态申请集群持久存储;用户可日常创建此 Resource 以申请存储资源
Storage ClassKubernetes指明存储的类别;管理员创建,用户创建 PVC 时引用
StorageShimTensorStack对各种存储系统的便捷支持,为用户自动创建 PVC;用户可日常创建此 Resource
ExplorerTensorStack文件浏览器,查看和管理 PVC 中的文件

参考

PVC(持久卷)

PVC 是一种 Kubernetes 原生资源,是对存储的需求声明,它抽象了底层存储细节,允许用户请求特定大小和访问模式的存储,而不必关心存储的具体实现。

创建 PVC

下面是一个基本的 PVC 示例:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: cephfs-hdd

在该例中:

  • spec.resources.requests.storage 字段定义了所申请的存储空间容量大小为 1Gi
  • spec.accessModes 字段定义了访问模式为 ReadWriteMany,表示该 PVC 能够同时被多个节点上的 Pod 使用。
  • spec.storageClassName 字段定义了所使用的存储类名称为 cephfs-hdd,集群中可用的存储类由管理员提供。

使用 PVC

下面是在 Pod 中使用 PVC 的示例:

apiVersion: v1
kind: Pod
metadata:
  name: pod-demo
spec:
  containers:
  - name: myfrontend
    image: nginx
    volumeMounts:
    - mountPath: "/var/www/html"
      name: data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: pvc-demo

在该例中,pod-demopvc-demo 作为一个数据卷(volume)来使用,其中容器 myfrontend 将该数据卷挂载到 /var/www/html 目录下。

在 TensorStack AI 平台中,PVC 是通用的持久化存储资源,你在 NotebookJobMLServiceWorkflow 等 TensorStack 资源中都可以使用 PVC。以 Notebook 为例:

apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: notebook-demo
spec:
  type: jupyter
  template:
    spec:
      containers:
      - image: t9kpublic/torch-2.0.0-notebook:1.72.0
        name: notebook
        resources:
          limits:
            cpu: "4"
            memory: 4Gi
          requests:
            cpu: "0.5"
            memory: 500Mi
        volumeMounts:
        - name: workingdir
          mountPath: /t9k/mnt
      volumes:
      - name: workingdir
        persistentVolumeClaim:
          claimName: pvc-demo

在该例中,notebook-demopvc-demo 作为一个数据卷(volume)来使用,其中容器 notebook 将该数据卷挂载到 /t9k/mnt 目录下。

生命周期

PVC 有以下几种状态:

  • Pending:PVC 正在由对应的存储类处理。
  • Bound:PVC 创建成功,可以被使用。
  • Unknown:无法获取 PVC 状态。

PVC 与 Pod

PVC 的生命周期独立于 Pod。一个 PVC 可以被多个 Pod 使用。当 PVC 正在被 Pod 使用时,它无法被删除。

PVC 与 StorageShim

在 TensorStack AI 平台中,你可以:

  1. 创建一个独立的 PVC,申请全新的存储空间。
  2. 创建一个 StorageShim,将已有存储系统的某个子目录挂载为一个 PVC。此时 StorageShim 控制器将为所创建的 StorageShim 创建一个同名的 PVC,此 PVC 的生命周期由 StorageShim 管理。

容量请求

创建 PVC 时,spec.resources.requests.storage 字段用于指定 PVC 的容量,你无法在 PVC 中存储超过此容量限制的文件。

访问模式

创建 PVC 时,spec.accessModes 字段用于指定 PVC 的访问模式,可选择以下几种访问模式:

  • ReadWriteMany:PVC 能被多个节点上的 Pod 读写。
  • ReadWriteOnce:PVC 只能被一个节点上的 Pod 读写。
  • ReadOnlyMany:PVC 只能被多个节点上的 Pod 读。

一般选择 ReadWriteMany 即可。

存储类

创建 PVC 时,spec.storageClassName 字段用于指定 PVC 的存储类,集群中可用的存储类由管理员提供。

例如,一个集群可能提供两个存储类,名为 cephfs-hddcephfs-ssd,分别提供基于 HDD 机械硬盘和 SSD 固态硬盘的存储空间,用于不同的数据存储目的。

下一步

PVC 快照

如果 PVC 存放了重要的数据,用户可适时制作快照(snapshot),以方便恢复。

CRD 资源

存储系统中与快照相关的 CRD 资源,列表如下:

来源说明
PVCKubernetes动态申请集群持久存储;用户可日常创建此 Resource 以申请存储资源
Volume SnapshotKubernetes针对某一个 PVC 进行快照;用户可日常创建此 Resource
Volume Snapshot ClassKubernetes指明快照的类别,与 StorageClass 一一对应;管理员创建,用户创建 Volume Snapshot 时引用

创建快照

下面是一个基本的 PVC 示例:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: cephfs-hdd

为了对该 PVC 进行快照,用户需要创建如下 VolumeSnapshot 资源:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: pvc-demo-snapshot
spec:
  volumeSnapshotClassName: cephfs-hdd-snapshotclass
  source:
    persistentVolumeClaimName: pvc-demo

其中:

  • spec.volumeSnapshotClassName 定义了所使用的快照类为 cephfs-hdd-snapshotclass,每个 StorageClass 都有对应的 VolumeSnapshotClass,由管理员负责创建;VolumeSnapshot 指定的 spec.volumeSnapshotClassName 应当与 PVC 的 spec.storageClassName 对应。
  • spec.source.persistentVolumeClaimName 定义了所要快照的 PVC 名称为 pvc-demo

创建完成后,用户可以对 PVC 中的数据进行继续修改;若需要放弃修改,则可方便地使用快照恢复到修改前的数据。

从快照中恢复

如果想将 PVC 中的数据恢复至快照创建时刻的状态,用户需要创建一个新的 PVC(之前的 PVC 仍然可以使用,两个 PVC 之间互不影响):

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-demo-restore
spec:
  accessModes:
  - ReadWriteMany
  dataSource:
    name: pvc-demo-snapshot
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  resources:
    requests:
      storage: 1Gi
  storageClassName: cephfs-hdd

其中:

  • spec.accessModes 必须与原 PVC 一致。
  • spec.dataSource 引用了所要恢复的名为 pvc-demo-snapshot 的快照,本 PVC 中的数据将与该快照中的数据完全一致。
  • spec.resources.requests.storage 必须与原 PVC 一致。
  • spec.storageClassName 必须与原 PVC 一致。

下一步

StorageShim

StorageShim 用于将已有的存储系统以 PVC 的形式提供给用户使用,例如 S3 bucket 的某个子路径可以作为一个 PVC,分布式文件系统的某个子目录可以作为一个 PVC。通过 StorageShim,用户能够方便地访问已经上传到各类存储系统中的数据,而无需进行复制。目前支持的存储系统包括 S3CephFS,未来可能支持更多的存储系统类型。

创建 StorageShim

S3 类型

下面是一个 S3 类型的 StorageShim 示例:

apiVersion: tensorstack.dev/v1beta1
kind: StorageShim
metadata:
  name: storageshim-s3-demo
spec:
  type: s3
  s3:
    uri: "s3://bucket/path/subpath"
    readOnly: false
    secretRef:
      name: s3-secret-demo

其中所引用的 Secret s3-secret-demo 配置如下:

apiVersion: v1
kind: Secret
metadata:
  name: s3-secret-demo
  labels:
    tensorstack.dev/resource: s3-cfg
stringData:
  .s3cfg: <s3cfg>

在该例中,StorageShim storageshim-s3-demo 被创建后,StorageShim 控制器将创建一个同名的 PVC storageshim-s3-demo,该 PVC 的根目录对应 S3 路径 s3://bucket/path/subpath,访问该 S3 路径的登录凭证存储在 Secret s3-secret-demo 中,该 Secret 必须为 S3-cfg 类型

CephFS 类型

下面是一个 CephFS 类型的 StorageShim 示例:

apiVersion: tensorstack.dev/v1beta2
kind: StorageShim
metadata:
  name: storageshim-cephfs-demo
spec:
  type: cephfs
  cephfs:
    path: /cephfs/data/user/mydata
    client:
      secretRef:
        name: ceph-client-key-demo
    server:
      configMapRef:
        name: ceph-cluster-config-demo

其中所引用的 Secret ceph-client-key-demo 配置示例如下:

apiVersion: v1
kind: Secret
metadata:
  name: ceph-client-key-demo
  labels:
    tensorstack.dev/resource: ceph-client
stringData:
  userID: <user-id>
  userKey: <user-key>

其中所引用的 ConfigMap ceph-cluster-config-demo 配置示例如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: ceph-cluster-config-demo
  labels:
    tensorstack.dev/resource: ceph-cluster
data:
  driver: <driver-name>
  clusterID: <cluster-id>
  fsName: <fs-name>

在该例中,StorageShim storageshim-cephfs-demo 被创建后,StorageShim 控制器将创建一个同名的 PVC storageshim-cephfs-demo,该 PVC 的根目录对应 CephFS 文件系统的子目录 /cephfs/data/user/mydata,访问该子目录的登录凭证存储在 Secret ceph-client-key-demo 中,该 Secret 必须为 S3-cfg 类型,该 CephFS 文件系统的相关信息存储在 ConfigMap ceph-cluster-config-demo 中。

下一步

Explorer

Explorer 提供几种展示和管理集群中数据的方法。

创建 Explorer

下面是一个基本的 Explorer 示例:

apiVersion: tensorstack.dev/v1beta1
kind: Explorer
metadata:
  name: example
spec:
  storageName: test
  storageType: pvc

在该例中,Explorer 展示和管理名为 test 的持久卷(Persistent Volume)中的数据。

存储方式

Explorer 目前仅支持展示存储在 PVC 中的文件(即 spec.storageType 字段暂时只能设置为 pvc)。

展示和管理方式

Explorer 会自动以多种方式展示和管理文件,目前支持文件浏览器和代码编辑器两种。

文件浏览器

使用第三方软件 File Browser 提供文件管理器形式的界面,支持文件系统浏览、文件上传、文件下载、基本的文件编辑等功能。

代码编辑器

使用第三方软件 VS Code 提供云端集成开发环境(IDE)的支持。开发者可以方便地运行网页版 VS Code,进行远程项目开发。

资源回收

Explorer 提供空闲资源回收的支持,在检测到 Explorer 处于空闲状态并超过一定时长时,删除工作负载以释放计算资源。默认情况下(管理员可修改配置):

  • Explorer 无人使用超过 1h 后,标记该 Explorer 为 Idle
  • Explorer 进入 Idle 状态超过 24h 后,删除该 Explorer 底层工作负载。

如果需要再次使用该 Explorer,你可以在模型构建控制台中手动点击恢复按钮。

下一步

辅助

TensorStack AI 平台提供了一些辅助性资源,它们为其他资源提供支持,或者为用户提供便捷、实用的功能。下表总结了所有辅助性资源:

资源来源作用
SecretKubernetes存储敏感信息并用于配置
ConfigMapKubernetes存储非敏感信息并用于配置
PodKubernetes运行容器,测试镜像和应用程序
ImageBuilderTensorStack构建自定义镜像

Secret

Secret 是一种 Kubernetes 原生资源,用于存储少量敏感信息,比如密码、OAuth 令牌、SSH 密钥等。使用 Secret 可以避免将敏感数据直接写入到 Pod 的定义中或者应用程序代码里,从而提高了安全性。

创建 Secret

下面是一个基本的 Secret 示例:

apiVersion: v1
kind: Secret
metadata:
  name: secret-demo
type: Opaque
data:
  key1: dmFsdWUxCg==
  key2: dmFsdWUyCg==

在该例中,secret-demo 存储了两对键值对,其中值经过了 base64 编码。

使用 Secret

PVC 类似,Secret 可以以同样的方式作为数据卷被 Pod、Notebook、Job 等资源挂载。以 PyTorchTrainingJob 为例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: pytorchtrainingjob-demo
spec:
  replicaSpecs:
    - type: worker
      replicas: 1
      restartPolicy: OnFailure
      template:
        spec:
          containers:
            - image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
              name: pytorch
              command:
                - python
                - dist_mnist.py
              resources:
                limits:
                  cpu: '1'
                  memory: 1Gi
                requests:
                  cpu: 500m
                  memory: 500Mi
              volumeMounts:
                - name: data
                  mountPath: /data
                - name: secret
                  mountPath: /secret
          volumes:
            - name: data
              persistentVolumeClaim:
                claimName: pvc-demo
            - name: secret
              secret:
                name: secret-demo

在该例中,pytorchtrainingjob-demopvc-demosecret-demo 均作为数据卷(volume)来使用,其中容器 pytorch 将两个数据卷分别挂载到 /data/secret 目录下。因此,容器 pytorch/secret 目录下将存在两个文件 /secret/key1/secret/key2,文件内容是经过 base64 解码后的对应的值。

Secret 用途

TensorStack AI 平台通过 label tensorstack.dev/resource 来标识 Secret 的用途,主要有以下几种:

  • API Key:拥有 label tensorstack.dev/resource: apikey,用于存放 API Key,可在安全管理控制台创建 API Key。
  • S3-cfg:拥有 label tensorstack.dev/resource: s3-cfg,用于存放 S3 配置文件的内容,可从本地的 $HOME/.s3cfg 文件中获取。
  • S3-env:拥有 label tensorstack.dev/resource: s3-env,用于存放 S3 配置文件的每个字段,请从本地的 $HOME/.s3cfg 文件中获取。
  • Docker:拥有 label tensorstack.dev/resource: docker,用于存放 Docker 配置文件的内容,可从本地的 $HOME/.docker/config.json 文件中获取。
  • SSH Public Key:拥有 label tensorstack.dev/resource: ssh,用于存放 SSH 公钥,可从本地的 $HOME/.ssh/id_rsa.pub 文件中获取。
  • Ceph Client:拥有 label tensorstack.dev/resource: ceph-client,用于存放 Ceph 客户端配置,可从管理员处获取。
  • Custom:拥有 label tensorstack.dev/resource: other,自定义用途。

例如:

下一步

ConfigMap

ConfigMap 是一种 Kubernetes 原生资源,用于存储非机密性配置信息,它可以用来保存配置文件、命令行参数和环境变量等数据。ConfigMap使得容器化应用程序的配置与镜像内容分离,从而提高了应用的可移植性和灵活性。

创建 ConfigMap

下面是一个基本的 ConfigMap 示例:

apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-demo
data:
  key1: value1
  key2: value2

在该例中,configmap-demo 明文存储了两对键值对。

使用 ConfigMap

PVC 类似,ConfigMap 可以以同样的方式作为数据卷被 Pod、Notebook、Job 等资源挂载。以 PyTorchTrainingJob 为例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: pytorchtrainingjob-demo
spec:
  replicaSpecs:
    - type: worker
      replicas: 1
      restartPolicy: OnFailure
      template:
        spec:
          containers:
            - image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-devel
              name: pytorch
              command:
                - python
                - dist_mnist.py
              resources:
                limits:
                  cpu: '1'
                  memory: 1Gi
                requests:
                  cpu: 500m
                  memory: 500Mi
              volumeMounts:
                - name: data
                  mountPath: /data
                - name: configuration
                  mountPath: /config
          volumes:
            - name: data
              persistentVolumeClaim:
                claimName: pvc-demo
            - name: configuration
              configMap:
                name: configmap-demo

在该例中,pytorchtrainingjob-demopvc-democonfigmap-demo 均作为数据卷(volume)来使用,其中容器 pytorch 将两个数据卷分别挂载到 /data/config 目录下。因此,容器 pytorch/config 目录下将存在两个文件 /config/key1/config/key2,文件内容分别是 value1value2

下一步

Pod

Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。

Pod 是一组(一个或多个)容器;这些容器共享存储、网络、以及怎样运行这些容器的声明。Pod 中的内容总是并置的并且一同调度,在共享的上下文中运行。Pod 模拟一个特定应用的“逻辑主机”,其中包含一个或多个应用容器,这些容器相对紧密地耦合在一起。在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。

除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 Init 容器。你也可以在集群支持临时性容器的情况下,为调试的目的注入临时性容器

通常你不需要直接创建 Pod,甚至单实例 Pod。你会使用诸如 Deployment 或 Job 这类工作负载资源来创建 Pod。如果 Pod 需要跟踪状态,可以考虑 StatefulSet 资源。

Kubernetes 集群中的 Pod 主要有两种用法:

  • 运行单个容器的 Pod:最常见的 Kubernetes 用例; 在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
  • 运行多个协同工作的容器的 Pod:Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众,而另一个单独的 sidecar 容器则刷新或更新这些文件。Pod 将这些容器和存储资源打包为一个可管理的实体。

每个 Pod 都旨在运行给定应用程序的单个实例。如果希望横向扩展应用程序(例如,运行多个实例以提供更多的资源),则应该每个实例使用一个 Pod。在 Kubernetes 中,这通常被称为副本。通常使用一种工作负载资源及其控制器来创建和管理一组 Pod 副本。

Pod 示例

以下是一个 Pod 的 YAML 示例:

apiVersion: v1
kind: Pod
metadata:
  name: test-sdk
spec:
  containers:
    - name: sdk
      image: t9kpublic/t9k-sdk:0.6.0-torch-2.0.1
      command:
        - sleep
        - inf
      resources:
        limits:
          cpu: 500m
          memory: 200Mi

在上述示例中:

  • Pod 使用 t9kpublic/t9k-sdk:0.6.0-torch-2.0.1(由 spec.containers[0].image 字段指定)镜像启动容器 sdk(由 spec.containers[0].name 字段指定)。
  • 容器中执行 sleep inf(由 spec.containers[0].command 字段指定)命令。
  • sdk 容器最多可使用 0.5 个 CPU 和 200Mi 内存(由 spec.containers[0].resources.limits 字段指定)。

应用场景

在 TensorStack AI 平台,你可以使用 Pod 实现以下操作:

  • 测试镜像:在你使用 ImageBuilder 构建镜像后,可通过创建 Pod 并进入 Pod 终端来验证镜像是否符合预期。
  • 存储卷预处理:在训练前,需提前下载好数据,此时可以通过创建 Pod 绑定对应 PVC,在 Pod 终端向其中下载数据。
  • 测试代码:你在 Notebook 中开发后的脚本在训练镜像中并不一定能正常运行,可以用训练镜像创建一个 Pod,来测试训练脚本在新镜像中是否可用。

下一步

ImageBuilder

平台提供 CRD ImageBuilder,用于在集群中构建容器镜像。

创建 ImageBuilder

下面是一个基本的 ImageBuilder 示例:

# image-builder-example.yaml
apiVersion: tensorstack.dev/v1beta1
kind: ImageBuilder
metadata:
  name: imagebuilder-example
spec:
  dockerConfig:
    secret: docker-config
  tag: t9kpublic/kaniko-executor:v1.19.2
  workspace:
    pvc:
      name: kaniko
      dockerfilePath: ./Dockerfile
      contextPath: "."
  builder:
    kaniko: {}

在该例中:

  • spec.dockerConfig.secret 字段指定使用 Secret docker-config 中记录的 docker 配置,以上传镜像。
  • spec.tag 字段指定目标镜像的名称和标签为 t9kpublic/kaniko-executor:v1.19.2
  • spec.workspace 字段指定构建镜像使用 PVC kaniko 作为工作空间,其中:
    • 在 PVC 相对路径 ./Dockerfile 中存放构建镜像所需的 Dockerfile。
    • 在 PVC 相对路径 . 中存放构建镜像所需要的上下文。
  • spec.builder 字段指定使用 kaniko 来构建镜像。

构建工具

目前 ImageBuilder 支持使用 kaniko 工具来构建镜像。

kaniko

用户可以通过 spec.builder.kaniko 字段来设置 kaniko 的参数。

在下面示例中,ImageBuilder 使用 t9kpublic/kaniko-executor:v1.19.2 启动 kaniko,并在该容器中构建用户镜像;ImageBuilder 不额外设置 kaniko 参数。

spec:
  builder:
    kaniko:
      image: t9kpublic/kaniko-executor:v1.19.2
      args: []

spec.builder.kaniko 的参数介绍:

  • image:如忽略,ImageBuilder 控制器会指定一个默认镜像,所以一般来说可以不设置该字段。
  • args:如忽略,ImageBuilder 构建镜像时执行 kaniko --destination=[image-tag] --context=[context-path] --dockerfile=[dockerfile-path] 命令。如果用户需要使用其他参数,可以在该字段中指定。参考 kaniko additional flags

参考

更加详细的 ImageBuilder API 可直接在集群中查询:

kubectl explain imagebuilder

下一步

VirtualServer

VirtualServer 在集群中创建一个虚拟机,与容器环境相比,虚拟机:

  • 提供与物理计算机类似的运行环境,在有些场景更加符合用户需求;
  • 提供更强的隔离,可以限制潜在的安全影响范围。

创建 VirtualServer

下面是一个基本的 VirtualServer 示例:

apiVersion: tensorstack.dev/v1beta1
kind: VirtualServer
metadata:
  name: vs-example
spec:
  resources:
    cpu:
      cores: "1"
    memory: 8Gi
  storage:
    root:
      pvc:
        size: 4Gi
        volumeMode: Filesystem
        accessModes: ["ReadWriteOnce"]
        storageClassName: cephfs-hdd
      source:
        http:
          url: https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.img
    additionalDisks:
      - name: disk-name
        persistentVolumeClaim:
          claimName: pvc-as-disk
    filesystems:
      - name: my-filesys
        persistentVolumeClaim:
          claimName: pvc-as-fs
  network:
    tcp: [80, 5901]
    udp: []
    macAddress: ""
    dnsConfig: {}
    dnsPolicy: ClusterFirst
  cloudInit: |-
    #cloud-config
    bootcmd:
    - test "$(lsblk /dev/vdb)" && mkfs.ext4 /dev/vdb
    - mkdir -p /mnt/vdb
    - mkdir -p /mnt/file-sys
    - mount -t virtiofs my-filesys /mnt/file-sys
    mounts:
    - [ "/dev/vdb", "/mnt/vdb", "ext4", "defaults,nofail", "0", "2" ]

在该例中:

  1. 虚拟机申请使用 1 个 CPU 和 8Gi 内存(由 spec.resources 字段指定)。
  2. 虚拟机绑定一个 4Gi 的 PVC 作为根磁盘,并在 PVC 中下载 https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.img 系统镜像(由 spec.storage.root 字段指定)。
  3. 虚拟机声明 PVC pvc-as-disk 为磁盘 /dev/vdb(由 spec.storage.additionalDisks 字段指定,根磁盘为 /dev/vda,其他磁盘按顺序命名,但预设名称的方式不完全可靠,建议使用 serial 字段确认磁盘,参考 disk),并将该磁盘格式化为 ext4 文件系统,挂载到 /mnt/vdb 路径(格式化和绑定操作由 spec.cloudInit 字段指定)。
  4. 虚拟机声明 PVC pvc-as-fs 为文件系统 my-filesys(由 spec.storage.filesystems 字段指定),并将该文件系统挂载到 /mnt/file-sys 路径(绑定操作由 spec.cloudInit 字段指定)。
  5. 虚拟机会暴露 805901 两个 TCP 服务端口(由 spec.network 字段指定)。

虚拟机配置详解

资源申请

VirtualServer 支持设置 spec.resources 字段来申请 CPU、GPU 和内存三种资源。

spec:
  resources:
    gpu:
      type: nvidia.com/GA100_A100_PCIE_40GB
      count: 2
    cpu:
      model: Conroe
      cores: 1
    memory: 10Gi

在该例中,虚拟机申请使用 2nvidia.com/GA100_A100_PCIE_40GB GPU 卡、1Conroe 型号的 CPU 以及 10Gi 的内存。

根磁盘

VirtualServer 根据 spec.storage.root.pvc 字段中的配置创建 PVC 作为根磁盘,并从 spec.storage.root.source 字段所指定的数据源下载操作系统。

spec:
  storage:
    root:
      ephemeral: false
      pvc:
        size: 4Gi
        volumeMode: Filesystem
        accessModes: ["ReadWriteOnce"]
        storageClassName: cephfs-hdd
      source:
        http:
          url: https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.img

在上述示例中:

  • VirtualServer 创建一个 4Gi PVC,绑定为根磁盘。
  • https://cloud-images.ubuntu.com/releases/focal/release/ubuntu-20.04-server-cloudimg-amd64.img 链接下载系统镜像到根磁盘中。
    • VirtualServer 支持从多种数据源下载数据,比如 HTTP 链接、s3 数据库、镜像仓库、其他 PVC 等,更多信息请参考 DataVolumeSource
  • 该根磁盘以非临时磁盘的方式绑定给虚拟机(通过 spec.storage.root.ephemeral 字段指定)。所谓临时磁盘,即在虚拟机中的所有改动不会反应到 PVC 中,而是以一个临时镜像的方式存储;如果虚拟机重启,则该临时镜像消失。

其他数据卷

除了根磁盘以外,VirtualServer 支持以 disk 和 filesystem 方式绑定任意数量的数据卷。

绑定方式

filesystem

VirtualServer 通过 spec.storage.filesystems 字段声明文件系统:

spec:
  storage:
    filesystems:
      - name: my-filesys
        persistentVolumeClaim:
          claimName: pvc-as-fs

在上述示例中,VirtualServer 将 PVC pvc-as-fs 声明为文件系统 my-filesys

上面字段值只声明了文件系统,用户还需要将文件系统挂载到一个路径才可以使用。用户可以用 spec.cloudInit 字段来挂载该文件系统:

spec:
  cloudInit: |-
    #cloud-config
    bootcmd:
    - mkdir -p /mnt/file-sys
    - mount -t virtiofs my-filesys /mnt/file-sys

此外,用户也可以在虚拟机启动后,进入虚拟机手动执行上述挂载命令,此处不再演示。

disk

VirtualServer 通过 spec.storage.additionalDisks 字段声明磁盘:

spec:
  storage:
    additionalDisks:
      - name: disk-name
        persistentVolumeClaim:
          claimName: pvc-as-disk
        serial: CVLY623300HK240D

在上述示例中:

  • VirtualServer 将 PVC pvc-as-disk 声明为一个磁盘;
  • 序列号为 CVLY623300HK240D,如果不设置该字段,则磁盘序列号会随机生成,在重启虚拟机后,序列号会发生改变。序列号有助于确认磁盘,如通过命令 lsblk --nodeps -no name,serial | grep CVLY623300HK240D | cut -f1 -d' ' 确认上述示例中磁盘的名称。

如果该磁盘是第一次使用,用户还需要将磁盘格式化并挂载到一个路径,可以用 spec.cloudInit 字段完成该操作:

spec:
  cloudInit: |-
    #cloud-config
    bootcmd:
    - test "$(lsblk /dev/vdb)" && mkfs.ext4 /dev/vdb
    - mkdir -p /mnt/file-sys
    mounts:
    - [ "/dev/vdb", "/mnt/vdb", "ext4", "defaults,nofail", "0", "2" ]

此外,用户也可以在虚拟机启动后,进入虚拟机手动执行格式化和挂载操作,此处不再演示。

数据卷类型

PersistentVolumeClaim

使用一个 PVC 作为磁盘或文件系统:

spec:
  storage:
    filesystems:
      - name: filesys-name
        persistentVolumeClaim:
          claimName: pvc-name
---
spec:
  storage:
    additionalDisks:
      - name: disk-name
        persistentVolumeClaim:
          claimName: pvc-name
临时 PVC

临时 PVC 指的是虚拟机将 PVC 作为只读存储,虚拟机在启动后会在本地维护一个临时镜像,记录用户对 PVC 的写入都会记录在该临时镜像中,而不会实际写入到 PVC 中。如果虚拟机停止或重启,则临时镜像丢失。

spec:
  storage:
    filesystems:
      - name: filesys-name
        ephemeral:
          persistentVolumeClaim:
            claimName: pvc-name
---
spec:
  storage:
    additionalDisks:
      - name: disk-name
        ephemeral:
          persistentVolumeClaim:
            claimName: pvc-name
ConfigMap

ConfigMap 也可以作为磁盘或文件系统绑定到虚拟机上:

spec:
  storage:
    filesystems:
      - name: config-fs
        configMap:
          name: app-config
  cloudInit: |-
    #cloud-config
    bootcmd:
    - "sudo mkdir /mnt/app-config"
    - "sudo mount -t virtiofs config-fs /mnt/app-config"
---
spec:
  storage:
    additionalDisks:
      - name: disk-name
        configMap:
          name: app-config
        serial: CVLY623300HK240D
  cloudInit: |-
    #cloud-config
    bootcmd:
    - "sudo mkdir /mnt/app-config"
    - "sudo mount /dev/$(lsblk --nodeps -no name,serial | grep CVLY623300HK240D | cut -f1 -d' ') /mnt/app-config"

与 PVC 不同,以 ConfigMap 作为 disk 绑定给虚拟机时不需要格式化,控制器会自动创建磁盘并将 ConfigMap data 中的内容以文件的形式存入磁盘。

用户可以给磁盘设置 serial 字段,以便查找磁盘。

ServiceAccount
spec:
  storage:
    filesystems:
      - name: sa-fs
        serviceAccount:
          serviceAccountName: app-secret
  cloudInit: |-
    #cloud-config
    bootcmd:
    - "sudo mkdir /mnt/app-sa"
    - "sudo mount -t virtiofs sa-fs /mnt/app-sa"
---
spec:
  storage:
    additionalDisks:
      - name: disk-name
        serviceAccount:
          serviceAccountName: serviceaccountdisk
        serial: SERVICEACCOUNT12
  cloudInit: |-
    #cloud-config
    bootcmd:
    - "sudo mkdir /mnt/app-sa"
    - "sudo mount /dev/$(lsblk --nodeps -no name,serial | grep SERVICEACCOUNT12 | cut -f1 -d' ') /mnt/app-sa"

以 ServiceAccount 作为 disk 绑定给虚拟机时不需要格式化,控制器会自动创建磁盘,并在磁盘中创建 ca.crtnamespacetoken 三个文件,这些文件中记录着 ServiceAccount 的权限信息。

以 ServiceAccount 作为 filesystem 绑定给虚拟机,控制器也会在挂在路径中创建 ca.crtnamespacetoken 三个文件,这些文件中记录着 ServiceAccount 的权限信息。

网络策略

用户可通过 spec.network 字段设置虚拟机的 DNS 策略,暴露虚拟机服务:

spec:
  network:
    tcp: [80, 5901]
    udp: []
    macAddress: ""
    dnsConfig: {}
    dnsPolicy: ClusterFirst

字段说明:

  • tcpudp:表示虚拟机所要暴露的服务端口。
  • macAddress:网络接口的 MAC 地址,以便在虚拟机重启前后 MAC 地址保持一致。如果不指定该字段,虚拟机每次重启都会被分配随机 MAC 地址。
  • dnsPolicy:DNS 策略,默认为 ClusterFirst,可选值参考 DNS Policy
  • dnsConfig:虚拟机 DNS 配置,参考 DNS Config

在设置 spec.network 字段后,控制器会自动创建一个与虚拟机同名的 Service。用户可以通过该 Service 访问虚拟机的上述 TCP/UDP 接口,比如通过以下命令将服务暴露到本地 8080 端口:

kubectl port-forward service/managed-virtualserver-9dda9 8080:80

CloudInit

CloudInit 是 Canonical 公司开发的系统初始化工具,已被许多云服务提供商和 Linux 发行版广泛接受。

用户可通过 spec.cloudInit 字段设置 CloudInit 配置来初始化虚拟机环境,包括用户密码、启动命令等:

spec:
  cloudInit: |-
    #cloud-config
    user: ubuntu
    password: ubuntu
    chpasswd: { expire: False }
    package_update: true
    package_upgrade: true
    packages: 
    - qemu-guest-agent
    runcmd:
    - [ systemctl, start, qemu-guest-agent ]
    bootcmd:
    - "sudo mkdir /mnt/app-configmap"
    - "sudo mount -t virtiofs configmap-fs /mnt/app-configmap"
    - "sudo mkdir /mnt/app-sa"
    - "sudo mount /dev/$(lsblk --nodeps -no name,serial | grep SERVICEACCOUNT12 | cut -f1 -d' ') /mnt/app-sa"

在上述示例中,虚拟机会执行以下初始化操作:

  • 创建用户 ubuntu:ubuntu(用户名:密码);
  • 更新系统软件包;
  • 安装并启动 qemu-guest-agent 服务;
  • 绑定文件系统 configmap-fs 和磁盘(序列号为 SERVICEACCOUNT12)。

更多 CloudInit 配置请参考 Cloud Config

虚拟机运行策略

apiVersion: tensorstack.dev/v1beta1
kind: VirtualServer
metadata:
  name: example-vs
spec:
  runStrategy: Always
  ...
status:
  runStrategy: Halted
  ...

在上述示例中:

  • spec.runStrategy 表示 VirtualServer 创建时,使用的运行策略
  • status.runStrategy 表示当前 VirtualServer 的运行策略。

用户可以通过虚拟机操作切换虚拟机运行策略:

Run Strategystartstoprestart
Always-HaltedAlways
RerunOnFailureRerunOnFailureHaltedRerunOnFailure
ManualManualManualManual
HaltedAlways--
  • 第一行后三项为虚拟机操作,分别为启动、停止和重启。
  • 最左侧一列为操作前的运行策略,右侧为操作后的运行策略。
  • - 表示在当前运行策略下,不可执行该操作。

虚拟机操作

用户可以通过 K8s 拓展 API 来操控虚拟机,常见的虚拟机操作方式包括:

  • kubectl virt start $vm_name:启动虚拟机;
  • kubectl virt stop $vm_name:停止虚拟机;
  • kubectl virt restart $vm_name:重启虚拟机;
  • kubectl virt console $vm_name:连接虚拟机终端。

更多虚拟机操作请通过 kubectl virt -h 命令查看。

状态

虚拟机名称

为避免资源名称过长,导致创建子资源时失败,VirtualServer 在创建虚拟机时,将名称和 UID 进行哈希编码构成虚拟机名称,并将虚拟机名称记录在 status.vm.name 字段中。

status:
  vm:
    name: managed-virtualserver-9dda9

VirtualServer 的状态

status.conditions 字段用于描述当前 VirtualServer 的状态,包括以下 4 种类型:

  • DataImported:VirtualServer 已经创建根磁盘 PVC,并下载好系统镜像。
  • Ready:虚拟机已经成功启动,这里指的是系统成功启动,但是不考虑 CloudInit 过程。
  • Failure:虚拟机意外关闭,如节点崩溃、OOMKILLED 等。
  • Paused:虚拟机暂停,无法使用 CPU 和内存。

在下面的示例中,VirtualServer 成功创建了根磁盘并下载好系统镜像,所以类型为 DataImportedcondition 被设为 True;VirtualServer 此时被停止(不是暂停),工作负载被删除,所以类型为 Readycondition 被设为 False

status:
  conditions:
    - lastTransitionTime: "2024-03-21T08:26:59Z"
      message: Root disk has been imported successfully.
      reason: Succeeded
      status: "True"
      type: DataImported
    - lastTransitionTime: "2024-03-21T08:35:23Z"
      message: VMI does not exist
      reason: VMINotExists
      status: "False"
      type: Ready

VirtualServer 的可读状态

status.printableStatus 字段是一个易被用户理解的状态字符串,该字段可能为以下取值:

  • Stopped:虚拟机当前处于停止状态,且不会主动启动。
  • Provisioning:集群正在为虚拟机准备资源,包括向磁盘中下载数据。
  • Starting:正在启动虚拟机。
  • Running:虚拟机处于运行阶段。
  • Paused:虚拟机被暂停。
  • Stopping:虚拟机正在停止,包括删除工作负载等步骤。
  • Terminating:虚拟机正在被删除。
  • CrashLoopBackOff:虚拟机目前已崩溃,正等待重启。
  • Migrating:虚拟机正在迁移到另一个主机(目前不支持)。
  • Unknown:虚拟机状态未知,通常发生在虚拟机所在主机失去连接。
  • FailedUnschedulable:虚拟机无法被分配,可能的原因包括集群资源不足等。

参考

DataCube

平台提供 CRD DataCube,用于 PVC 和数据存储服务之间的数据传输:

  • 下载数据到 PVC。
  • 上传数据到 Git、Hugging Face 和 S3 等数据存储服务。

创建 DataCube

下面是一个基本的 DataCube 示例:

apiVersion: tensorstack.dev/v1beta1
kind: DataCube
metadata:
  name: git-download
spec:
  source:
    type: git
    options:
    - name: url
      value: https://github.com/owner/repo.git
  sink: 
    type: pvc
    pvc:
      name: datacube-pvc

在该例中,下载(克隆)Git 仓库(repository)https://github.com/user/repo.git(由 spec.source.options 字段指定)到 PVC datacube-pvc(由 spec.sink.pvc.name 字段指定)。

下载数据

设置 PVC

下载数据到 PVC 时,支持自动创建 PVC 和指定 PVC 子目录:

spec:
  sink: 
    type: pvc
    pvc:
      template:
        spec:
          accessModes:
          - ReadWriteMany
          resources:
            requests:
              storage: 100Gi
      name: datacube-pvc
      subPath: dev/git

在该例中,声明创建一个存储容量为 100Gi(由 spec.sink.pvc.template.spec.resources 字段指定)、可多处读写(由 spec.sink.pvc.template.spec.accessModes 字段指定)的 PVC datacube-pvc,并将数据下载到该 PVC 的 dev/git(由 spec.sink.pvc.subPath 字段指定)子目录下。

设置源存储服务

Git

下载(克隆)一个 Git 仓库到 PVC:

spec:
  source:
    type: git
    options:
    - name: token
      valueFrom:
        secretKeyRef:
          name: github-token
          key: token
    - name: url
      value: https://$(TOKEN)@github.com/user/repo.git
    - name: ref
      value: main

在该例中,通过 spec.source.type 字段指定源存储服务类型为 Git,通过 spec.source.options 字段指定源存储服务选项:

  • token:个人访问令牌(personal access token),使用 Secret github-token 的键 token 的值,该字段是可选的。
  • url:Git 仓库路径,以 $(TOKEN) 引用的形式嵌入 token。
  • ref:分支、标签或 commit,下载完成后切换到该 ref。该字段是可选的,默认为 master

Hugging Face

下载一个 Hugging Face 仓库(repository)或其中的部分文件到 PVC:

spec:
  source:
    type: huggingface
    options:
    - name: token
      valueFrom:
        secretKeyRef:
          name: hf-token
          key: token
    - name: repo
      value: openai/whisper-large-v3
    - name: files
      value: README.md,tokenizer.json,tokenizer_config.json

在该例中,通过 spec.source.type 字段指定源存储服务类型为 Hugging Face,通过 spec.source.options 字段指定源存储服务选项:

  • token:Hugging Face token,引用 Secret hf-token 的键 token 的值,该字段是可选的。
  • repo:Hugging Face 仓库名称。
  • files:下载的文件列表。该字段是可选的,默认下载仓库的所有文件。

S3

下载 S3 的文件或目录到 PVC:

spec:
  source:
    type: s3
    options:
    - name: s3-endpoint
      valueFrom:
        secretKeyRef:
          name: s3-config
          key: endpoint
    - name: s3-access-key-id
      valueFrom:
        secretKeyRef:
          name: s3-config
          key: accessKeyID
    - name: s3-secret-access-key
      valueFrom:
        secretKeyRef:
          name: s3-config
          key: secretAccessKey
    - name: s3-uri
      value: s3://bucket/path/subpath

在该例中,通过 spec.source.type 字段指定源存储服务类型为 S3,通过 spec.source.options 字段指定源存储服务选项:

  • s3-endpoint:S3 端点,引用 Secret s3-config 的键 endpoint 的值。
  • s3-access-key-id:S3 服务的 AccessKeyID 凭证,引用 Secret s3-config 的键 accessKeyID 的值。
  • s3-secret-access-key:S3 服务的 SecretAccessKey 凭证,引用 Secret s3-config 的键 secretAccessKey 的值。
  • s3-uri:S3 文件或目录的路径。

上传数据

设置 PVC

上传 PVC 数据:

spec:
  source:
    type: pvc
    pvc:
      name: datacube-pvc
      subPath: dev/hf/whisper-large-v3

在该例中,上传 PVC datacube-pvc 的子路径 dev/hf/whisper-large-v3 到目标存储服务。

设置目标存储服务

Git

上传 PVC 的一个 Git 仓库到目标数据存储服务:

spec:
  source: 
    type: pvc
    pvc:
      name: datacube-pvc
      subPath: dev/git/
  sink:
    type: git
    options:
    - name: token
      valueFrom:
        secretKeyRef:
          name: github-token
          key: token
    - name: url
      value: https://$(TOKEN)@github.com/user/repo.git

在该例中,上传 PVC datacube-pvcdev/git/ 路径下的 repo 目录(由 spec.sink.options 字段指定,其中 url 指向的仓库名称即为目录名称),通过 spec.sink.type 字段指定目标存储服务类型为 Git,通过 spec.sink.options 字段指定目标存储选项:

  • token:个人访问令牌(personal access token),引用 Secret github-token 的键 token 的值,该字段是可选的。
  • url:Git 仓库路径,以 $(TOKEN) 引用的形式嵌入 token。

Hugging Face

上传 PVC 的文件或目录到 Hugging Face 仓库:

spec:
  sink: 
    type: huggingface
    options:
    - name: token
      valueFrom:
        secretKeyRef:
          name: hf-token
          key: token
    - name: repo
      value: user/repo
    - name: path-in-repo
      value: pvc/demo
    - name: commit-message
      value: Upload files from PVC

在该例中,通过 spec.sink.type 字段指定目标存储服务类型为 Hugging Face,通过 spec.sink.options 字段指定目标存储选项:

  • token:Hugging Face token,引用 Secret hf-token 的键 token 的值,该字段是可选的。
  • repo:Hugging Face 仓库名称。
  • path-in-repo:仓库中的路径,数据将被上传到这里。
  • commit-message:提交信息,该字段是可选的。

S3

上传 PVC 的文件或目录到 S3:

spec:
  sink: 
    type: s3
    options:
    - name: s3-endpoint
      valueFrom:
        secretKeyRef:
          name: s3-config
          key: endpoint
    - name: s3-access-key-id
      valueFrom:
        secretKeyRef:
          name: s3-config
          key: accessKeyID
    - name: s3-secret-access-key
      valueFrom:
        secretKeyRef:
          name: s3-config
          key: secretAccessKey
    - name: s3-uri
      value: s3://bucket/path/subpath
    - name: s3-no-check-bucket
      value: "true"

在该例中,通过 spec.sink.type 字段指定目标存储服务类型为 S3,通过 spec.sink.options 字段指定目标存储选项:

  • s3-endpoint:S3 端点,引用 Secret s3-config 的键 endpoint 的值。
  • s3-access-key-id:S3 服务的 AccessKeyID 凭证,引用 Secret s3-config 的键 accessKeyID 的值。
  • s3-secret-access-key:S3 服务的 SecretAccessKey 凭证,引用 Secret s3-config 的键 secretAccessKey 的值。
  • s3-uri:S3 路径,上传数据到该路径下。
  • s3-no-check-bucket:不检查 bucket 是否存在,当上述凭证不具备检查 bucket 的权限时需要设置,该字段是可选的。

数据传输设置

执行策略

DataCube 支持限制数据传输的失败重试次数,以及每次数据传输的最大执行时间:

spec:
  executor:
    options:
      backoffLimit: 2
      activeDeadlineSeconds: 3600

在该例中:

  • 设置最多失败重试 2 次(由 spec.executor.options.backoffLimit 字段指定),重试达到限制次数时,标记该 DataCube 失败;默认为 0,即不执行失败重试。
  • 设置每次数据传输最多执行 3600 秒(由 spec.executor.options.activeDeadlineSeconds 字段指定),当本次数据传输达到限制时长时,标记本次数据传输失败,将会进行重试;默认为空,即不限制执行时间。

额外参数

指定数据传输时额外的参数:

spec:
  executor:
    options:
      extraArgs:
      - --cache-dir
      - /tmp/cache/hf

在该例中,通过 spec.executor.options.extraArgs 指定缓存目录 --cache-dir/tmp/cache/hf,适用于下载 Hugging Face 文件。

环境变量

设置数据传输时的环境变量:

spec:
  executor:
    env:
    - name: HTTPS_PROXY
      value: <host>:<port>

在该例中,通过 spec.executor.env 定义了数据传输时的网络代理,表示使用该网络代理进行数据下载或上传。

S3 同步

在下载 S3 数据到 PVC 时,可以设置使用同步模式:

spec:
  executor:
    options:
      sync: true

在该例中,通过 spec.executor.options.sync 定义了使用同步模式,表示完全同步 S3 数据内容到 PVC,会删除 PVC 子目录中多余的文件。

状态

Pod 状态

执行数据传输的 Pod 状态信息记录在 status.pod 中:

status:
  pod:
    phase: Succeeded
    reference:
      name: s3-upload-file-batchjob-h4fsn
      uid: 8789c49a-ce14-4daa-b2d3-46a32a1decec
    status: Completed

DataCube 状态

DataCube 的状态信息记录在 status.conditions 中,包括 3 种类型:

  • Initialized:DataCube 已经成功创建 Pod 并正常启动,执行数据传输任务。
  • Complete:DataCube 数据传输完成。
  • Failed:DataCube 数据传输失败。

下面是一个状态信息的示例:

status:
  conditions:
  - lastProbeTime: "2024-04-25T06:28:45Z"
    lastTransitionTime: "2024-04-25T06:28:45Z"
    message: The DataCube is initialized
    status: "True"
    type: Initialized
  - lastProbeTime: "2024-04-25T06:28:45Z"
    lastTransitionTime: "2024-04-25T06:28:45Z"
    message: The DataCube is complete
    status: "True"
    type: Complete
  - lastProbeTime: "2024-04-25T06:28:45Z"
    lastTransitionTime: "2024-04-25T06:28:38Z"
    status: "False"
    type: Failed

参考

ServiceAccountToken

平台提供 CRD ServiceAccountToken,用于生成一个 kubeconfig,以便用户从本地通过 kubectl 访问集群。

创建 ServiceAccountToken

下面是一个基本的 ServiceAccountToken 示例:

apiVersion: tensorstack.dev/v1beta1
kind: ServiceAccountToken
metadata:
  name: sat-sample
spec:
  duration: 1h

在该例中,创建一个有效期为 1h(由 spec.duration 字段指定)的 ServiceAccountToken。系统将会生成一个 JSON 网络令牌(JSON Web Token)和一个 kubeconfig,你可以使用它们作为凭证来访问集群。

有效期设置

spec.duration 字段定义 ServiceAccountToken 的有效期:

  • 类型是 string,并且需要匹配正则表达式 ^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?)$
  • 支持的时间单位:y, w(周), d, h, m, s。
  • 示例:“3w”,“2h45m”。

状态

Secret 名称

ServiceAccountToken 创建后,系统同步创建的 tokenkubeconfig 存储在一个 Secret 中,并将 Secret 名称记录在 status.secretRef.name 中:

status:
  secretRef:
    name: sat-sample-fced8

Secret sat-sample-fced8 存储以下两个键值对:

  • token:表示一个 ServiceAccount token,你可以在 HTTP 请求头中以 Authorization: Bearer <token> 的形式使用。
  • kubeconfig:表示一个 kubeconfig 文件内容,你可以将该内容保存到本地路径下,并在 kubectl 命令中通过 --kubeconfig 参数指定文件路径使用。

通过如下命令将 kubeconfig 保存到本地并使用:

kubectl get secret sat-sample-fced8 -o jsonpath='{.data.kubeconfig}' | base64 -d > mykubeconfig
kubectl --kubeconfig mykubeconfig get pod

过期时间

ServiceAccountToken 创建后,token 的实际过期时间记录在 status.expirationTime 中:

status:
  expirationTime: "2024-05-10T04:11:41Z"

在该例中,ServiceAccountToken 将在 2024-05-10T04:11:41Z(即北京时间 2024-05-10 12:11:41)过期。

ServiceAccountToken 状态

status.conditions 字段用于描述当前 ServiceAccountToken 的状态,包括以下一种类型:

  • Ready:ServiceAccountToken 准备就绪,处于可用状态。

下面是一个状态信息的示例:

status:
  conditions:
  - lastTransitionTime: "2024-05-10T02:51:41Z"
    message: All subresources are ready
    reason: SubresourcesReady
    status: "True"
    type: Ready

在该例中,所有子资源均就绪,ServiceAccountToken 是可用的。

参考

工作流

AI 任务由很多基础计算步骤构成,具有很大的灵活性,在不同场景需要做各种定制计算处理。例如,一个模型训练过程可能包含数据取样、数据转换、模型训练、模型质检、模型导出等步骤。

为此 TensorStack AI 平台提供了一个灵活的工作流服务,将这些计算步骤组合在一起,集中进行管理和调度,自动化复杂的流程。

架构

工作流模块提供了 WorkflowTemplateWorkflowRunCronWorkflowRun 等自定义扩展资源,以及控制台、服务器、操作器等组件。整体架构如下图所示:

architecture

其中:

  • 控制台(Console)提供前端界面,方便用户对 WorkflowTemplate、WorkflowRun 等资源进行创建、查看、删除等操作。
    • 用户也可以直接使用命令行工具 kubectl 创建 workflow 的资源。
  • 服务器(Server)向工作流控制台提供 API 接口,帮助获取 WorkflowTemplate、WorkflowRun 等资源的详细信息。
  • 控制器(Controller),负责监控集群中的 WorkflowTemplate、WorkflowRun 等资源,并执行一些与资源相关的操作,使资源当前的状态与其理想状态一致。

与其他模块的关系

如下图所示,Workflow 可以将分布式并行作业、非并行作业组合在一起成为复合作业,而且复合作业中可以嵌套复合作业,并通过 T9k 调度器进行计算资源的匹配,最终完成复杂的多步骤计算。

workflow-and-jobs

WorkflowTemplate

WorkflowTemplate 用于在 Kubernetes 中有序、高效、方便地组织运行各类工作负载,例如机器学习流水线中的数据处理、模型训练、推理测试等具有依赖关系的多个步骤。WorkflowTemplate 是一个静态模板,指定了任务的详细规范,最终由 WorkflowRun 实例化并真正开始运行。

创建 WorkflowTemplate

下面的 WorkflowTemplate 示例创建并运行一个 Kubernetes Pod

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: workflowtemplate-sample
spec:
  description: This WorkflowTemplate creates and runs a Pod.
  type: Pod
  pod:
    containers:
      - name: hello
        image: ubuntu:latest
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["echo"]
        args: ["Hello TensorStack!"]

在该例中:

  • description 字段简要介绍了该 WorkflowTemplate 的用途,会在控制台中展示。
  • WorkflowTemplate 的类型(由 type 字段指定)是 Pod,表示 WorkflowTemplate 会创建并运行一个 Pod。
  • pod 字段定义所要创建的 Pod 的规约,指示 Pod 运行一个 hello 容器,该容器运行镜像 ubuntu:latest 并打印一个字符串 Hello TensorStack!

WorkflowTemplate 类型

WorkflowTemplate 的 spec.type 字段用于指定 WorkflowTemplate 的类型,可能的取值有:

Pod WorkflowTemplate

Pod WorkflowTemplate 用于创建一个原生的 Kubernetes Pod。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: pod-workflowtemplate-sample
spec:
  type: Pod
  pod:
    containers:
      - name: hello
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["sh", "-c"]
        args: ["echo Hello World!"]

spec.pod 中可以填写的字段与 Kubernetes Pod 相同。

SeqPod WorkflowTemplate

SeqPod WorkflowTemplate 用于创建一个经过包装的 Pod,在 Pod 中按顺序执行一些步骤。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: seqpod-workflowtemplate-sample
spec:
  type: SeqPod
  seqPod:
    steps:
      - name: hello
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["sh", "-c"]
        args: ["echo Hello World!"]
      - name: working
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["sh", "-c"]
        args: ["echo I am working!"]
      - name: bye
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["sh", "-c"]
        args: ["echo Goodbye!"]

SeqPod 中的每个步骤(step)对应 Kubernetes Pod 中的一个容器,但 SeqPod 会按照顺序依次执行每个步骤,直到所有的步骤成功运行完毕,或者其中某个步骤失败(后续的步骤不会再运行)。

pod.containers[*].commandpod.containers[*].argsseqPod.steps[*].commandseqPod.steps[*].args 等字段中,你有时候可能需要填写带有引号的字符串,有以下几种合法的方式:

command: ["echo"]
args: ["this is a 'quote'"]
command: ['echo']
args: ['this is a "quote"']
command:
  - echo
args:
  - this is a "quote"
command:
  - echo
args:
  - this is a 'quote'

指定 script

SeqPod 的每个步骤可以指定 script 字段,即一段脚本语言(例如 Bash、Python)编写的代码,用于代替 command 字段。script 脚本会在容器开始运行时代替 command 被调用,而 args 会被当做参数传递给 script 脚本。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: seqpod-workflowtemplate-sample-script
spec:
  type: SeqPod
  seqPod:
    steps:
      - name: hello
        image: python
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        script: |
          #!/usr/bin/env python3
          print("Hello from Python!")

如果 script 脚本的开头不包含以 #! 开头的字符串(shebang),以下字符串会被自动添加到 script 脚本的开头:

#!/bin/bash
set -e # Immediately exit if any command exited with non-zero status. 

保留目录

为了 SeqPod WorkflowTemplate 的正常工作,最终生成的 Pod 有一些特殊的保留目录:

  • /t9k/workspaces:用于挂载 workspaces,你可以通过 $(workspaces.<workspaceName>.path) 来使用该路径。
  • /t9k/results:用于存储 results,你可以通过 $(results.<resultName>.path) 来使用该路径。
  • /t9k/tools:用于保证 SeqPod 中 steps 顺序执行的辅助工具,与用户无关。
  • /t9k/termination:用于写入 Pod 的 termination message,与用户无关。

Resource WorkflowTemplate

Resource WorkflowTemplate 用于创建另一个 Kubernetes 资源,并监测该资源的运行状态。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: resource-workflowtemplate-sample
spec:
  type: Resource
  resource:
    manifest: |
      apiVersion: batch/v1
      kind: Job
      metadata:
        generateName: pi-job-
      spec:
        template:
          metadata:
            name: pi
          spec:
            containers:
            - name: pi
              image: perl
              command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
            restartPolicy: Never
        backoffLimit: 4
    successRules:
      fieldSelector: status.succeeded > 0
    failureRules:
      fieldSelector: status.failed > 3

spec.resource 的各个字段含义如下:

  • manifest:所要创建的 Kubernetes 资源的详细配置。
  • successRules:如果所创建的资源满足该条件,本 WorkflowTemplate 视为成功。
  • failureRules:如果所创建的资源满足该条件,本 WorkflowTemplate 视为失败。

fieldSelector 的写法与 Kubernetes 标签选择器的语法相同但更强大,除了标签之外还能应用到资源的任意字段,支持的运算符有 ><==!=innotin 等,多个需要同时满足的条件可以用逗号连接。例如,以下都是合法的 fieldSelector

  • status.succeeded>0
  • status.succeeded > 0
  • status.succeeded > 0,status.failed == 0
  • status.phase in (Succeeded, Failed),status.workflowTemplateSpec.type == DAG

另外,successRulesfailureRules 还支持设置 conditionSelector。如果所创建的资源的 status.conditions 字段包含一个 condition,其 typestatus 都与 conditionSelector 相同,就认为该资源满足条件。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: resource-workflowtemplate-sample-condition
spec:
  type: Resource
  resource:
    manifest: |
      apiVersion: batch.tensorstack.dev
      kind: TensorFlowTrainingJob
      metadata:
        generateName: t9k-training-job-
      spec:
        ...
    successRules:
      conditionSelector:
        type: Succeeded
        status: "True"
    failureRules:
      conditionSelector:
        type: Failed
        status: "True"

如果所创建的资源类型是下列 T9k Job 之一,系统将自动帮助填写 successRulesfailureRules,以减轻你的负担:

  • GenericJob
  • MPIJob
  • BeamJob
  • TensorFlowTrainingJob
  • PyTorchTrainingJob
  • XGBoostTrainingJob

创建 Resource WorkflowTemplate 对应的 WorkflowRun 时需要提供一个 Service Account,使得 WorkflowRun 具有在 Kubernetes 中创建该 Resource 的权限。例如:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
  name: resource-workflowtemplate-sample-run
spec:
  workflowTemplateRef: resource-workflowtemplate-sample
  serviceAccountName: managed-project-sa

在网页中创建 WorkflowRun 时,系统将自动为你配置名为 managed-project-sa 的 Service Account,你不用关心这一项的填写。

T9k Job WorkflowTemplate

T9k Workflow 系统对 T9k Job 提供更进一步的原生支持,添加以下 WorkflowTemplate 类型:

  • GenericJob
  • TensorFlowTrainingJob
  • PyTorchTrainingJob
  • XGBoostTrainingJob
  • ColossalAIJob
  • DeepSpeedJob
  • MPIJob
  • BeamJob

并在 WorkflowTemplate 的 spec 中添加了相应字段用于填写 T9k Job 的 spec

  • spec.genericJob
  • spec.tensorflowTrainingJob
  • spec.pytorchTrainingJob
  • spec.xgboostTrainingJob
  • spec.colossalaiJob
  • spec.deepspeedJob
  • spec.mpiJob
  • spec.beamJob

相比于在 Resource 类型中将资源的 spec 视作一个很长的字符串,添加原生类型支持的好处是在创建 WorkflowTemplate 时 T9k Job 的 spec 就会得到语法检查,能更早地发现错误,加深了 T9k Workflow 系统和 T9k Job 系统的集成配合。

例如,创建一个 MPIJob 可以使用如下格式(其中 MPIJob 示例来自 MPIJob 文档):

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: mpijob-workflowtemplate-sample
spec:
  type: MPIJob
  mpiJob:
    spec:
      worker:
        replicas: 5
        processesPerWorker: 3
        processRecovery:
          enable: true
          limit: 100
        cmd:
          - ./random_walk
          - "20"
          - "40"
          - "2"
        template:
          spec:
            containers:
              - name: mpi-worker
                image: t9kpublic/mpi-tutorial:2021022-2
                resources:
                  limits:
                    cpu: 100m
                  requests:
                    cpu: 50m
                workingDir: /usr/local/code
      mca:
        btl: ^openib
      runPolicy:
        cleanUpWorkers: true
      ssh:
        sshdPath: /usr/sbin/sshd
      mpiHome: /usr/local

DAG WorkflowTemplate

DAG WorkflowTemplate 用于创建一个由其他 WorkflowTemplate 组成的有向无环图(DAG,Directed Acyclic Graph),按照有向无环图中的依赖关系按顺序执行这些 WorkflowTemplate。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: dag-workflowtemplate-sample
spec:
  type: DAG
  dag:
    templates:
      - name: a
        workflowTemplateRef: pod-workflowtemplate-sample
        dependencies: []
      - name: b1
        workflowTemplateRef: pod-workflowtemplate-sample
        dependencies: ["a"]
      - name: b2
        workflowTemplateRef: pod-workflowtemplate-sample
        dependencies: ["a"]
      - name: c
        workflowTemplateRef: pod-workflowtemplate-sample
        dependencies: ["b1", "b2"]

在上面的示例中,首先运行 WorkflowTemplate a,等待 WorkflowTemplate a 运行完毕之后再同时运行 WorkflowTemplate b1 和 b2。WorkflowTemplate c 会在 b1 和 b2 都结束后运行。这些 WorkflowTemplates 组成一个从上往下顺序执行的有向无环图:

   a
 /   \
b1   b2
 \   /
   c

指定参数

你可以为 WorkflowTemplate 指定一些参数,并在 spec 中用 $(params.<paramName>) 来引用参数。WorkflowRun 会在运行时为这些参数提供实际值。支持 params 的 WorkflowTemplate 类型有 Pod、SeqPod、DAG,详见支持变量替换的 WorkflowTemplate 字段

Pod WorkflowTemplate 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: pod-workflowtemplate-sample-params
spec:
  params:
    - name: message
      default: "hi"
  type: Pod
  pod:
    containers:
      - name: hello
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["sh", "-c"]
        args: ["echo $(params.message)"]

SeqPod WorkflowTemplate 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: seqpod-workflowtemplate-sample-params
spec:
  params:
    - name: message
      default: hi
  type: SeqPod
  seqPod:
    steps:
      - name: hello
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        script: |
          #!/bin/sh
          echo $(params.message)

DAG WorkflowTemplate 在引用其他的 WorkflowTemplate 作为节点时,必须提供该节点需要的 params,可以是静态的字符串,也可以引用 DAG WorkflowTemplate 自身的 params 变量或其他变量。示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: dag-workflowtemplate-sample-params
spec:
  params:
    - name: dag-param
  type: DAG
  dag:
    templates:
      - name: step0
        workflowTemplateRef: pod-workflowtemplate-sample-params
        dependencies: []
        params:
          - name: message
            value: Hello World!
      - name: step1
        workflowTemplateRef: seqpod-workflowtemplate-sample-params
        dependencies: ["step0"]
        params:
          - name: message
            value: "$(params.dag-param)"
      - name: step2
        workflowTemplateRef: seqpod-workflowtemplate-sample-params
        dependencies: ["step1"]
        params:
          - name: message
            value: "DAG WorkflowTemplate provides param $(params.dag-param) for you"

指定工作空间

你可以为 WorkflowTemplate 指定可用的存储空间,并在 spec 中用 $(workspaces.<workspaceName>.path) 来引用存储空间的路径。WorkflowRun 会在运行时指定具体挂载何种存储空间,例如 PVC、Secret、ConfigMap 等。支持 workspaces 的 WorkflowTemplate 类型有 Pod、SeqPod、DAG。

Pod WorkflowTemplate 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: pod-workflowtemplate-sample-workspace
spec:
  workspaces:
    - name: pod-workspace
  type: Pod
  pod:
    containers:
      - name: hello
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["sh", "-c"]
        args: ["echo Hello World! > $(workspaces.pod-workspace.path)/output.txt"]

SeqPod WorkflowTemplate 示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: seqpod-workflowtemplate-sample-workspaces
spec:
  workspaces:
    - name: seqpod-workspace
  type: SeqPod
  seqPod:
    steps:
      - name: hello
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        script: |
          #!/bin/sh
          echo Hello World! > $(workspaces.seqpod-workspace.path)/output.txt

DAG WorkflowTemplate 在引用其他的 WorkflowTemplate 作为节点时,必须提供该节点需要的 workspaces,一般通过 DAG WorkflowTemplate 自身的 workspaces 继承而来。示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: dag-workflowtemplate-sample-workspaces
spec:
  workspaces:
    - name: dag-workspace
  type: DAG
  dag:
    templates:
      - name: step0
        workflowTemplateRef: pod-workflowtemplate-sample-workspace
        dependencies: []
        workspaces:
          - name: pod-workspace
            workspace: dag-workspace
      - name: step1
        workflowTemplateRef: seqpod-workflowtemplate-sample-workspace
        dependencies: ["step0"]
        workspaces:
          - name: seqpod-workspace
            workspace: dag-workspace
      - name: step2
        workflowTemplateRef: seqpod-workflowtemplate-sample-workspace
        dependencies: ["step1"]
        workspaces:
          - name: seqpod-workspace
            workspace: dag-workspace

输出结果

WorkflowTemplate 可以在运行过程中输出一些字符串,并最终展示在 WorkflowRun 的 status 中。支持 results 的 WorkflowTemplate 类型有 SeqPod、DAG。

每个 result 本质上是一个文件,如下例所示,你可以向 $(results.<resultName>.path) 这个路径写入想要输出的内容。注意写入内容的总和不能超过 4096 字节。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: seqpod-workflowtemplate-sample-result
spec:
  results:
    - name: my-status
      description: "My status"
  type: SeqPod
  seqPod:
    steps:
      - name: echo
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        script: |
          echo I am OK > $(results.my-status.path)

results 更重要的用途是在 DAG WorkflowTemplate 的节点之间传递信息。DAG 的各个节点可以通过 $(templates.<workflowtemplateName>.results.<resultName>) 来引用这些 results,一般有两种用途:

  • DAG 的下层节点可以在 paramswhen 字段引用上层节点的 results
  • DAG WorkflowTemplate 可以组合节点的 results 来输出自身的 results
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: add-workflowtemplate
spec:
  params:
    - name: first
      description: the first operand
    - name: second
      description: the second operand
  results:
    - name: sum
      description: the sum of the first and second operand
  type: SeqPod
  seqPod:
    steps:
      - name: add
        image: ubuntu
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        env:
          - name: OP1
            value: $(params.first)
          - name: OP2
            value: $(params.second)
        command: ["/bin/sh", "-c"]
        args:
          - echo -n $((${OP1}+${OP2})) | tee $(results.sum.path);
---
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: sum-three-workflowtemplate
spec:
  params:
    - name: first
      description: the first operand
    - name: second
      description: the second operand
    - name: third
      description: the third operand
  type: DAG
  dag:
    templates:
      - name: first-add
        workflowTemplateRef: add-workflowtemplate
        params:
          - name: first
            value: $(params.first)
          - name: second
            value: $(params.second)
      - name: second-add
        workflowTemplateRef: add-workflowtemplate
        params:
          - name: first
            value: $(templates.first-add.results.sum)
          - name: second
            value: $(params.third)
  results:
    - name: total-sum
      description: the sum of all three operands
      value: $(templates.second-add.results.sum)
    - name: partial-sum
      description: the sum of first two operands
      value: $(templates.first-add.results.sum)

条件分支

在 DAG WorkflowTemplate 中,如果需要在某个条件满足时才执行某个节点,可以设置 when 字段。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: flip-coin
spec:
  results:
    - name: coin
      description: Which side? Heads or tails?
  type: SeqPod
  seqPod:
    steps:
      - name: flip-coin
        image: python
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        script: |
          #!/usr/bin/env python3
          import random
          f = open("$(results.coin.path)", "w")
          if random.random() > 0.5:
            f.write("heads")
          else:
            f.write("tails")
          f.close()
---
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: dag-workflowtemplate-sample-when
spec:
  type: DAG
  dag:
    templates:
      - name: flip-coin
        workflowTemplateRef: flip-coin
      - name: execute-only-if-heads
        workflowTemplateRef: pod-workflowtemplate-sample
        dependencies: ["flip-coin"]
        when:
          - input: "$(templates.flip-coin.results.coin)"
            operator: in
            values: ["heads"]

when 字段包含一些表达式:

  • input:表达式的输入,可以是静态字符串或 paramsresults 等变量。如果未填写,默认为一个空的字符串。
  • operator:表示 inputvalues 的关系,可以是 in 或者 notin
  • values:字符串数组,可以是静态字符串或 paramsresults 等变量。

只有当 when 字段包含的所有表达式结果都为真时,该节点才会被运行,否则会跳过该节点继续运行其他节点。

如果一个节点的 when 表达式中引用了其他节点的 results 变量,相当于引入了前者对后者的依赖关系,前者会在后者运行结束后才开始运行。

失败处理

对于 Pod/SeqPod/Resource WorkflowTemplate,一个 WorkflowRun 只对应一次运行,即使失败也不会重启。也就是说,一个 WorkflowRun 对应产生的 Pod 的 specrestartPolicy 永远是 Never

对于 DAG WorkflowTemplate,DAG 的每个节点都有可能会失败,我们使用 retries 字段来控制节点的重启。

  • retries = 0(默认选项)表示不重启失败的节点。
  • retries > 0 表示会重启失败的节点,并用一个正整数来限制最多可重启的次数。

如果 DAG 的某个节点失败并超过了最大可重启次数,该节点将被视为永久失败,并由 spec.dag.failureStrategy 决定接下来的行为:

  • failureStrategy = StopAllWorkflowTemplates(默认选项)表示停止创建任何新的节点。
  • failureStrategy = StopDependentWorkflowTemplates 表示只停止创建依赖于失败节点的节点,其他分支上的节点正常创建。

注意无论是哪种策略,已开始运行的节点都会等待其运行结束。

在下面的 DAG WorkflowTemplate 示例中,共有两个节点 ab

  • 如果 a 节点运行失败,它最多可以重试 5 次。
  • 如果 b 节点运行失败,它不能进行重试,直接被认定为失败。
  • 如果任意一个节点被认定为失败,整个 DAG WorkflowTemplate 也会被认定为失败,并且由于 spec.dag.failureStrategy 字段的值为 StopAllWorkflowTemplates,所有未开始运行的节点都不再运行。
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: dag-workflowtemplate-sample-retries
spec:
  type: DAG
  dag:
    failureStrategy: StopAllWorkflowTemplates
    templates:
      - name: a
        workflowTemplateRef: pod-workflowtemplate-sample
        dependencies: []
        retries: 5
      - name: b
        workflowTemplateRef: pod-workflowtemplate-sample
        dependencies: ["a"]
        retries: 0

下一步

WorkflowRun

WorkflowRun 是 WorkflowTemplate 的一次执行,为 WorkflowTemplate 提供运行时所需的一切资源,例如参数(params)、工作空间(workspaces)。

创建引用某个 WorkflowTemplate 的 WorkflowRun

下面的 WorkflowRun 示例为一个 WorkflowTemplate 创建一次运行。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
  name: workflowrun-sample
spec:
  workflowTemplateRef: workflowtemplate-sample

在该例中,workflowTemplateRef 字段标明所要运行的 WorkflowTemplate 的名称,该 WorkflowTemplate 必须是一个已经创建好的、与该 WorkflowRun 在同一个命名空间的 WorkflowTemplate。

创建内嵌 WorkflowTemplate 规约的 WorkflowRun

下面的 WorkflowRun 示例也是为一个 WorkflowTemplate 创建一次运行,但是该 WorkflowTemplate 的规约直接在 WorkflowRun 的规约中填写。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
  name: embedded-workflowrun-sample
spec:
  workflowTemplateSpec:
    type: Pod
    pod:
      containers:
        - name: hello
          image: ubuntu:latest
          command: ["echo"]
          args: ["Hello TensorStack!"]

在该例中,workflowTemplateSpec 字段用于填写所要运行的 WorkflowTemplate 的规约,WorkflowTemplate 规约的写法详见 WorkflowTemplateSpec(坏链)。

WorkflowRun 状态

在下面的示例中,首先创建一个类型为 DAG 的 WorkflowTemplate,然后创建一个 WorkflowRun 引用该 WorkflowTemplate。

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: dag-workflowtemplate-sample
spec:
  type: DAG
  dag:
    templates:
      - name: a
        workflowTemplateRef: pod-workflowtemplate-sample
      - dependencies:
          - a
        name: b1
        workflowTemplateRef: pod-workflowtemplate-sample
      - dependencies:
          - a
        name: b2
        workflowTemplateRef: pod-workflowtemplate-sample
      - dependencies:
          - b1
          - b2
        name: c
        workflowTemplateRef: pod-workflowtemplate-sample
---
apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowRun
metadata:
  labels:
    batch.tensorstack.dev/workflowTemplate: dag-workflowtemplate-sample
  name: dag-workflowtemplate-sample-run
spec:
  serviceAccountName: ''
  workflowTemplateRef: dag-workflowtemplate-sample
status:
  completionTime: '2021-04-16T07:39:05Z'
  conditions:
    - lastTransitionTime: '2021-04-16T07:39:05Z'
      status: 'False'
      type: Running
    - lastTransitionTime: '2021-04-16T07:39:05Z'
      status: 'True'
      type: Completed
  message: All nodes in DAG have succeeded
  nodes:
    a:
      phase: Succeeded
      workflowRunName: dag-workflowtemplate-sample-run-a-pmb2m
    b1:
      phase: Succeeded
      workflowRunName: dag-workflowtemplate-sample-run-b1-mssn6
    b2:
      phase: Succeeded
      workflowRunName: dag-workflowtemplate-sample-run-b2-5db66
    c:
      phase: Succeeded
      workflowRunName: dag-workflowtemplate-sample-run-c-sjpb2
  phase: Succeeded
  startTime: '2021-04-16T07:38:10Z'
  workflowTemplateSpec:
    dag:
      templates:
        - name: a
          workflowTemplateRef: pod-workflowtemplate-sample
        - dependencies:
            - a
          name: b1
          workflowTemplateRef: pod-workflowtemplate-sample
        - dependencies:
            - a
          name: b2
          workflowTemplateRef: pod-workflowtemplate-sample
        - dependencies:
            - b1
            - b2
          name: c
          workflowTemplateRef: pod-workflowtemplate-sample
    type: DAG

WorkflowTemplate dag-workflowtemplate-sample 有四个节点,分别是:

  • a
  • b1
  • b2
  • c

WorkflowRun dag-workflowtemplate-sample-run 被创建后,WorkflowRun 控制器会为这四个节点创建四个 WorkflowRun,分别是

  • dag-workflowtemplate-sample-run-a-pmb2m
  • dag-workflowtemplate-sample-run-b1-mssn6
  • dag-workflowtemplate-sample-run-b2-5db66
  • dag-workflowtemplate-sample-run-c-sjpb2

如果这四个 WorkflowRun 均运行成功,WorkflowRun dag-workflowtemplate-sample-run 即运行成功。

WorkflowRun dag-workflowtemplate-sample-runstatus 字段显示,该 WorkflowRun 处于 Succeeded 状态(见 status.phase 字段),原因是 “All nodes in DAG have succeeded”(见 status.message 字段)。status.nodes 字段记录了该 WorkflowRun 中每个 DAG 节点的名称以及对应的 WorkflowRun 名称和状态。

下一步

CronWorkflowRun

CronWorkflowRun 用于方便地定时执行 WorkflowRun,对于创建周期性的、反复重复的任务很有用。

cron 是一种书写定时计划的格式,用一个字符串指定何时触发任务的执行,通常由以空格分隔的 5 个部分组成:

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                   7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *

例如:

  • 1 0 * * * 表示在每天的 00:01 执行。
  • 45 23 * * 6 表示在每个星期六的 23:45 执行。
  • */5 1,2,3 * * * 表示在每天的第 1、2、3 个小时每隔 5 分钟执行一次(即 01:00,01:05,01:10,...,03:55)。

注意 */n 表示每隔 n 个时间单位执行一次,在某个时间单位多次执行可以用逗号连接(例如 1,2,3)。

为了更方便地创建 cron 表达式,可以使用第三方网页工具,例如 crontab.guru

创建 CronWorkflowRun

下面的 CronWorkflowRun 示例会每分钟创建一个 WorkflowRun。

apiVersion: batch.tensorstack.dev/v1beta1
kind: CronWorkflowRun
metadata:
  name: cronworkflowrun-sample
spec:
  schedule: "*/1 * * * *"
  workflowRun:
    spec:
      workflowTemplateRef: workflowtemplate-sample

在该例中:

  • schedule 字段是一个 cron 格式的字符串,表示每分钟触发一次 WorkflowRun 的运行。
  • 所要运行的 WorkflowRun 由 workflowRun 字段定义,是一个引用 workflowtemplate-sample 的 WorkflowRun。

详细配置 CronWorkflowRun

下面是一个经过详细配置的 CronWorkflowRun 示例,与上一节类似,也会每分钟创建一个 WorkflowRun。

apiVersion: batch.tensorstack.dev/v1beta1
kind: CronWorkflowRun
metadata:
  name: cronworkflowrun-sample
spec:
  schedule: "*/1 * * * *"
  startingDeadlineSeconds: 30
  concurrencyPolicy: "Allow"
  suspend: true
  successfulRunsHistoryLimit: 10
  failedRunsHistoryLimit: 10
  workflowRun:
    spec:
      workflowTemplateRef: workflowtemplate-sample

在该例中:

  • 如果某个 WorkflowRun 由于任何原因未能准时在预设的时间点开始执行,它在 30 秒钟的期限内必须开始执行(由 startingDeadlineSeconds 字段指定),否则将被认为该次执行已失败。
  • 如果到了某个 WorkflowRun 应该开始执行的时间点,但是上一个 WorkflowRun 仍未运行完成,允许这两个 WorkflowRun 同时运行(由 concurrencyPolicy 字段指定)。
  • suspend 字段为 true 表示暂时停止创建新的 WorkflowRun,该字段可以随时变化。
  • 由该 CronWorkflowRun 创建的所有 WorkflowRun 中,最多保留 10 个运行成功的 WorkflowRun 和 10 个运行失败的 WorkflowRun(分别由 successfulRunsHistoryLimitfailedRunsHistoryLimit 字段指定),多余的运行时间较早的 WorkflowRun 会被删除。

CronWorkflowRun 状态

下面是 CronWorkflowRun 的状态示例:

apiVersion: batch.tensorstack.dev/v1beta1
kind: CronWorkflowRun
metadata:
  name: cronworkflowrun-sample
spec:
  schedule: "*/1 * * * *"
  startingDeadlineSeconds: 30
  concurrencyPolicy: "Allow"
  suspend: true
  successfulRunsHistoryLimit: 10
  failedRunsHistoryLimit: 10
  workflowRun:
    spec:
      workflowTemplateRef: workflowtemplate-sample
status:
  active:
  - apiVersion: batch.tensorstack.dev/v1beta1
    kind: WorkflowRun
    name: cronworkflowrun-sample-1631093400
    namespace: t9k-example
    resourceVersion: "220623640"
    uid: 39634803-d8cf-41d4-8a8e-649e0133b11b
  lastScheduleTime: "2021-09-08T09:30:00Z"
  conditions:
  - lastTransitionTime: "2021-09-08T09:23:00Z"
    message: At least one WorkflowRun has started
    status: "True"
    type: HasStarted
  - lastTransitionTime: "2021-09-08T09:30:00Z"
    message: There are running WorkflowRuns
    status: "True"
    type: IsRunning
  - lastTransitionTime: "2021-09-08T09:23:35Z"
    message: There are successful WorkflowRuns
    status: "True"
    type: HasSuccessfulRun
  - lastTransitionTime: "2021-09-08T09:22:08Z"
    message: No failed WorkflowRuns yet
    status: "False"
    type: HasFailedRun

该 CronWorkflowRun 的 status 字段显示:

  • 正在执行中的 WorkflowRun 有一个,其基本信息记录在 status.active 字段中。
  • 最新的 WorkflowRun 的创建时间是 2021-09-08T09:30:00Z(由 status.lastScheduleTime 字段描述)。
  • 在由该 CronWorkflowRun 创建的 WorkflowRun 中,已开始过至少一次 WorkflowRun(可能已结束或未结束),有正在运行中的 WorkflowRun,有已成功的 WorkflowRun,没有失败的 WorkflowRun(由 status.conditions 字段描述)。

WorkflowTrigger

TensorStack AI 平台提供了一个灵活的工作流服务,除了支持手动执行工作流 WorkflowRun,还提供了 CronWorkflowRun 用于定时执行。

Workflow Trigger 模块额外提供了一种基于特定事件自动触发执行 WorkflowRun 的能力,便于用户在一些特定场景下的自动化工作流运行。

架构

Workflow Trigger 模块提供了 EventListener 和 WorkflowTrigger 自定义扩展资源,整体架构如下图所示:

workflow-trigger-architecture

其中:

  • EventListener 作为事件入口接收 JSON 格式的 HTTP POST 请求,同时将请求信息转换成 CloudEvents 格式并转发至事件队列。
  • WorkflowTrigger 绑定一个或多个 EventListener 作为事件源,接收来自这些 EventListener 的 CloudEvents 格式的事件消息,并触发一个 WorkflowRun 的运行。特别地,支持对事件内容进行过滤,以及解析事件的某些字段的值填充到 WorkflowRun 的参数中。

快速开始

下面将通过几个简单的步骤来演示 Workflow Trigger 模块的基本使用方法。下面创建的所有资源请确保属于同一个命名空间。

1)创建 WorkflowTemplate

创建文件 workflow-template-sample.yaml:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: workflow-template-sample
spec:
  description: This WorkflowTemplate creates and runs a Pod.
  params:
    - name: message
      default: "TensorStack"
  type: Pod
  pod:
    containers:
      - name: hello
        image: ubuntu:latest
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
        command: ["echo"]
        args: ["Hello $(params.message)!"]

上面的示例定义了一个名为 message 的参数,同时将该参数值以 $(params.message) 的形式传递到 Pod 的容器的 args 参数上,执行下面的命令创建 WorkflowTemplate:

kubectl apply -f workflow-template-sample.yaml

该 WorkflowTemplate 将作为一个静态模板用于执行一次 WorkflowRun 的运行。

2)创建 EventListener

创建文件 event-listener-sample.yaml:

apiVersion: tensorstack.dev/v1beta1
kind: EventListener
metadata:
  name: event-listener-sample
spec:
  replicas: 1

执行下面的命令创建一个 EventListener:

kubectl apply -f event-listener-sample.yaml

3)创建 WorkflowTrigger

创建文件 workflow-trigger-sample.yaml:

apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
  name: workflow-trigger-sample
spec:
  eventSources:
  - eventListenerName: event-listener-sample
  replicas: 1
  serviceAccountName: managed-project-sa
  workflowRunSpec:
    params:
    - name: message
      value: $(body.hello)
    workflowTemplateRef: workflow-template-sample

上面的示例以 $(body.hello) 的形式将 HTTP 请求体中的 hello 字段值传递到 param message 上,执行下面的命令创建 WorkflowTrigger:

kubectl apply -f workflow-trigger-sample.yaml

4)触发事件

通过执行下面的命令来查询 EventListener HTTP 服务的访问地址:

$ kubectl get eventlisteners event-listener-sample -o json | jq .status.address
{
  "inClusterURL": "http://event-listener-sample-eventlistener-2dbfe.default.svc.cluster.local",
  "url": "https://<tensorstack-host>/t9k/workflow/triggers/default/event-listener-sample"
}

其中 url 字段为集群外部访问 EventListener HTTP 服务的地址,使用 curl 命令向此地址发送 HTTP 请求来模拟触发事件:

curl -X POST https://<tensorstack-host>/t9k/workflow/triggers/default/event-listener-sample \
  -d '{"hello": "world"}'

其中 -d '{"hello": "world"}' 标识 HTTP 请求的 JSON 格式的 body 内容为 {"hello": "world"}hello 字段值 "world" 将作为参数传递到 WorkflowRun,HTTP 服务将返回 success 表示请求已经发送成功。

5)查看 WorkflowRun

上面的步骤全部执行成功以后,WorkflowTrigger 将会触发一次 WorkflowRun 的运行,通过下面的命令进行查询:

$ kubectl get workflowruns
NAME                                                  PHASE
event-listener-sample-workflow-trigger-sample-87a0d   Succeeded

根据返回的结果可以看出,WorkflowRun 已经创建成功。该 WorkflowRun 将根据上面 WorkflowTemplate 静态模块的内容创建一个 Pod,通过下面的命令进行查询:

$ kubectl get pod -l batch.tensorstack.dev/workflowRun=event-listener-sample-workflow-trigger-sample-87a0d
NAME                                                            READY   STATUS      RESTARTS   AGE
event-listener-sample-workflow-trigger-sample-87a0d-pod-6stvb   0/1     Completed   0          3m23s

根据返回的结果可以看出,Pod 已经创建成功,通过查询该 Pod 日志来校验参数传递:

$ kubectl logs event-listener-sample-workflow-trigger-sample-87a0d-pod-6stvb
Hello world!

Pod 日志成功打印出 “world” 内容,其为手动触发事件中发送的 HTTP 请求的 body 内容,参数成功传递。

至此,Workflow Trigger 模块的基本使用方法已经介绍完成,阅读下面的章节来获取更详细的配置信息。

EventListener

EventListener 内部运行着一个 HTTP 服务,用于接收第三方的请求,同时将请求消息转换成 CloudEvents 并将它们转发至事件队列。当前 EventListener 只支持 JSON 格式的 HTTP POST 请求。

创建 EventListener

下面是一个基本的 EventListener 示例:

apiVersion: tensorstack.dev/v1beta1
kind: EventListener
metadata:
  name: event-listener-sample
spec:
  replicas: 1
  resources:
    requests:
      memory: "100Mi"
      cpu: "100m"
    limits:
      memory: "200Mi"
      cpu: "200m"

在该例中:

  • replicas 字段定义所要创建的 Pod 副本数量,默认是 1。
  • resources 字段定义每个 Pod 的资源限制,上述示例为缺省时的默认值。

EventListener 状态

通过 EventListener 的状态字段可以获取其访问地址和运行状态信息,示例如下:

status:
  address:
    inClusterURL: http://<eventlistener-service-name>.default.svc.cluster.local
    url: https://<tensorstack-host>/t9k/workflow/triggers/default/<eventlistener-name>
  conditions:
  - lastTransitionTime: "2022-12-05T10:23:49Z"
    message: The EventListener is Ready
    status: "True"
    type: Ready

其中:

  • status.address 表示 EventListener 所创建的 HTTP 服务的访问地址,第三方可向此地址发送请求,其中:
    • inClusterURL 是只能从集群内部访问的地址。
    • url 是可以从集群外部访问的地址。
  • status.conditions 表示 EventListener 的状态:
    • type: Ready 表示 EventListener 是否就绪,可能的值有 TrueFalseUnknown

WorkflowTrigger

WorkflowTrigger 从一个或多个 EventListener 事件源获取事件消息,并触发一个 WorkflowRun 的运行。

WorkflowTrigger 支持对每个 EventListener 配置过滤条件,只有符合过滤条件的事件消息才会被进一步处理;WorkflowTrigger 同时支持将事件消息的某些字段解析并填充到 WorkflowRun 的参数执行。

创建 WorkflowTrigger

下面是一个基本的 WorkflowTrigger 示例:

apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
  name: workflow-trigger-sample
spec:
  eventSources:
  - eventListenerName: event-listener-sample
  replicas: 1
  resources:
    requests:
      memory: "100Mi"
      cpu: "100m"
    limits:
      memory: "200Mi"
      cpu: "200m"
  serviceAccountName: managed-project-sa
  workflowRunSpec:
    workflowTemplateRef: workflow-template-sample

在该例中:

  • eventSources 字段定义了该 WorkflowTrigger 需要订阅事件消息的事件源集合,其中:
  • eventListenerName 表示上述 EventListener 的名称,该 EventListener 必须与该 WorkflowTrigger 同命名空间、且已成功创建。
  • replicas 字段定义了该 WorkflowTrigger 创建的 Pod 副本数量,默认是 1。
  • resources 字段定义每个 Pod 的资源限制,上述示例为缺省时的默认值。
  • serviceAccountName 字段定义了该 WorkflowTrigger 创建的 Pod 的 ServiceAccount,为创建 WorkflowRun 提供权限。
  • workflowRunSpec 字段定义了将要创建的 WorkflowRun 的配置规约,其中:
    • workflowTemplateRef 表示所要运行的 WorkflowTemplate 的名称,该 WorkflowTemplate 必须与该 WorkflowTrigger 同命名空间、且已成功创建。该字段同时支持内嵌 WorkflowTemplate 规约,详见 WorkflowRun

过滤事件

WorkflowTrigger 支持对来自 EventListener 的事件消息进行过滤,只有符合过滤条件的事件消息才会被进一步处理。下面是一个包含过滤条件的 WorkflowTrigger 示例:

apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
  name: filter-workflow-trigger-sample
spec:
  eventSources:
  - eventListenerName: event-listener-sample
    filters:
    - path: body.object_attributes.work_in_progress
      type: bool
      values:
      - "false"
    - path: body.labels.0.id
      type: number
      values:
      - "219"
      - "3"
      - "99"
    - path: body.object_kind
      type: string
      values:
      - "merge_request"
  serviceAccountName: managed-project-sa
  workflowRunSpec:
    workflowTemplateRef: workflow-template-sample

在该例中,spec.eventSources.filters 定义了该 EventListener 的过滤条件集合,其中:

  • path 表示 HTTP 请求路径,例如 header.X-Github-Event、body.pull_request.state。
  • type 表示该路径指向字段的值的类型,当前支持 bool、number、string。
  • values 表示该路径指向字段的值的可允许值的集合,其为 string 类型。

每个 EventListener 的 filters 互不影响,针对某一个 EventListener,其所有的 filters 必须全部通过才算符合条件。

解析参数

WorkflowTrigger 支持对来自 EventListener 的事件消息进行解析,并将指定字段的值通过参数的形式传递到 WorkflowRun。下面是一个包含解析参数的 WorkflowTrigger 示例:

apiVersion: tensorstack.dev/v1beta1
kind: WorkflowTrigger
metadata:
  name: param-workflow-trigger-sample
spec:
  eventSources:
  - eventListenerName: event-listener-sample
  serviceAccountName: managed-project-sa
  workflowRunSpec:
    params:
    - name: bool-name
      value: $(body.test.boolT)
    - name: number-name
      value: $(body.test.numberT)
    - name: string-name
      value: $(body.test.stringT)
    workflowTemplateRef: workflow-template-sample

在该例中,spec.workflowRunSpec.params 定义了将创建的 WorkflowRun 的参数集合,其中:

  • name 表示参数名称。
  • value 表示参数的值,可通过 $() 形式从事件消息中获取指定字段的值。当前不支持 $() 嵌套。

WorkflowTrigger 状态

通过 WorkflowTrigger 的状态字段可以获取其运行状态信息,示例如下:

status:
  conditions:
  - lastTransitionTime: "2022-12-05T10:26:46Z"
    message: The WorkflowTrigger is Ready
    status: "True"
    type: Ready

其中:

  • status.conditions 表示 WorkflowTrigger 的状态:
    • type: Ready 表示 WorkflowTrigger 是否就绪,可能的值有 TrueFalseUnknown

数据管理

AI 开发和应用的过程中会使用和产生各种各样的数据,包括训练/测试数据集、模型权重、训练/评估配置、训练/评估指标和日志等等。TensorStack AI 平台提供了一套完善的数据管理方案:自研存储系统 AIStore 存储全部数据文件,其实现了版本控制、权限管理、协同开发等功能;资产管理和实验管理两个模块建立在 AIStore 之上,前者专用于存储模型和数据集,后者专用于追踪模型训练。

架构

structure

资产管理和实验管理模块的架构如上图所示,它们使用 AIStore 存储数据,用户可以通过控制台、命令行工具和 SDK 工具与 AIStore 连接,实现这两个模块的各项功能。

资产管理

资产管理模块(Asset Hub,以下简称 AH)提供对模型和数据集的管理功能,包括版本管理、持续开发和协同开发等。这里的资产指的是模型、数据集等 AI 相关的重要资产。

版本控制

AH 支持多版本模型管理,用户可以训练和提交多个临时版本模型,发布其中符合预期的模型。

多版本管理通过以下机制实现:

  • Branch:分支,用户可以创建一个新分支来记录模型的临时版本;将新分支合并到主分支上,完成模型的发布。
  • Commit:“交付”,相当于版本快照,便于确定版本和追溯历史。
  • Tag:标签,用户可以为具有“特殊意义”的 Commit 标记标签,比如 best、v1 等。

数据集同样支持 Branch、Commit 和 Tag 的管理方式,不过数据集不会如模型那样频繁产出,所以一般建议数据集只在主分支上持续更新。

S3 接口

在训练(或部署服务)时,除了将数据集和模型下载到本地使用,大多数框架也支持直接从 S3 数据服务上动态获取数据文件。

AH 提供 S3 接口,用户可以在 AH 控制台上创建 S3 凭证,然后使用页面上生成的 S3 配置文件在训练过程中直接通过 S3 接口获取数据。

协同开发

AH 支持文件夹粒度的权限共享。用户可以将一组模型或数据集分享给其他人,实现多人共同开发和训练结果共享的目的。

可分享的权限包括查看权限或编辑权限,编辑权限包含查看权限。分享的目标可以是另一个用户、用户组或者公开给所有人。

下一步

实验管理

实验管理模块(Experiment Management,以下简称 EM)提供实验数据追踪功能,能够收集实验元数据、实验中间产物,并可视化和比较实验结果,推动模型进步。这里的实验指的是以特定配置运行的一次模型训练,旨在探究某产生的指标表现如何。

存储结构

EM 使用树状结构组织一个用户的实验数据,在 Web UI 中体现为目录结构。

# EM 目录结构示意图
user:demo
  ├── em-example/
  │   ├── mnist_dataset
  │   └── mnist_keras
  └── autotune/
      └── keras-tune

节点类型

EM 树状结构中,节点根据存储方式分为四类,用 StorageType 表示:

  • StorageType == 0:不存储数据文件,仅用于组织 EM 树状结构。EM 中文件夹即该类型节点。
  • StorageType == 1:存储一个文件数据。
  • StorageType == 2:存储一组数据文件。
  • StorageType == 3:该类型节点可以创建和管理多个版本,每一个版本中可以存储一组数据文件。

在这四种存储类型的基础上,EM 根据用途实现以下 7 个节点类型:

  • Folder:Storage Type == 0,文件夹结构,用来组织实验数据。
  • Shotrcut:Storage Type == 0,快捷方式,指向另一个节点。
  • Run:Storage Type == 2,记录实验元数据,包括实验基本信息、实验参数和实验指标。
  • Artifact:Storage Type == 2,记录实验的中间产物,也包括未发布的数据集和模型。
  • AutoTune:Storage Type == 2,记录超参数调优实验数据,参考超参数调优实验
  • Model:Storage Type == 3,记录机器学习模型。
  • Dataset:Storage Type == 3,记录机器学习所使用的数据集。

Artifact 没有特定的文件组织结构,用户可根据需要组织上传。

Model 和 Dataset 由平台的资产管理模块,具体请参考 EM 和 Asset Hub 之间的关系

Run 和 Autotune 是实验元数据的存储节点,具有特定的文件组织结构,EM Web 根据这些特定的文件组织结构进行实验数据的可视化。

Run 节点

Run 记录实验元数据,包括实验基本信息、实验参数和实验指标。

Run 节点中包含一个 index.yaml 文件,其中记录其他实验数据在该节点中的相对路径:

hyperparameters: hyperparameters.yaml
metrics:
  train: metrics/train.yaml
  val: metrics/val.yaml
  test: metrics/test.yaml
platform: platform.yaml
git: git.yaml
log: stdout.log
  • hypterparameters:机器学习超参数。
  • metrics:训练指标,由于指标可能产生自不同阶段,同一阶段也可能有多种指标,所以使用上例中的结构记录多个指标文件。
  • platform:平台信息,包括系统版本、python 包版本等。
  • git:代码存储位置,我们一半会将机器学习脚本存储在 GitHub 中。
  • log:日志文件。

上述文件的生成可以由 em 工具自动完成,用户只需要了解如何使用 em 工具。参考 em API 文档

AutoTune 节点

AutoTune 记录超参数调优实验数据,包括实验的基本配置以及每一次训练的参数和指标。

AutoTune 节点的文件结构如下:

.
├── profile.json
├── 17671/
│   ├── metadata.json
│   └── metrics.yaml
...
  • profile.json:记录超参数调优实验的训练配置、超参数搜索空间和调优配置等信息
  • 17671:超参数调优过程中,每一次训练都会创建一个文件夹用来记录训练数据,文件夹名称即训练的 ID(随机生成)。
    • metadata.json:记录训练参数和训练状态。
    • metrics.yaml:记录训练指标,超参数调优创建的训练都只会产生一个指标,调优控制器会根据该指标调整超参数。

可视化

EM 支持使用以下方式对 Run 数据进行可视化:

  • 数据流图:Run 和 Artifact 之间是存在使用和产出关系的,比如一次实验(Run)使用一个 Artifact 作为训练数据,最后产出另一个 Artifact。这种使用和产出关系构成了一个数据流动路线图,即数据流图。用户可以通过数据流图快速跳转到对应数据节点。
image
  • 指标折线图
image

EM 支持使用以下方式对 AutoTune 数据进行可视化:

  • “超参数-指标”图

autotune-pm

  • 指标优化曲线

autotune-opt

  • 各次训练的指标信息

autotune-trial-detail

权限管理

EM 支持节点粒度的权限控制:

  • 用户可以将一个节点分享给另一个用户、用户组或者公开给所有人。
  • 可分享的权限包括查看权限或编辑权限,编辑权限包含查看权限。
  • 文件夹权限修改会传递给所有子节点(当用户被分享了一个文件夹的编辑权限,则该用户自动拥有文件夹中所有节点的编辑权限;取消分享同理)。
  • 当一个节点被移动到另一个文件夹中,节点完全继承该文件夹的权限,覆盖节点之前的权限设置。

EM 和 Asset Hub 之间的关系

Asset Hub 是 TensorStack AI 平台的资产管理模块,用于管理数据集和模型。

数据集和模型作为实验的输入和输出,也应当作为实验管理的一部分,所以在 EM 中也可以看到 Asset Hub 中的数据集和模型数据,如下图所示:

# EM 目录结构示意图
user:demo
  └── t9k-assethub/
      ├── model/
      │   ├── folder1
      │   │   ├── model1
      │   │   ...
      │   ├── folder2
      │   ...
      └── dataset/

数据集和模型分别记录在 EM 的 ./t9k-assethub/dataset./t9k-assethub/model 文件夹中,model 文件夹(dataset 文件夹同样)维护文件夹和模型两级结构,每一个模型都是一个具有版本管理功能的节点。

下一步

操作指南

使用模型构建控制台

模型构建控制台提供了大量功能,你可以在此进行模型构建,并管理 Job存储辅助资源。本部分将演示如何在模型构建控制台中使用 Notebook 和 TensorBoard,构建和调试镜像,以及管理存储、配置和隐私信息。

对于如何使用 T9k Job 和 AutoTune,请分别参阅运行模型训练进行超参数优化

创建 Notebook

本教程演示如何创建 Notebook。

准备工作

创建 PVC

创建 Notebook 时,需要至少绑定一个 PVC 来存储代码、数据等文件。如果你的项目中已有合适的持久卷,则可以直接进入下一节。

在模型构建控制台的左侧导航菜单中点击存储 > 持久卷进入 PVC 管理页面。然后点击右上角的创建 PVC 进入创建页面:

pvc-manage

在 PVC 创建页面,名称填写 create-notebook存储填写 1Gi,其他参数保持默认值,然后点击创建

pvc-create-filled

创建标准的 Notebook

在模型构建控制台的左侧导航菜单中点击构建 > Notebook 进入 Notebook 管理页面,然后点击右上角的创建 Notebook 进入创建页面:

notebook-manage

在 Notebook 创建页面,如下填写各个参数:

  • 名称填写 create-notebook
  • 存储卷选择上一节创建的 create-notebook(或其他合适的存储卷)。存储卷会被挂载到 Notebook 的 /t9k/mnt 目录下。
  • 镜像根据你想使用的机器学习框架(如 TensorFlow、PyTorch 等)及其版本选择一个标准 Notebook 镜像。
  • 模板根据你的资源需求选择一个合适大小的资源模板。

其他参数保持默认值,完成之后,点击创建

notebook-create-filled

回到 Notebook 管理页面查看新创建的 Notebook:

notebook-created

Notebook 就绪后,就可以使用 Notebook

其他配置

使用 T9k 调度器

计算资源模块还提供了选项,使用调度器 t9k-scheduler,以支持便捷的资源使用申请,使用 t9k-scheduler 调度任务时必须指定一个队列。相比默认调度器,t9k-scheduler 需要额外填写如下参数:

  • 队列 (queue):必填,选择一个队列(如果没有队列,请联系管理员创建一个队列)。
  • 优先级 (priority):可选,默认值是 0。代表任务在队列内部的优先级。当发生资源抢占时,优先级数字较小的工作负载会比同一个队列中的其他负载优先被驱逐。
t9k-scheduler

使用数据卷

可以为 Notebook 绑定额外的数据卷(存放数据的 PVC),如下图所示:

notebook-dataVolume

每绑定一个数据卷需要填写如下参数:

  • 名称:使用的 PVC 名称。
  • 绑定路径:将 PVC 绑定到 Notebook 的指定路径下。

在上图的示例中,我们将 PVC examples 绑定到了 Notebook 的 /t9k/examples 路径下。你可以在 Notebook 中通过对应路径访问 PVC 中的数据。

启用 SSH 选项

如果你想使用 SSH 连接到 Notebook 容器中来管理其中的文件,或者使用本地的 IDE 来编辑 Notebook 中的代码,启用 SSH 能够帮助你在 Notebook 中运行一个 SSH 服务。

Notebook 的 SSH 服务只允许通过密钥对进行验证,因此你需要上传公钥以使用 SSH 连接。TensorStack AI 平台使用 Secret 存储公钥信息。如果你已经创建了包含公钥的 Secret,则可以直接进入下一节。

在模型构建控制台的左侧导航菜单中点击辅助 > Secret,然后点击右上角的创建 Secret 进入的创建页面:

secret-create

在 Secret 创建页面,选择类型为 SSH Public Key,填写名称和公钥内容。最后点击创建 Secret 进行创建:

secret-create-ssh

创建 Notebook 时,开启启用 SSH 按钮,然后选择前面创建的 Secret(此处为一个多选框,你可以同时设置多个 SSH 公钥):

notebook-ssh

点击创建,等待运行之后,你可以通过 SSH 连接远程使用 Notebook

使用 Notebook

本教程演示如何使用 Notebook 进行模型开发相关的工作。

打开 JupyterLab

在模型构建控制台的左侧导航菜单中点击构建 > Notebook 进入 Notebook 管理页面,然后点击运行中的 Notebook 右侧的打开

notebook-manage

进入到 JupyterLab 的页面:

jupyterLab

使用 Jupyter Notebook

点击 Launcher 标签页下,Notebook 下方的 Python3 图标以创建 Jupyter Notebook:

jupyterLab-select-notebook

Jupyter Notebook 提供了交互式的 Python 开发环境。你可以在这里分块编辑并运行 Python 代码。比如运行 keras_mnist.py

from tensorflow.keras import callbacks, datasets, layers, models, optimizers

model = models.Sequential([
    layers.Conv2D(32, 3, activation='relu', input_shape=(28, 28, 1)),
    layers.MaxPool2D((2, 2)),
    layers.Conv2D(64, 3, activation='relu'),
    layers.MaxPool2D((2, 2)),
    layers.Conv2D(64, 3, activation='relu'),
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(10, activation='softmax'),
])
model.compile(optimizer=optimizers.Adam(learning_rate=0.001),
            loss='sparse_categorical_crossentropy',
            metrics=['accuracy'])


(train_images, train_labels), (test_images,
                            test_labels) = datasets.mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

train_images, test_images = train_images / 255.0, test_images / 255.0

model.fit(train_images,
        train_labels,
        batch_size=32,
        epochs=5,
        validation_split=0.2)
model.evaluate(test_images, test_labels)
jupyterLab-notebook

编辑文件

在左侧的文件系统导航菜单空白处右击,可以创建文件和目录:

jupyterLab-newfile

创建名为 keras_mnist.py 的文件,双击以进行编辑。复制上文中 keras_mnist.py 的内容,粘贴在文本编辑器中并保存:

jupyterLab-editor

使用 Terminal

点击左上角蓝色底色的 + 符号打开新的 Launcher 标签页,然后点击 Other 中的 Terminal 进入命令行终端。你可以在这里运行各种 bash 命令,例如运行 python ./keras_mnist.py 来进行模型训练:

jupyterLab-terminal

查看详情

在 Notebook 管理页面,点击 Notebook 的名称进入其详情页面:

notebook-show-details

Notebook 的详情页面展示了 Notebook 的基本信息、状况和事件。点击 Pod 右侧的链接可以查看 Pod 的日志、状况、事件、资源监测等信息:

notebook-details

查看日志

点击日志,查看 Notebook Pod 的运行日志:

notebook-logs

查看资源监测

点击资源监测,查看 Notebook Pod 运行时实际使用的资源,包括 CPU、内存、存储 I/O 的使用量:

notebook-resource-1
notebook-resource-2

通过 SSH 远程使用 Notebook

本教程演示如何通过 SSH 连接远程使用 Notebook。

准备

  • 创建了一个启用 SSH 选项的 Notebook。
  • 确认该 Notebook 处于正常运行状态。

端口转发

命令行工具 t9k-pf

命令行工具 t9k-pf 的功能类似于 kubectl port-forward,可以让用户能够在本地通过端口转发的方式访问 TensorStack AI 平台的各种资源。

请参照用户指南,下载安装 t9k-pf 并配置身份认证和授权

端口转发命令

在 Notebook 详情页面,查看并复制SSH 服务提示的命令:

copy-t9k-pf-command

在终端执行该命令以进行端口转发:

$ t9k-pf notebook <URL> <Port>
now you can forward to your target by 127.0.0.1:<Port>

参数说明如下:

  • URL:Notebook 的 Web UI 地址。除上述获取方式外,你也可以在打开 Notebook 后,复制浏览器地址栏中的地址作为 URL 参数使用。
  • Port:转发的本地端口。在 SSH 远程连接教程中会使用到该端口。

根据终端打印的提示信息,使用本地的端口与目标 Notebook 建立 SSH 连接,具体命令请参阅 SSH 远程连接

建立 SSH 连接

使用终端

在终端中运行以下命令以连接到 Notebook:

ssh t9kuser@localhost -p <Port> \
  -o StrictHostKeyChecking=no \
  -o GlobalKnownHostsFile=/dev/null \
  -o UserKnownHostsFile=/dev/null

然后在终端中操作 Notebook:

terminal-ssh

使用 VSCode

安装 Remote SSH 插件

在 VSCode 中搜索 Remote - SSH 插件并安装:

vscode-plugin

添加 SSH Config

安装完成后,需要在 SSH Config 中添加主机(Notebook)的信息。

VSCode 提供了编辑 SSH Config 的方式。点击左下角的绿色 >< 符号,选择 Connect to Host,然后拉动滚动条到最下方,点击 Add New SSH Host

vscode-new-host

根据提示,输入以下内容,然后按下回车键(Enter):

ssh t9kuser@localhost -p <Port>
vscode-ssh-command

VSCode 会提示 Select SSH configuration file to update,第一个选择项通常是位于 $HOME/.ssh/config 的配置文件,你可以选择将主机的信息存储在第一个配置文件中。

连接到 Notebook

点击左下角的绿色 >< 符号,选择 Connect to Host

vscode-connect

然后选择 SSH Config 中对应的主机名(使用上述配置方式时,主机名为 localhost):

vscode-connect-select

VSCode 会新建一个窗口,等待连接建立之后,左下角会提示 SSH: Host

点击 Open Folder 可以选择打开的目录或者文件。你可以和本地开发一样使用 VSCode 来操作 Notebook:

vscode-connected

使用 PyCharm

使用 PyCharm 远程连接到 Notebook 需要满足以下前提条件:

  1. 安装了 PyCharm 专业版,且版本不低于 2022.2。PyCharm 有专业版(Professional)和社区版(Community),目前仅 PyCharm Professional 支持远程 SSH 开发。
  2. Notebook 的资源配置至少为 3 个 CPU,3 GiB 内存,Notebook 绑定的持久卷至少有 2.5 GiB 的可用空间。推荐配置为至少 4 个 CPU,4 GiB 内存,5 GiB 持久卷。

打开 PyCharm,在左侧的导航菜单中点击 Remote Development > SSH,然后点击右侧的 New Connection

pycharm-ssh

在弹出的对话框中填写如下参数:

  • Username:SSH 使用的用户名。
  • Host:主机地址,通常为 127.0.0.1
  • Port:端口。
  • Specify private key:建议勾选,并选择与你上传的公钥对应的私钥。
pycharm-connect

点击 Check Connection and Continue,进入下一步:

pycharm-connected

这里选择了在 Notebook 中安装的 IDE Backend 版本为 PyCharm 2022.2.3,远程打开的项目目录为 /t9k/mnt。点击 Download IDE and Connect 后,就可以通过 PyCharm 访问 Notebook 中的文件了。

pycharm-edit

你可以和本地开发一样使用 PyCharm 来操作 Notebook:

参考

创建 TensorBoard

本教程演示如何创建 TensorBoard。

准备工作

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

查看训练指标

TensorBoard 处于 Running 状态后,进入模型构建控制台的 TensorBoard 页面,可以看到 TensorBoard tensorboard 正在运行:

running

点击 TensorBoard 右侧的 打开 进入 TensorBoard 页面,查看可视化展示的训练和验证指标:

tensorboard

构建镜像

本教程演示如何在平台上构建容器镜像(container image)并推送到指定的容器镜像仓库(container registry)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

其中,创建包含身份信息的 Secret 这一步骤也可以在模型构建控制台中通过创建 Docker 类型的 Secret 来完成,如下图所示。详情请参阅创建 Secret

secret-form

检查构建进度和结果

在模型构建控制台的左侧导航菜单中点击构建 > Image Builder,然后点击刚创建的 Image Builder 右侧的详情,查看其详情和日志。拉取基础镜像、构建镜像和推送镜像都需要花费一定的时间,请耐心等待。

image-builder
detail
log

一段时间后,构建完成的镜像被推送到相应的 registry 中。

pushed-to-registry

FAQs

Unpacking rootfs 失败

使用 ImageBuilder 制作镜像时,有时会出现类似以下的错误:

INFO[0009] Unpacking rootfs as cmd RUN apt-get -qq update &&     apt-get -qq install --no-install-recommends -y curl requires it. 
error building image: error building stage: failed to get filesystem from image: stream error: stream ID 17; PROTOCOL_ERROR; received from peer

但是该错误信息并不准确,经分析,实际导致镜像 build 失败的可能原因是:镜像(Dockerfile 中 FROM 语句所引用的镜像)提取失败。

提取失败可能有以下原因:

  • 镜像来源于无法访问或下载速度过慢的仓库

解决方法:

  1. 切换到服务质量更好的的 Registry,例如本地网络部署的私有化 Registry,或其他 caching Regisry。
  2. 使用代理服务器,通过该代理下载镜像。

调试镜像

本教程演示如何方便地在模型构建控制台通过命令行进入一个镜像,以便对镜像进行探索和测试。

准备工作

示例

假设我们想知道镜像 t9kpublic/tensorflow-2.11.0-notebook-cpu:1.70.0 中安装了哪些 pip 包。

进入模型构建控制台后,点击构建 > Pod 进入 Pod 管理页面。

pod-list

点击右上角的创建以创建一个 Pod,执行 sleep 命令使镜像保持运行状态,以便我们连接镜像中的 bash(或 sh)终端。

pod-create
pod-create

分别填写项目名称、镜像名称、运行命令和资源使用量,然后点击创建

pod-list-2

所创建的 Pod 变为运行状态后,点击 Pod 名称进入 Pod 详情页面。

pod-detail

点击终端按钮,打开终端。

pod-terminal

在打开的终端中,输入 pip list 显示该镜像中安装的所有 pip 包,或者输入其他任何命令。

最后,点击右上角的 X 关闭终端。

管理 PVC

本教程演示如何在模型构建控制台中管理和使用 PVC

准备工作

创建 PVC

进入模型构建控制台,在左侧导航菜单(或右侧卡片)中点击存储 > 持久卷进入 PVC 管理页面。

overview-pvc

点击 PVC 管理页面右上角的创建 PersistentVolumeClaim 进入 PVC 创建页面。

create-pvc

在 PVC 创建页面填写名称和存储卷大小,选择存储卷访问模式和存储类,然后点击创建

create-pvc-detail

你可以点击左上角的导入 PersistentVolumeClaim 以加载当前存在的 PVC 的配置。

删除 PVC

在 PVC 管理页面,点击要删除的 PVC 右侧的更多按钮 > 删除

delete-pvc

使用 Explorer

本教程演示如何使用 Explorer 查看和修改存储在 PVC 和 StorageShim 中的文件。

启动 Explorer

在模型构建控制台的左侧导航菜单中点击存储 > 持久卷进入 PVC 管理页面,点击 PVC 右侧的启动

start-explorer

将光标悬停在打开上,等待 File Browser 和 VS Code 就绪。随后点击 File BrowserVS Code 即可进入。

enter

使用 File Browser

进入 File Browser 的前端页面,我们可以看到 PVC 中的所有文件和目录:

file-browser

这里支持以下操作:

  • 浏览目录和文本文件
  • 创建、删除、重命名、复制、移动目录和文件
  • 上传、下载文件
  • 修改文本文件

使用 VS Code

进入 File Browser 的前端页面,我们可以看到 PVC 中的所有文件和目录:

vs-code

这里支持以下操作:

  • 浏览目录和文本文件
  • 创建、删除、重命名、复制、移动目录和文件
  • 修改文本文件,进行轻量级代码修改
  • 启动终端并执行命令
  • 进行源代码控制
  • 安装 VS Code 插件

暂停和关闭 Explorer

使用结束后,我们可以关闭 Explorer。之后重新启用即可。

pause-close-explorer

使用 StorageShim 适配 S3 服务

概述

TensorStack AI 平台支持用户在多个环节使用 S3 协议的存储服务。本教程演示如何通过 StorageShim 把 S3 存储服务转换成 PVC,以方便在一些需要使用 POSIX 文件系统接口的场景。

本教程涉及如下基本概念:

  • S3(Simple Storage Service)提供可扩展、安全、高可用的对象存储服务,可以存储和检索任意数量和类型的数据,包括文档、图片、视频、音频等。更多详细信息请参阅附录
  • PVC(PersistentVolumeClaim)是 Kubernetes 提供的一种声明式的存储卷请求,用于向 Kubernetes 集群申请持久化存储卷。PVC 使应用程序与存储资源解耦,提高了存储资源的管理和使用效率。
  • StorageShim 提供了把 S3 服务转换为 PVC 的能力,让用户能够以 Kubernetes 原生的方式使用 S3。

详细过程

要访问 S3 服务,需要提供使用其服务的相应配置,包括:

  • S3 访问凭证:用于访问 S3 服务的一组密钥,包括访问密钥(access key)和秘密访问密钥(secret key)。S3 访问凭证是必需的,以在访问 S3 服务时进行身份验证和授权。
  • S3 服务的终端地址(endpoint):HTTP 或 HTTPS 格式的地址,例如:http://100.1.1.2:8000
  • S3 bucket:存储用户数据的容器;访问特定的 bucket 需要有合适权限的访问凭证。

准备 S3 配置

以下面的格式准备一个名为 s3cfg 的文件:

[default]
# Setup access keys
access_key = <you-access-key>
secret_key = <your-secret-key>

# Setup endpoint
host_base = http[s]://<host-or-ip>:<port>
use_https = <False | True>

其中需要修改的内容包括:

  • access_key:你的访问密钥(access key)。
  • secret_key:你的秘密访问密钥(secret key)。
  • host_base:S3 服务的地址(endpoint)。
  • use_https:是否使用 HTTPS。

你可以安装 s3cmd,在本地运行命令来验证 s3cfg 是否正确配置:

s3cmd -c s3cfg ls s3://<my-bucket>

创建 Secret

通过控制台

进入模型构建控制台,选择左侧导航菜单的辅助 > Secret,点击创建 Secret

选择类型为 S3-cfg,填写名称,然后填写 Details 的内容:

  • 服务端点:S3 服务的地址(endpoint)
  • Access Key ID:你的访问密钥(access key)。
  • 密码:你的秘密访问密钥(secret key)。

最后点击创建 Secret

create-pvc-s3cfg.png

通过命令行工具

用户也可以使用 kubectl 命令行工具创建 Secret:

kubectl -n <project> create secret generic <s3cfg-secret> \
  --from-file=.s3cfg=<s3cfg>

其中需要修改的内容包括:

  • <project>:项目名称。
  • <s3cfg-secret>:Secret 的名称。
  • <s3cfg>:本地 s3cfg 文件的路径。前面的 --from-file=.s3cfg= 不需要修改。

验证

运行以下命令,查看 Secret 中保存的 .s3cfg 内容:

kubectl -n <project> get secret <s3cfg-secret> \
    -o jsonpath={.data."\.s3cfg"} | base64 -d

其中需要修改的内容包括:

  • <project>:项目名称。
  • <s3cfg-secret>:Secret 的名称。

对比输出内容与你本地的 s3cfg,确认内容一致,重点是 access_keyhost_basesecret_key 字段。

创建 StorageShim

通过控制台

进入模型构建控制台,选择左侧导航菜单的存储 > 持久卷,点击上方的 S3,然后点击右上角的创建 StorageShim

view-storageshim.png

输入持久卷名称、S3 URI(s3://<your-bucket>),然后选择 S3 Secret 名称,最后点击右上角的创建 StorageShim 完成创建:

create-storageshim.png

在 S3 标签页查看新创建的 StorageShim:

new-storageshim.png

通过命令行工具

使用以下命令创建 StorageShim 类型的 PVC:

kubectl -n <project> create -f - <<EOF
apiVersion: tensorstack.dev/v1beta1
kind: StorageShim
metadata:
  name: dataset
spec:
  readOnly: false
  s3:
    uri: 's3://42a3de90-d9e7-4769-8fc4-48a65fb561d5'
  secretRef:
    name: s3cfg-secret
EOF

其中需要修改的内容包括:

  • <project>:项目名称。
  • .spec.s3.uri:S3 bucket 的路径,你也可以具体指定 bucket 中的一个文件夹。
  • .spec.secretRef.name:保存 S3 凭证的 Secret 名称。
  • readOnly:如果为 true,那么用户只能读取这个 StorageShim 的内容,而不能修改它。

查看 PVC 状态,确认 STATUS 为 Bound:

$ kubectl -n <project> get pvc
NAME                STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     AGE
dataset             Bound    pvc-cc7f789a-6fcb-44a0-8f42-0e6c86e51a1a   1          RWX            csi-s3           4m5s

附录

S3 基本概念

S3(Simple Storage Service)提供了可扩展、安全、高可用的对象存储服务,可以存储和检索任意数量和类型的数据,包括文档、图片、视频、音频等。

S3 使用:

  • Bucket:Bucket 是 S3 存储中的基本容器,类似于文件夹,用于存储和组织对象。每个 Bucket 必须具有唯一的名称,并且名称必须符合 DNS 命名规则。
  • Object:Object 是 S3 存储中的基本数据单元,可以是任意类型的数据,例如文档、图片、视频、音频等。每个 Object 由一个唯一的键(Key)和一个值(Value)组成,键是 Object 在 Bucket 中的唯一标识符,值是 Object 的实际数据。

S3 管理:

  • Region:Region 是 S3 存储的物理位置,用于指定 Bucket 存储的地理位置。每个 Region 都由多个可用区域(Availability Zone)组成,以提供高可用性和容错性。
  • ACL:ACL(Access Control List)是 S3 存储的访问控制列表,用于控制 Bucket 和 Object 的访问权限。ACL 可以指定特定用户或组的访问权限,也可以指定公共访问权限。
  • Versioning:Versioning 是 S3 存储的版本控制功能,用于保留 Object 的所有版本。启用版本控制后,每次更新 Object 时都会创建一个新版本,并可以通过指定版本号来访问特定版本的 Object。
  • Lifecycle:Lifecycle 是 S3 存储的生命周期管理功能,用于自动化管理 Bucket 和 Object 的生命周期。Lifecycle 可以指定 Object 的存储期限、转换存储类别、自动删除 Object 等操作,以优化存储成本和管理效率。

S3 基本使用:s3cmd

有多种工具(s3browser、WinSCP、s3cmd、s5cmd、rclone 等)可以访问 S3 存储服务,以下使用 s3cmd 演示 S3 的基本操作:

安装 s3cmd 工具:在 Linux 系统中使用命令行安装 s3cmd 工具,例如在 Ubuntu 系统中可以使用以下命令进行安装:

sudo apt-get install s3cmd

配置 s3cmd 工具:在命令行中执行 s3cmd --configure 命令,按照提示输入 S3 访问密钥和秘密访问密钥,以及 S3 服务的访问地址和区域等参数,完成 s3cmd 工具的配置。

创建 S3 存储桶:使用 s3cmd mb 命令创建 S3 存储桶,例如:

s3cmd mb s3://my-bucket-name

上传对象:使用 s3cmd put 命令上传对象到 S3 存储桶中,例如:

s3cmd put /path/to/local/file s3://my-bucket-name/path/to/remote/file

下载对象:使用 s3cmd get 命令从 S3 存储桶中下载对象到本地,例如:

s3cmd get s3://my-bucket-name/path/to/remote/file /path/to/local/file

删除对象:使用 s3cmd del 命令从 S3 存储桶中删除对象,例如:

s3cmd del s3://my-bucket-name/path/to/remote/file

设置对象 ACL:使用 s3cmd setacl 命令设置对象的 ACL,例如:

s3cmd setacl --acl-public s3://my-bucket-name/path/to/remote/file

对象存储(object storage)

对象存储是一种将数据存储为对象的数据存储架构,这与文件系统将数据作为文件层次结构进行管理不同。 每个对象通常包括数据本身(object)、元数据(metadata)和全局唯一标识符(object key)。

对象存储是存储海量非结构化数据(例如图像、视频和文档)的不错选择,例如大规模机器学习中使用的海量训练数据、特征、模型等。

与其他存储架构相比,对象存储具有许多优势,包括:

  • 可扩展性:对象存储可以轻松扩展以满足不断增长的应用程序的需求。
  • 耐用性:对象存储被设计成高度耐用的,数据以冗余方式存储在多个位置。
  • 可用性:对象存储旨在提供高可用性,可以从世界任何地方访问数据。
  • 安全性:对象存储提供了许多安全功能,包括加密和访问控制。

对象存储是一种强大而灵活的数据存储架构,是存储大量非结构化数据、需要从多个位置访问的数据以及需要高可用性和安全性的数据的不错选择。

参考

管理 Secret

本教程演示如何在模型构建控制台中管理和使用 Secret

准备工作

创建 Secret

进入模型构建控制台,在左侧导航菜单(或右侧卡片)中点击辅助 > Secret 进入 Secret 管理页面。

overview-secret

点击 Secret 管理页面右上角的创建 Secret 进入 Secret 创建页面。

create-secret

在 Secret 创建页面选择模板,填写名称和要存储的数据,然后点击创建

create-secret-detail

你可以点击左上角的导入 Secret 以加载当前存在的 Secret 的配置。

删除 Secret

在 Secret 管理页面,点击要删除的 Secret 右侧的更多按钮 > 删除

delete-secret

管理 ConfigMap

本教程演示如何在模型构建控制台中管理和使用 ConfigMap

准备工作

创建 ConfigMap

进入模型构建控制台,在左侧导航菜单(或右侧卡片)中点击辅助 > ConfigMap 进入 ConfigMap 管理页面。

overview-configmap

点击 ConfigMap 管理页面右上角的创建 ConfigMap 进入 ConfigMap 创建页面。

create-configmap

在 ConfigMap 创建页面填写名称、标签和要存储的数据,然后点击创建

create-configmap-detail

你可以点击左上角的导入 ConfigMap 以加载当前存在的 ConfigMap 的配置。

删除 ConfigMap

在 ConfigMap 管理页面,点击要删除的 ConfigMap 右侧的更多按钮 > 删除

delete-configmap

运行模型训练

这一部分演示如何使用 T9k Job 运行不同机器学习框架的模型训练任务。对于常用的机器学习框架,如 PyTorch、TensorFlow、Horovod,你都可以在这里找到相应的教程来帮助你开始训练模型。

使用 PyTorchTrainingJob 进行数据并行训练

本教程演示如何使用 PyTorchTrainingJob 对 PyTorch 模型进行多工作器同步训练(使用 torch.nn.parallel.DistributedDataParallel 分布式数据并行模块)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

检查训练日志和指标

训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 torch-mnist-trainingjob 的 PyTorchTrainingJob 正在运行:

running

点击其名称进入详情页面,可以看到刚才创建的 PyTorchTrainingJob 的基本信息、状况信息和事件信息:

details

点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:

tensorboard

点击上方的副本标签页,查看 PyTorchTrainingJob 的 Pod 信息:

replicas

点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:

view-log

点击上方的资源监测标签页,查看 PyTorchTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:

replicas

一段时间之后,PyTorchTrainingJob 的状态变为 Succeeded,表示训练成功完成。

done

若 PyTorchTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。

使用 PyTorchTrainingJob 进行参数服务器训练

本教程演示如何使用 PyTorchTrainingJob 对 PyTorch 模型进行基于 RPC 的参数服务器训练(使用分布式 RPC 框架 torch.distributed.rpc)。示例修改自 PyTorch 官方教程 Implementing a Parameter Server Using Distributed RPC Framework,关于训练脚本的更多细节信息请参考此教程。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

检查训练日志和指标

训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 torch-mnist-trainingjob-ps 的 PyTorchTrainingJob 正在运行:

running

点击其名称进入详情页面,可以看到刚才创建的 PyTorchTrainingJob 的基本信息、状况信息和事件信息:

details

点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:

tensorboard

点击上方的副本标签页,查看 PyTorchTrainingJob 的 Pod 信息:

replicas

点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:

view-log

点击上方的资源监测标签页,查看 PyTorchTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:

replicas

一段时间之后,PyTorchTrainingJob 的状态变为 Succeeded,表示训练成功完成。

done

若 PyTorchTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。

使用 TensorFlowTrainingJob 进行数据并行训练

本教程演示如何使用 TensorFlowTrainingJob 对 Keras 模型进行数据并行训练(采用 tf.distribute.MultiWorkerMirroredStrategy 分布式策略)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

检查训练日志和指标

训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 keras-mnist-trainingjob 的 TensorFlowTrainingJob 正在运行:

running

点击其名称进入详情页面,可以看到刚才创建的 TensorFlowTrainingJob 的基本信息、状况信息和事件信息:

details

点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:

tensorboard

点击上方的副本标签页,查看 TensorFlowTrainingJob 的 Pod 信息:

replicas

点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:

view-log

点击上方的资源监测标签页,查看 TensorFlowTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:

replicas

一段时间之后,TensorFlowTrainingJob 的状态变为 Succeeded,表示训练成功完成。

done

若 TensorFlowTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。

使用 TensorFlowTrainingJob 进行参数服务器训练

本教程演示如何使用 TensorFlowTrainingJob 对 Keras 模型进行参数服务器(parameter server)训练(采用 tf.distribute.experimental.ParameterServerStrategy 分布式策略)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

检查训练日志和指标

训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 keras-mnist-trainingjob-ps 的 TensorFlowTrainingJob 正在运行:

running

点击其名称进入详情页面,可以看到刚才创建的 TensorFlowTrainingJob 的基本信息、状况信息和事件信息:

details

点击 TensorBoard 右侧的 Running 打开 TensorBoard,可以查看可视化展示的训练和验证指标:

tensorboard

点击上方的副本标签页,查看 TensorFlowTrainingJob 的 Pod 信息:

replicas

点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:

view-log

点击上方的指标标签页,查看 TensorFlowTrainingJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:

replicas

一段时间之后,TensorFlowTrainingJob 的状态变为 Succeeded,表示训练成功完成。

done

若 TensorFlowTrainingJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。

使用 Horovod 进行 PyTorch 模型的数据并行训练

本教程演示如何使用 MPIJob 对 PyTorch 模型进行多工作器同步训练(使用 horovod.torch 模块)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

检查训练日志和指标

训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 torch-mnist-mpijob 的 MPIJob 正在运行:

running

点击其名称进入详情页面,可以看到刚才创建的 MPIJob 的基本信息、状况信息和事件信息:

details

点击上方的副本标签页,查看 MPIJob 的 Pod 信息:

replicas

点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:

view-log

点击上方的指标标签页,查看 MPIJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:

replicas

一段时间之后,MPIJob 的状态变为 Succeeded,表示训练成功完成:

done

若 MPIJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。

使用 Horovod 进行 Keras 模型的数据并行训练

本教程演示如何使用 MPIJob 对 Keras 模型进行多工作器同步训练(使用 horovod.tensorflow.keras 模块)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

检查训练日志和指标

训练开始后,进入模型构建控制台的 Job 页面,可以看到名为 keras-mnist-mpijob 的 MPIJob 正在运行:

running

点击其名称进入详情页面,可以看到刚才创建的 MPIJob 的基本信息、状况信息和事件信息:

details

点击上方的副本标签页,查看 MPIJob 的 Pod 信息:

replicas

点击副本右侧的更多按钮 > 日志以查看训练脚本执行过程中的日志输出:

view-log

点击上方的指标标签页,查看 MPIJob 运行过程中使用集群计算资源、网络资源和存储资源的情况:

replicas

一段时间之后,MPIJob 的状态变为 Succeeded,表示训练成功完成:

done

若 MPIJob 在运行过程中出错,其状态会变为 Error,并在事件信息和 Pod 信息部分显示错误信息,此时需要根据给出的错误信息进行问题排查。

使用 Profiler 分析模型训练性能

概述

PyTorch 提供的 profiler 工具允许在训练和推理过程中收集性能指标,从而帮助用户更好地理解运算的代价和内存等资源消耗,测量 CPU 计算代价,CPU-GPU 之间数据复制成本,研究 GPU 内核程序性能并可视化执行追踪等。用户在 Notebook 中可以方便地使用这一工具。

本教程将介绍如何在 Notebook 中对启动 LLM 大规模预训练中的训练进行性能分析。

准备

启动 LLM 大规模预训练给出的准备工作的基础上,还需要修改 Megatron-DeepSpeed 的训练代码,用 profiler 上下文管理器包装训练循环的代码。直接使用 Notebook 的文本编辑器修改代码即可。

# Megatron-DeepSpeed/megatron/training.py
...

    profile_path = os.path.join(os.path.dirname(args.tensorboard_dir), 'profiling')

    with torch.profiler.profile(
            schedule=torch.profiler.schedule(wait=1, warmup=1, active=3, repeat=2),
            on_trace_ready=torch.profiler.tensorboard_trace_handler(profile_path),
            record_shapes=True,
            profile_memory=True,
            with_stack=True,
            with_flops=True,
            with_modules=True
    ) as prof:  # profiler context manager
        while iteration < args.train_iters and (args.train_tokens is None or \
            args.consumed_train_tokens < args.train_tokens):  # training loop

            ...

            prof.step()

...

其中对于 profiler 的配置为:

  • profiler 跳过 1 个 step,热身 1 个 step,然后记录 3 个 step;总共重复 2 次。
  • 生成用于 TensorBoard 展示的结果文件,与 TensorBoard 日志文件保存到同一父目录下。
  • 记录算子的源信息和输入形状,记录模块(module)的调用栈,估计 FLOPS,跟踪张量内存的分配和释放。

启动性能分析

以 4 个 GPU 训练 125M 参数的 GPT 模型,启动训练:

kubectl create -f \
  examples/deepspeed/megatron-gpt/training/gpt-125m-4xdp.yaml

通过以下命令查看训练过程中打印的日志:

export POD=$(kubectl get dj gpt-125m -o jsonpath="{.status.tasks[0].replicas[0].name}")
kubectl logs $POD -f
log

性能分析完成之后,结果文件被保存在 output/gpt-125m-4xdp/profiling 路径下,前往该路径并启动一个 TensorBoard 实例以查看可视化结果。

create-tensorboard

查看可视化结果

Overview 展示了训练性能的总体情况,包含 GPU 的总体情况、不同执行类别花费的时间和占比,以及自动生成的性能优化建议:

overview

Operator View 展示了所有 PyTorch 算子被调用的次数、花费的时间以及它的调用栈:

operator-view

Kernel View 展示了所有 GPU 内核被调用的次数、花费的时间的统计以及它是否使用了 Tensor Core 等:

kernel-view

Memory View 展示了内存使用曲线图、内存事件(分配和释放)以及内存统计数据:

memory-view

TensorBoard 所展示的数据和提供的功能还远不止这些,请参阅官方教程以了解更多。这些数据应当能为用户分析和改进性能提供非常有用的帮助。

调试 Job

本教程演示如何使用 Job 的调试模式这一功能来对计算任务进行调试。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

通过 SSH 远程连接

对于开启了 SSH 服务的容器,建立 SSH 连接的操作步骤和 Notebook 相同,请参照通过 SSH 远程使用 Notebook进行操作。唯一不同的是端口转发使用 t9k-pf pod 命令,而非 t9k-pf notebook 命令:

t9k-pf pod <POD_NAME> 5001:2222 -n <PROJECT_NAME>

进行调试

不论是进入休眠的容器,还是远程连接开启了 SSH 服务的容器,调试都是通过执行一些命令来进行。例如使用 nvidia-smi 命令检查当前可用的 GPU,再使用 ls 命令检查训练脚本是否存在:

# 在容器中
nvidia-smi
ls

然后使用 torchrun 命令启动训练:

# 在容器中
cd ~/tutorial-examples/job/debug
torchrun --nnodes 1 --nproc_per_node 4 --rdzv_backend c10d torch_mnist_trainingjob.py --save_path model_state_dict.pt --log_dir log --backend nccl

随即分布式训练开始进行。如果训练脚本出错,则可以立即在终端中进行调试,不会造成 Job 的失败。调试完成后禁用 debug 模式(将 spec.runMode.debug.enable 设为 false,或直接注释第 6-12 行),再次创建 PyTorchTrainingJob 则正常启动训练。

进行超参数优化

超参数优化是机器学习中的一项关键任务,其目标是选择一组最佳的超参数来改进模型性能。这一任务面临多重挑战:超参数通常不可微分,搜索空间高维且非凸,评估成本高,手动调参既繁琐又低效。为此 TensorStack AI 平台提供了自动化工具 AutoTune,其支持多种超参数优化算法,能够自动搜索超参数空间、存储搜索结果并进行可视化,并且配置简单,使用方便。

这一部分将使用 AutoTune 进行模型的超参数优化。

使用 AutoTune 进行超参数优化

本教程演示如何使用 AutoTune 对模型进行超参数优化(以 Keras 模型的单机训练为例)。

准备训练脚本

在开始超参数优化实验之前,你需要提前准备训练脚本。你可以使用模型构建控制台中的 Notebook 编辑训练脚本。

创建 PVC

参照创建 PVC 教程创建名为 autotune-mnist-keras、大小为 1Gi 的 PVC。

创建 Notebook

从模型构建控制台进入 Notebook 列表,点击右上角的创建 Notebook

notebook-table

创建 Notebook 时,在存储卷选择前面创建的 PVC 的名称 autotune-mnist-keras

create-notebook

创建完成之后,点击打开进入 Notebook。

after-creating-notebook

在 Notebook 中编辑训练脚本

以下是一个 Keras 训练脚本,在此基础上做简单的修改以应用在 AutoTune 实验中。

import argparse
import json
import logging
import os
import time

import tensorflow as tf
from tensorflow.keras import callbacks, datasets, layers, models, optimizers

parser = argparse.ArgumentParser(
    description='Distributed training of Keras model for MNIST with '
    'MultiWorkerMirroredStrategy.')
parser.add_argument('--log_dir',
                    type=str,
                    default=None,
                    help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
                    action='store_true',
                    default=False,
                    help='Disable CUDA training.')
parser.add_argument('--save_path',
                    type=str,
                    default=None,
                    help='Save path of the trained model.')
args = parser.parse_args()
logger = logging.getLogger('print')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
logger.propagate = False

if args.no_cuda:
    tf.config.set_visible_devices([], 'GPU')
gpus = tf.config.get_visible_devices('GPU')
if gpus:
    # Print GPU info
    logger.info('NVIDIA_VISIBLE_DEVICES: {}'.format(
        os.getenv('NVIDIA_VISIBLE_DEVICES')))
    logger.info('T9K_GPU_PERCENT: {}'.format(os.getenv('T9K_GPU_PERCENT')))
    logger.info('Visible GPUs: {}'.format(
        tf.config.get_visible_devices('GPU')))
    # Set memory growth
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(gpu, True)
    # # Set GPU memory limit
    # tf.config.set_logical_device_configuration(
    #     gpus[0], [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])

strategy = tf.distribute.MultiWorkerMirroredStrategy()

# Get information for current worker.
tf_config = json.loads(os.environ['TF_CONFIG'])
world_size = len(tf_config['cluster']['worker'])
task_index = tf_config['task']['index']

params = {
    # Search space:
    # 'batch_size': ...
    # 'learning_rate': ...
    # 'conv_channels1': ...
    'epochs': 10,
    'conv_channels2': 64,
    'conv_channels3': 64,
    'conv_kernel_size': 3,
    'maxpool_size': 2,
    'linear_features1': 64,
    'seed': 1,
}

with strategy.scope():
    model = models.Sequential([
        layers.Conv2D(params['conv_channels1'],
                      params['conv_kernel_size'],
                      activation='relu',
                      input_shape=(28, 28, 1)),
        layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
        layers.Conv2D(params['conv_channels2'],
                      params['conv_kernel_size'],
                      activation='relu'),
        layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
        layers.Conv2D(params['conv_channels3'],
                      params['conv_kernel_size'],
                      activation='relu'),
        layers.Flatten(),
        layers.Dense(params['linear_features1'], activation='relu'),
        layers.Dense(10, activation='softmax'),
    ])
    model.compile(
        optimizer=optimizers.Adam(learning_rate=params['learning_rate']),
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy'])

(train_images, train_labels), (test_images,
                               test_labels) = datasets.mnist.load_data(
                                   path=os.path.join(os.getcwd(), 'mnist.npz'))
train_images = train_images.reshape((60000, 28, 28, 1)).astype("float32") / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype("float32") / 255
train_images, val_images = train_images[:48000], train_images[48000:]
train_labels, val_labels = train_labels[:48000], train_labels[48000:]
train_dataset = tf.data.Dataset.from_tensor_slices(
    (train_images, train_labels)).shuffle(
        48000, seed=params['seed']).repeat().batch(params['batch_size'])
val_dataset = tf.data.Dataset.from_tensor_slices(
    (val_images, val_labels)).batch(400)
test_dataset = tf.data.Dataset.from_tensor_slices(
    (test_images, test_labels)).batch(1000)

model.fit(train_images,
          train_labels,
          batch_size=params['batch_size'],
          epochs=params['epochs'],
          validation_split=0.2,
          verbose=2)

# TODO: Automatically save best n models.
# if args.save_path and task_index == 0:
#     t9k.autotune.utils.save_best_n_models(model, args.save_path)

model.evaluate(test_images, test_labels, callbacks=test_callbacks, verbose=2)

if task_index > 0:
    # wait a while for index 0
    time.sleep(1)

在上述脚本中导入 t9k.tuner 模块,在训练模型之前调用 get_next_parameter() 函数获取训练超参数,替换原来的参数。

from t9k import tuner

def main():
    ...
    tuner_params = tuner.get_next_parameter()
    params.update(tuner_params)
    ...

在训练过程中,添加 AutoTuneCallback 上传实验指标。

train_callbacks = []
test_callbacks = []

if task_index == 0:
    from t9k.tuner.keras import AutoTuneFitCallback, AutoTuneEvalCallback
    train_callbacks.append(AutoTuneFitCallback(metric='accuracy'))
    test_callbacks.append(AutoTuneEvalCallback(metric='accuracy'))
    if args.log_dir:
        tensorboard_callback = callbacks.TensorBoard(log_dir=args.log_dir)
        train_callbacks.append(tensorboard_callback)

如下为修改后的训练脚本:

import argparse
import json
import logging
import os
import time

import tensorflow as tf
from tensorflow.keras import callbacks, datasets, layers, models, optimizers

from t9k import tuner

parser = argparse.ArgumentParser(
    description='Distributed training of Keras model for MNIST with '
    'MultiWorkerMirroredStrategy.')
parser.add_argument('--log_dir',
                    type=str,
                    default=None,
                    help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
                    action='store_true',
                    default=False,
                    help='Disable CUDA training.')
parser.add_argument('--save_path',
                    type=str,
                    default=None,
                    help='Save path of the trained model.')
args = parser.parse_args()
logger = logging.getLogger('print')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
logger.propagate = False

if args.no_cuda:
    tf.config.set_visible_devices([], 'GPU')
gpus = tf.config.get_visible_devices('GPU')
if gpus:
    # Print GPU info
    logger.info('NVIDIA_VISIBLE_DEVICES: {}'.format(
        os.getenv('NVIDIA_VISIBLE_DEVICES')))
    logger.info('T9K_GPU_PERCENT: {}'.format(os.getenv('T9K_GPU_PERCENT')))
    logger.info('Visible GPUs: {}'.format(
        tf.config.get_visible_devices('GPU')))
    # Set memory growth
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(gpu, True)
    # # Set GPU memory limit
    # tf.config.set_logical_device_configuration(
    #     gpus[0], [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])

strategy = tf.distribute.MultiWorkerMirroredStrategy()

# Get information for current worker.
tf_config = json.loads(os.environ['TF_CONFIG'])
world_size = len(tf_config['cluster']['worker'])
task_index = tf_config['task']['index']

tuner_params = tuner.get_next_parameter()
params = {
    # Search space:
    # 'batch_size': ...
    # 'learning_rate': ...
    # 'conv_channels1': ...
    'epochs': 10,
    'conv_channels2': 64,
    'conv_channels3': 64,
    'conv_kernel_size': 3,
    'maxpool_size': 2,
    'linear_features1': 64,
    'seed': 1,
}
params.update(tuner_params)

with strategy.scope():
    model = models.Sequential([
        layers.Conv2D(params['conv_channels1'],
                      params['conv_kernel_size'],
                      activation='relu',
                      input_shape=(28, 28, 1)),
        layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
        layers.Conv2D(params['conv_channels2'],
                      params['conv_kernel_size'],
                      activation='relu'),
        layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
        layers.Conv2D(params['conv_channels3'],
                      params['conv_kernel_size'],
                      activation='relu'),
        layers.Flatten(),
        layers.Dense(params['linear_features1'], activation='relu'),
        layers.Dense(10, activation='softmax'),
    ])
    model.compile(
        optimizer=optimizers.Adam(learning_rate=params['learning_rate']),
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy'])

(train_images, train_labels), (test_images,
                               test_labels) = datasets.mnist.load_data(
                                   path=os.path.join(os.getcwd(), 'mnist.npz'))
train_images = train_images.reshape((60000, 28, 28, 1)).astype("float32") / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype("float32") / 255
train_images, val_images = train_images[:48000], train_images[48000:]
train_labels, val_labels = train_labels[:48000], train_labels[48000:]
train_dataset = tf.data.Dataset.from_tensor_slices(
    (train_images, train_labels)).shuffle(
        48000, seed=params['seed']).repeat().batch(params['batch_size'])
val_dataset = tf.data.Dataset.from_tensor_slices(
    (val_images, val_labels)).batch(400)
test_dataset = tf.data.Dataset.from_tensor_slices(
    (test_images, test_labels)).batch(1000)

train_callbacks = []
test_callbacks = []

if task_index == 0:
    from t9k.tuner.keras import AutoTuneFitCallback, AutoTuneEvalCallback
    train_callbacks.append(AutoTuneFitCallback(metric='accuracy'))
    test_callbacks.append(AutoTuneEvalCallback(metric='accuracy'))
    if args.log_dir:
        tensorboard_callback = callbacks.TensorBoard(log_dir=args.log_dir)
        train_callbacks.append(tensorboard_callback)

model.fit(train_images,
          train_labels,
          batch_size=params['batch_size'],
          epochs=params['epochs'],
          validation_split=0.2,
          callbacks=train_callbacks,
          verbose=2)

# TODO: Automatically save best n models.
# if args.save_path and task_index == 0:
#     t9k.autotune.utils.save_best_n_models(model, args.save_path)

model.evaluate(test_images, test_labels, callbacks=test_callbacks, verbose=2)

if task_index > 0:
    # wait a while for index 0
    time.sleep(1)

在 Notebook 中创建文件 main.py,写入上述脚本并保存文件。

notebook-detail

创建 download_dataset.py 文件,写入并执行以下脚本来下载实验数据。

import os
import tensorflow as tf

_, _ = tf.keras.datasets.mnist.load_data(os.path.join(os.getcwd(), 'mnist.npz'))
notebook-download-script
download-data

准备数据库

你可以使用实验管理平台(以下称 EM)记录超参数调优实验中的超参数组合和训练结果。(如果你选择不使用 EM 持久记录 AutoTune 实验结果,请忽略这一步,并在开始实验时删掉 AutoTuneExperiment 的 spec.aistore 字段)

在实验管理控制台中新建文件夹

EM 的实验数据是以文件夹形式管理的,所以你首先需要在实验管理控制台点击右上角的 + 新建一个文件夹。

create-aistore-folder

进入文件夹,点击 ID 来复制该文件夹的 ID。

folder-id

获得访问 EM 所需的 API Key

在超参数优化实验中,如果你希望使用 EM 来存储实验数据,需要生成一个具有访问 EM 文件夹权限的 API Key,你可以通过这个 API Key 上传实验数据。

你需要按照生成 API Key 教程中的步骤,在安全控制台中生成一个 API Key,其中必须勾选 AIStore 选项。

create-apikey

生成 API Key 之后,点击复制按钮复制该 API Key。

after-creating-apikey

然后,你需要按照管理 Secret 教程中的步骤,在模型构建控制台中将所复制的 API Key 存入名为 aistore 的 Secret 中,以方便后续实验使用。

create-apikey-secret

开始实验

在模型构建控制台的 AutoTune 列表页面,点击右上角的创建 AutoTuneExperiment 进入 AutoTuneExperiment 创建页面。

autotune-table

在 AutoTuneExperiment 创建页面,点击预览 YAML,输入以下配置,点击创建

apiVersion: tensorstack.dev/v1beta1
kind: AutoTuneExperiment
metadata:
  name: autotune-mnist-keras
spec:
  maxExecSeconds: 3600
  maxTrialNum: 20
  trialConcurrency: 3
  storage: 100Mi
  aistore:
    secret: 'aistore'
    folder: 'b6c17378-965c-4467-9a43-eed65597f976'
  searchSpace: |-
    {
      "batch_size": {"_type": "choice", "_value": [16, 32, 64, 128]},
      "learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]},
      "conv_channels1": {"_type": "choice", "_value": [16, 32, 64, 128]}
    }
  trainingConfig:
    type: tensorflow
    tasks:
      - type: worker
        replicas: 4
        template:
          spec:
            securityContext:
              runAsUser: 1000
            containers:
              - command:
                  - sh
                  - -c
                  - "python3 main.py --log_dir /mnt/log --no_cuda"
                workingDir: /mnt/
                imagePullPolicy: IfNotPresent
                image: t9kpublic/tensorflow-2.5.1:20220216
                name: tensorflow
                resources:
                  requests:
                    cpu: 2000m
                    memory: 2Gi
                  limits:
                    cpu: 4000m
                    memory: 4Gi
                volumeMounts:
                  - mountPath: /mnt
                    name: data
            volumes:
              - name: data
                persistentVolumeClaim:
                  claimName: autotune-mnist-keras
  tuner:
    builtinTunerName: TPE
    classArgs: |-
      {
        "optimize_mode": "maximize", 
        "constant_liar_type": "min"
      }

在此例中,实验绑定了准备过程中创建的名为 autotune-mnist-keras 的 PVC,其中存有在 Notebook 中编辑的训练脚本;使用了名为 aistore 的存有 API Key 的 Secret;填入了前面创建的 EM Folder 的 ID。

create-autotune

查看实验

你可以在 AutoTune 列表页面看到已创建的 AutoTuneExperiment,点击连接进入实验详情页面。

after-creating-autotune

下图为实验详情页面,你可以在该页面查看实验基本信息、各试验的参数与结果,以及查看试验之间的对比。

autotune-detail
trial-detail

部署模型推理服务

这一部分演示如何使用平台的模型部署模块部署推理服务。

简单推理服务

本教程演示如何使用 SimpleMLService 快速部署一个模型推理服务。

运行示例

请按照使用方法准备环境,然后前往本教程的示例,参照其 README 文档运行。本示例使用 PVC 中存储的模型创建了一个 SimpleMLService 服务。

查看推理服务状态

部署完成后,进入模型部署控制台的 SimpleMLService 页面,可以看到名为 mnist 的 SimpleMLService。

list

点击 SimpleMLService 的名称 mnist 可以看见 SimpleMLService 的基本信息,其中 URL 是在集群内访问这个推理服务的地址:

detail

参考

模型推理服务

本教程演示如何使用 MLService 部署一个功能完善、自动化程度高,可用于生产环境的模型推理服务。

运行示例

请按照使用方法准备环境,然后前往本教程的示例,参照其 README 文档运行。本示例使用 PVC 中存储的模型创建了一个 MLService 服务。

查看推理服务状态

部署完成后,进入模型部署控制台的 MLService 页面,可以看到名为 torch-mnist-pvc 的 MLService,稍等片刻,等其进入 Ready 状态:

ready

使用推理服务

你可以直接使用命令行工具访问 MLService 的预测服务。运行命令获取 MLService 的 URL:

url=$(kubectl get mlservice torch-mnist-pvc -o jsonpath='{.status.address.url}') && echo $url

发送推理请求:

curl -T test_data/0.png ${url}/v1/models/mnist:predict # or use `1.png`, `2.png`

监控推理服务

在模型部署控制台,点击对应的 MLService,然后切换到资源监测页面,可以查看该 MLService 的资源统计:

resource-usage

参考

包含 Transformer 的推理服务

本教程演示如何使用 TensorStack SDK 创建 Transformer 镜像,然后部署包含该 Transformer 的 MLService。

运行示例

请按照使用方法准备环境,然后前往本教程的示例,参照其 README 文档运行。本示例运行了一个带有 Transformer 的 MLService 推理服务。

Transformer 实现

Transformer 是 MLService 中的一个组件,它可以对推理的请求进行预处理和后处理:

  • 预处理:用户发向推理服务的原始数据,先经过 Transformer 预处理,然后再被发送到推理服务。
  • 后处理:推理服务返回的预测结果,先经过 Transformer 后处理,然后再返回给用户。

查看推理服务状态

部署完成后,进入模型部署控制台的 MLService 页面,可以看到名为 pic-mnist 的 MLService,稍等片刻,等其进入 Ready 状态:

create-mlservcie-transformer

使用推理服务

你可以直接使用命令行工具访问 MLService 的预测服务。运行命令获取 MLService 的 URL:

address=$(kubectl get mls pic-mnist -ojsonpath='{.status.address.url}') && echo $address

使用图片 shoe.png 作为测试数据发送预测请求:

curl --data-binary @./shoe.png ${address}/v1/models/model:predict

参考

管理 AI 资产

这一部分演示如何使用 AsestHub 上传、使用和分享模型和数据集。

操作文件夹、模型和数据集

本教程演示如何通过多种方式操作文件夹、模型和数据集,包括创建、查看和删除。

准备工作

通过命令行工具

切换到你的工作路径下:

$ cd /your/workpath

假设当前用户(这里假设用户名为 demo)没有可以访问的文件夹,使用 ah create 命令创建一个模型文件夹和一个数据集文件夹:

$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created

$ ah create dataset/text
AH INFO: Folder /demo/t9k-assethub/dataset/text created

然后使用 ah create 命令在模型文件夹中创建一个模型,以及在数据集文件夹中创建一个数据集:

$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm

$ ah create dataset/text/openwebtext
AH INFO: Dataset openwebtext created for Folder /demo/t9k-assethub/dataset/text

创建完成之后,使用 ah ls 命令查看当前用户的模型文件夹和数据集文件夹:

$ ah ls model
NAME    PATH                          LABELS    PERMISSION
llm     /demo/t9k-assethub/model/llm             own

$ ah ls dataset
NAME    PATH                              LABELS    PERMISSION
text    /demo/t9k-assethub/dataset/text              own

使用 ah ls 命令查看模型文件夹下的所有模型以及数据集文件夹下的所有数据集:

$ ah ls model/llm
NAME    PATH                              LABELS    PERMISSION
gpt2    /demo/t9k-assethub/model/llm/gpt2            own

$ ah ls dataset/text
NAME         PATH                                        LABELS    PERMISSION
openwebtext  /demo/t9k-assethub/dataset/text/openwebtext            own

最后使用 ah delete 命令删除所有创建的模型、数据集和文件夹:

$ ah delete model/llm/gpt2
AH INFO: Model /demo/t9k-assethub/model/llm/gpt2 deleted

$ ah delete dataset/text/openwebtext
AH INFO: Dataset /demo/t9k-assethub/dataset/text/openwebtext deleted

# 可以直接删除文件夹, 其中的模型或数据集都会被一并删除
$ ah delete model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm deleted

$ ah delete dataset/text
AH INFO: Folder /demo/t9k-assethub/dataset/text deleted

通过 Python SDK

切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。

导入 t9k.ah 模块,使用 ah.login() 函数登录到 Asset Hub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):

from t9k import ah

ah.login(host='<asset-hub-server-url>',
         api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>

假设当前用户(这里假设用户名为 demo)没有可以访问的文件夹,使用 ah.create() 函数创建一个模型文件夹和一个数据集文件夹,各返回一个 Folder 实例:

model_folder = ah.create('model/llm')
dataset_folder = ah.create('dataset/text')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Folder /demo/t9k-assethub/dataset/text created

继续使用 ah.create() 函数在模型文件夹中创建一个模型,以及在数据集文件夹中创建一个数据集:

model = ah.create('model/llm/gpt2')
dataset = ah.create('dataset/text/openwebtext')
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
AH INFO: Dataset openwebtext created for Folder /demo/t9k-assethub/dataset/text

创建完成之后,使用 ah.list() 函数返回当前用户的文件夹:

from pprint import pprint

pprint(ah.list('model'))
pprint(ah.list('dataset'))
[{'description': '',
  'editor': 'demo',
  'extra': '{"createdTimestamp": "2023-08-17T08:05:24.044319Z"}',
  'id': '967a5135-8b13-4283-9fad-ba53503612b3',
  'labels': [],
  'modifiedTimestamp': '2023-08-17T08:05:24.390002Z',
  'name': 'llm',
  'path': '/demo/t9k-assethub/model/llm',
  'permission': 'own',
  'storageType': 0,
  'type': 'Folder'}]
[{'description': '',
  'editor': 'demo',
  'extra': '{"createdTimestamp": "2023-08-17T08:05:24.196610Z"}',
  'id': 'd0d9f4b2-6c15-4dbb-b2d1-0619b6774c4a',
  'labels': [],
  'modifiedTimestamp': '2023-08-17T08:05:24.519213Z',
  'name': 'text',
  'path': '/demo/t9k-assethub/dataset/text',
  'permission': 'own',
  'storageType': 0,
  'type': 'Folder'}]

继续使用 ah.list() 函数返回模型文件夹下的所有模型和数据集文件夹下的所有数据集:

pprint(ah.list('model/llm'))
pprint(ah.list('dataset/text'))
[{'description': '',
  'editor': 'demo',
  'extra': '{"createdTimestamp": "2023-08-17T08:11:09.948554Z"}',
  'id': '2157a139-e20b-4736-9e25-d4495e287af8',
  'labels': [],
  'modifiedTimestamp': '2023-08-17T08:11:10.327166Z',
  'name': 'gpt2',
  'path': '/demo/t9k-assethub/model/llm/gpt2',
  'permission': 'own',
  'storageType': 3,
  'type': 'Model'}]
[{'description': '',
  'editor': 'demo',
  'extra': '{"createdTimestamp": "2023-08-17T08:11:10.508407Z"}',
  'id': '6826131c-2c88-483e-8a48-0f6d8fa59cfa',
  'labels': [],
  'modifiedTimestamp': '2023-08-17T08:11:10.830665Z',
  'name': 'openwebtext',
  'path': '/demo/t9k-assethub/dataset/text/openwebtext',
  'permission': 'own',
  'storageType': 3,
  'type': 'Dataset'}]

最后使用 ah.delete() 函数删除所有创建的模型、数据集和文件夹:

ah.delete('model/llm/gpt2')
ah.delete('dataset/text/openwebtext')
ah.delete('model/llm')    # 可以直接删除文件夹, 其中的模型或数据集都会被一并删除
ah.delete('dataset/text')
AH INFO: Model /demo/t9k-assethub/model/llm/gpt2 deleted
AH INFO: Dataset /demo/t9k-assethub/dataset/text/openwebtext deleted
AH INFO: Folder /demo/t9k-assethub/model/llm deleted
AH INFO: Folder /demo/t9k-assethub/dataset/text deleted

通过控制台

数据集文件夹、数据集的控制台操作分别和模型文件夹、模型完全一致。本教程后续仅展示模型文件夹和模型的创建、查看、删除、分享功能,你可以用同样的方式操作数据集文件夹和数据集。

在左侧的导航菜单中点击模型,选择查看范围为 My Own,查看当前用户的所有模型文件夹。然后点击右上角的 + 创建新的模型文件夹:

model-all

填写名称 image-classification,点击创建

folder-create

接下来分享这个文件夹。点击文件夹右侧的 更多 > 分享

folder-share

点击添加分享目标,选择分享的对象为 Public(所有用户可见),分享的权限是 Edit,最后点击分享

folder-share-setting

回到 Asset Hub 控制台,点击模型文件夹 image-classification 查看其中的模型:

folder-list

新创建的模型文件夹中没有模型,点击右上角的 + 创建一个模型:

model-list

填写名称 mnist,然后点击创建

model-create

创建成功后,在模型文件夹中可以看到模型信息:

model-created

点击更多 > 删除,删除创建的模型,然后点击左上角的返回,返回模型文件夹的页面:

model-delete

最后,返回 Asset Hub 控制台,点击更多 > 删除,删除模型文件夹:

folder-delete

通过 S3 访问模型和数据集

本教程演示如何 S3 访问模型。

数据集同理。

准备工作

创建 S3 凭证

在 Asset Hub 控制台进入模型详情页面,点击 S3 凭证可以查看目前已有的所有 S3 凭证。然后点击表格右上角的 + 创建一个 S3 凭证:

s3-cred-list

填写名称 s3-rw,选择类型为可读/可写,最后点击创建

s3-cred-create

查看 S3 凭证

创建完成后,点击表格左上角的可读/可写,查看所有类型为可读/可写的 S3 凭证:

s3-cred-list-rw

点击刚刚创建的 S3 凭证 s3-rw,查看其详情:

s3-cred-detail

S3 凭证有三种格式:

  1. .s3cfg:命令行工具 s3cmd 的配置文件。
  2. S3-cfg Secret:s3cfg 形式的 Secret YAML,创建后可在 Notebook、Job、Workflow 等工作负载时挂载此 Secret。
  3. S3-env Secret:s3 环境变量形式的 Secret YAML,创建后可在 Notebook、Job、Workflow 等工作负载时挂载此 Secret。

通过 s3cmd 访问模型

点击右侧的复制,复制 .s3cfg 格式的 S3 凭证,保存在 $HOME/.s3cfg 文件中,即可通过 s3cmd 命令行工具访问此模型中的文件。

例如,在上述示例中,所创建的 S3 凭证 s3-rw 仅可用于访问名为 neox 的模型。根据页面上的提示,此模型对应的 bucket 名称为 adb2a768-f01a-467b-b146-e82c0693c16b,用户可以通过以下命令查看此模型的 main 分支的 README.md 文件:

s3cmd ls s3://baa98ded-2f93-4e9b-835a-6515a63a6eb4/main/README.md

通过以下命令下载此模型的某个分支下某个路径的文件:

s3cmd get s3://baa98ded-2f93-4e9b-835a-6515a63a6eb4/branch-name/path/to/object

通过 StorageShim 访问模型

除了通过命令行工具访问,用户还可以创建一个 StorageShim,将 S3 bucket 的某个子路径形式化为一个持久卷,以便在 Notebook、Job、Workflow 等工作负载中挂载,直接以文件系统的形式查看、编辑 S3 bucket 中的文件。

在创建 StorageShim 之前,用户首先需要创建一个 Secret 保存 S3 bucket 的相关信息。在 S3 凭证的详情页面,点击左侧的 S3-cfg Secret 标签,然后点击右上角的复制

s3-cred-detail-s3-cfg-secret

在模型构建控制台的左侧导航菜单中点击辅助 > Secret 进入 Secret 管理页面,然后点击右上角的创建 Secret进入 Secret 创建页面:

secret-list

在 Secret 创建页面,点击预览 YAML,将所复制的 S3-cfg Secret 粘贴到 YAML 编辑框中,最后点击创建

secret-create

在模型构建控制台的左侧导航菜单中点击存储 > 持久卷进入持久卷管理页面,然后点击上方的 S3 进入 S3 类型的持久卷管理页面,最后点击右上角的创建进入 StorageShim 创建页面:

storageshim-list

在 StorageShim 创建页面,

  1. 名称填写 neox
  2. 类型选择 S3
  3. S3 URI 填写 s3://adb2a768-f01a-467b-b146-e82c0693c16b/main,以便把上述示例模型的 main 分支挂载为持久卷;
  4. S3 Secret 选择刚刚创建的 s3-rw

最后点击创建

storageshim-create

StorageShim 创建完成后,等待其阶段变为 Bound,用户即可通过以下方式使用这个名为 neox 的持久卷:

  1. 点击启动,创建一个 Explorer 来浏览持久卷中的文件。
  2. 在创建 Notebook 时,添加持久卷 neox,以便在 Notebook 中查看和编辑此模型中的文件。
  3. 在创建 Job 时,添加持久卷 neox,以便在 Job 中使用此模型中的文件。
storageshim-list-after-create

修改文件夹、模型和数据集的基本信息

本教程演示如何通过多种方式修改文件夹、模型和数据集的基本信息。

准备工作

通过命令行工具

切换到你的工作路径下:

$ cd /your/workpath

修信息的方式对于文件夹、模型和数据集都是相同的。下面将以模型文件夹和模型为例进行演示(这里假设用户名为 demo)。

依次创建模型文件夹和模型:

$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created

$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm

使用 ah update 命令修改文件夹和模型的名称:

$ ah update model/llm -n chat
AH INFO: Folder /demo/t9k-assethub/model/llm updated to /demo/t9k-assethub/model/chat

$ ah update model/chat/gpt2 -n gpt3
AH INFO: Model /demo/t9k-assethub/model/chat/gpt2 updated to /demo/t9k-assethub/model/chat/gpt3

使用 ah ls 命令查看文件夹和模型的标签:

$ ah ls model --detail
NAME    PATH                          ...  LABELS  ...
chat    /demo/t9k-assethub/model/chat

$ ah ls model/chat
NAME    PATH                               LABELS  ...
gpt3    /demo/t9k-assethub/model/chat/gpt3

两者都没有标签,再次使用 ah update 命令为它们添加标签:

$ ah update model/chat --label "NLP" --label "AIGC"
AH INFO: Folder /demo/t9k-assethub/model/chat updated

$ ah ls model --detail
NAME    PATH                          ...  LABELS     ...
chat    /demo/t9k-assethub/model/chat       AIGC, NLP
$ ah update model/chat/gpt3 --label "GPT"
AH INFO: Model /demo/t9k-assethub/model/chat/gpt3 updated

$ ah ls model/chat
NAME    PATH                               LABELS    PERMISSION
gpt3    /demo/t9k-assethub/model/chat/gpt3  GPT       own

通过 Python SDK

切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。

导入 t9k.ah 模块,使用 ah.login() 函数登录到 Asset Hub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):

from t9k import ah

ah.login(host='<asset-hub-server-url>',
         api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>

修改信息的方式对于文件夹、模型和数据集都是相同的。下面将以模型文件夹和模型为例进行演示(这里假设用户名为 demo)。

依次创建模型文件夹和模型:

model_folder = ah.create('model/llm')
model = ah.create('model/llm/gpt2')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm

使用 ah.update() 函数修改文件夹和模型的名称:

ah.update('model/llm', name='chat')
ah.update('model/chat/gpt2', name='gpt3')
AH INFO: Folder /demo/t9k-assethub/model/llm updated to /demo/t9k-assethub/model/chat
AH INFO: Model /demo/t9k-assethub/model/chat/gpt2 updated to /demo/t9k-assethub/model/chat/gpt3

使用 ah.list() 函数查看文件夹和模型的标签:

from pprint import pprint

pprint(ah.list('model'))
pprint(ah.list('model/chat'))
[{...
  'labels': [],
  'name': 'chat',
  'path': '/demo/t9k-assethub/model/chat',
  'type': 'Folder'}]
[{...
  'labels': [],
  'name': 'gpt3',
  'path': '/demo/t9k-assethub/model/chat/gpt3',
  'type': 'Model'}]

两者都没有标签,继续使用 ah.update() 函数为它们添加标签:

ah.update('model/chat', labels=['NLP', 'AIGC'])
ah.update('model/chat/gpt3', labels=['GPT'])
AH INFO: Folder /demo/t9k-assethub/model/chat updated
AH INFO: Model /demo/t9k-assethub/model/chat/gpt3 updated
pprint(ah.list('model'))
pprint(ah.list('model/chat'))
[{...
  'labels': ['AIGC', 'NLP'],
  'name': 'chat',
  'path': '/demo/t9k-assethub/model/chat',
  'type': 'Folder'}]
[{...
  'labels': ['GPT'],
  'name': 'gpt3',
  'path': '/demo/t9k-assethub/model/chat/gpt3',
  'type': 'Model'}]

通过控制台

数据集文件夹、数据集的控制台操作分别和模型文件夹、模型完全一致。本教程后续仅展示如何修改模型文件夹和模型的基本信息,你可以用同样的方式操作数据集文件夹和数据集。

在进行教程之前,先按照操作文件夹、模型和数据集一节完成模型文件夹和模型的创建(chat/gpt2)。

在模型文件夹列表中,选中需要修改的模型文件夹,点击更多 > 编辑

folder-list

填写新的名称和描述信息,添加新标签,点击更新按钮:

folder-edit

回到文件夹列表,可以看到文件夹信息发生改变:

folder-list-after-edit

点击文件夹名称,进入模型列表,选中需要修改的模型,点击更多 > 编辑

model-list

填写新的名称和描述信息,添加新标签,点击更新按钮:

model-edit

回到模型列表,可以看到模型信息发生改变:

model-list-after-edit

操作模型和数据集的分支、tag 和 commit

本教程演示如何通过多种方式操作模型的分支、tag 和 commit,包括创建、查看和删除分支,创建、查看和删除 tag,以及查看 commit。

数据集同理。

准备工作

通过命令行工具

切换到你的工作路径下:

$ cd /your/workpath

操作 tag 和 commit 的方式对于模型和数据集都是相同的,只有模型允许操作分支。下面将以模型为例进行演示(这里假设用户名为 demo)。

依次创建模型文件夹和模型:

$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created

$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm

继续使用 ah create 命令为模型创建一个分支:

$ ah create model/llm/gpt2:v1
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2

使用 ah ls --branch 命令查看模型的所有分支:

$ ah ls model/llm/gpt2 --branch
NAME    COMMIT_ID
main    fe46da7e
v1      fe46da7e

继续使用 ah create 命令为模型创建一个 tag:

$ ah create model/llm/gpt2:20230101 --tag --source v1
AH INFO: Tag 20230101 created from branch v1 for Model /demo/t9k-assethub/model/llm/gpt2

使用 ah ls --tag 命令查看模型的所有 tag:

$ ah ls model/llm/gpt2 --tag
    NAME  COMMIT_ID
20230101  fe46da7e

使用 ah ls --commit 命令查看模型的一个分支下的所有 commit:

$ ah ls model/llm/gpt2:v1 --commit
COMMIT_ID    MESSAGE             CREATED
fe46da7e     Repository created  3m16s ago

最后使用 ah delete 命令删除所有创建的分支和 tag:

$ ah delete model/llm/gpt2:v1
AH INFO: Branch v1 deleted for Model /demo/t9k-assethub/model/llm/gpt2

$ ah delete model/llm/gpt2:20230101
AH INFO: Tag 20230101 deleted for Model /demo/t9k-assethub/model/llm/gpt2

通过 Python SDK

切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。

导入 t9k.ah 模块,使用 ah.login() 函数登录到 Asset Hub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):

from t9k import ah

ah.login(host='<asset-hub-server-url>',
         api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>

操作 tag 和 commit 的方式对于模型和数据集都是相同的,只有模型允许操作分支。下面将以模型为例进行演示(这里假设用户名为 demo)。

依次创建模型文件夹和模型:

model_folder = ah.create('model/llm')
model = ah.create('model/llm/gpt2')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm

继续使用 ah.create() 函数为模型创建一个分支:

branch = ah.create('model/llm/gpt2:v1')
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2

使用 ah.list() 函数查看模型的所有分支:

from pprint import pprint

pprint(ah.list('model/llm/gpt2', resource='branch'))
[{'commit_id': 'a15799f8f601d514a1a385a57b3078f8e178614a66aa920217175f6dcac2b083',
  'id': 'main'},
 {'commit_id': 'a15799f8f601d514a1a385a57b3078f8e178614a66aa920217175f6dcac2b083',
  'id': 'v1'}]

继续使用 ah.create() 函数为模型创建一个 tag:

tag = ah.create('model/llm/gpt2:20230101', create_tag=True, source='v1')
AH INFO: Tag 20230101 created from branch v1 for Model /demo/t9k-assethub/model/llm/gpt2

使用 ah.list() 函数查看模型的所有 tag:

pprint(ah.list('model/llm/gpt2', resource='tag'))
[{'commit_id': 'a15799f8f601d514a1a385a57b3078f8e178614a66aa920217175f6dcac2b083',
  'id': '20230101'}]

最后使用 ah.delete() 函数删除所有创建的分支和 tag:

ah.delete('model/llm/gpt2:v1')
ah.delete('model/llm/gpt2:20230101')
AH INFO: Branch v1 deleted for Model /demo/t9k-assethub/model/llm/gpt2
AH INFO: Tag 20230101 deleted for Model /demo/t9k-assethub/model/llm/gpt2

操作模型和数据集的对象

本教程演示如何通过多种方式操作模型的对象,包括修改、查看和下载 Asset Hub 中存储的对象文件。数据集同理。

准备工作

通过命令行工具

切换到你的工作路径下:

$ cd /your/workpath

操作对象的方式对于模型和数据集都是相同的,除了数据集只允许操作主分支(main 分支)中的对象。下面将以模型为例进行演示(这里假设用户名为 demo)。

依次创建模型文件夹、模型和分支:

$ ah create model/llm
AH INFO: Folder /demo/t9k-assethub/model/llm created

$ ah create model/llm/gpt2
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm

$ ah create model/llm/gpt2:v1
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2

使用 ah commit 命令向该分支上传本地文件(这里以 model_state_dict.ptREADME.md 为例)作为对象存储:

$ ah commit model/llm/gpt2:v1 --message "Add model file" --add model_state_dict.pt --add README.md
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object 1/2 model_state_dict.pt:
         Done        
AH INFO: Uploading object 2/2 README.md:
         Done        
AH INFO: Commit 29d6f29e created

使用 ah ls 命令查看分支的所有对象:

$ ah ls model/llm/gpt2:v1
PATH                   BYTES  CHECKSUM                          MODIFIED
README.md               110B  d1f0e72bd20091c3869cefff8c72661b  1m29s ago
model_state_dict.pt  375943B  1203ee282c235c9fb4c2ea932a7b7cc8  1m29s ago

再次使用 ah commit 命令,当重复上传文件到同一路径时,原有的对象会被替换:

$ ah commit model/llm/gpt2:v1 --message "Update README" --add README.md
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object 1/1 README.md:
         Done        
AH INFO: New commit 53097cba created

$ ah ls model/llm/gpt2:v1
PATH                   BYTES  CHECKSUM                          MODIFIED
README.md               221B  84c44f1510389ea7de91e550be8a7130  15s ago
model_state_dict.pt  375943B  1203ee282c235c9fb4c2ea932a7b7cc8  5m37s ago

使用 -d PATH 选项以删除指定路径的对象:

$ ah commit model/llm/gpt2:v1 --message "Remove README" --delete README.md
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Deleting object README.md:
         Done
AH INFO: Commit cf8dcc26 created

$ ah ls model/llm/gpt2:v1
PATH                   BYTES  CHECKSUM                          MODIFIED
model_state_dict.pt  375943B  1203ee282c235c9fb4c2ea932a7b7cc8  6m2s ago

每次使用 ah commit 命令修改分支(添加、覆盖或删除对象)时,分支都会创建一个新的 commit。使用 ah ls commit 命令查看上面的操作所创建的 3 个 commit:

$ ah ls model/llm/gpt2:v1 --commit
COMMIT_ID     MESSAGE               CREATED
cf8dcc26      Remove README         5m47s ago
53097cba      Update README         21m46s ago
29d6f29e      Add model file        33m8s ago
c4bebb3a      Repository created    33m18s ago   # 初始 commit

之后想要使用这些对象时,使用 ah download 命令下载对象保存为本地文件:

$ ah download model/llm/gpt2:v1
AH INFO: Downloading object 1/1 model_state_dict.pt:
         ━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 375.9/375.9 kB • 2.6 MB/s • 0:00:00

$ ls
model_state_dict.pt ...

通过 Python SDK

切换到你的工作路径下,然后以任意方式执行下面的 Python 代码。

导入 t9k.ah 模块,使用 ah.login() 函数登录到 Asset Hub 服务器(如果配置文件中的凭据仍有效,则无需提供参数):

from t9k import ah

ah.login(host='<asset-hub-server-url>',
         api_key='<your-api-key>')
AH INFO: Logged in to Asset Hub server and AIStore server as user <your-user-name>

操作对象的方式对于模型和数据集都是相同的,除了数据集只允许操作主分支(main 分支)中的对象。下面将以模型为例进行演示(这里以 user 表示当前用户)。

依次创建模型文件夹、模型和分支:

model_folder = ah.create('model/llm')
model = ah.create('model/llm/gpt2')
branch = ah.create('model/llm/gpt2:v1')
AH INFO: Folder /demo/t9k-assethub/model/llm created
AH INFO: Model gpt2 created for Folder /demo/t9k-assethub/model/llm
AH INFO: Branch v1 created for Model /demo/t9k-assethub/model/llm/gpt2

使用 ah.commit() 函数向该分支上传本地文件作为对象存储:

commit1 = ah.commit('model/llm/gpt2:v1',
                    msg='Add model file',
                    add=['model_state_dict.pt', 'README.md'])
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object model_state_dict.pt:
         Done        
AH INFO: Uploading object README.md:
         Done        
AH INFO: Commit 6a57546b created

使用 ah.list() 函数查看分支的所有对象:

from pprint import pprint

pprint(ah.list('model/llm/gpt2:v1'))
[{'checksum': 'f0db68fc4327c528b3a23fdc47c30c9e',
  'content_type': 'application/octet-stream',
  'mtime': 1683881423,
  'path': 'README.md',
  'path_type': 'object',
  'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjoi2hci2stu7un0',
  'size_bytes': 110},
 {'checksum': '1203ee282c235c9fb4c2ea932a7b7cc8',
  'content_type': 'application/octet-stream',
  'mtime': 1683881423,
  'path': 'model_state_dict.pt',
  'path_type': 'object',
  'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjgi2hci2stu7umg',
  'size_bytes': 375943}]

再次使用 ah.commit() 函数,当重复上传文件到同一路径时,原有的对象会被替换:

commit2 = ah.commit('model/llm/gpt2:v1', msg='Update README', add=['README.md'])

pprint(ah.list('model/llm/gpt2:v1'))
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Uploading object README.md:
         Done        
AH INFO: Commit 8183e1df created
[{'checksum': '1cbd5021ee923905bbdc29883c50a1b0',
  'content_type': 'application/octet-stream',
  'mtime': 1683881478,
  'path': 'README.md',
  'path_type': 'object',
  'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevs1gi2hci2stu7uog',
  'size_bytes': 221},
 {'checksum': '1203ee282c235c9fb4c2ea932a7b7cc8',
  'content_type': 'application/octet-stream',
  'mtime': 1683881423,
  'path': 'model_state_dict.pt',
  'path_type': 'object',
  'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjgi2hci2stu7umg',
  'size_bytes': 375943}]

使用 delete 选项以删除指定路径的对象:

commit3 = ah.commit('model/llm/gpt2:v1', msg='Remove README', delete=['README.md'])

pprint(branch.list_object())
AH INFO: Committing changes to branch /demo/t9k-assethub/model/llm/gpt2:v1
AH INFO: Deleting object README.md:
         Done
AH INFO: Commit 00af1151 created
[{'checksum': '1203ee282c235c9fb4c2ea932a7b7cc8',
  'content_type': 'application/octet-stream',
  'mtime': 1683881423,
  'path': 'model_state_dict.pt',
  'path_type': 'object',
  'physical_address': 's3://t9k-aistore/d3a98ad0-50ca-42df-becf-8bbf4351d2c9/data/gnoggd0i2hci2stu7uhg/chevrjgi2hci2stu7umg',
  'size_bytes': 375943}]

每次使用 ah.commit() 函数修改分支(添加、覆盖或删除对象)时,分支都会创建一个新的 commit。继续使用 ah.list() 函数查看上面的操作所创建的 3 个 commit:

pprint(ah.list('model/llm/gpt2:v1', resource='commit'))
[{'committer': 'admin',
  'creation_date': 1683881538,
  'id': '00af1151865121a79233af326b21864f2f6dbcc3b5bebb2f8768e2b13154f754',
  'message': 'Remove README',             # commit3
  'meta_range_id': 'c959b9ce4301591b82517c97ca277b034fd4a4d181b63db7571a2a8174844848',
  'metadata': {},
  'parents': ['8183e1dfb0dcded478aff1b5cb2975ae22e83ca4f37333fb904e5bcd27897923']},
 {'committer': 'admin',
  'creation_date': 1683881479,
  'id': '8183e1dfb0dcded478aff1b5cb2975ae22e83ca4f37333fb904e5bcd27897923',
  'message': 'Update README',             # commit2
  'meta_range_id': '2184d241abdc0ce3e26db44ad2c1df3e1e6a7a6b231fa1f17db7684982a55243',
  'metadata': {},
  'parents': ['6a57546b1275ba6b7f1399e0f7213552ac7bdf545de8692e494db47b93623b9d']},
 {'committer': 'admin',
  'creation_date': 1683881423,
  'id': '6a57546b1275ba6b7f1399e0f7213552ac7bdf545de8692e494db47b93623b9d',
  'message': 'Add model file',            # commit1
  'meta_range_id': '0b8943e0b3b4a3b8661f6146f47f85562aea5c7eb88bc2c66f2adf7443a08451',
  'metadata': {},
  'parents': ['610af4d2991e5c9b9d527dedf34db3cd11c8bd5bb7cc0e8ed0b97505319f8f11']},
 {'committer': '',
  'creation_date': 1683881388,
  'id': '610af4d2991e5c9b9d527dedf34db3cd11c8bd5bb7cc0e8ed0b97505319f8f11',
  'message': 'Repository created',        # 初始 commit
  'meta_range_id': '',
  'metadata': {},
  'parents': []}]

之后想要使用这些对象时,使用 ah.download() 函数下载对象保存为本地文件:

ah.download('model/llm/gpt2:v1')

import os
print(os.listdir())
AH INFO: Downloading object 1/1 model_state_dict.pt:
         ━━━━━━━━━━━━━━━━━━━━━━━━━━ 100.0% • 375.9/375.9 kB • 2.6 MB/s • 0:00:00
['model_state_dict.pt', ...]

通过控制台

数据集的控制台操作和模型完全一致。本教程后续仅展示模型对象的上传和下载,你可以用同样的方式操作数据集。

在进行教程之前,先按照操作文件夹、模型和数据集一节完成模型文件夹和模型的创建(chat/gpt3)。

进入模型详情页后,点击所有文件 > 上传图标

model-detail

点击选择文件选择所要上传的文件,填写描述信息,然后点击提交

model-upload

完成提交后,可以在所有文件中看到刚刚上传的文件,点击下载图标下载该文件:

model-object-list

点击介绍 > 添加介绍

model-introduce

在编辑框中按照 markdown 格式编辑模型的描述信息,填写提交信息,点击提交

model-readme

添加完介绍后,在模型详情页可以看到模型介绍:

model-introduce-after-add

模型介绍本质上是 README.md 文件,在所有文件中可以看到:

model-object-list-readme

从 Hugging Face 下载模型和数据集到 Asset Hub

Hugging Face 是一个 AI 开源社区,其提供的 Git 仓库托管了大量流行的开源模型和数据集。本教程演示如何使用工作流将 Hugging Face 的模型下载并存储到 Asset Hub,即在 Asset Hub 中创建一个副本。数据集同理。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

查看运行结果

创建 WorkflowRun 之后,进入工作流控制台的 WorkflowRun 列表页面,可以看到名为 hf-to-ah-xxxxx 的 WorkflowRun 正在运行。

workflowrun-list

点击其名称进入详情页面,可以看到 WorkflowRun 的日志。点击右上角的刷新图标以手动刷新日志。

workflowrun-detail

等待 WorkflowRun 运行完成。

查看模型

在 WorkflowRun 运行完成之后,进入 Asset Hub 控制台,进入模型文件夹 llm,可以看到下载的模型已经被放置在这里。

model-list

点击其名称进入详情页面,可以看到 facebook/opt-125m 模型的介绍,其解析自 README.md 文件。

model-reamd

点击上方的所有文件标签页,可以看到所有模型文件。检查确认与原模型文件一致。

model-reamd

追踪模型训练

在复杂的模型训练实验中,研究人员或工程师需要处理数以百计的实验配置和结果,在缺乏有效管理工具的情况下很容易迷失在海量的数据和文件中。因此,追踪和记录实验变得十分重要,它能够帮助研究人员快速识别最佳模型,比较不同模型的差异,洞悉关键因素的作用,并且迅速迭代改进,从而大幅提升研究和开发的效率。

这一部分将使用实验管理模块Python SDK 追踪模型的训练过程和结果。Python SDK 负责自动记录超参数、指标、平台信息以及任何重要的输入输出文件,实验管理控制台则提供直观的可视化界面以及便捷的团队协作体验。我们将从介绍实验管理控制台与 Python SDK 的基本用法开始,进而到实际场景中追踪模型的训练,最后我们查看 AutoTune 进行超参数优化的结果。

本部分常见任务如下:

在实验管理控制台查看和管理数据

本教程演示如何使用实验管理控制台来查看和管理记录的模型训练数据。

进入实验管理控制台

在 TensorStack AI 平台的首页,点击实验管理进入实验管理控制台。

enter-experiment-console

浏览文件夹

当前用户的所有数据以类似于文件系统的方式组织,每个 Run(或 Artifact、AutoTune)都位于特定的路径之下。点击一个文件夹(Folder)以进入,查看其下的所有子文件夹和 Run(或 Artifact、AutoTune)。

enter-folder

使用上方的面包屑导航或左侧的导航菜单可以返回上级文件夹或跳转到其他文件夹。

jump-to-folder

创建和删除文件夹

若要创建一个文件夹,点击右上角的添加,在对话框中提供文件夹名称并点击创建

create-folder

若要删除一个文件夹,点击文件夹项右侧的操作,或点击面包屑导航中的当前文件夹,然后点击删除

delete-folder1
delete-folder2

共享文件夹

点击文件夹项右侧的操作,或点击面包屑导航中的当前文件夹,点击分享,在对话框中管理文件夹的分享成员列表。空白表示文件夹当前没有被分享给任何其他用户。

share-folder

分享成员列表可以任意添加(点击加号)或移除(点击用户项右侧的减号)平台的其他用户或用户组,选择用户或用户组的名称和权限,最后点击保存以确定。

share-user-list

来自其他用户分享的文件夹、Run、Artifact 或 AutoTune 将出现在导航菜单的分享给我的标签下。

shared-with-me

其他文件夹操作

同样点击文件夹项右侧的操作,或点击面包屑导航中的当前文件夹,你还可以进行创建快捷方式移动以及重命名操作。

查看 Run 和 Artifact

点击一个 Run 或 Artifact 的名称以进入它的详情页面。

enter-run-artifact

Run 的详情页面中,多个标签页分别展示了平台信息、指标、超参数以及数据流。

run-details

Artifact 的详情页面中,多个标签页分别展示了文件列表以及数据流。

artifact-details

创建和删除 Run、Artifact 和 AutoTune

创建 Run 和 Artifact 的方法请参阅使用 Python SDK 记录和上传数据;创建 AutoTune 的方法请参阅使用 AutoTune 进行超参数优化

若要删除一个 Run(或 Artifact、AutoTune,下同),与删除文件夹的操作相同,点击 Run 项右侧的操作,或点击面包屑导航中的当前 Run,然后点击删除

delete-run

分享 Run、Artifact 和 AutoTune 以及其他操作

分享 Run(或 Artifact、AutoTune)或者进行其他操作的方法都与文件夹相同,这里不再赘述。

退出登录或切换用户

如果你想要退出当前用户的登录,点击右上角的用户头像,然后点击退出登录

sign-out

再次进入实验管理控制台时,你需要输入用户名和密码以重新登录。

使用 Python SDK 记录和上传数据

本教程介绍如何使用 Python SDK 进行创建、加载、上传 Run 和 Artifact,设定超参数,记录指标等操作。

创建 Run

基本方法

在模型的训练脚本中,你需要首先创建一个 Run,通过调用 t9k.em.create_run() 函数。其返回的 Run 实例即代表了一次训练的运行。此方法调用后,Run 将被创建,具有状态“Running”,其本地文件默认保存在相对路径 .em/runs 下,每个 Run 拥有一个独立的名为 <run_name>_<date>_<time>_<random_suffix>(称为该 Run 的备用名称)的子目录。

最基本的初始化方法只需要提供名称作为参数。

from t9k import em

run = em.create_run(name='mnist_torch')    # 返回Run实例

自动上传

如果想要自动异步上传 Run 的更新,可以设定 auto_upload=True,并提供文件夹路径,以及设定是否创建不存在的各级文件夹。在这种情况下,你在创建 Run 之前需要先登录到 AIStore 服务器

run = em.create_run(name='mnist_torch',
                    auto_upload=True,      # 启用自动上传
                    folder='new-folder',   # 文件夹路径
                    make_folder=True)      # 创建不存在的各级文件夹

如果目标文件夹已经存在同名的 Run,则需要指定 conflict_strategy 参数以处理冲突,参数接受以下值:

  • 'skip':跳过上传。
  • 'error':错误退出。
  • 'new':以 Run 的备用名称上传。
  • 'replace':替换同名的 Run。

例如,运行以下代码两次,第二次创建的 Run 会以类似 mnist_torch_231231_235959_61p5jc 的名称被上传到 new-folder 文件夹下。

run = em.create_run(name='mnist_torch',
                    auto_upload=True,
                    folder='new-folder',
                    make_folder=True,
                    conflict_strategy='new')

提供标签和描述

你可以为创建的 Run 提供用于分类或介绍的标签或描述。

run = em.create_run(
    name='mnist_torch',
    labels=['torch', 'CNN'],  # 标签
    description=              # 描述
    'Train a simple CNN model that classifies images of handwritten digits.')

提供配置文件

你可以将上面的所有配置(以及下面将要提到的超参数)都写进一个 YAML 文件里,然后传入该配置文件的路径即可。

run = em.create_run(config_path='./run_config.yaml')  # 提供配置文件

其中 run_config.yaml 的内容如下:

name: mnist_torch
auto_upload: true
folder: new-folder
make_folder: true
conflict_strategy: new
labels:
- torch
- CNN
description: Train a simple CNN model that classifies images of handwritten digits.

设定超参数

基本方法

超参数是影响模型训练效果的重要因素,记录训练的超参数十分必要,尤其是当你聚焦于某几个特定的超参数时。Run 实例的 hparams 属性是一个容器对象,用于保存你想要记录的所有超参数,你可以像操作 Python 字典一样操作它。一种推荐的设定超参数的方法是调用一次该容器对象的 update() 方法完成所有超参数的设定。

run.hparams.update({
    'batch_size': 32,
    'epochs': 10,
    'learning_rate': 0.001,
    'conv_channels': 32,
    'conv_kernel_size': 3,
    'maxpool_size': 2,
    'linear_features': 64,
})

hparams = run.hparams      # 便于之后访问

另一种推荐的方法是在创建 Run 的时候就传入所有超参数,此时可以将超参数也写进配置文件。

run = em.create_run(
    name='mnist_torch',
    hparams={
    'batch_size': 32,
    'epochs': 10,
    'learning_rate': 0.001,
    'conv_channels': 32,
    'conv_kernel_size': 3,
    'maxpool_size': 2,
    'linear_features': 64,
})

# 或

run = em.create_run(config_path='./run_config.yaml')

其中 run_config.yaml 的内容如下:

name: mnist_torch
hparams:
  batch_size: 32
  epochs: 10
  learning_rate: 0.001
  conv_channels: 32
  conv_kernel_size: 3
  maxpool_size: 2
  linear_features: 64

当然,你也可以多次调用 update() 方法,或者使用类似 Python 字典的键值对赋值方法设定单个超参数。

run.hparams['batch_size'] = 32

设定完成之后,使用这些超参数配置模型,同样使用类似 Python 字典的键值对访问方法。

from tensorflow.keras import layers, models, optimizers

model = models.Sequential()
model.add(layers.Conv2D(hparams['conv_channels'],     # 使用超参数配置模型
                        hparams['conv_kernel_size'],
                        input_shape=(28, 28, 1)))
...
optimizer = optimizers.Adam(learning_rate=hparams['learning_rate'])
model.compile(
    optimizer=optimizer,
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy'])
...
model.fit(train_images,
          train_labels,
          batch_size=hparams['batch_size'],
          epochs=hparams['epochs'])

设定作为标记的超参数

在上面的示例中,所有超参数都是直接传入各函数以配置模型。你也可以设定一些作为标记的超参数,例如网络类型、优化器类型、损失函数类型、激活函数类型等,以便日后快速回顾重要信息。

run.hparams.update({
    'network_structure': 'CNN',
    'optimizer': 'Adam',
    'loss': 'sparse categorical crossentropy',
    'linear_acti': 'relu',
})

配合 argparse 模块使用

许多训练脚本的超参数都是从命令行传入,由 argparse 模块解析。这些超参数可以方便地转换为字典对象并传入 update() 方法。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument(...)
args = parser.parse_args()

run.hparams.update(args.__dict__)

记录指标

手动记录

Run 实例的 log() 方法用于记录模型在训练、验证或测试过程中产生的指标。被传入的字典对象会被作为指标记录,与此同时还需要提供指标的类型、当前的全局训练步数以及(可选的)当前的回合数。

# PyTorch模型
for epoch in range(1, epochs + 1):
    model.train()
    for step, (data, target) in enumerate(train_loader, 1):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()

        if step % 500 == 0:
            train_loss = loss.item()
            logging.info(
                'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
                format(epoch, epochs, step, steps_per_epoch, train_loss))
            global_step = (epoch - 1) * steps_per_epoch + step

            run.log(
                type='train',                    # 指标类型
                metrics={'loss': train_loss},    # 指标名称及相应值
                step=global_step,                # 当前全局步数
                epoch=epoch)                     # 当前回合数

自动记录

对于建立在 Keras API 上的模型,更简单的方法是在模型的训练和测试方法中分别添加回调 t9k.em.keras.EMFitCallbackt9k.em.keras.EMEvalCallback 的实例。回调会相应地调用 log() 方法以自动记录各指标并同步到服务器。

# Keras模型
# 训练/验证过程和测试过程分别使用不同的回调
from t9k.em.keras import EMFitCallback, EMEvalCallback

model.fit(train_images,
          train_labels,
          epochs=10,
          validation_split=0.2,
          callbacks=EMFitCallback(run))

model.evaluate(test_images,
               test_labels,
               callbacks=EMEvalCallback(run))

结束 Run

模型的训练与测试全部完成后,你需要结束 Run,通过调用 Run 实例的 finish() 方法。此方法调用后,Run 的状态将更新为“Complete”。

run.finish()

创建 Artifact

基本方法

如要记录和保存与训练过程有关的文件,你需要创建一个 Artifact,通过调用 t9k.em.create_artifact() 函数。此方法调用后,Artifact 将被创建,其本地文件默认保存在相对路径 .em/artifacts 下。与 Run 相同,每个 Artifact 拥有一个独立的名为 <artifact_name>

最基本的初始化方法只需要提供名称作为参数。

dateset_artifact = em.create_artifact(name='mnist_dataset')

提供标签和描述

你可以为创建的 Artifact 提供用于分类或介绍的标签或描述。

dateset_artifact = em.create_artifact(
    name='mnist_dataset',
    labels=['dataset', 'MNIST'],                           # 标签
    description='Image dataset of handwritten digits.')    # 描述

为 Artifact 添加文件

与训练过程有关的文件通过 Artifact 实例的 add_file()add_dir() 方法添加到 Artifact 中。

dateset_artifact.add_file(file_path='./mnist.npz')    # 添加单个文件
dateset_artifact.add_dir(dir_path='./mnist/')         # 添加目录

Artifact 中的文件对象具有层次结构,你可以指定文件或目录位于 Artifact 的何路径下。

dateset_artifact.add_file(file_path='./mnist.npz', obj_path='dataset/')
dateset_artifact.add_dir(dir_path='./mnist/', obj_path='dataset/')

还可以通过 add_reference() 方法为 Artifact 添加一个网络文件的引用。

dateset_artifact.add_reference(uri='https://storage.googleapis.com/cvdf-datasets/mnist/train-images-idx3-ubyte.gz', obj_path='dataset/')

标记 Artifact 为 Run 的输入输出

为了构成 Run 与 Artifact 之间的数据流,需要调用 Run 实例的 mark_input()mark_output() 方法以标记 Artifact 实例为其输入或输出。

run.mark_input(dateset_artifact)
run.mark_output(model_artifact)

上传数据

基本方法

上传数据之前,你需要先登录到 AIStore 服务器,通过调用 t9k.em.login() 函数。

em.login(ais_host='<your-server-host>', api_key='<your-api-key>')

然后调用 RunArtifact 实例的 upload() 方法。

run.upload()
artifact.upload()

上传本地保存的数据

你也可以在训练结束之后将本地保存的数据上传到 AIStore 服务器,以应对训练时无网络连接、最初未打算上传、误删服务器中的数据等情形。

首先登录到 AIStore 服务器,然后加载保存在本地的 Run 或 Artifact,调用其 upload() 方法。

run = em.load_run(path='.em/runs/mnist_torch_231222_141932_61p5jc')
run.upload(folder='default', make_folder=True)

artifact = em.load_artifact(path='.em/runs/mnist_torch_saved_model_230908_165433_tou3ai')
artifact.upload(folder='default', make_folder=True)

下一步

单设备训练场景

本教程演示如何记录并展示单设备训练场景下的训练产生的信息、指标和文件(以 PyTorch 模型在单个 CPU 或 GPU 上的训练为例)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

下面介绍训练脚本进行了哪些修改以追踪训练。

准备训练脚本

准备一个 PyTorch 训练脚本,其模型对 MNIST 数据集的图像进行分类,具体代码如下所示。接下来将在此脚本的基础上进行简单的修改以进行追踪。

torch_mnist.py
import argparse
import logging
import os

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms

parser = argparse.ArgumentParser(
    description='Recording of training data of PyTorch model for MNIST with EM.'
)
parser.add_argument('--no_cuda',
                    action='store_true',
                    default=False,
                    help='Disable CUDA training.')
logging.basicConfig(format='%(message)s', level=logging.INFO)


class Net(nn.Module):

    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 64, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.pool = nn.MaxPool2d(2, 2)
        self.dense1 = nn.Linear(576, 64)
        self.dense2 = nn.Linear(64, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = F.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = F.relu(self.dense1(x))
        output = F.softmax(self.dense2(x), dim=1)
        return output


def train(scheduler):
    global global_step
    for epoch in range(1, epochs + 1):
        model.train()
        for step, (data, target) in enumerate(train_loader, 1):
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()

            if step % 500 == 0:
                train_loss = loss.item()
                logging.info(
                    'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
                    format(epoch, epochs, step, steps_per_epoch, train_loss))
                global_step = (epoch - 1) * steps_per_epoch + step

        scheduler.step()
        global_step = epoch * steps_per_epoch
        test(val=True, epoch=epoch)


def test(val=False, epoch=None):
    label = 'val' if val else 'test'
    model.eval()
    running_loss = 0.0
    correct = 0

    with torch.no_grad():
        loader = val_loader if val else test_loader
        for data, target in loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            loss = criterion(output, target)
            running_loss += loss.item()
            prediction = output.max(1)[1]
            correct += (prediction == target).sum().item()

    test_loss = running_loss / len(loader)
    test_accuracy = correct / len(loader.dataset)
    msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
        label, test_loss, label, test_accuracy)
    if val:
        msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
    logging.info(msg)


if __name__ == '__main__':
    args = parser.parse_args()

    use_cuda = not args.no_cuda and torch.cuda.is_available()
    if use_cuda:
        logging.info('Using CUDA')
    device = torch.device('cuda' if use_cuda else 'cpu')
    kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}

    torch.manual_seed(1)

    model = Net().to(device)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001)
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)

    dataset_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                'data')
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5), (0.5))])
    train_dataset = datasets.MNIST(root=dataset_path,
                                   train=True,
                                   download=True,
                                   transform=transform)
    train_dataset, val_dataset = torch.utils.data.random_split(
        train_dataset, [48000, 12000])
    test_dataset = datasets.MNIST(root=dataset_path,
                                  train=False,
                                  download=True,
                                  transform=transform)
    train_loader = torch.utils.data.DataLoader(
        train_dataset,
        batch_size=32,
        shuffle=True,
        **kwargs)
    val_loader = torch.utils.data.DataLoader(val_dataset,
                                             batch_size=400,
                                             shuffle=False,
                                             **kwargs)
    test_loader = torch.utils.data.DataLoader(test_dataset,
                                              batch_size=1000,
                                              shuffle=False,
                                              **kwargs)

    global_step = 0
    epochs = 10
    steps_per_epoch = len(train_loader)
    train(scheduler)
    test()

    torch.save(model.state_dict(), 'model_state_dict.pt')

创建 Run

在建立模型之前,创建并初始化一个 Run 实例。

from t9k import em

if __name__ == '__main__':
    ...
    run = em.create_run(name='mnist_torch')  # Run 的名称
    ...

Run 实例的 hparams 属性用于保存超参数,使用类似 Python 字典的方法更新它以设定超参数。

if __name__ == '__main__':
    ...
    run.hparams.update({
        'batch_size': 32,
        'epochs': 10,
        'learning_rate': 0.001,
        'learning_rate_decay_period': 1,
        'learning_rate_decay_factor': 0.7,
        'conv_channels1': 32,
        'conv_channels2': 64,
        'conv_channels3': 64,
        'conv_kernel_size': 3,
        'maxpool_size': 2,
        'linear_features1': 64,
        'seed': 1,
    })
    hparams = run.hparams
    ...

使用设定的超参数配置模型

使用上面设定的试验的超参数替换直接提供的超参数值,以配置模型各层、数据集、优化器、训练流程等。

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, hparams['conv_channels1'],
                               hparams['conv_kernel_size'], 1)
        self.conv2 = nn.Conv2d(hparams['conv_channels1'],
                               hparams['conv_channels2'],
                               hparams['conv_kernel_size'], 1)
        self.conv3 = nn.Conv2d(hparams['conv_channels2'],
                               hparams['conv_channels3'],
                               hparams['conv_kernel_size'], 1)
        self.pool = nn.MaxPool2d(hparams['maxpool_size'],
                                 hparams['maxpool_size'])
        self.dense1 = nn.Linear(576, hparams['linear_features1'])
        self.dense2 = nn.Linear(hparams['linear_features1'], 10)
    ...

if __name__ == '__main__':
    ...
    torch.manual_seed(hparams['seed'])
    ...
    optimizer = optim.Adam(model.parameters(), lr=hparams['learning_rate'])
    scheduler = optim.lr_scheduler.StepLR(
        optimizer,
        step_size=hparams['learning_rate_decay_period'],
        gamma=hparams['learning_rate_decay_factor'])
    ...
    train_loader = torch.utils.data.DataLoader(
        train_dataset,
        batch_size=hparams['batch_size'],
        shuffle=True,
        **kwargs)
    ...
    epochs = hparams['epochs']
    ...

记录指标

在模型的训练和测试过程中调用 Run 实例的 log() 方法,以记录模型在此期间产生的指标。

def train(scheduler):
    ...
            if step % 500 == 0:
                train_loss = loss.item()
                logging.info(
                    'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
                    format(epoch, epochs, step, steps_per_epoch, train_loss))
                global_step = (epoch - 1) * steps_per_epoch + step

                run.log(type='train',                    # 记录训练指标
                        metrics={'loss': train_loss},    # 指标名称及相应值
                        step=global_step,                # 当前全局步数
                        epoch=epoch)                     # 当前回合数
    ...

def test(val=False, epoch=None):
    ...
    test_loss = running_loss / len(loader)
    test_accuracy = correct / len(loader.dataset)
    msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
        label, test_loss, label, test_accuracy)
    if val:
        msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
    logging.info(msg)

    run.log(type=label,    # 记录验证/测试指标
            metrics={
                'loss': test_loss,
                'accuracy': test_accuracy,
            },
            step=global_step,
            epoch=epoch)

创建 Artifact 并添加模型检查点文件

在保存模型检查点文件之后,创建并初始化一个新的 Artifact 实例,为其添加该检查点文件,并标记为 Run 的输出。

if __name__ == '__main__':
    ...
    torch.save(model.state_dict(), 'model_state_dict.pt')
    model_artifact = em.create_artifact(name='mnist_torch_saved_model')
    model_artifact.add_file('model_state_dict.pt')
    run.mark_output(model_artifact)
    ...

结束和上传 Run

模型的训练和测试结束后,调用 Run 实例的 finish()upload() 方法以结束和上传 Run(Artifact 也会被一并上传)。在上传之前需要调用 em.login() 函数以登录到 AIStore 服务器。

if __name__ == '__main__':
    ...
    run.finish()
    em.login()
    run.upload(folder='em-examples', make_folder=True)

检查 Run 和 Artifact

训练结束后,进入实验管理控制台,可以看到名为 mnist_torch 的 Run 及其输出的 Artifact 被上传:

uploaded

点击 Run 或 Artifact 的名称进入其详情页面,可以看到 Run 的平台信息、指标、超参数和数据流,以及 Artifact 的文件和数据流。并且它们的数据流是连通的。

run
artifact
dataflow

下一步

分布式训练场景

本教程演示如何记录并展示 PyTorchTrainingJob 分布式训练场景下的训练产生的信息、指标和文件(以 PyTorch 模型的数据并行训练为例)。

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

下面介绍训练脚本进行了哪些修改以追踪训练。该方法是通用的,可以推广到任意类型的 TrainingJob、DeepSpeedJob、ColossalAIJob、MPIJob 或 GenericJob。

准备训练脚本

准备一个 PyTorch 训练脚本,其模型对 MNIST 数据集的图像进行分类,使用 DistributedDataParallel(DDP)模块进行分布式训练,具体代码如下所示(这里使用与使用 PyTorchTrainingJob 进行数据并行训练相同的脚本)。接下来将在此脚本的基础上进行简单的修改以进行追踪。

torch_mnist_trainingjob_em.py
import argparse
import logging
import os
import shutil

import torch
import torch.distributed as dist
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.parallel import DistributedDataParallel as DDP
import torch.optim as optim
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets, transforms

parser = argparse.ArgumentParser(
    description='Distributed training of Keras model for MNIST with DDP.')
parser.add_argument(
    '--backend',
    type=str,
    help='Distributed backend',
    choices=[dist.Backend.GLOO, dist.Backend.NCCL, dist.Backend.MPI],
    default=dist.Backend.GLOO)
parser.add_argument('--log_dir',
                    type=str,
                    default='/mnt/log',
                    help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
                    action='store_true',
                    default=False,
                    help='Disable CUDA training.')
logging.basicConfig(format='%(message)s', level=logging.INFO)


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, 3, 1)
        self.conv2 = nn.Conv2d(32, 64, 3, 1)
        self.conv3 = nn.Conv2d(64, 64, 3, 1)
        self.pool = nn.MaxPool2d(2, 2)
        self.dense1 = nn.Linear(576, 64)
        self.dense2 = nn.Linear(64, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = F.relu(self.conv3(x))
        x = torch.flatten(x, 1)
        x = F.relu(self.dense1(x))
        output = F.softmax(self.dense2(x), dim=1)
        return output


def train(scheduler):
    global global_step
    for epoch in range(1, epochs + 1):
        model.train()
        for step, (data, target) in enumerate(train_loader, 1):
            data, target = data.to(device), target.to(device)
            optimizer.zero_grad()
            output = model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()

            if step % (500 // world_size) == 0:
                train_loss = loss.item()
                logging.info(
                    'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
                    format(epoch, epochs, step, steps_per_epoch, train_loss))
                global_step = (epoch - 1) * steps_per_epoch + step

                if args.log_dir and rank == 0:
                    writer.add_scalar('train/loss', train_loss, global_step)

        scheduler.step()
        global_step = epoch * steps_per_epoch
        test(val=True, epoch=epoch)


def test(val=False, epoch=None):
    label = 'val' if val else 'test'
    model.eval()
    running_loss = 0.0
    correct = 0

    with torch.no_grad():
        loader = val_loader if val else test_loader
        for data, target in loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            loss = criterion(output, target)
            running_loss += loss.item()
            prediction = output.max(1)[1]
            correct += (prediction == target).sum().item()

    test_loss = running_loss / len(loader)
    test_accuracy = correct / len(loader.dataset)
    msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
        label, test_loss, label, test_accuracy)
    if val:
        msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
    logging.info(msg)

    if args.log_dir and rank == 0:
        writer.add_scalar('{:s}/loss'.format(label), test_loss, global_step)
        writer.add_scalar('{:s}/accuracy'.format(label), test_accuracy,
                          global_step)


if __name__ == '__main__':
    args = parser.parse_args()

    use_cuda = not args.no_cuda and torch.cuda.is_available()
    if use_cuda:
        logging.info('Using CUDA')
    device = torch.device("cuda" if use_cuda else "cpu")
    kwargs = {'num_workers': 1, 'pin_memory': True} if use_cuda else {}

    logging.info('Using distributed PyTorch with {} backend'.format(
        args.backend))
    dist.init_process_group(backend=args.backend)
    rank = dist.get_rank()
    world_size = dist.get_world_size()

    torch.manual_seed(1)

    model = Net().to(device)
    model = DDP(model)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001 * world_size)
    scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=1, gamma=0.7)

    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5), (0.5))])
    train_dataset = datasets.MNIST(root='./data',
                                   train=True,
                                   download=False,
                                   transform=transform)
    train_dataset, val_dataset = torch.utils.data.random_split(
        train_dataset, [48000, 12000])
    test_dataset = datasets.MNIST(root='./data',
                                  train=False,
                                  download=False,
                                  transform=transform)
    train_loader = torch.utils.data.DataLoader(train_dataset,
                                               batch_size=32 * world_size,
                                               shuffle=True,
                                               **kwargs)
    val_loader = torch.utils.data.DataLoader(val_dataset,
                                             batch_size=400,
                                             shuffle=False,
                                             **kwargs)
    test_loader = torch.utils.data.DataLoader(test_dataset,
                                              batch_size=1000,
                                              shuffle=False,
                                              **kwargs)

    if args.log_dir and rank == 0:
        log_dir = args.log_dir
        if os.path.exists(log_dir):
            shutil.rmtree(log_dir, ignore_errors=True)
        writer = SummaryWriter(log_dir)

    global_step = 0
    epochs = 10
    steps_per_epoch = len(train_loader)
    train(scheduler)
    test()

创建 Run

创建一个包含所有(想要记录的)超参数的 Python 字典。

from t9k import em

if __name__ == '__main__':
    ...
    hparams = {
        'batch_size': 32 * world_size,
        'epochs': 10,
        'learning_rate': 0.001 * world_size,
        'learning_rate_decay_period': 1,
        'learning_rate_decay_factor': 0.7,
        'conv_channels1': 32,
        'conv_channels2': 64,
        'conv_channels3': 64,
        'conv_kernel_size': 3,
        'maxpool_size': 2,
        'linear_features1': 64,
        'seed': 1,
    }
    ...

指定一个工作器负责在建立模型之前创建并初始化一个 Run 实例,传入名称和上面的超参数字典。

if __name__ == '__main__':
    ...
    if rank == 0:
        run = em.create_run(name='mnist_torch_distributed', hparams=hparams)
    ...

使用设定的超参数配置模型

使用上面的超参数字典的值替换直接提供的超参数值,以配置模型各层、数据集、优化器、训练流程等。

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, hparams['conv_channels1'],
                               hparams['conv_kernel_size'], 1)
        self.conv2 = nn.Conv2d(hparams['conv_channels1'],
                               hparams['conv_channels2'],
                               hparams['conv_kernel_size'], 1)
        self.conv3 = nn.Conv2d(hparams['conv_channels2'],
                               hparams['conv_channels3'],
                               hparams['conv_kernel_size'], 1)
        self.pool = nn.MaxPool2d(hparams['maxpool_size'],
                                 hparams['maxpool_size'])
        self.dense1 = nn.Linear(576, hparams['linear_features1'])
        self.dense2 = nn.Linear(hparams['linear_features1'], 10)
    ...

if __name__ == '__main__':
    ...
    torch.manual_seed(hparams['seed'])
    ...
    optimizer = optim.Adam(model.parameters(), lr=hparams['learning_rate'])
    scheduler = optim.lr_scheduler.StepLR(
        optimizer,
        step_size=hparams['learning_rate_decay_period'],
        gamma=hparams['learning_rate_decay_factor'])
    ...
    train_loader = torch.utils.data.DataLoader(
        train_dataset,
        batch_size=hparams['batch_size'],
        shuffle=True,
        **kwargs)
    ...
    epochs = hparams['epochs']
    ...

记录指标

在模型的训练和测试过程中,被指定的工作器调用 Run 实例的 log() 方法以记录模型在此期间产生的指标。

def train(scheduler):
    ...
            if step % (500 // world_size) == 0:
                train_loss = loss.item()
                logging.info(
                    'epoch {:d}/{:d}, batch {:5d}/{:d} with loss: {:.4f}'.
                    format(epoch, epochs, step, steps_per_epoch, train_loss))
                global_step = (epoch - 1) * steps_per_epoch + step

                if rank == 0:
                    run.log(type='train',                  # 记录训练指标
                            metrics={'loss': train_loss},  # 指标名称及相应值
                            step=global_step,              # 当前全局步数
                            epoch=epoch)                   # 当前回合数
    ...

def test(val=False, epoch=None):
    ...
    test_loss = running_loss / len(loader)
    test_accuracy = correct / len(loader.dataset)
    msg = '{:s} loss: {:.4f}, {:s} accuracy: {:.4f}'.format(
        label, test_loss, label, test_accuracy)
    if val:
        msg = 'epoch {:d}/{:d} with '.format(epoch, epochs) + msg
    logging.info(msg)

    if rank == 0:
        run.log(type=label,    # 记录验证/测试指标
                metrics={
                    'loss': test_loss,
                    'accuracy': test_accuracy,
                },
                step=global_step,
                epoch=epoch)

创建 Artifact 并添加模型检查点文件

在保存模型检查点文件之后,被指定的工作器创建并初始化一个新的 Artifact 实例,为其添加该检查点文件,并标记为 Run 的输出。

if __name__ == '__main__':
    ...
    if rank == 0:
        torch.save(model.state_dict(), 'model_state_dict.pt')
        model_artifact = em.create_artifact(name='mnist_torch_saved_model')
        model_artifact.add_file('model_state_dict.pt')
        run.mark_output(model_artifact)
    ...

结束和上传试验

模型的训练和测试结束后,被指定的工作器调用 Run 实例的 finish()upload() 方法以结束和上传 Run(Artifact 也会被一并上传)。在上传之前需要调用 em.login() 函数以登录到服务器。

if __name__ == '__main__':
    ...
    if rank == 0:
        run.finish()
        em.login()
        run.upload(folder='em-examples', make_folder=True)

检查 Run 和 Artifact

训练结束后,进入实验管理控制台,可以看到名为 mnist_torch_distributed 的 Run 及其输出的 Artifact 被上传:

uploaded

点击 Run 或 Artifact 的名称进入其详情页面,可以看到 Run 的平台信息、指标、超参数和数据流,以及 Artifact 的文件和数据流。并且它们的数据流是连通的。

run
artifact
dataflow

在实验管理控制台查看 AutoTune

如果 AutoTune 使用 AIStore 作为数据库,那么 AutoTune 会自动记录实验以及其中所有试验的数据到 AIStore 中。

参照使用 AutoTune 进行超参数优化创建一个 AutoTuneExperiment。唯一需要修改的部分是,将 AutoTuneExperiment 配置文件的 spec.em.folder 字段修改为文件夹 em-examples 的 ID。

创建完成之后,进入实验管理控制台,可以看到 em-examples/ 路径下出现了一个名为 keras-mnist-autotune 的 AutoTune:

created

点击其名称进入详情页面,可以看到 AutoTuneExperiment 的信息、当前进度、各试验的信息以及可视化图表:

details

点击任意一个试验的右侧的详情可以看到试验使用的超参数以及指标:

trial-hparams
trial-metrics

构建自动化工作流

这一部分演示如何使用工作流系统进行 AI 开发和实验,帮助管理 AI 项目中数据清洗、特征工程、模型训练、评估等多个步骤之间的依赖关系,确保它们以正确的顺序执行,并提高可复用性。

创建工作流的基本单元

本教程演示如何创建工作流的基本单元。

准备工作

创建 WorkflowTemplate

在浏览器中进入工作流控制台之后,点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,然后点击右上角的 Project 框选择一个 Project,然后点击列表右上角的 + 在该 Project 中创建一个 WorkflowTemplate。

workflowtemplate-list

进入创建 WorkflowTemplate 页面之后,左侧的表格和右侧的 YAML 都可以进行编辑,并且两侧始终是同步变化的。你可以在此填写所要创建的 WorkflowTemplate。

create-workflowtemplate

首先,你需要在名为 WorkflowTemplate Name 的文本框中填写 WorkflowTemplate 的名称,然后在名为 Type 的下拉框中选择 WorkflowTemplate 的类型(可以是 PodSeqPodResource 等),最后根据 WorkflowTemplate 类型的不同,继续填写余下配置。

编辑好 WorkflowTemplate 之后,点击表格右上角的 Create WorkflowTemplate 创建该 WorkflowTemplate,右下角会有悬浮框提示是否创建成功。

创建 WorkflowRun

再次点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,找到你刚才创建的 WorkflowTemplate hello,点击 WorkflowTemplate 的名称进入 WorkflowTemplate 的详情页面。

workflowtemplate-detail

在 WorkflowTemplate 的详情页面,你可以点击 SPECSYAML 标签查看 WorkflowTemplate 的详细情况,检查是否有错误。如果没有错误,点击右上角的 Create WorkflowRun 为该 WorkflowTemplate 创建一个 WorkflowRun。

create-workflowrun

在弹出的创建 WorkflowRun 对话框中,按步骤依次填写 WorkflowRun 所需要的参数,最后点击 Create 创建 WorkflowRun,右下角会有悬浮框提示是否创建成功。

create-workflowrun

查看 WorkflowRun 运行情况

点击左侧导航菜单的 WorkflowRun 进入 WorkflowRun 列表页面,找到你刚刚创建的 WorkflowRun hello-run-3xrlm,点击 WorkflowRun 的名称进入 WorkflowRun 的详情页面。

workflowrun-detail

在 WorkflowRun 的详情页面,你可以点击 LOGSSTATUSSPECSYAML 等标签,分别查看 WorkflowRun 的日志、状态、规约和 YAML。如果 WorkflowRun 正在运行而且其类型是 Pod 或 SeqPod,你可以点击 TERMINAL 标签,连接到 WorkflowRun 创建的 Pod 的某个容器的终端(shell),利用命令行工具进行调试。

创建执行各类任务的工作流单元

本教程演示如何创建执行各类任务的工作流单元。

准备工作

创建类型为 PodSeqPod 的 WorkflowTemplate

WorkflowTemplate 介绍中所述,PodSeqPod 类型的区别在于,Pod 中的所有容器是一起(近乎同时)开始运行的,而 SeqPod 中的每个步骤是按照定义的顺序依次执行的。如无特殊情况,我们一般使用 SeqPod 类型即可。以下均以 SeqPod 类型为基础进行讲解。

选择镜像

在教程创建工作流的基本单元中,我们已经完成了 SeqPod 类型的 WorkflowTemplate 的创建和运行。如教程中所述,在 SeqPod 的每个步骤(step)中,都要填写所使用的镜像。一般来说,镜像的来源可能有以下几种:

准备好镜像之后,在 Image 框中填入镜像的地址。

select-image

执行 PVC 中的脚本

当你在 Notebook 中编写了一些 Python 脚本或 Shell 脚本后,你可以创建 WorkflowTemplate 以及对应的 WorkflowRun 来运行该脚本。只要 WorkflowRun 和 Notebook 绑定的是同一个 PVC,WorkflowRun 就能访问到你在 Notebook 中编写的脚本。

首先,在 Notebook 中编写想要运行的脚本,并 Ctrl+S 保存。

script-1

查看 Notebook 所绑定的 PVC 名称,以便创建 WorkflowRun 时使用。

script-2

按照下图所示填写表格,创建一个 SeqPod 类型的 WorkflowTemplate。

script-3

或者,你也可以复制粘贴下面的 YAML 配置文件来创建 WorkflowTemplate:

apiVersion: batch.tensorstack.dev/v1beta1
kind: WorkflowTemplate
metadata:
  name: run-script
  labels: {}
spec:
  params: []
  results: []
  seqPod:
    steps:
      - args:
          - $(workspaces.notebook-pvc.path)/run.py
        command:
          - python
        image: 'registry.tensorstack.cn/t9k/tensorflow-2.8.0-notebook-cpu:1.50.0'
        name: step1
        resources:
          limits:
            cpu: 100m
            memory: 200Mi
  type: SeqPod
  workspaces:
    - description: the pvc used by notebook
      name: notebook-pvc

然后,创建 WorkflowRun 来运行该 WorkflowTemplate。

script-4

WorkflowRun 运行完成后,可以看到打印结果与所编写的脚本运行预期结果一致。

script-5

执行自定义脚本

除了在 Notebook 中编写脚本,你还可以在创建 WorkflowTemplate 的过程中现场编写 Python 或 Shell 脚本。

如下图所示,创建 WorkflowTemplate 时选择类型为 SeqPod,然后点击 Add Step,在 Step 中选择 Script 即可嵌入自定义脚本。

embedded-1

目前支持 Python 和 Shell 两种语言,可通过下拉框进行选择。

embedded-2

创建 WorkflowTemplate 和对应的 WorkflowRun 来运行,可以看到打印结果与脚本运行与其结果一致。

embedded-3

创建类型为 Resource 的 WorkflowTemplate

WorkflowTemplate 介绍中所述,Resource 类型的 WorkflowTemplate 用于创建一个 Kubernetes 资源。下面展示两个常用示例。

创建分布式训练

假设你已经有一个可以运行的 TrainingJob YAML 配置文件:

apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
  name: mnist
spec:
  tensorboardSpec:               # TensorBoard服务器规约
    trainingLogFilesets:
      - t9k://pvc/mnist/log      # 日志文件路径
    image: tensorflow/tensorflow:2.8.0
                                # TensorBoard服务器使用的镜像
  replicaSpecs:
    - type: worker               # 工作器
      replicas: 4                # 工作器数量
      restartPolicy: ExitCode
      template:
        spec:
          securityContext:
            runAsUser: 1000
          containers:
            - image: tensorflow/tensorflow:2.8.0
                                  # 容器的镜像
              workingDir: /mnt
              name: tensorflow
              command:           # 执行`python`命令以执行训练脚本
                - sh
                - '-c'
                - >-
                  python /mnt/keras_mnist_trainingjob.py --log_dir /mnt/log --save_path /mnt/saved_model
                  --no_cuda
              env: []
              resources:
                limits:          # 限制量
                  cpu: '4'       # CPU
                  memory: 2Gi    # 内存
                requests:        # 请求量
                  cpu: '2'
                  memory: 1Gi
              volumeMounts:
                - name: data
                  mountPath: /mnt
          volumes:
            - name: data
              persistentVolumeClaim:
                claimName: mnist

如果你想将创建 TrainingJob 插入工作流中成为其中一个步骤,可以使用 Resource 类型的 WorkflowTemplate。如下图所示,在 WorkflowTemplate 创建页面,选择类型为 Resource,然后将上面的 YAML 配置文件复制粘贴到 Resource Manifest 文本框中,即可创建一个 WorkflowTemplate 来运行这个 TrainingJob。

trainingjob-1

但是,由于在同一个项目中不能创建两个同名的 TrainingJob,上述方式创建的 WorkflowTemplate 只能运行一次,不具备可复用性。因此我们可以对 TrainingJob 配置文件做一些修改,利用 WorkflowTemplate 的指定参数功能,使其能被重复使用。

经过修改的 TrainingJob 配置文件如下:

apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
  name: $(params.trainingjob_name)
spec:
  tensorboardSpec:               # TensorBoard服务器规约
    trainingLogFilesets:
      - t9k://pvc/mnist/log      # 日志文件路径
    image: tensorflow/tensorflow:2.8.0
                                # TensorBoard服务器使用的镜像
  replicaSpecs:
    - type: worker               # 工作器
      replicas: 4                # 工作器数量
      restartPolicy: ExitCode
      template:
        spec:
          securityContext:
            runAsUser: 1000
          containers:
            - image: tensorflow/tensorflow:2.8.0
                                # 容器的镜像
              workingDir: /mnt
              name: tensorflow
              command:          # 执行`python`命令以执行训练脚本
                - sh
                - '-c'
                - >-
                  python /mnt/keras_mnist_trainingjob.py --log_dir /mnt/log --save_path /mnt/saved_model
                  --no_cuda
              env: []
              resources:
                limits:
                  cpu: '4'
                  memory: 4Gi
                requests:
                  cpu: '2'
                  memory: 2Gi
              volumeMounts:
                - name: data
                  mountPath: /mnt
          volumes:
            - name: data
              persistentVolumeClaim:
                claimName: $(params.pvc_name)

改动有两处:

  • metadata.name 从固定的 mnist 改为 $(params.trainingjob_name)
  • spec.replicaSpecs.template.volumes.persistentVolumeClaim.claimName 从固定的 mnist 改为 $(params.pvc_name)

这两个改动使得 TrainingJob 的名称和所使用的 PVC 的名称在运行时才被传入,这样创建的 WorkflowTemplate 就能够多次重复使用了。

在 WorkflowTemplate 创建页面,将上述改动过的 Trainingjob 配置文件复制粘贴到 Resource Manifest 文本框中,并为 WorkflowTemplate 添加两个参数,分别名为 trainingjob_namepvc_name,然后点击 Create WorkflowTemplate 进行创建。

trainingjob-2

在创建 WorkflowRun 时,为 trainingjob_namepvc_name 这两个参数提供实际值。

trainingjob-3

等待 WorkflowRun 完成运行。

trainingjob-4

创建推理服务

创建分布式训练类似,我们可以在简单推理服务的 YAML 配置文件基础上,加入可变的参数:

apiVersion: tensorstack.dev/v1beta1
kind: SimpleMLService
metadata:
  name: $(params.simplemlservice_name)
spec:
  replicas: 1
  storage:
    pvc:
      containerPath: /var/lib/t9k/models/mnist
      name: tutorial
      subPath: tutorial-examples/deployment/model/tensorflow/mnist
  tensorflow:
    image: t9kpublic/tensorflow-serving:2.6.0

在 WorkflowTemplate 创建页面,将上述 YAML 配置文件复制粘贴到 Resource Manifest 文本框中,并为 WorkflowTemplate 添加一些参数。

simplemlservice-1

创建 WorkflowTemplate,然后创建对应的 WorkflowRun 并提供参数的实际值。

与分布式训练不同,推理服务是一个长时间运行的服务,没有结束时间。因此所创建的 WorkflowRun 也不会结束运行,而是一直处于 Running 状态。

simplemlservice-2

创建存在依赖关系的工作流

本教程演示如何创建存在依赖关系的工作流。

准备工作

创建一些简单的 WorkflowTemplate

在浏览器中进入工作流控制台之后,点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,然后点击右上角的 Project 选择框选择一个 Project。

本教程使用创建工作流的基本单元教程中创建好的 WorkflowTemplate hello 即可。如果有需要,你可以点击列表右上角的加号,按照创建工作流的基本单元教程中的步骤,创建一些简单的 WorkflowTemplate。

创建 DAG WorkflowTemplate

点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,然后点击列表右上角的树状图标来创建一个 DAG WorkflowTemplate。

workflowtemplate-list

进入创建 DAG WorkflowTemplate 页面之后,除了最左侧的导航菜单之外整个页面分为三个部分,左边是 WorkflowTemplate 列表,中间是用于组建 DAG 的画布,右边是 DAG WorkflowTemplate 的详情。你可以从左边的 WorkflowTemplate 列表中用鼠标选取一个 WorkflowTemplate 拖拽到中间的画布上,然后通过绿色锚点连接多个 WorkflowTemplate,表示它们的执行顺序。画布中所有的 WorkflowTemplate 由依赖关系组成一个有向无环图(DAG)。

create-workflowtemplate

建立好有向无环图之后,你可以在右边的表格编辑 DAG WorkflowTemplate 的详情,例如 WorkflowTemplate 的名称、工作空间、参数等。点击画布中的方块即可编辑该节点的详情,点击画布的空白处可以编辑整个 DAG WorkflowTemplate 的详情。

最后,点击表格上方的 Create DAG WorkflowTemplate 创建该 DAG WorkflowTemplate,右下角会有悬浮框提示是否创建成功。

创建 WorkflowRun

再次点击左侧导航菜单的 WorkflowTemplate 进入 WorkflowTemplate 列表页面,找到你刚刚创建的 WorkflowTemplate hello-again,点击 WorkflowTemplate 的名称进入 WorkflowTemplate 的详情页面。

workflowtemplate-detail

在 WorkflowTemplate 的详情页面,点击右上角的 Create WorkflowRun 为该 WorkflowTemplate 创建一个 WorkflowRun。

create-workflowrun

在弹出的创建 WorkflowRun 对话框中。按步骤依次填写 WorkflowRun 所需要的参数,最后点击 Create 创建 WorkflowRun,右下角会有悬浮框提示是否创建成功。

查看 WorkflowRun 运行情况

点击左侧导航菜单的 WorkflowRun 进入 WorkflowRun 列表页面,找到你刚刚创建的 WorkflowRun hello-again-run-9214x,点击 WorkflowRun 的名称进入 WorkflowRun 的详情页面。

workflowrun-detail

在 WorkflowRun 的详情页面,你可以点击 GRAPH 标签,查看 DAG 的详细情况,点击 DAG 的节点可以在弹框中查看节点的详细情况。

workflowrun-detail-node

建立从数据采样到模型导出的自动化工作流

本教程演示如何建立一个端到端的机器学习工作流,包括数据预处理、模型训练、模型分析等步骤。本教程使用的机器学习应用样例是一个二分类问题,根据乘客搭乘出租车的位置、路程、用时等特征数据预测乘客是否会付小费。

准备工作

运行示例

请按照使用方法准备环境,然后前往本教程对应的示例,参照其 README 文档运行。

查看运行结果

创建 WorkflowRun 之后,进入工作流控制台的 WorkflowRun 列表页面,可以看到名为 taxi-tips-prediction-run-xxxxx 的 WorkflowRun 正在运行:

workflowrun-list-success

点击其名称进入详情页面,可以看到 WorkflowRun 的详细运行状态:

workflowrun-detail

本页面会自动刷新以获取 WorkflowRun 的最新状态,你也可以点击右上角的刷新图标手动刷新。

调度工作负载

为工作负载指定队列

本教程演示如何为不同类型的工作负载指定队列

Pod

对于 Pod 有两种指定队列的方法:直接指定队列和通过 PodGroup 间接指定队列。

直接指定队列

Pod 的 scheduler.tensorstack.dev/queue 标签标识其属于哪一个队列。创建 Pod 时,用户可以设置 spec.schedulerName 字段为 t9k-scheduler,并设置该标签以直接指定队列。

在下面的示例中,Pod 被指定了队列 default

apiVersion: v1
kind: Pod
metadata:
  name: pod-test
  labels:
    scheduler.tensorstack.dev/queue: default
spec:
  schedulerName: t9k-scheduler
  containers:
  - name: nginx
    image: nginx

通过 PodGroup 间接指定队列

Pod 的 scheduler.tensorstack.dev/group-name 标签标识其属于哪一个 PodGroup。创建 Pod 时,用户可以设置该标签以指定所属的 PodGroup,这样 Pod 会使用该 PodGroup 的队列。

PodGroup

手动创建 PodGroup 时,需要设置 spec.queue 字段以指定队列。属于 PodGroup 的所有 Pod 都会使用该队列。

在下面的示例中,PodGroup 被指定了队列 default

apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
  name: podgroup-test
spec:
  minMember: 2
  queue: default
  priority: 50

T9k Job

T9k Job 包括 TensorFlowTrainingJob、PyTorchTrainingJob、XGBoostTrainingJob、GenericJob、MPIJob、ColossalAIJob、DeepSpeedJob 和 BeamJob,这些 T9k Job 中都有相同的 spec.scheduler 字段。

创建这些 T9k Job 时,用户可以设置 spec.scheduler.t9kScheduler 字段以使用 T9k Scheduler 并指定队列。T9k Job 创建的所有 Pod 都会使用该队列。

在下面的示例中,GenericJob 被指定了队列 default

apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
 name: t9k-job-test
spec:
 scheduler:
   t9kScheduler:
     queue: default
     priority: 10
 replicaSpecs:
   - type: worker
     replicas: 4
     ...
   - type: ps
     replicas: 1
     ...

batch/v1 Job

创建 batch/v1 Job 时,用户可以参照 Pod 设置 Pod 模板(spec.template 字段),从而为 batch/v1 Job 的所有 Pod 指定队列。

在下面的示例中,batch/v1 Job 的 Pod 被指定了队列 default

apiVersion: batch/v1
kind: Job
metadata:
  name: batch-v1-job-test
spec:
  parallelism: 2
  template:
    metadata:
      labels:
        scheduler.tensorstack.dev/queue: default
    spec:
      schedulerName: t9k-scheduler
      containers:
        - name: nginx
          image: nginx
          command: ["sleep", "10"]

创建和使用 PodGroup

本教程演示如何创建和使用 PodGroup

手动创建 PodGroup

用户可以手动创建 PodGroup 以关联一组进行协同工作的 Pod,步骤如下:

  1. (使用 YAML 配置文件)创建一个 PodGroup。
  2. 创建若干个 Pod,设置 scheduler.tensorstack.dev/group-name 标签为步骤 1 中创建的 PodGroup 的名称。
  3. Pod 的数量(和角色)达到 PodGroup 的运行需求后,T9k Scheduler 开始调度 PodGroup。

示例:基本场景

首先创建一个 PodGroup,设置其最小数量、队列和优先级:

apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
  name: podgroup-test
spec:
  minMember: 2
  queue: default
  priority: 50

然后创建两个 Pod 并指定所属的 PodGroup,scheduler.tensorstack.dev/group-name: podgroup-test 标签表示它们属于 PodGroup podgroup-test

apiVersion: v1
kind: Pod
metadata:
  name: nginx1
  labels:
    scheduler.tensorstack.dev/group-name: podgroup-test
spec:
  schedulerName: t9k-scheduler
  containers:
  - image: nginx
    name: nginx
    resources:
      requests:
        cpu: 1
        memory: 200Mi
--
apiVersion: v1
kind: Pod
metadata:
  name: nginx2
  labels:
    scheduler.tensorstack.dev/group-name: podgroup-test
spec:
  schedulerName: t9k-scheduler
  containers:
  - image: nginx
    name: nginx
    resources:
      requests:
        cpu: 1
        memory: 200Mi

此时 PodGroup 的运行需求得到满足,从而开始被调度。

示例:设置角色最小数量

本示例创建有两种角色的 PodGroup。

首先创建一个 PodGroup:

apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
  name: role-test
spec:
  roles:
  - name: master
    minMember: 1
  - name: worker
    minMember: 1
  minMember: 3
  queue: default
  priority: 50

该 PodGroup 的运行需求如下:

  • 有 3 个 Pod。
  • 有 1 个角色名称是 master 的 Pod。
  • 有 1 个角色名称是 worker 的 Pod。

然后创建 3 个 Pod 并指定所属的 PodGroup,scheduler.tensorstack.dev/role: <role-name> 标签表示它们自己的角色名称:

apiVersion: v1
kind: Pod
metadata:
  name: master
  labels:
    scheduler.tensorstack.dev/group-name: role-test
    scheduler.tensorstack.dev/role: master
spec:
  schedulerName: t9k-scheduler
  containers:
  - name: nginx
    image: nginx

--

apiVersion: v1
kind: Pod
metadata:
  name: worker
  labels:
    scheduler.tensorstack.dev/group-name: role-test
    scheduler.tensorstack.dev/role: worker
spec:
  schedulerName: t9k-scheduler
  containers:
  - name: nginx
    image: nginx

--

apiVersion: v1
kind: Pod
metadata:
  name: worker1
  labels:
    scheduler.tensorstack.dev/group-name: role-test
    scheduler.tensorstack.dev/role: worker
spec:
  schedulerName: t9k-scheduler
  containers:
  - name: nginx
    image: nginx

此时 PodGroup 的运行需求得到满足,从而开始被调度。

T9k Job 自动创建 PodGroup

T9k Job 包括 TensorFlowTrainingJob、PyTorchTrainingJob、XGBoostTrainingJob、GenericJob、MPIJob、ColossalAIJob、DeepSpeedJob 和 BeamJob,这些 Job 中都有相同的 spec.scheduler 字段。

创建这些 Job 时,用户可以设置 spec.scheduler.t9kScheduler 字段以使用 T9k Scheduler 并指定队列。在这种情况下,Job 会自动创建一个 PodGroup 以及若干属于该 PodGroup 的 Pod 来执行计算任务,PodGroup 会继承 Job 的队列和优先级。

示例:基本场景

创建一个使用 T9k Scheduler 的 GenericJob,设置其队列和优先级:

apiVersion: batch.tensorstack.dev/v1beta1
kind: GenericJob
metadata:
 name: job-test
spec:
 scheduler:
   t9kScheduler:
     queue: default
     priority: 10
 replicaSpecs:
   - type: ps
     replicas: 1
     ...
   - type: worker
     replicas: 4
     ...

Job 会自动创建一个 PodGroup,其 spec.priorityspec.queue 字段的值继承自 Job 的 spec.scheduler.t9kScheduler 字段,spec.minMember 字段的值则为 Job 的总副本(replica)数:

apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
  name: job-test
  ownerReferences: [...]
spec:
  minMember: 5
  priority: 10
  queue: default

随后,Job 会自动创建 5 个副本的 Pod,并为它们设置 scheduler.tensorstack.dev/group-name: job-test 标签以指定它们属于这个 PodGroup:

# worker-2 的 Pod
apiVersion: v1
kind: Pod
metadata:
  labels:
    genericjob: job-test
    genericjob-replica: job-test-worker-2
    scheduler.tensorstack.dev/group-name: job-test
    scheduler.tensorstack.dev/queue: default
    tensorstack.dev/component: genericjob
    tensorstack.dev/component-type: user
  name: job-test-worker-0
  namespace: demo
  ownerReferences: [...]

示例:启用弹性训练

弹性训练要求训练规模可以动态调整,所以对 PodGroup 的设置也有所不同。

T9k Job 中,PyTorchTrainingJob 和 DeepSpeedJob 支持弹性训练,它们具有相同的 spec.elastic 字段,以此启动弹性训练。

创建一个使用 T9k Scheduler 并启用弹性训练的 GenericJob:

apiVersion: batch.tensorstack.dev/v1beta1
kind: PyTorchTrainingJob
metadata:
  name: elastic-test
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 10
  elastic:
    enabled: true
    minReplicas: 4
    maxReplicas: 10
    expectedReplicas: 7
  ...

其中:

  • spec.elastic.enabled 字段设为 true 表示启用弹性训练。
  • 训练规模(即副本数量)的伸缩范围为 [4,10],期望值为 7。

PyTorchTrainingJob 会自动创建一个 PodGroup,其 spec.minMember 字段的值继承自 PyTorchTrainingJob 的 spec.elastic.minReplicas 字段,即为弹性训练的最小副本数。

apiVersion: scheduler.tensorstack.dev/v1beta1
kind: PodGroup
metadata:
  name: elastic-test
  ownerReferences: [...]
spec:
  minMember: 4
  priority: 10
  queue: default

使用平台存储

上传和下载文件

通过 PVC 使用集群存储非常方便,它可作为存储卷被挂载到 Notebook、Job、MLService 等各种工作负载的 Pod 中。例如在进行模型训练时,你可以把训练脚本以及训练数据存放到 PVC,然后挂载在 Job 的 Pod 中。

本教程将分场景介绍从集群外部下载/上传文件到 PVC,以及从 PVC 上传/下载文件到集群外部的若干方法。

由于下面的部分方法需要使用到命令行工具,而 Notebook 提供了终端并且 Notebook 的镜像中预装了这些命令行工具,因此我们推荐把 PVC 挂载到一个 Notebook 上,然后在 Notebook 中进行操作。

本地文件系统

Notebook

把 PVC 挂载到 Notebook 上,本地文件系统和 PVC 之间的文件传输,可以直接在 Notebook 的前端页面上操作:

notebook-upload-download

File Browser

在 PVC 上启动 Explorer 之后,则可以通过 File Browser

file-browser-upload-download

云存储中转

也可以通过其他云存储服务进行中转,即本地 -> 云存储 -> 集群 PVC

  1. 本地与云存储之间的文件传输方法请参阅相应云存储的文档;
  2. 云存储与 PVC 之间的文件传输方法请参阅云存储服务

云存储服务

rclone 命令

要在云存储与 PVC 之间复制或同步文件,可以在 Notebook 的终端中使用命令行工具 rclone。这里以 Amazon S3 为例,首先参照 Amazon S3 Config 进行配置,完成后执行以下命令:

rclone copy <REMOTE>:<BUCKET>/path/to/the/file .   # 从 S3 存储下载
rclone copy ./file <REMOTE>:<BUCKET>/path/to/the/  # 上传到 S3 存储

rclone sync <REMOTE>:<BUCKET>/path/to/the/dir .    # 从 S3 存储同步
rclone sync . <REMOTE>:<BUCKET>/path/to/the/dir    # 同步到 S3 存储

对于 Amazon S3,除了 rclone 之外还有其他命令行工具可供使用,例如 s3cmds5cmd 等。

DataCube

对于 Amazon S3 也可以使用平台提供的 DataCube。使用以下 YAML 配置文件创建 DataCube(修改 PVC 名称、PVC 路径、Secret 名称和 S3 URL)以下载和上传文件:

download-s3.yaml
apiVersion: tensorstack.dev/v1beta1
kind: DataCube
metadata:
  name: download-s3
spec:
  source:
    type: s3
    options:
    - name: s3-endpoint
      valueFrom:
        secretKeyRef:
          name: <S3ENV_SECRET_NAME>  # s3-env 类型的 Secret
          key: endpoint
    - name: s3-access-key-id
      valueFrom:
        secretKeyRef:
          name: <S3ENV_SECRET_NAME>
          key: accessKeyID
    - name: s3-secret-access-key
      valueFrom:
        secretKeyRef:
          name: <S3ENV_SECRET_NAME>
          key: secretAccessKey
    - name: s3-uri
      value: s3://<BUCKET>/path/to/the/dir   # 下载目录下的所有子目录和文件
      # value: s3://<BUCKET>/path/to/the/file  # 下载文件
  sink: 
    type: pvc
    pvc:
      name: <PVC_NAME>
      subPath: save/path
  # executor:
  #   options:
  #     sync: true  # 完全同步,会删除多余的文件
upload-s3.yaml
apiVersion: tensorstack.dev/v1beta1
kind: DataCube
metadata:
  name: upload-s3
spec:
  source:
    type: pvc
    pvc:
      name: <PVC_NAME>
      subPath: path/to/the/dir        # 上传目录下的所有子目录和文件
      # subPath: path/to/the/file     # 上传文件
  sink: 
    type: s3
    options:
    - name: s3-endpoint
      valueFrom:
        secretKeyRef:
          name: <S3ENV_SECRET_NAME>   # s3-env 类型的 Secret
          key: endpoint
    - name: s3-access-key-id
      valueFrom:
        secretKeyRef:
          name: <S3ENV_SECRET_NAME>
          key: accessKeyID
    - name: s3-secret-access-key
      valueFrom:
        secretKeyRef:
          name: <S3ENV_SECRET_NAME>
          key: secretAccessKey
    - name: s3-uri
      value: s3://<BUCKET>/save/path  # 目标 S3 路径
kubectl create -f download-s3.yaml
kubectl create -f upload-s3.yaml

HTTP/FTP 服务

要通过 HTTP(S)、(S)FTP 等协议从网络下载文件到 PVC,可以在 Notebook 的终端中使用 wget(或 curl)命令进行下载:

wget <URL>

# 或

curl -O <URL>

Git 仓库

git 命令

可以在 Notebook 的终端中使用 git 命令,从 GitHub 等代码托管平台克隆或拉取 Git 仓库,并在提交修改后推送回去:

git clone <REPO_URL>
git pull
git fetch
git push

DataCube

也可以使用平台提供的 DataCube。使用以下 YAML 配置文件创建 DataCube(修改 PVC 名称、PVC 路径、Secret 名称和 S3 URL)以克隆(或拉取)和推送提交到 Git 仓库:

download-git.yaml
apiVersion: tensorstack.dev/v1beta1
kind: DataCube
metadata:
  name: download-git
spec:
  source:
    type: git
    options:
    # - name: token  # 个人访问令牌
    #   valueFrom:
    #     secretKeyRef:
    #       name: <CUSTOM_SECRET_NAME>  # custom 类型的 Secret
    #       key: token                  # 引用键 token 的值
    - name: url
      value: <GIT_REPO_URL>       # 克隆(或拉取)的 Git 仓库
      # value: https://$(TOKEN)@github.com/<OWNER>/<REPO_NAME>.git  # GitHub 仓库
    - name: ref
      value: <BRANCH_TAG_OR_COMMIT>     # 切换到此 ref
  sink: 
    type: pvc
    pvc:
      name: <PVC_NAME>
      subPath: save/path
upload-git.yaml
apiVersion: tensorstack.dev/v1beta1
kind: DataCube
metadata:
  name: upload-git
spec:
  source:
    type: pvc
    pvc:
      name: <PVC_NAME>
      subPath: path/to/the/parent/dir  # 若目标 Git 仓库为 https://github.com/owner/repo.git,
  sink:                                # 则推送的本地 Git 仓库为 path/to/the/parent/dir/repo
    type: git
    options:
    - name: token  # 个人访问令牌
      valueFrom:
        secretKeyRef:
          name: <CUSTOM_SECRET_NAME>   # custom 类型的 Secret
          key: token                   # 引用键 token 的值
    - name: url
      value: <GIT_REPO_URL>      # 目标 Git 仓库
      # value: https://$(TOKEN)@github.com/<OWNER>/<REPO_NAME>.git  # GitHub 仓库
kubectl create -f download-git.yaml
kubectl create -f upload-git.yaml

Hugging Face

Hugging Face 是一个 AI 开源社区,其提供的 Git 仓库托管了大量流行的开源模型和数据集。

这里介绍从 Hugging Face 下载模型文件到 PVC(以模型 facebook/opt-125m 为例),以及从 PVC 上传模型文件到 Hugging Face(以用户自己创建的模型 user/llm 为例)的若干方法。数据集类似。

git 命令

Hugging Face 模型或数据集本身就是一个 Git 仓库,因此可以参照 Git 仓库的方法。需要注意的是:

  • Git 仓库的 HTTPS URL 为 https://huggingface.co/<OWNER>/<MODEL_OR_DATASET_NAME>,例如模型 facebook/opt-125m 的 HTTPS URL 为 https://huggingface.co/facebook/opt-125m

  • Git LFS 被用于管理大于 10MB 的文件(Notebook 的镜像已经安装了 Git LFS,并在启动时进行了初始化)。如要推送大于 10MB 的文件,请先通过 Git LFS 追踪该文件:

    git lfs track large_file
    git add large_file
    git commit -m "Add the large file"
    git push
    
  • 如要访问受保护的模型或数据集(例如模型 meta-llama/Meta-Llama-3-8B),访问私有模型或数据集,或推送提交到模型或数据集,则需要提供拥有相应权限的用户的用户名和 token:

    # 克隆受保护的模型的 Git 仓库
    git clone https://<HF_USERNAME>:<HF_TOKEN>@huggingface.co/meta-llama/Meta-Llama-3-8B
    
    # 克隆私有模型的 Git 仓库
    git clone https://<HF_USERNAME>:<HF_TOKEN>@huggingface.co/user/private-llm
    
    # 克隆模型的 Git 仓库并在提交修改后推送回去
    git clone https://<HF_USERNAME>:<HF_TOKEN>@huggingface.co/user/llm
    git add ...
    git commit ...
    git push
    

transformers 库和 datasets

可以使用 transformers下载和上传模型文件以及 tokenizer 文件。使用浏览器访问模型 facebook/opt-125mFiles 标签页。点击 Use in Transformers,按照提示进行操作,即在 Python 程序中调用 transformers 库加载模型。首次加载时,仓库中的模型文件和 tokenizer 文件会被下载到缓存目录下,即 PVC 的 .cache/huggingface/hub/models--facebook--opt-125m/ 路径下。

use-in-transformers
use-in-transformers-detail
from transformers import pipeline
pipe = pipeline("text-generation", model="facebook/opt-125m")

# 或

from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("facebook/opt-125m")
model = AutoModelForCausalLM.from_pretrained("facebook/opt-125m")

对于受保护的或私有的模型或数据集(例如模型 meta-llama/Meta-Llama-3-8B),需要提供拥有访问权限的用户的 token:

from transformers import pipeline
pipe = pipeline("text-generation", model="meta-llama/Meta-Llama-3-8B", token="<HF_TOKEN>")

# 或

from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B", token="<HF_TOKEN>")
model = AutoModelForCausalLM.from_pretrained("meta-llama/Meta-Llama-3-8B", token="<HF_TOKEN>")

使用 datasets下载和上传数据集文件。相比加载模型,加载数据集要更加复杂一些,请直接参阅教程 Load a datasetLoad

调用模型对象tokenizer 对象数据集对象push_to_hub() 方法以将其文件上传到仓库:

huggingface-cli login --token <HF_TOKEN>  # 登录到 Hugging Face
...
model.push_to_hub("user/llm")
tokenizer.push_to_hub("user/llm")
dataset.push_to_hub("user/data")

huggingface-cli 命令和 huggingface_hub

可以使用 huggingface-cli download 命令下载仓库中的所有文件或指定文件。文件会被下载到与 transformers相同的缓存目录下。

huggingface-cli download facebook/opt-125m                                           # 下载所有文件
huggingface-cli download facebook/opt-125m pytorch_model.bin                         # 下载单个指定文件
huggingface-cli download facebook/opt-125m pytorch_model.bin generation_config.json  # 下载多个指定文件
huggingface-cli download facebook/opt-125m --include="*.bin"                         # 模式匹配
huggingface-cli download facebook/opt-125m --cache-dir .                             # 指定缓存目录
huggingface-cli download cais/mmlu all/test-00000-of-00001.parquet --repo-type=dataset  # 下载数据集文件

对于受保护的或私有的模型或数据集(例如模型 meta-llama/Meta-Llama-3-8B),需要提供拥有访问权限的用户的 token:

huggingface-cli login --token <HF_TOKEN>  # 登录到 Hugging Face
huggingface-cli download meta-llama/Meta-Llama-3-8B

# 或

huggingface-cli download meta-llama/Meta-Llama-3-8B --token <HF_TOKEN>

使用 huggingface-cli upload 命令上传文件或整个目录到仓库:

# Usage: huggingface-cli upload <REPO_ID> <LOCAL_PATH> [REPO_PATH]

huggingface-cli login --token <HF_TOKEN>  # 登录到 Hugging Face
huggingface-cli upload user/llm . .                       # 上传整个目录
huggingface-cli upload user/llm ./pytorch_model.bin       # 上传单个指定文件
huggingface-cli upload user/llm . . --exclude="/logs/*"   # 模式匹配
huggingface-cli upload user/data . . --repo-type=dataset  # 上传数据集文件

# 或

huggingface-cli upload user/llm . . --token <HF_TOKEN>

实际上,huggingface-clihuggingface_hub的命令行工具。huggingface-cli download 命令在内部调用了该库的 hf_hub_download()snapshot_download() 函数,huggingface-cli upload 命令在内部调用了该库的 upload_file()upload_folder() 函数。我们同样可以在 Python 程序中调用该库的这些函数来下载和上传文件,这里不再展开,请直接参阅教程 Download filesUpload files

wget 命令

如果只需要下载个别文件,那么也可以复制相应文件的下载链接,然后在终端中使用 wget(或 curl)命令下载:

wget https://huggingface.co/facebook/opt-125m/resolve/main/pytorch_model.bin?download=true -O pytorch_model.bin

# 或

curl -L https://huggingface.co/facebook/opt-125m/resolve/main/pytorch_model.bin?download=true -o pytorch_model.bin

对于受保护的或私有的模型或数据集(例如模型 meta-llama/Meta-Llama-3-8B),需要提供拥有访问权限的用户的 token:

wget --header="Authorization: Bearer <HF_TOKEN>" https://huggingface.co/meta-llama/Meta-Llama-3-8B/resolve/main/model-00001-of-00004.safetensors?download=true -O model-00001-of-00004.safetensors

# 或

curl --header "Authorization: Bearer <HF_TOKEN>" -L https://huggingface.co/meta-llama/Meta-Llama-3-8B/resolve/main/model-00001-of-00004.safetensors?download=true -o model-00001-of-00004.safetensors

DataCube

也可以使用平台提供的 DataCube,其在内部调用的就是 huggingface-cli 命令。使用以下 YAML 配置文件创建 DataCube(修改 PVC 名称、PVC 路径、Secret 名称和 S3 URL)以下载和上传文件:

download-hf.yaml
apiVersion: tensorstack.dev/v1beta1
kind: DataCube
metadata:
  name: download-hf
spec:
  source:
    type: huggingface
    options:
    # - name: token  # Hugging Face token
    #   valueFrom:
    #     secretKeyRef:
    #       name: <CUSTOM_SECRET_NAME>  # custom 类型的 Secret
    #       key: token                  # 引用键 token 的值
    - name: repo
      value: <OWNER>/<MODEL_OR_DATASET_NAME>  # 下载的 Hugging Face 仓库 ID
    # - name: files
    #   value: <FILE1>, <FILE2>, ...          # 下载的文件列表,默认为所有文件
  sink: 
    type: pvc
    pvc:
      name: <PVC_NAME>
      subPath: save/path
  # executor:
  #   env:
  #   - name: HTTPS_PROXY
  #     value: <host>:<port>            # HTTPS 代理
upload-hf.yaml
apiVersion: tensorstack.dev/v1beta1
kind: DataCube
metadata:
  name: upload-hf
spec:
  source:
    type: pvc
    pvc:
      name: <PVC_NAME>
      subPath: path/to/the/dir         # 上传目录下的所有子目录和文件
      # subPath: path/to/the/file      # 上传文件
  sink:
    type: huggingface
    options:
    - name: token  # Hugging Face token
      valueFrom:
        secretKeyRef:
          name: <CUSTOM_SECRET_NAME>   # custom 类型的 Secret
          key: token                   # 引用键 token 的值
    - name: repo
      value: <OWNER>/<MODEL_OR_DATASET_NAME>  # 上传的 Hugging Face 仓库 ID
    - name: path-in-repo
      value: upload/path               # 目标路径
    - name: commit-message
      value: <COMMIT_MESSAGE>          # 提交消息
  # executor:
  #   env:
  #   - name: HTTPS_PROXY
  #     value: <host>:<port>            # HTTPS 代理
kubectl create -f download-hf.yaml
kubectl create -f upload-hf.yaml

ModelScope

ModelScope 是一个中文 AI 开源社区,可以视作中国版的 Hugging Face。ModelScope 上托管的模型和数据集相比 Hugging Face 要少得多,但对于国内用户,访问 ModelScope 的网络连通性更好。

这里介绍从 ModelScope 下载模型文件到 PVC(以模型 AI-ModelScope/opt-125 为例),以及从 PVC 上传模型文件到 ModelScope(以用户自己创建的模型 user/llm 为例)的若干方法。数据集类似。

git 命令

Hugging Face 类似,除了:

  • Git 仓库的 HTTPS URL 为 https://www.modelscope.cn/<OWNER>/<MODEL_OR_DATASET_NAME>.git,例如模型 AI-ModelScope/opt-125 的 HTTPS URL 为 https://www.modelscope.cn/AI-ModelScope/opt-125.git

  • Git LFS 被用于管理大于 100MB 的文件(Notebook 的镜像已经安装了 Git LFS,并在启动时进行了初始化)。如要推送大于 100MB 的文件,请先通过 Git LFS 追踪该文件:

    git lfs track large_file
    git add large_file
    git commit -m "Add the large file"
    git push
    
  • 如要访问受保护的模型或数据集,访问私有模型或数据集,或推送提交到模型或数据集,则需要提供拥有相应权限的用户的 token:

    # 克隆私有模型的 Git 仓库
    git clone http://oauth2:<MODELSCOPE_TOKEN>@www.modelscope.cn/user/private-llm.git
    
    # 克隆模型的 Git 仓库并在提交修改后推送回去
    git clone http://oauth2:<MODELSCOPE_TOKEN>@www.modelscope.cn/user/llm.git
    git add ...
    git commit ...
    git push
    

modelscope

可以使用 modelscope 库下载和上传文件。第一种下载模型文件的方法类似于 transformers(在内部也调用了 transformers 库)。首次加载时,仓库中的所有文件会被下载到缓存目录下,即 PVC 的 .cache/modelscope/hub/AI-ModelScope/opt-125/ 路径下。

from modelscope.models import Model
model = Model.from_pretrained("AI-ModelScope/opt-125")

第二种下载模型文件的方法类似于 huggingface_hub。文件会被下载到与第一种方法相同的缓存目录下。

from modelscope import snapshot_download
from modelscope.hub.file_download import model_file_download

snapshot_download("AI-ModelScope/opt-125")                                   # 下载所有文件
model_file_download("AI-ModelScope/opt-125", file_path="pytorch_model.bin")  # 下载单个指定文件
snapshot_download("AI-ModelScope/opt-125", cache_dir=".")                    # 指定缓存目录

下载数据集文件的方法类似于 datasets。这里以数据集 MMLU 的子集 Abstract Algebra 为例,注意不同的数据集拥有不同的可用子集。首次加载时,仓库中的数据集文件会被下载到缓存目录下,即 PVC 的 .cache/modelscope/hub/datasets/mmlu/abstract_algebra/ 路径下。

from modelscope.msdatasets import MsDataset
dataset = MsDataset.load("mmlu", subset_name="abstract_algebra")

对于受保护的或私有的模型或数据集,需要提供拥有访问权限的用户的 token:

from modelscope import HubApi

api=HubApi()
api.login("<MODELSCOPE_TOKEN>")  # 登录到 ModelScope

# 然后参照上面的方法下载

上传模型文件的方法如下所示。modelscope 库暂不支持上传数据集文件。

from modelscope.hub.api import HubApi

api = HubApi()
api.login("<MODELSCOPE_TOKEN>")  # 登录到 ModelScope

api.push_model(
    model_id="<OWNER>/<MODEL_NAME>",
    model_dir="<LOCAL_PATH>"     # 本地模型目录,要求目录中必须包含 configuration.json
)

大规模数据

在处理大规模数据(如 100TB 级别)的导入和导出时,根据数据源的不同,我们采用不同的策略以确保数据传输的效率和安全性。以下是针对不同数据源的一些方法:

数据源为云存储时:

数据源为 HDD/SDD 外置驱动器或类似设备时:

  1. 将驱动器连接到集群外的与集群网络连接速度较快的计算机上,然后参照本地文件系统继续操作。
  2. 或者,请求管理员操作,将驱动器连接到存储集群的节点上,直接使用存储系统的工具进行数据传输。这种方法的数据传输速度一般较快,但需要能够访问存储集群的工具和接口。

参考

管理个人账户

这一部分演示如何使用生成并使用 API Key 来进行身份验证,以及如何管理自己负责的项目(如果你是项目管理员)。

生成 API Key

本教程演示如何生成一个 API Key。

准备工作

  • 了解 API Key 的基本概念。

开启 API Key 服务

进入安全管理控制台之后,在左侧的导航菜单中点击账号 > API Key 进入 API Key 管理页面。如果你是第一次使用 API Key 服务,需要进行一次额外的登录认证。点击启用开始登录认证。

enable-apikey

在弹出的对话框中,输入你的用户名和密码,并点击启用以开启 API Key 服务,右下角会有悬浮框提示是否成功。

login

生成一个 API Key

开启 API Key 服务之后,再次进入 API Key 管理页面,此时会列出你拥有的所有 API Key。点击右上角的创建新的 API Key 以生成一个新的 API Key。

apikey-list

在 API Key 生成页面,填写名称并勾选你想要包含在 API Key 中的权限,然后点击创建新的 API Key,右下角会有悬浮框提示是否成功。

gen-apikey

使用 API Key

本教程演示几种 API Key 的使用实例。

在 TensorStack CLI 中使用 API Key

你可以使用以下命令并按照提示信息完成 API Key 的录入,随后命令行工具将使用该 API Key 作为用户身份凭证向平台服务器发送请求。

t9k config auth <server-address> -u <user-name> -k

登录操作实质上就是将身份信息记录在 T9k Config 文件中作为一个上下文(context),该配置文件中可以同时记录多个上下文,使用以下命令查看、切换和删除:

# 查看所有上下文
% t9k config get-contexts
CURRENT   NAME            SERVER                     AUTH_TYPE
*         <config-name>   <server-address>           apikey

# 切换所要使用的上下文,即当前上下文
% t9k config use-context <config-name>

# 删除上下文
% t9k config delete-context <config-name>

关于 TensorStack CLI 的详细使用说明,请参阅CLI 用户指南

使用 API Key 作为凭证向 AIStore 上传数据

你可以在模型训练中使用 API Key 作为凭证向 AIStore 上传数据。

通常的模型训练

在使用 Python SDK 将数据上传到 AIStore 中时,你需要调用 t9k.em 模块的 login() 函数进行身份验证,在不设置 login() 函数参数的情况下,SDK 会自动使用 T9k Config 文件中当前上下文中的身份信息,如果你想在训练时使用其他身份信息,则可以设置 ais_hostapi_key 参数。

from t9k import em

# 使用 T9k Config 中当前上下文中的身份信息
em.login()

# 使用其他身份信息
em.login(ais_host='url-of-em-server', api_key='api-key-of-user')

AutoTuneExperiment

为了让 AutoTuneExperiment 能够使用 API Key,你需要创建一个 Secret 来存储 API Key,Secret 的格式如下:

apiVersion: v1
kind: Secret
metadata:
  name: aistore-secret
  namespace: t9k-example
data:
  apikey: ZDQyMjJjZjUtMmI0Ni00Mjk2LWFiMzYtYWI4NmVhZGUwZjQx  # API Key 的 Base64 编码
type: Opaque

在上述 Secret 中,在 data.apikey 字段中记录 API Key 的 Base64 编码。然后在 AutoTuneExperiment 的配置中引用这个 Secret,具体方式请参阅 AutoTuneExperiment 文档

添加项目成员

本教程演示如何为一个项目添加成员。

准备工作

  • 了解项目的基本概念。
  • 成为一个项目的管理员。如果你不是任何一个项目的管理员,请联系平台管理员为你创建一个项目。

查看自己的项目

在浏览器中进入安全管理控制台之后,在左侧的导航菜单中点击资源 > 项目进入项目列表页面。其中,我的项目部分列出了所有你作为管理员的项目,分享给我的项目部分列出了所有你作为成员的项目。

project-list

为项目添加用户

我的项目部分,点击其中一个项目的名称进入该项目的详情页面,这里展示了项目的所有成员(你是项目的管理员)。

project-detail

点击成员右侧的修改按钮,再点击 为该项目添加成员。在弹出的对话框中,你需要选择所要添加的成员名以及该成员可使用的范围(scope),填写完成之后点击保存提交更改,右下角会有悬浮框提示是否添加成功。

add-member

管理告警信息

这一部分演示如何查看、订阅集群的告警信息。

查看告警信息

准备

  • 了解 告警通知的基本概念
  • 成为一个项目的成员。如果你不是任何一个项目的成员:
    • 请联系平台管理员为你创建一个项目
    • 或联系某个项目管理员将你设为项目成员

查看

在浏览器进入“账户管理”控制台之后,在左侧的导航菜单中点击告警通知 > 告警信息进入告警信息列表页面。

subscribe-alert-main-page

然后选择你想查看的项目

subscribe-alert-main-page

点击一个具体的告警信息名称,可以展开的告警信息详情。以下图为例,集群中产生了两个 KubeImagePullError 告警:

  1. 第一个告警信息
    1. 橙色:表明告警处于 pending 状态。pending 意思是告警条件已触发,但还未达到特定时长,系统不会将 pending 告警信息通知给订阅用户。
    2. 描述:Pod demo/test1(hey)无法拉取镜像,原因是 ErrImagePull。
  2. 第二个告警信息:
    1. 红色:红色表明告警处于 firing 状态。firing 表明告警条件触发时长已经达到特定时长,系统会将 firing 告警信息通知给订阅用户。
    2. 描述:Pod demo/test(hey)无法拉取镜像,原因是 ImagePullBackoff。
subscribe-alert-main-page

订阅告警信息

准备

  • 了解 告警通知的基本概念
  • 成为一个项目的成员。如果你不是任何一个项目的成员:
    • 请联系平台管理员为你创建一个项目
    • 或联系某个项目管理员将你设为项目成员

订阅

在浏览器进入“账户管理”控制台之后,在左侧的导航菜单中点击告警通知 > 通知进入订阅告警信息的页面。

subscribe-alert-main-page

选择一个项目:

subscribe-alert-main-page

填写接收订阅通知的邮箱:

subscribe-alert-main-page

订阅你关心的告警信息,最后点击保存修改按钮,即可完成订阅。

subscribe-alert-main-page

在上述例子中,当项目 demo 中产生 KubePodCrashLoopingKubeImagePullError 告警信息时,系统会将这些告警发送到邮箱 demo@tensorstack.com

小技巧

本教程汇总了一些实用的小技巧,可以帮助用户更好地使用平台。

让 Notebook 不被资源回收

如果想要让 Notebook 不被资源回收,可以在该 Notebook 中创建一个 Jupyter Notebook,并运行以下代码:

# To keep the kernel active
import time

while True:
    time.sleep(60)

上述代码使 Notebook 保持活跃状态,而又不占用额外的计算资源。如要恢复对该 Notebook 的资源回收,只需停止上述代码的运行即可。

在终端中获取资源帮助

在创建、查看或调试 Kubernetes API 资源(包括 Kubernetes 原生资源和平台提供的 CRD)时,我们需要了解资源有哪些字段以及它们的含义。要获取这些信息,一种方法是查阅相应的参考文档,但更便捷的方式是在终端使用 kubectl explain 命令:

# 获取资源及其字段的描述
kubectl explain pod

# 获取资源的指定字段及其子字段的描述
kubectl explain pod.spec.containers

# 获取资源的所有子字段
kubectl explain pod --recursive

例如现在我们想要启用 DeepSpeedJob 的调试模式,但不知道该如何编写 YAML 配置文件,那么可以在 Notebook 的终端中执行以下命令:

kubectl explain dj --recursive    # `dj` 是 DeepSpeedJob 的简称

输出应类似于:

KIND:     DeepSpeedJob
VERSION:  batch.tensorstack.dev/v1beta1

DESCRIPTION:
     DeepSpeedJob defines the schema for the DeepSpeedJob API.

FIELDS:
   ...
   spec <Object>
      ...
      runMode   <Object>
         debug  <Object>
            enabled     <boolean>
            replicaSpecs        <[]Object>
               command  <[]string>
               skipInitContainer        <boolean>
               type     <string>
         pause  <Object>
            enabled     <boolean>
            resumeSpecs <[]Object>
               args     <[]string>
               command  <[]string>
               skipInitContainer        <boolean>
               type     <string>
      ...
   ...

由此我们得以写出正确的配置:

apiVersion: batch.tensorstack.dev/v1beta1
kind: DeepspeedJob
metadata:
  name: deepspeed-example
spec:
  runMode:
    debug:
      enabled: true
  ...

查看容器的日志

查看 Pod 中的容器的日志有两种方法。第一种方法是在终端使用 kubectl logs 命令:

# 首先列举所有 Pod
kubectl get pod

# 返回指定 Pod 的(唯一容器的)日志快照
kubectl logs nginx

# 持续输出日志
kubectl logs -f nginx

# 返回日志的最后 20 行
kubectl logs --tail=20 nginx

# 返回最近 1 个小时的日志
kubectl logs --since=1h nginx

第二种方法是在控制台中查看。进入模型构建控制台,在左侧的导航菜单中点击构建 > Pod 进入 Pod 管理页面,然后点击 Pod 的名称进入详情页面:

list

点击日志右侧的按钮即可查看日志:

details
log

此外,部分 CRD 所创建的 Pod 的容器日志也可以从相应 CRD 的详情页面查看,请参阅:

命令行工具和 SDK

除了在网页控制台进行操作外,你还可以使用命令行工具和 Python SDK 来与 TensorStack AI 平台进行交互。

此外,命令行工具和 Python SDK 也为平台的部分功能提供支持。

命令行工具:t9k

TensorStack CLI(简称 T9k CLI)是 TensorStack AI 平台的命令行工具,用于对 TensorStack AI 平台的各种资源对象进行增、删、改、查操作。

功能

TensorStack CLI 目前包含了两大功能:其一是管理 T9k 集群计算资源分配,主要的使用者是 TensorStack AI 平台管理员;其二是管理 TensorStack AI 平台中被创建的作业、服务等资源,主要的使用者是使用平台进行机器学习模型开发、训练、部署等工作的数据科学家。

TensorStack CLI 的目标是:提供对于 T9k 自定义资源的有效支持。对于平台管理员来说,这些功能可以作为 kubectl 的补充来管理 TensorStack AI 平台。对于数据科学家来说,这些功能和控制台一起,帮助他们在 TensorStack AI 平台上开展机器学习相关的工作,而不需要过多的 Kubernetes 基础知识。

architecture
图 1:T9k CLI 示意图

资源类型

T9k CLI 支持的资源类型有:

  • 基于 Kubernetes 定义的,用来解决机器学习相关问题的 TensorStack AI 平台资源:
    • AutoTune
    • BeamJob
    • ColossalAIJob
    • DeepSpeedJob
    • GenericJob
    • MLService
    • MPIJob
    • Notebook
    • PyTorchTrainingJob
    • SimpleMLService
    • TensorFlowTrainingJob
    • WorkflowTemplate
    • WorkflowRun
    • XGBoostTrainingJob
  • 基于 Kubernetes 定义的,用来管理集群资源及权限的 TensorStack AI 平台资源:
    • PodGroup
    • Project
    • Queue

用户指南

下载安装

下载

TensorStack CLI(以下简称 T9k CLI)可以从平台首页下载。请根据操作系统和架构(可以在命令行运行 uname -om 获取)选择适当的版本。

安装

你需要根据下载的版本,设置 T9k CLI 的版本和系统架构等变量:

version=1.78.6
os=darwin
arch=amd64

然后解压下载好的 T9k CLI,并把得到的二进制文件移动到 /usr/local/bin 路径下:

tar -zxvf "$HOME/Downloads/t9k-$version-$os-$arch.tar.gz"
mv t9k-$os-$arch /usr/local/bin/t9k
rm -f "$HOME/Downloads/t9k-$version-$os-$arch.tar.gz"

你可以运行以下命令来验证 T9k CLI 安装完成:

t9k version

卸载

删除二进制文件以卸载 T9k CLI。

rm -f /usr/local/bin/t9k

配置文件

TensorStack CLI 使用 T9k Config 作为配置文件。T9k Config 文件的路径通过命令行参数 -c, --config 进行指定,在未被指定时,使用默认路径 $HOME/.t9k/t9k-config.yaml。第一次使用时,可以通过 t9k config auth 命令来生成配置文件,详情请参阅 t9k config auth

T9k Config 示例如下:

current-context: default-context
contexts:
- name: default-context
  server: https://<example.com>
  image-registry: https://<example.io>
  prefixes:
    aistore: /t9k/aistore/server
    asset-hub: /t9k/asset-hub/server
    build-console: /t9k/build-console/server
    cluster-admin: /t9k/cluster-admin/server
    deploy-console: /t9k/deploy-console/server
    security-console: /t9k/security/server
    workflow-manager: /t9k/workflow/server
  auth:
    apikey: <your-apikey>
    token: <your-token>
  extension:
    codepack:
      data-copy-image: <your-image>

T9k Config 包括以下两个部分:

  • current-context:字符串,记录默认使用的 Context 名称。你可以通过设置命令行参数 -x, --context 访问其他的 Context。
  • contexts:数组,包含集群相关信息。
    • name:字符串,Context 的名称。
    • server:字符串,记录访问这个集群服务的域名。
    • image-registry:字符串,记录这个集群使用镜像仓库的地址。
    • prefixes:数组,记录这个集群中的 T9k Servers 路径前缀。
    • auth:,记录认证信息,支持 apikeytoken 两种认证方式,需要填写其中一种。
    • extension:记录其他工具需要用到的拓展配置。

全局选项

TensorStack CLI 定义了以下的全局命令行参数:

  -c, --config string      t9k config file (default: $HOME/.t9k/t9k-config.yaml)
  -x, --context string     name of the context to use (default: current-context in t9k config)
  -h, --help               t9k help
  -n, --namespace string   alias of -p and --project, invalid if --project is set by user.
  -p, --project string     project to use (default: from t9k config file)
  -v, --verbose int        Set level-based filter in logging (default -1)

具体说明如下:

  • -c, --config:字符串,指定 T9k Config 文件的路径。对于子命令 config,设置的 T9k Config 文件会被创建或修改。默认路径是 $HOME/.t9k/t9k-config.yaml
  • -x, --context:字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 current-context 字段指定的 Context。
  • -h, --help :查看当前指令的帮助信息和示例。
  • -p, --project:字符串,指定使用的项目(本文档中的项目和命名空间同义)。
  • -n, --namespace:字符串,和 -p, --project 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
  • -v, --verbose:指定输出 log 信息的详细程度。

项目(命名空间)的使用优先级是(排在前面的优先级更高):

  1. 你通过命令行参数 -p, --project 设置的项目。
  2. 你通过命令行参数 -n, --namespace 设置的项目。
  3. 使用项目 default

命令

autotune

用于管理 AutoTune

delete

删除指定的 AutoTune。

使用

t9k autotune delete [names...] [--all] [-f]

t9k autotune delete 也可以用 t9k autotune rm 代替。

选项

--all                   删除当前 Project 中的所有 AutoTunes。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 AutoTune:

t9k autotune delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 AutoTune:

t9k autotune delete foo -p demo -f

删除 Project demo 下所有的 AutoTune:

t9k autotune delete foo -p demo --all

describe

查看某个 AutoTune 的详细信息。

使用

t9k at describe <name> [--color]

t9k at describe 也可以用 t9k at desc 代替。

选项

--color                 使用彩色的输出信息(默认全是黑色)。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 AutoTune 的详细描述:

t9k at describe foo -p demo

get

查看 AutoTune 相关信息。

使用

t9k at get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 AutoTune:

t9k at get -p example

以默认格式查看所有 Project 下的所有 AutoTune:

t9k at get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 AutoTune:

t9k at get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 AutoTune:

t9k at get foo -p example -o yaml

wait

等待 AutoTune 完成。

使用

t9k at wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 AutoTune foo 完成:

t9k at wait foo -p example

等待 Project example 下的 AutoTune foo 完成,只等待 10 分钟:

t9k at wait foo -p example --timeout 10m

等待 Project example 下的 AutoTune foo 完成,同时打印 server 的日志:

t9k at wait foo -p example --print-log

beamjob

用于管理 BeamJob

delete

删除指定的 BeamJob。

使用

t9k beamjob delete [names...] [--all] [-f]

t9k beamjob delete 也可以用 t9k bj rm 代替。

选项

--all                   删除当前 Project 中所有的 BeamJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 BeamJob:

t9k beamjob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 BeamJob:

t9k beamjob delete foo -p demo -f

删除 Project demo 下所有的 BeamJob:

t9k beamjob delete foo -p demo --all

describe

查看某个 BeamJob 的详细信息。

使用

t9k bj describe <name>

t9k bj describe 也可以用 t9k bj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 BeamJob 的详细描述:

t9k bj describe foo -p demo

get

查看 BeamJob 相关信息。

使用

t9k bj get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 BeamJob:

t9k bj get -p example

以默认格式查看所有 Project 下的所有 BeamJob:

t9k bj get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 BeamJob:

t9k bj get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 BeamJob:

t9k bj get foo -p example -o yaml

logs

查看 BeamJob 某个计算节点的日志。

使用

t9k bj logs [--type=jobmanager|taskmanager|batchjob] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `taskmanager`,`batchjob` 以及默认值 `jobmanager`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 BeamJob foo 第 replicaIndexreplicaType 节点的日志:

t9k bj logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 BeamJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k bj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 BeamJob foo 第 0 个 jobmanager 节点的最后 20 行日志:

t9k bj logs foo --tail 20

wait

等待 BeamJob 完成。

使用

t9k bj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=jobmanager|taskmanager|batchjob] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `taskmanager`,`batchjob` 以及默认值 `jobmanager`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 BeamJob foo 完成:

t9k bj wait foo -p example

等待 Project example 下的 BeamJob foo 完成,只等待 10 分钟:

t9k bj wait foo -p example --timeout 10m

等待 Project example 下的 BeamJob foo 完成,同时打印节点 flinkcluster-taskmanager-0 的日志:

t9k bj wait foo -p example --print-log --type taskmanager --index 0

colossalaijob

用于管理 ColossalAIJob

delete

删除指定的 ColossalAIJob。

使用

t9k colossalaijob delete [names...] [--all] [-f]

t9k colossalaijob delete 也可以用 t9k caij rm 代替。

选项

--all                   删除当前 Project 中所有的 ColossalAIJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 ColossalAIJob:

t9k colossalaijob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 ColossalAIJob:

t9k colossalaijob delete foo -p demo -f

删除 Project demo 下所有的 ColossalAIJob:

t9k colossalaijob delete foo -p demo --all

describe

查看某个 ColossalAIJob 的详细信息。

使用

t9k caij describe <name>

t9k caij describe 也可以用 t9k caij desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 ColossalAIJob 的详细描述:

t9k caij describe foo -p demo

get

查看 ColossalAIJob 相关信息。

使用

t9k caij get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 ColossalAIJob:

t9k caij get -p example

以默认格式查看所有 Project 下的所有 ColossalAIJob:

t9k caij get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 ColossalAIJob:

t9k caij get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 ColossalAIJob:

t9k caij get foo -p example -o yaml

logs

查看 ColossalAIJob 某个计算节点的日志。

使用

t9k caij logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 ColossalAIJob foo 第 replicaIndexreplicaType 节点的日志:

t9k caij logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 ColossalAIJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k caij logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 ColossalAIJob foo 第 0 个 worker 节点的最后 20 行日志:

t9k caij logs foo --tail 20

wait

等待 ColossalAIJob 完成。

使用

t9k caij wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 ColossalAIJob foo 完成:

t9k caij wait foo -p example

等待 Project example 下的 ColossalAIJob foo 完成,只等待 10 分钟:

t9k caij wait foo -p example --timeout 10m

等待 Project example 下的 ColossalAIJob foo 完成,同时打印节点 master-0 的日志:

t9k caij wait foo -p example --print-log --type master --index 0

config

对指定的 T9k Config 进行生成、管理、查看。T9k Config 默认使用文件 ${HOME}/.t9k/t9k-config.yaml,可通过全局选项 -c, --config 指定该文件路径。

auth

完成用户身份认证,生成 T9k Config。用户第一次使用 T9k 命令行工具时,需要使用此命令来进行身份认证。认证成功后,此命令会修改(如果是首次认证会新建)T9k Config。之后用户便可以通过该认证信息去使用 T9k 其他命令。

使用

t9k config auth <server> [--apikey] [--user=<username>]

选项

-k, --apikey            启用交互式输入 API Key。
-u, --user string       字符串,指定用户密码登录的用户名称。

全局选项

-c, --config            字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定新增 Context 的名称。
-h, --help              查看当前指令的帮助信息和示例。
-v, --verbose           指定输出 log 信息的详细程度。

示例

通过用户密码完成认证

用户指定要登录的域名,然后输入用户名和密码完成认证。认证完成后,当前的 T9k Config 中便会新增一个 <用户名>-<域名> 的 Context,用户也可以自己指定 Context 的名称。

$ t9k config auth <http://example.com>
Authenticating using username and password by default, add --apikey to use apikey.
Please enter your username: demo
Please enter your password:
Please enter Context name [default: demo-example.com]: demo
Login succeeded!

!!! note "注意" Context 的名称需要满足 DNS Subdomain Names 的要求,如果 Context 名字重复,可以选择覆盖原内容或者重新输入。

通过 API Key 完成认证

用户指定要登录的域名,然后输入 API Key。认证完成后,当前的 T9k Config 中便会新增一个 apikey-<hash>-<域名> 的 Context,用户也可以自己指定 Context 的名称。

$ t9k config auth <http://example.com> --apikey
Authenticating using API Key...
Please enter your API Key:
Please enter Context name [default: apikey-<hash>-example.com]: demo-apikey
Login succeeded!

delete-context

删除指定的 Context。

!!! note "注意" 即使指定的 Context 是 current-context,此命令也会直接删除掉。所以务必确认之后再删除。

使用

t9k config delete-context <name>

全局选项

-c, --config            字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help              查看当前指令的帮助信息和示例。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Context demo:

t9k config delete-context demo

get-contexts

用于获取当前使用的 T9k Config 中 Context 的相关信息。具体包括:

  • CURRENT:是否是当前正在使用的 Context
  • NAME:Context 的名称
  • SERVER:T9k 平台的地址
  • AUTH_TYPE:认证信息的类型(token 或者 apikey)

使用

t9k config get-contexts [name] 

全局选项

-c, --config            字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help              查看当前指令的帮助信息和示例。
-v, --verbose           指定输出 log 信息的详细程度。

示例

获取当前 T9k Config 中所有 Context 的信息:

t9k config get-contexts

获取指定 Context 的信息:

t9k config get-contexts my-context

use-context

切换当前使用的 Context,此命令会修改当前 T9k Config 中 current-context 的值。

使用

t9k config use-context <name>

全局选项

-c, --config            字符串,指定要查看、修改的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help              查看当前指令的帮助信息和示例。
-v, --verbose           指定输出 log 信息的详细程度。

示例

切换到 Context foo:

t9k config use-context foo

将文件 $HOME/t9kConfig.yaml 下的 Context 切换到 foo:

t9k config use-context foo -c $HOME/t9kConfig.yaml

create

通过文件创建 TensorStack AI 平台的资源或者其他支持的资源(PVC 和 secret)。

使用

t9k create --filename=<file>

选项

-f, --filename          文件路径

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

通过文件在 Project demo 下创建一个 Notebook 资源。

t9k create -f notebook.yaml -p demo

delete

根据文件删除资源。

使用

t9k delete --filename=<file>

选项

-f, --filename          文件路径

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

根据文件内容删除 Project demo 下相应的 Notebook 资源。

t9k delete -f notebook.yaml -p demo

deepspeedjob

用于管理 DeepSpeedJob

delete

删除指定的 DeepSpeedJob。

使用

t9k deepspeedjob delete [names...] [--all] [-f]

t9k deepspeedjob delete 也可以用 t9k dj rm 代替。

选项

--all                   删除当前 Project 中所有的 DeepSpeedJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 DeepSpeedJob:

t9k deepspeedjob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 DeepSpeedJob:

t9k deepspeedjob delete foo -p demo -f

删除 Project demo 下所有的 DeepSpeedJob:

t9k deepspeedjob delete foo -p demo --all

describe

查看某个 DeepSpeedJob 的详细信息。

使用

t9k dj describe <name>

t9k dj describe 也可以用 t9k dj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 DeepSpeedJob 的详细描述:

t9k dj describe foo -p demo

get

查看 DeepSpeedJob 相关信息。

使用

t9k dj get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 DeepSpeedJob:

t9k dj get -p example

以默认格式查看所有 Project 下的所有 DeepSpeedJob:

t9k dj get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 DeepSpeedJob:

t9k dj get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 DeepSpeedJob:

t9k dj get foo -p example -o yaml

logs

查看 DeepSpeedJob 某个计算节点的日志。

使用

t9k dj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 DeepSpeedJob foo 第 replicaIndexreplicaType 节点的日志:

t9k dj logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 DeepSpeedJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k dj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 DeepSpeedJob foo 第 0 个 worker 节点的最后 20 行日志:

t9k dj logs foo --tail 20

wait

等待 DeepSpeedJob 完成。

使用

t9k dj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 DeepSpeedJob foo 完成:

t9k dj wait foo -p example

等待 Project example 下的 DeepSpeedJob foo 完成,只等待 10 分钟:

t9k dj wait foo -p example --timeout 10m

等待 Project example 下的 DeepSpeedJob foo 完成,同时打印节点 master-0 的日志:

t9k dj wait foo -p example --print-log --type master --index 0

genericjob

用于管理 GenericJob

delete

删除指定的 GenericJob。

使用

t9k genericjob delete [names...] [--all] [-f]

t9k genericjob delete 也可以用 t9k gj rm 代替。

选项

--all                   删除当前 Project 中所有的 GenericJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 GenericJob:

t9k genericjob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 GenericJob:

t9k genericjob delete foo -p demo -f

删除 Project demo 下所有的 GenericJob:

t9k genericjob delete foo -p demo --all

describe

查看某个 GenericJob 的详细信息。

使用

t9k gj describe <name>

t9k gj describe 也可以用 t9k gj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 GenericJob 的详细描述:

t9k gj describe foo -p demo

get

查看 GenericJob 相关信息。

使用

t9k gj get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 GenericJob:

t9k gj get -p example

以默认格式查看所有 Project 下的所有 GenericJob:

t9k gj get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 GenericJob:

t9k gj get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 GenericJob:

t9k gj get foo -p example -o yaml

logs

查看 GenericJob 某个计算节点的日志。

使用

t9k gj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 GenericJob foo 第 replicaIndexreplicaType 节点的日志:

t9k gj logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 GenericJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k gj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 GenericJob foo 第 0 个 worker 节点的最后 20 行日志:

t9k gj logs foo --tail 20

wait

等待 GenericJob 完成。

使用

t9k gj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 GenericJob foo 完成:

t9k gj wait foo -p example

等待 Project example 下的 GenericJob foo 完成,只等待 10 分钟:

t9k gj wait foo -p example --timeout 10m

等待 Project example 下的 GenericJob foo 完成,同时打印节点 master-0 的日志:

t9k gj wait foo -p example --print-log --type master --index 0

mlservice

用于管理 MLService

canary

设置金丝雀发布

使用

t9k mlservice set-canary [--default=default-release] [--canary=canary-release] [--traffic=canary-percentage] [--dry-run] [-o yaml|json]

选项

--canary string         字符串,指定金丝雀发布的版本名称
--default string        字符串,指定默认发布的版本名称
--dry-run               只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string     字符串,指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。
--traffic int           整数,指定金丝雀发布的路由权重

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

将 Project demo 下 MLService maskdetection 的默认发布版本设为 foo,金丝雀发布版本设为 bar 且权重为 20%:

t9k mlservice set-canary maskdetection --default=foo --canary=bar --traffic=20 -n demo

将 Project demo 下 MLService maskdetection 的金丝雀发布版本权重设为 30%:

t9k mlservice set-canary maskdetection --traffic=30 -n demo

将 Project demo 下 MLService maskdetection 的默认发布版本设为 foo

t9k mlservice set-canary maskdetection --default=foo

将 Project demo 下 MLService maskdetection 的金丝雀发布版本设为 bar

t9k mlservice set-canary maskdetection --canary=bar -n demo

delete

删除指定的 MLService。

使用

t9k mls delete [names...] [-f] [--all]

t9k mls delete 也可以用 t9k mls rm 代替。

选项

--all                   删除当前 Project 中所有的 XGBoostTrainingJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 MLService:

t9k mls delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 MLService:

t9k mls delete foo -p demo -f

删除 Project demo 下所有的 MLService:

t9k mls delete foo -p demo --all

describe

查看 MLService 详细信息。

使用

t9k mls describe <name> [--color]

选项

--color                 使用彩色的输出信息(默认全是黑色)。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 MLService 的详细描述:

t9k mls describe foo -p demo

get

查看 MLService 相关信息。

使用

t9k mls get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces       获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string        指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 MLService:

t9k mls get -p example

以默认格式查看所有 Project 下的所有 MLService:

t9k mls get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 MLService:

t9k mls get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 MLService:

t9k mls get foo -p example -o yaml

delete-release

删除 MLService 中发布的版本。

使用

t9k delete-release <name> [--release=release-names...]

选项

--release string        字符串,删除的版本名称,如要删除多个版本,用 `,` 进行分割。
--dry-run               只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string     字符串,指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下的推理服务 maskdetection 的 foo 和 bar 两个已发布的版本:

t9k delete-release maskdetection --release foo,bar -p demo

mpijob

用于管理 MPIJob

delete

删除指定的 MPIJob。

使用

t9k mpijob delete [names...] [--all] [-f]

t9k mpijob delete 也可以用 t9k mj rm 代替。

选项

--all                   删除当前 Project 中所有的 MPIJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 MPIJob:

t9k mpijob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 MPIJob:

t9k mpijob delete foo -p demo -f

删除 Project demo 下所有的 MPIJob:

t9k mpijob delete foo -p demo --all

describe

查看某个 MPIJob 的详细信息。

使用

t9k mj describe <name>

t9k mj describe 也可以用 t9k mj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 MPIJob 的详细描述:

t9k mj describe foo -p demo

get

查看 MPIJob 相关信息。

使用

t9k mj get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 MPIJob:

t9k mj get -p example

以默认格式查看所有 Project 下的所有 MPIJob:

t9k mj get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 MPIJob:

t9k mj get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 MPIJob:

t9k mj get foo -p example -o yaml

logs

查看 MPIJob 某个计算节点的日志。

使用

t9k mj logs [--type=launcher|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `launcher` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 MPIJob foo 第 replicaIndexreplicaType 节点的日志:

t9k mj logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 MPIJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k mj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 MPIJob foo 第 0 个 worker 节点的最后 20 行日志:

t9k mj logs foo --tail 20

wait

等待 MPIJob 完成。

使用

t9k mj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=launcher|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `launcher` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 MPIJob foo 完成:

t9k mj wait foo -p example

等待 Project example 下的 MPIJob foo 完成,只等待 10 分钟:

t9k mj wait foo -p example --timeout 10m

等待 Project example 下的 MPIJob foo 完成,同时打印节点 launcher 的日志:

t9k mj wait foo -p example --print-log --type launcher

notebook

用于管理 Notebook

delete

删除指定的 Notebook。

使用

t9k notebook delete [names...] [--all] [-f]

t9k notebook delete 也可以用 t9k nb rm 代替。

选项

--all                   删除当前 Project 中所有的 Notebook。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 Notebook:

t9k notebook delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 Notebook:

t9k notebook delete foo -p demo -f

删除 Project demo 下所有的 Notebook:

t9k notebook delete foo -p demo --all

describe

查看某个 Notebook 的详细信息。

使用

t9k nb describe <name>

t9k nb describe 也可以用 t9k nb desc 代替。

选项

--color                 使用彩色的输出信息(默认全是黑色)。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 Notebook 的详细描述:

t9k nb describe foo -p demo

get

查看 Notebook 相关信息。

使用

t9k nb get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 Notebook:

t9k nb get -p example

以默认格式查看所有 Project 下的所有 Notebook:

t9k nb get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 Notebook:

t9k nb get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 Notebook:

t9k nb get foo -p example -o yaml

podgroup

用于管理 PodGroup,只有集群管理员才有相关权限。

get

查看 PodGroup 相关信息。

使用

t9k podgroup get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces       获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string        指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 PodGroup:

t9k podgroup get -p example

以默认格式查看所有 Project 下的所有 PodGroup:

t9k podgroup get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 PodGroup:

t9k podgroup get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 PodGroup:

t9k podgroup get foo -p example -o yaml

project

用于管理 Project

create

创建新项目,只有集群管理员才有权限创建新项目。

使用

t9k project create <name> <owner> [--build] [--deploy]

选项

--build                 项目拥有者是否拥有模型构建权限
--deploy                项目拥有者是否拥有模型部署权限

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

创建一个名为 sample 的项目,管理员为 admin,且 admin 只有模型构建的权限,没有模型部署的权限:

t9k project create sample admin --build

describe

查看项目详细描述,只能查看当前用户所拥有的项目。

使用

t9k proj describe <name>

t9k proj describe 也可以用 t9k proj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

详细描述项目 demo:

t9k proj describe demo

get

查看项目的相关信息,只能查看用户拥有权限的项目。

使用

t9k project get [name...]

可以通过指定 name 获取一个或多个 project,不指定的话默认获取所有当前用户有权限的项目。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看当前用户有权限的所有项目:

t9k project get

查看当前用户有权限的项目中名为 foo 的项目:

t9k project get foo

pytorchtrainingjob

用于管理 PyTorchTrainingJob

delete

删除指定的 PyTorchTrainingJob。

使用

t9k pytorchtrainingjob delete [names...] [--all] [-f]

t9k pytorchtrainingjob delete 也可以用 t9k pj rm 代替。

选项

--all                   删除当前 Project 中所有的 PyTorchTrainingJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 PyTorchTrainingJob:

t9k pytorchtrainingjob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 PyTorchTrainingJob:

t9k pytorchtrainingjob delete foo -p demo -f

删除 Project demo 下所有的 PyTorchTrainingJob:

t9k pytorchtrainingjob delete foo -p demo --all

describe

查看某个 PyTorchTrainingJob 的详细信息。

使用

t9k pj describe <name>

t9k pj describe 也可以用 t9k pj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 PyTorchTrainingJob 的详细描述:

t9k pj describe foo -p demo

get

查看 PyTorchTrainingJob 相关信息。

使用

t9k pj get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 PyTorchTrainingJob:

t9k pj get -p example

以默认格式查看所有 Project 下的所有 PyTorchTrainingJob:

t9k pj get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 PyTorchTrainingJob:

t9k pj get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 PyTorchTrainingJob:

t9k pj get foo -p example -o yaml

logs

查看 PyTorchTrainingJob 某个计算节点的日志。

使用

t9k pj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 PyTorchTrainingJob foo 第 replicaIndexreplicaType 节点的日志:

t9k pj logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 PyTorchTrainingJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k pj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 PyTorchTrainingJob foo 第 0 个 worker 节点的最后 20 行日志:

t9k pj logs foo --tail 20

wait

等待 PyTorchTrainingJob 完成。

使用

t9k pj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 PyTorchTrainingJob foo 完成:

t9k pj wait foo -p example

等待 Project example 下的 PyTorchTrainingJob foo 完成,只等待 10 分钟:

t9k pj wait foo -p example --timeout 10m

等待 Project example 下的 PyTorchTrainingJob foo 完成,同时打印节点 master-0 的日志:

t9k pj wait foo -p example --print-log --type master --index 0

queue

用于管理 Queue,只有集群管理员才有相关权限。

close

关闭 Queue。

使用

t9k queue close <name>

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-v, --verbose           指定输出 log 信息的详细程度。

示例

关闭 Queue foo:

t9k queue close foo

get

查看 Queue 相关信息。

使用

t9k queue get [names...] [-o json|yaml|template]

选项

-o, --output string        指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看所有 Queue:

t9k queue get

以默认格式查看名为 foo 和 bar 的两个 Queue:

t9k queue get foo bar

以 yaml 格式查看名为 foo 的 Queue:

t9k queue get foo -o yaml

open

打开 Queue。

使用

t9k queue open <name>

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-v, --verbose           指定输出 log 信息的详细程度。

示例

打开 Queue foo:

t9k queue open foo

simplemlservice

用于管理 SimpleMLService

create

创建一个新的 SimpleMLService。

使用

t9k simplemlservice create <name> --model=<model-url>  -image=<serving-image> [--secret=<serect-name>] [--tech tensorflow|pytorch|xgboost] [--dry-run] [-o yaml|json]

选项

--model string          字符串,推理服务使用的模型地址
--image string          字符串,推理服务使用的镜像
--dry-run               只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string     字符串,指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。
--tech string           字符串,推理服务使用的机器学习框架,如果 image 中已经含有关键字,可不填此参数。可选值有 `tensorflow`,`pytorch`,`xgboost`。
--secret string         字符串,加载模型所使用的密钥名称

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

在 Project demo 下创建一个名为 mnist 的推理服务。其使用的镜像为registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0,模型地址为 mms://aihub.tensorstack.dev/t9kpublic/mnist:v1

t9k simplemlservice create mnist \
  --model="mms://aihub.tensorstack.dev/t9kpublic/mnist:v1" \
  --image="registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0" \
  -n demo

在 Project t9k-sample 下创建一个名为 mnist-cnn 的推理服务。其使用的镜像为registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0,模型地址为 mms://aihub.tensorstack.dev/private/mnist:v2,模型下载使用的密钥为同一个 Project demo 下的 secret mms-access

t9k mls create mnist-cnn \
  --project=t9k-sample \
  --model="mms://aihub.tensorstack.dev/private/mnist:v2" \
  --image="registry.tensorstack.dev/t9kmirror/tensorflow-serving:1.15.0" \
  --tech="tensorflow" \
  --secret="mms-access" 

delete

删除指定的 SimpleMLService。

使用

t9k smls delete [names...] [-f] [--all]

t9k smls delete 也可以用 t9k smls rm 代替。

选项

--all                   删除当前 Project 中所有的 XGBoostTrainingJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 SimpleMLService:

t9k smls delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 SimpleMLService:

t9k smls delete foo -p demo -f

删除 Project demo 下所有的 SimpleMLService:

t9k smls delete foo -p demo --all

describe

查看 SimpleMLService 详细信息。

使用

t9k mls describe <name>

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 SimpleMLService 的详细描述:

t9k mls describe foo -p demo

get

查看 SimpleMLService 相关信息。

使用

t9k smls get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces       获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string        指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 SimpleMLService:

t9k smls get -p example

以默认格式查看所有 Project 下的所有 SimpleMLService:

t9k smls get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 SimpleMLService:

t9k smls get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 SimpleMLService:

t9k smls get foo -p example -o yaml

tensorflowtrainingjob

用于管理 TensorFlowTrainingJob

delete

删除指定的 TensorFlowTrainingJob。

使用

t9k tensorflowtrainingjob delete [names...] [--all] [-f]

t9k tensorflowtrainingjob delete 也可以用 t9k tj rm 代替。

选项

--all                   删除当前 Project 中所有的 TensorFlowTrainingJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 TensorFlowTrainingJob:

t9k tensorflowtrainingjob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 TensorFlowTrainingJob:

t9k tensorflowtrainingjob delete foo -p demo -f

删除 Project demo 下所有的 TensorFlowTrainingJob:

t9k tensorflowtrainingjob delete foo -p demo --all

describe

查看某个 TensorFlowTrainingJob 的详细信息。

使用

t9k tj describe <name>

t9k tj describe 也可以用 t9k tj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 TensorFlowTrainingJob 的详细描述:

t9k tj describe foo -p demo

get

查看 TensorFlowTrainingJob 相关信息。

使用

t9k tj get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 TensorFlowTrainingJob:

t9k tj get -p example

以默认格式查看所有 Project 下的所有 TensorFlowTrainingJob:

t9k tj get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 TensorFlowTrainingJob:

t9k tj get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 TensorFlowTrainingJob:

t9k tj get foo -p example -o yaml

logs

查看 TensorFlowTrainingJob 某个计算节点的日志。

使用

t9k tj logs <name> [--type=chief|ps|evaluator|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `chief`,`ps`,`evaluator` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 TensorFlowTrainingJob foo 第 replicaIndexreplicaType 节点的日志:

t9k tj logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 TensorFlowTrainingJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k tj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 TensorFlowTrainingJob foo 第 0 个 worker 节点的最后 20 行日志:

t9k tj logs foo --tail 20

wait

等待 TensorFlowTrainingJob 完成。

使用

t9k tj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=chief|ps|evaluator|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `chief`,`ps`,`evaluator` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 TensorFlowTrainingJob foo 完成:

t9k tj wait foo -p example

等待 Project example 下的 TensorFlowTrainingJob foo 完成,只等待 10 分钟:

t9k tj wait foo -p example --timeout 10m

等待 Project example 下的 TensorFlowTrainingJob foo 完成,同时打印节点 chief-0 的日志:

t9k tj wait foo -p example --print-log --type chief --index 0

version

查看当前 T9k CLI 版本信息。

使用

t9k version

示例

查看当前 t9k 二进制文件的版本信息。

t9k version

workflowrun

用于管理 WorkflowRun

delete

删除指定的 WorkflowRun。

使用

t9k workflowrun delete [names...] [--all] [-f]

t9k workflowrun delete 也可以用 t9k wr rm 代替。

选项

--all                   删除当前 Project 中所有的 WorkflowRun。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 WorkflowRun:

t9k workflowrun delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 WorkflowRun:

t9k workflowrun delete foo -p demo -f

删除 Project demo 下所有的 WorkflowRun:

t9k workflowrun delete foo -p demo --all

describe

查看某个 WorkflowRun 的详细信息。

使用

t9k wr describe <name>

t9k wr describe 也可以用 t9k wr desc 代替。

选项

--color                 使用彩色的输出信息(默认全是黑色)。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 WorkflowRun 的详细描述:

t9k wr describe foo -p demo

get

查看 WorkflowRun 相关信息。

使用

t9k wr get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 WorkflowRun:

t9k wr get -p example

以默认格式查看所有 Project 下的所有 WorkflowRun:

t9k wr get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 WorkflowRun:

t9k wr get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 WorkflowRun:

t9k wr get foo -p example -o yaml

logs

查看 WorkflowRun 某个容器的日志,不支持直接查看 DAG 类型的 WorkflowRun 的日志。

使用

t9k wr logs [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下 WorkflowRun foo 唯一容器的日志:

t9k wr logs foo -p demo

流式查看 Project demo 下 WorkflowRun foo 容器 mnist 的日志:

t9k wr logs foo --container=mnist -p demo -f

查看 Project demo 下 WorkflowRun foo 唯一容器的最后 20 行日志:

t9k wr logs foo -p demo --tail=20

wait

等待 WorkflowRun 完成,该命令不支持 DAG 类型的 WorkflowRun。

使用

t9k wr wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--timestamps            是否展示时间戳。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 WorkflowRun foo 完成:

t9k wr wait foo -p example

等待 Project example 下的 WorkflowRun foo 完成,只等待 10 分钟:

t9k wr wait foo -p example --timeout 10m

等待 Project example 下的 WorkflowRun foo 完成,同时打印其容器 mnist 的日志:

t9k wr wait foo -p example --print-log --container mnist

workflowtemplate

用于管理 WorkflowTemplate

delete

删除指定的 WorkflowTemplate。

使用

t9k workflowtemplate delete [names...] [--all] [-f]

t9k workflowtemplate delete 也可以用 t9k wr rm 代替。

选项

--all                   删除当前 Project 中所有的 WorkflowTemplate。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 WorkflowTemplate:

t9k workflowtemplate delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 WorkflowTemplate:

t9k workflowtemplate delete foo -p demo -f

删除 Project demo 下所有的 WorkflowTemplate:

t9k workflowtemplate delete foo -p demo --all

describe

查看某个 WorkflowTemplate 的详细信息。

使用

t9k wt describe <name>

t9k wt describe 也可以用 t9k wt desc 代替。

选项

--color                 使用彩色的输出信息(默认全是黑色)。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 WorkflowTemplate 的详细描述:

t9k wt describe foo -p demo

get

查看 WorkflowTemplate 相关信息。

使用

t9k wt get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 WorkflowTemplate:

t9k wt get -p example

以默认格式查看所有 Project 下的所有 WorkflowTemplate:

t9k wt get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 WorkflowTemplate:

t9k wt get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 WorkflowTemplate:

t9k wt get foo -p example -o yaml

start

执行 WorkflowTemplate。

使用

t9k wt start <name> [-l <labelStrings>] [-r <paramStrings>] [-s <serviceAccount>] [--timeout=<timeoutTime>] [-w <workplaceStrings>] [--use-param-defaults] [--dry-run] [-o yaml|json]

选项

-l, --label strings          以键值对的方式指定 workflowRun 的 label。例如 -l "LABEL_1=VAL_1,LABEL_2=VAL_2"。
-r, --param strings          以键值对的方式指定 workflowRun 的参数。例如 -l "KEY_1=VAL_1,KEY_2=VAL_2"。
-w, --workspace strings      以键值对的方式指定 workspace 相关信息。例如 -w "name=$workspace_name,type=$workspace_type,$key$value"。
--use-param-defaults         是否采用默认参数
--timeout string             字符串,指定 workflowRun 的超时时间。
--dry-run                    只打印更新后的 yaml 文件,但是不执行 apply 操作。
-o, --output string          指定 --dry-run 打印的格式。可选值有 `json`,`yaml`。
-s, --serviceaccount string  指定 workflowRun 的 serviceAccount。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

执行 Project demo 下的 WorkflowTemplate foo:

t9k wt start foo -p demo

根据指定的 workspace 信息执行 Project demo 下的 WorkflowTemplate foo:

t9k wt start foo --workspace=name=bar,type=pvc,claimName=bar-pvc,subPath=/user/local/Document -p demo

执行 Project demo 下的 WorkflowTemplate foo,并设置参数 bar 值为 hello:

t9k wt start foo --param=bar=hello

xgboosttrainingjob

用于管理 XGBoostTrainingJob

delete

删除指定的 XGBoostTrainingJob。

使用

t9k xgboosttrainingjob delete [names...] [--all] [-f]

t9k xgboosttrainingjob delete 也可以用 t9k xj rm 代替。

选项

--all                   删除当前 Project 中所有的 XGBoostTrainingJob。
-f, --force             跳过确认,直接执行删除操作。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

删除 Project demo 下名为 foo 和 bar 的两个 XGBoostTrainingJob:

t9k xgboosttrainingjob delete foo bar -p demo

跳过确认,直接删除 Project demo 下名为 foo 的 XGBoostTrainingJob:

t9k xgboosttrainingjob delete foo -p demo -f

删除 Project demo 下所有的 XGBoostTrainingJob:

t9k xgboosttrainingjob delete foo -p demo --all

describe

查看某个 XGBoostTrainingJob 的详细信息。

使用

t9k xj describe <name>

t9k xj describe 也可以用 t9k xj desc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project demo 下名为 foo 的 XGBoostTrainingJob 的详细描述:

t9k xj describe foo -p demo

get

查看 XGBoostTrainingJob 相关信息。

使用

t9k xj get [names...] [-A] [-o json|yaml|template]

选项

-A, --all-namespaces    获取用户具有权限的所有 Namespace(Project)中的资源。
-o, --output string     字符串,指定输出信息的形式。可选值有 `json`,`yaml` 和默认的 `template`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

以默认格式查看 Project example 下所有 XGBoostTrainingJob:

t9k xj get -p example

以默认格式查看所有 Project 下的所有 XGBoostTrainingJob:

t9k xj get -A

以默认格式查看 Project example 下名为 foo 和 bar 的两个 XGBoostTrainingJob:

t9k xj get foo bar -p example

以 yaml 格式查看 Project example 下名为 foo 的 XGBoostTrainingJob:

t9k xj get foo -p example -o yaml

logs

查看 XGBoostTrainingJob 某个计算节点的日志。

使用

t9k xj logs [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [-f] [--tail] [--timestamps]

选项

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
-f, --follow            流式查看日志。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--tail int              整数,要查看的日志的行数(从后往前)。默认值:-1,查看全部日志。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

查看 Project example 下 XGBoostTrainingJob foo 第 replicaIndexreplicaType 节点的日志:

t9k xj logs foo --type=replicaType --index=replicaIndex -p example

流式查看 Project example 下 XGBoostTrainingJob foo 第 replicaIndexreplicaType 节点的容器 mnist 的日志:

t9k xj logs foo --type=replicaType --index=replicaIndex --container=mnist --follow

查看 XGBoostTrainingJob foo 第 0 个 worker 节点的最后 20 行日志:

t9k xj logs foo --tail 20

wait

等待 XGBoostTrainingJob 完成。

使用

t9k xj wait <name> [--timeout=<timeoutTime>] [--period=<periodTime>] [--print-log [--type=master|worker] [--index=<replicaIndex>] [--container=<containerName>] [--timestamps]]

选项

--timeout string        字符串,最长等待时间。默认值:"1h",1 小时。
--period  string        字符串,检查任务是否完成的周期。默认值:"1s",每秒检查一次。
--print-log             是否在等待时流式查看日志。

以下参数只有在开启了 `--print-log` 后才生效。

--container string      字符串,指定要查看的 container 名称,如果计算节点的 container 不止 1 个,必须指定此项。
--index string          字符串,要查看的计算节点的序号。默认值:0。
--timestamps            是否展示时间戳。
--type string           字符串,要查看的计算节点的角色。可选值有 `master` 以及默认值 `worker`。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-x, --context           字符串,指定使用 T9k Config 中的哪一个 Context,在未设置这个参数时,会使用 T9k Config 中 `current-context` 字段指定的 Context。
-h, --help              查看当前指令的帮助信息和示例。
-p, --project           字符串,指定使用的项目(本文档中的项目和命名空间同义)。
-n, --namespace         字符串,和 `-p, --project` 作用一致,指定使用的项目。这个设计是为了符合 kubectl 用户的习惯。
-v, --verbose           指定输出 log 信息的详细程度。

示例

等待 Project example 下的 XGBoostTrainingJob foo 完成:

t9k xj wait foo -p example

等待 Project example 下的 XGBoostTrainingJob foo 完成,只等待 10 分钟:

t9k xj wait foo -p example --timeout 10m

等待 Project example 下的 XGBoostTrainingJob foo 完成,同时打印节点 master-0 的日志:

t9k xj wait foo -p example --print-log --type master --index 0

命令行工具:t9k-pf

TensorStack AI 平台提供了命令行工具 t9k-pf,其功能类似于 kubectl port-forward,使用户能够在本地通过端口转发的方式访问 TensorStack AI 平台的各种资源。目前支持的资源类型有 Notebook、Pod、Service。

用户指南

下载安装

下载

t9k-pf 可以从平台首页下载。请根据操作系统和架构(可以在命令行运行 uname -om 获取)选择适当的版本。

安装

根据下载的版本,设置 t9k-pf 的版本和系统架构等变量:

version=0.2.8
os=darwin
arch=amd64

然后解压下载好的 t9k-pf,并把得到的二进制文件移动到 /usr/local/bin 路径下:

tar -zxvf "$HOME/Downloads/t9k-pf-$version-$os-$arch.tar.gz"
mv t9k-pf-$os-$arch /usr/local/bin/t9k-pf
rm -f "$HOME/Downloads/t9k-pf-$version-$os-$arch.tar.gz"

安装完成后,运行以下命令来验证安装是否成功:

t9k-pf version

卸载

删除二进制文件即可卸载 t9k-pf。

rm -f /usr/local/bin/t9k-pf

身份认证和授权

通过 T9k Config 进行身份认证和授权

t9k-pf 默认使用 T9k Config 来进行身份认证和授权。你可以通过命令行参数 -c, --config 来指定 t9k-pf 使用的 T9k Config 文件的路径,未指定时,默认使用 $HOME/.t9k/t9k-config.yaml 路径下 T9k Config 中 current-context 的认证信息。

下面是一个 T9k Config 的示例,其中 current-context 为 demo1,该 Context 的 token 字段不为空,因此最终 t9k-pf 使用该值 demo1-token 来完成身份验证(如果 apikey 和 token 均不为空,t9k-pf 优先使用 apikey)。

current-context: demo1
contexts:
- name: demo1
  server: https://<example.com>
  image-registry: https://<example.io>
  prefixes:
    aistore: /t9k/aistore/server
    asset-hub: /t9k/asset-hub/server
    build-console: /t9k/build-console/server
    cluster-admin: /t9k/cluster-admin/server
    deploy-console: /t9k/deploy-console/server
    security-console: /t9k/security/server
    workflow-manager: /t9k/workflow/server
  auth:
    apikey: ""
    token: demo1-token
  extension:
    codepack:
      data-copy-image: <your-image>
- name: demo2
  server: https://<example.com>
  ...

通过 API Key 进行临时身份认证和授权

t9k-pf 支持通过命令行参数 -k,--apikey 直接指定 API Key,完成单次端口转发的身份认证和授权。

例如输入以下指令(其中 notebook <URL> 会在命令中介绍,此处只用关注 --apikey 的使用):

t9k-pf notebook <url> --apikey

命令行会进入交互式输入界面,粘贴你的 API Key 再按下回车即可。

全局选项

  • -c, --config

    使用的 T9k Config 文件的路径。默认路径是 $HOME/.t9k/t9k-config.yaml

  • -k, --apikey

    开启交互式输入 API Key。

  • -n, --namespace

    使用的项目(命名空间)名称。

  • -h, --help

    查看当前指令的帮助信息和示例。

  • --address

    本地监听地址。默认为 localhost

  • --retryMaxTimes

    整数,最大重试次数。默认为 10

  • --retryPeriod

    整数,重试间隔时间(单位:秒)。默认为 10

命令

notebook

针对 TensorStack AI 平台的 Notebook 资源,我们提供了直接通过其 URL 地址获取 SSH 连接方式的功能。使用该命令,你不需要指定名称、命名空间等信息。关于 SSH 连接的详细内容请参阅通过 SSH 连接远程使用 Notebook

使用

t9k-pf notebook <url> <localPort>

其中 <url> 代表地址栏中的地址,<localPort> 代表你指定的本地端口号(小于 1024 的本地端口需要管理员权限才可以绑定),如果不指定,会随机使用一个本地端口。

t9k-pf notebook 也可以用 t9k-pf nb 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help              查看当前指令的帮助信息和示例。
-n, --namespace         字符串,指定使用的项目(命名空间)名称。
-k, --apikey            开启交互式输入 API Key。
--address               本地监听地址。默认为 `localhost`。
--retryMaxTimes         整数,最大重试次数。默认为 `10`。
--retryPeriod           整数,重试间隔时间(单位:秒)。默认为 `10`。

示例

通过本地 127.0.0.1 的随机端口访问 Project demo 下 Notebook ml-labs 的 SSH 端口。

t9k-pf notebook <tensorstack-host>/t9k/build-console/projects/demo/notebooks/ml-labs/lab

通过本地 127.0.0.1:8888 访问 Project demo 下 Notebook ml-labs 的 SSH 端口。

t9k-pf nb <tensorstack-host>/t9k/build-console/projects/demo/notebooks/ml-labs/lab 8888

通过本地 0.0.0.0:8888 访问 Project demo 下 Notebook ml-labs 的 SSH 端口。

t9k-pf nb <tensorstack-host>/t9k/build-console/projects/demo/notebooks/ml-labs/lab 8888 --address 0.0.0.0

pod

访问指定 Pod 的指定端口。

使用

t9k-pf pod <name> [<localPort>:]<targetPort>

其中 <localPort> 代表本地监听的端口(小于 1024 的本地端口需要管理员权限才可以绑定),<targetPort> 代表目标 Pod 的端口。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help              查看当前指令的帮助信息和示例。
-n, --namespace         字符串,指定使用的项目(命名空间)名称。
-k, --apikey            开启交互式输入 API Key。
--address               本地监听地址。默认为 `localhost`。
--retryMaxTimes         整数,最大重试次数。默认为 `10`。
--retryPeriod           整数,重试间隔时间(单位:秒)。默认为 `10`。

示例

通过本地 127.0.0.1:3333 访问命名空间 dev 下的 Pod example 的 2222 端口。

t9k-pf pod example 3333:2222 -n dev

通过本地 0.0.0.0:3333 访问命名空间 dev 下的 Pod example 的 2222 端口。

t9k-pf pod example 3333:2222 -n dev --address 0.0.0.0

通过本地 127.0.0.1 的随机端口访问命名空间 dev 下的 Pod example 的 2222 端口。

t9k-pf pod example 2222 -n dev

service

访问指定 Service 的指定端口。

使用

t9k-pf service <name> [<localPort>:]<targetPort>

其中 <localPort> 代表本地监听的端口(小于 1024 的本地端口需要管理员权限才可以绑定),<targetPort> 代表目标 Service 的端口。

t9k-pf service 也可以用 t9k-pf svc 代替。

全局选项

-c, --config            字符串,指定使用的 T9k Config 文件的路径。默认路径是 `$HOME/.t9k/t9k-config.yaml`。
-h, --help              查看当前指令的帮助信息和示例。
-n, --namespace         字符串,指定使用的项目(命名空间)名称。默认是 `default`。
-k, --apikey            开启交互式输入 API Key。
--address               本地监听地址。默认为 `localhost`。
--retryMaxTimes         整数,最大重试次数。默认为 `10`。
--retryPeriod           整数,重试间隔时间(单位:秒)。默认为 `10`。

示例

通过本地 127.0.0.1:8888 访问默认命名空间 default 下的 Service myservice 的 80 端口。

t9k-pf service myservice 8888:80

通过本地 0.0.0.0:8888 访问默认命名空间 default 下的 Service myservice 的 80 端口。

t9k-pf service myservice 8888:80 --address 0.0.0.0

通过本地 127.0.0.1 的随机端口访问命名空间 dev 下的 Service myservice 的 80 端口。

t9k-pf service myservice 80 -n dev

Python SDK:t9k

TensorStack AI 平台提供了 Python SDK t9k,其为平台中的多种功能提供支持。

用户指南

安装

目前 TensorStack SDK 仅提供用于本地安装的 Python 包,你可以从平台首页下载。

然后使用以下命令进行安装:

pip install t9k-sdk-<version>.tar.gz [-i <pypi-mirror-url>]

配置

配置文件

TensorStack SDK 没有单独的配置文件,而是使用 TensorStack CLI 的配置文件。在导入 t9k 模块时,会自动读取位于路径 ~/.t9k/t9k-config.yaml 的配置文件(如果设置了环境变量 T9K_CONFIG,则读取其值给出的路径)。如果配置文件不存在或缺少部分配置项,则缺少的这些配置项会被设置为 None,这可能导致 TensorStack SDK 的部分功能不能正常工作。

使用和修改配置

在 Python 脚本中导入 t9k 模块之后,t9k.CONFIG 对象就代表了 TensorStack SDK 的配置,你可以像操作 Python 字典一样操作它,例如获取、设置、更新值。

import t9k

print(t9k.CONFIG['api_key'])
t9k.CONFIG['api_key'] = 'e4ccd2a3-3425-44b0-8b44-148bd303a0f9'
t9k.CONFIG.update({'api_key': 'e4ccd2a3-3425-44b0-8b44-148bd303a0f9'})

命令行工具

TensorStack SDK 提供了两个命令行工具:

  • em:对应于 t9k.em 模块,用于用户登录和登出 AIStore 服务器(会修改配置文件),查看和上传本地保存的 Run 和 Artifact 数据。执行 em --helpem COMMAND --help 以查看相应命令的详细使用方法。
  • ah:对应于 t9k.ah 模块,用于用户登录和登出 Asset Hub 服务器(会修改配置文件),查看、创建、修改和删除资产和资产目录,以及上传、修改和下载资产文件。执行 ah --helpah COMMAND --help 命令以查看相应命令的详细使用方法。

各主题教程

API

t9k.ah

t9k.ah.commit

commit(path: str, msg: str, delete: Optional[Sequence[str]] = None, add: Union[Sequence[str], Mapping[str, str], None] = None, force: bool = False) ‑> Optional[t9k.ah.core.Commit]

Commits changes to a branch of an Asset.

First delete, then add.

If no branch is provided, :main will be used.

For Windows platform, if you provide absolute paths for parameter add, change its format from 'C:\local\path' to '\C\local\path'.

Examples

Add a file as object to specified branch of Model:

ah.commit('model/llm/gpt2:v1', msg='add ...', add=['model.pt'])

Specify a path in Asset for a file to add:

ah.commit('model/llm/gpt2:v1', msg='add ...', add={'model.pt': 'saved_model/'})

Add all files under a directory as objects (with the directory):

ah.commit('model/llm/gpt2:v1', msg='add ...', add=['./saved_model'])

Add all files under a directory as objects (without the directory):

ah.commit('model/llm/gpt2:v1', msg='add ...', add=['./saved_model/*'])

Specify a path in Asset for a directory to add:

ah.commit('model/llm/gpt2:v1', msg='add ...', add={'./saved_model': 'path/to/[saved_model]'})
## or
ah.commit('model/llm/gpt2:v1', msg='add ...', add={'./saved_model': 'path/to/renamed_dir'})

Delete an object from a Dataset:

ah.commit('dataset/images/cifar10', msg='delete ...', delete=['0.png'])

Delete all objects under the specified path:

ah.commit('dataset/images/cifar10', msg='delete ...', delete=['data/'])

Args

  • path (str)

    Path of the branch.

  • msg (str)

    Commit message.

  • delete (Optional[Sequence[str]])

    Files or directories to delete from the branch, can be a sequence of paths in branch or None. If empty sequence or None, delete nothing. If the files or directories to delete do not exist, do nothing (rather than raise an error). Here format a/.../b signifies a file, while a/.../b/ signifies a directory.

  • add (Union[Sequence[str], Mapping[str, str], None])

    Files or directories to add to the branch, can be a sequence of local paths, a mapping from local paths to their paths in Asset, or None. If empty sequence, empty mapping or None, add nothing.

  • force (bool)

    Whether to create a new commit if unknown changes or unimplemented changes are found.

Returns

A Commit instance representing created commit if changes are commited, None if not.

t9k.ah.create

create(path: str, labels: Optional[Sequence[str]] = None, description: str = '', exist_ok: bool = False, create_tag: bool = False, source: str = 'main') ‑> Union[t9k.ah.core.Folder, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag]

Creates a resource.

Note that you cannot create a Folder for another user.

Examples

Create a Folder:

folder = ah.create('model/llm')

Create a Model with labels:

model = ah.create('model/llm/gpt2', labels=['PyTorch'])

Create a Dataset with a description:

description = 'CIFAR-10 is a widely used benchmark dataset ...'
dataset = ah.create('dataset/images/cifar10', description=description)

Create a non-main branch of specified Model:

branch = ah.create('model/llm/gpt2:v1')

Create a tag:

tag = ah.create('model/llm/gpt2:20220101', create_tag=True, source='v1')
## or
tag = ah.create('model/llm/gpt2:20220101', create_tag=True, source='model/llm/gpt2:v1')

Create a Model for another user:

model = ah.create('/user/t9k-assethub/model/llm/gpt2')

Args

  • path (str)

    Path of the resource.

  • labels (Optional[Sequence[str]])

    Labels of the resource. Only applicable for creating a Folder, Model or Dataset.

  • description (str)

    Description of the resource. Only applicable for creating a Folder, Model or Dataset.

  • exist_ok (bool)

    If True and the resource already exists, return a corresponding instance representing the resource; if False and resource exists, raise a RuntimeError. Only applicable for creating a Folder, Model or Dataset.

  • create_tag (bool)

    Whether to create a tag instead of a branch. Only applicable for creating a branch or tag.

  • source (str)

    Name/ID or path of the source reference (branch, tag or commit) from which a tag is created. Only applicable for creating a tag.

Returns

A corresponding instance representing retrieved resource.

t9k.ah.delete

delete(path: str, force: bool = False) ‑> None

Deletes a resource.

Examples

Delete a Folder:

ah.delete('model/llm')

Delete a Model:

ah.delete('model/llm/gpt2')

Delete a Dataset:

ah.delete('dataset/images/cifar10')

Delete a non-main branch of specified Model:

ah.delete('model/llm/gpt2:v1')

Delete a tag:

ah.delete('model/llm/gpt2:20220101')

Delete another user's Folder:

ah.delete('/user/t9k-assethub/model/llm')

If the Folder does not exist, do nothing:

ah.delete('model/llm', force=True)

Args

  • path (str)

    Path of the resource.

  • force (bool)

    If True, ignore non-existent resources.

t9k.ah.download

download(path: str, objects: Optional[Sequence[str]] = None, save_dir: str = '.')

Download objects of a reference of an Asset.

If no reference is provided, :main will be used.

Examples

Download all objects of specified branch of Model to current working directory:

ah.download('model/llm/gpt2:v1')

Download an object to specified directory:

ah.download('model/llm/gpt2:v1', objects=['model.pt'], save_dir='./saved_model')

Download all objects under the same path:

ah.download('model/llm/gpt2:v1', objects=['saved_model/'])

Specify the reference by tag:

ah.download('dataset/images/cifar10:20220101')

Specify the reference by commit:

ah.download('dataset/images/cifar10:a41ac4ec')

Args

  • path (str)

    Path of the reference from which objects are downloaded.

  • objects (Optional[Sequence[str]])

    Objects to download.

  • save_dir (str)

    Local directory which objects are downloaded to.

t9k.ah.get

get(path: str) ‑> Union[t9k.ah.core.Folder, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag, t9k.ah.core.Commit]

Gets a resource.

To get a commit, please provide a commit ID with a length of at least 4 to avoid potential conflicts with branches or tags.

Examples

Get a Folder:

folder = ah.get('model/llm')

Get a Model:

model = ah.get('model/llm/gpt2')

Get a Dataset:

dataset = ah.get('dataset/images/cifar10')

Get a non-main branch of specified Model:

branch = ah.get('model/llm/gpt2:v1')

Get a tag:

tag = ah.get('model/llm/gpt2:20220101')

Get another user's Folder:

folder = ah.get('/user/t9k-assethub/model/llm')

Args

  • path (str)

    Path of the resource.

Returns

A instance representing retrieved resource.

t9k.ah.list

list(path: str, resource: str = 'default') ‑> List[Dict[str, Any]]

Lists resources.

Based on the provided path, list Folders with the specified Asset kind, Assets within the specified Folder, or all objects of the specified reference (branch, tag or commit) of Asset.

To list Folders that are shared with you, set path='shared/model' (or path='shared/dataset'); to list Folders that are public, set path='/public/t9k-assethub/model' (or path='/public/t9k-assethub/dataset').

To list branches, provide a path that points to an Asset and set resource='branch'; to list tags, provide a path that points to an Asset and set resource='tag'; to list commits, provide a path that points to a branch of an Asset and set resource='commit'.

If a reference is expected but omitted, :main will be used.

Examples

List Model Folders that you own:

folders = ah.list('model')

List Model Folders that are shared with you:

folders = ah.list('shared/model')

List Model Folders that are public:

folders = ah.list('/public/t9k-assethub/model')

List Models in your own Folder:

models = ah.list('model/llm')

List Models in another user's Folder:

models = ah.list('/user1/t9k-assethub/model/llm')

List objects of specified branch of Model:

objects = ah.list('model/llm/gpt2:v1')

List objects of specified tag of Dataset:

objects = ah.list('dataset/images/cifar10:20220101')

List branches of specified Model:

branches = ah.list('model/llm/gpt2', resource='branch')

List tags of specified Model:

tags = ah.list('model/llm/gpt2', resource='tag')

List commits of specified branch of Model:

commits = ah.list('model/llm/gpt2:v1', resource='commit')

List commits of specified Dataset:

commits = ah.list('dataset/images/cifar10', resource='commit')

Args

  • path (str)

    Path to be listed.

  • resource (str)

    Kind of the resources, must be 'default', 'branch', 'tag' or 'commit'. This parameter is used to list branches, tags or commits: to list branches, provide a path that points to an Asset and set resource='branch'; to list tags, provide a path that points to an Asset and set resource='tag'; to list commits, provide a path that points to a branch of an Asset and set resource='commit'.

Returns

A list of resources.

t9k.ah.login

login(ah_host: Optional[str] = None, ais_host: Optional[str] = None, api_key: Optional[str] = None, timeout: Optional[int] = None) ‑> None

Logs in to AIStore server and Asset Hub server.

Sets up the client that corresponds with AIStore server and Asset Hub server.

Args

  • ah_host (Optional[str])

    URL of Asset Hub server. Defaults to t9k.CONFIG['asset_hub_host'].

  • ais_host (Optional[str])

    URL of AIStore server. Defaults to t9k.CONFIG['aistore_host'].

  • api_key (Optional[str])

    API Key for requesting server. Defaults to t9k.CONFIG['api_key'].

  • timeout (Optional[int])

    How many seconds to wait for server to send data before giving up.

Raises

  • requests.HTTPError

    Unable to connect to the server.

t9k.ah.logout

logout() ‑> None

Logs out from the current AIStore server and Asset Hub server.

The client is unset, it can no longer correspond with AIStore server and Asset Hub server until it is set up again.

t9k.ah.merge

merge(path: str) ‑> None

Merges a branch of a Model to the main branch.

Here, the specific operation of "merge" involves deleting all objects from the main branch and then copying all objects from the specified branch to the main branch.

Note that the specified branch itself cannot be the main branch.

Examples

ah.merge('model/llm/gpt2:v1')

Args

  • path (str)

    Path of the branch.

t9k.ah.reset

reset(path: str) ‑> None

Resets a branch to clear all uncommitted changes.

Examples

ah.reset('model/llm/gpt2:main')

Args

  • path (str)

    Path of the branch.

t9k.ah.update

update(path: str, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None

Updates a resource.

Only Folders and Assets can be updated.

If none of the args is provided, do nothing.

Examples

Rename a Folder:

ah.update('model/llm', name='generative-language-model')

Relabel a Model:

ah.update('model/llm/gpt2', labels=['JAX'])

Args

  • name (Optional[str])

    New name of the resource.

  • labels (Optional[Sequence[str]])

    New labels of the resource.

  • description (Optional[str])

    New description of the resource.

t9k.ah.core

t9k.ah.core.Branch

Branch(asset: Union[t9k.ah.core.Model, t9k.ah.core.Dataset], name: str, commit_id: str)

Represents a branch of Asset.

Attributes

  • path (str)

    Path of the branch.

  • asset (Union[t9k.ah.core.Model, t9k.ah.core.Dataset])

    A Model or Dataset instance corresponding to the Asset that the branch belongs to.

  • kind (str)

    A string 'branch'.

  • name (str)

    Name of the branch.

  • commit_id (str)

    ID of the commit that the branch points to.

  • alive (bool)

    Whether the branch is alive.

Ancestors

  • t9k.ah.core._Ref

Methods

create_commit

create_commit(self, msg: str, delete: Optional[Sequence[str]] = None, add: Union[Sequence[str], Mapping[str, str], None] = None, force: bool = False) ‑> Optional[t9k.ah.core.Commit]

Commits changes to this branch.

First delete, then add.

Examples

Add a file as object to this branch:

branch.create_commit(msg='add ...', add=['model.pt'])

Specify a path in Asset for a file to add:

branch.create_commit(msg='add ...', add={'model.pt': 'saved_model/'})

Add all files under a directory as objects (with the directory):

branch.create_commit(msg='add ...', add=['./saved_model'])

Add all files under a directory as objects (without the directory):

branch.create_commit(msg='add ...', add=['./saved_model/*'])

Specify a path in Asset for a directory to add:

branch.create_commit(msg='add ...', add={'./saved_model': 'path/to/[saved_model]'})
## or
branch.create_commit(msg='add ...', add={'./saved_model': 'path/to/renamed_dir'})

Delete an object from this branch:

branch.create_commit(msg='delete ...', delete=['model.pt'])

Delete all objects under the specified path:

branch.create_commit(msg='delete ...', delete=['saved_model/'])
Args
  • msg (str)

    Commit message.

  • delete (Optional[Sequence[str]])

    Files or directories to delete from the branch, can be a sequence of paths in branch or None. If empty sequence or None, delete nothing. If the files or directories to delete do not exist, do nothing (rather than raise an error). Here format a/.../b signifies a file, while a/.../b/ signifies a directory.

  • add (Union[Sequence[str], Mapping[str, str], None])

    Files or directories to add to the branch, can be a sequence of local paths, a mapping from local paths to their paths in Asset, or None. If empty sequence, empty mapping or None, add nothing.

  • force (bool)

    Whether to create a new commit if unknown changes or unimplemented changes are found.

Returns

A Commit instance representing created commit if changes are commited, None if not.

create_tag

create_tag(self, name: str) ‑> t9k.ah.core.Tag

Creates a tag that points to this branch.

Args
  • name (str)

    Name of the tag.

Returns

A Tag instance representing created tag.

delete

delete(self) ‑> None

Deletes this branch.

download

download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None

Downloads objects of this branch.

Args
  • paths (Optional[Sequence[str]])

    Files or directories to download from this branch, is a sequence of paths in branch. Here format a/.../b signifies a file while a/.../b/ signifies a directory. Defaults to all objects.

  • save_dir (str)

    Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.

get_commit

get_commit(self, index: Optional[int] = None, id: Optional[str] = None) ‑> t9k.ah.core.Commit

Gets a commit of this branch.

If neither index or id is provided, return the last commit. If both index and id are provided, id will not be used.

Args
  • index (Optional[int])

    Index of the commit in this branch, 0 for the last commit, -1 for the first commit.

  • id (Optional[str])

    A prefix of ID of the commit.

Returns

A Commit instance representing retrieved commit.

list_commit

list_commit(self) ‑> List[Dict[str, Any]]

Lists commits of this branch.

list_object

list_object(self) ‑> List[Dict[str, Any]]

Lists objects of this branch.

merge

merge(self) ‑> None

Merges this branch to the main branch.

Here, the specific operation of "merge" involves deleting all objects from the main branch and then copying all objects from this branch to the main branch.

Note that this branch itself cannot be the main branch.

reset

reset(self) ‑> None

Resets this branch to clear all uncommitted changes.

t9k.ah.core.Commit

Commit(asset: Union[t9k.ah.core.Model, t9k.ah.core.Dataset], id_: str)

Represents a commit of Asset.

Attributes

  • path (str)

    Path of the commit.

  • asset (Union[t9k.ah.core.Model, t9k.ah.core.Dataset])

    A Model or Dataset instance corresponding to the Asset that the commit belongs to.

  • kind (str)

    A string 'commit'.

  • name (str)

    First 8 characters of ID of the commit.

  • id (str)

    ID of the commit.

  • alive (bool)

    Whether the commit is alive.

Ancestors

  • t9k.ah.core._Ref

Methods

create_tag

create_tag(self, name: str) ‑> t9k.ah.core.Tag

Creates a tag that points to this commit.

Args
  • name (str)

    Name of the tag.

Returns

A Tag instance representing created tag.

download

download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None

Downloads objects of this commit.

Args
  • paths (Optional[Sequence[str]])

    Files or directories to download from this commit, is a sequence of paths in commit. Here format a/.../b signifies a file while a/.../b/ signifies a directory. Defaults to all objects.

  • save_dir (str)

    Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.

list_commit

list_commit(self) ‑> List[Dict[str, Any]]

Lists commits of this commit.

list_object

list_object(self) ‑> List[Dict[str, Any]]

Lists objects of this commit.

t9k.ah.core.Dataset

Dataset(id_: str, folder: t9k.ah.core.Folder, name: str, labels: List[str], description: str, extra: str)

Represents a Dataset in server.

Attributes

  • path (str)

    Path of the Dataset in server.

  • id (str)

    ID of the Dataset in server.

  • folder (t9k.ah.core.Folder)

    A Folder instance corresponding to the Folder that the Dataset belongs to.

  • kind (str)

    A string 'Dataset'.

  • name (str)

    Name of the Dataset.

  • labels (List[str])

    Labels of the Dataset.

  • description (str)

    Description of the Dataset.

  • commit_id (str)

    ID of the commit that the main branch points to.

  • extra (str)

    Extra information about the Dataset.

  • alive (bool)

    Whether the Dataset is alive.

Ancestors

  • t9k.ah.core._Dataset

Methods

create_commit

create_commit(self, msg: str, delete: Optional[Sequence[str]] = None, add: Union[Sequence[str], Mapping[str, str], None] = None) ‑> Optional[t9k.ah.core.Commit]

Commits changes to this Dataset.

First delete, then add.

Examples

Add a file as object to this Dataset:

dataset.create_commit(msg='add ...', add=['0.png'])

Specify a path in Dataset for an object to add:

dataset.create_commit(msg='add ...', add={'0.png': 'data/'})

Add all files under a directory as objects:

dataset.create_commit(msg='add ...', add=['./data'])

Delete an object from this Dataset:

dataset.create_commit(msg='delete ...', delete=['0.png'])

Delete all objects under the specified path:

dataset.create_commit(msg='delete ...', delete=['data/'])
Args
  • msg (str)

    Commit message.

  • delete (Optional[Sequence[str]])

    Files or directories to delete from the Dataset, can be a sequence of paths in Dataset or None. If empty sequence or None, delete nothing. If the files or directories to delete do not exist, do nothing (rather than raise an error). Here format a/.../b signifies a file, while a/.../b/ signifies a directory.

  • add (Union[Sequence[str], Mapping[str, str], None])

    Files or directories to add to the Dataset, can be a sequence of local paths, a mapping from local paths to their paths in Dataset, or None. If empty sequence, empty mapping or None, add nothing.

Returns

A Commit instance representing created commit if changes are commited, None if not.

delete

delete(self) ‑> None

Deletes this Dataset.

download

download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None

Downloads objects of this Dataset.

Args
  • paths (Optional[Sequence[str]])

    Files or directories to download from this Dataset, is a sequence of paths in Dataset. Here format a/.../b signifies a file while a/.../b/ signifies a directory. Defaults to all objects.

  • save_dir (str)

    Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.

get_commit

get_commit(self, index: Optional[int] = None, id: Optional[str] = None) ‑> t9k.ah.core.Commit

Gets a commit of this Dataset.

If neither index or id is provided, return the last commit. If both index and id are provided, id will not be used.

Args
  • index (Optional[int])

    Index of the commit in this branch, 0 for the last commit, -1 for the first commit.

  • id (Optional[str])

    A prefix of ID of the commit.

Returns

A Commit instance representing retrieved commit.

get_tag

get_tag(self, name: str, verbose: bool = True) ‑> t9k.ah.core.Tag

Gets a tag of this Dataset.

Args
  • name (str)

    Name of the tag.

  • verbose (bool)

    Whether to log error.

Returns

A Tag instance representing retrieved tag.

list_branch

list_branch(self) ‑> List[Dict[str, Any]]

Lists branches in this Dataset.

list_commit

list_commit(self) ‑> List[Dict[str, Any]]

Lists commits of this Dataset.

list_object

list_object(self) ‑> List[Dict[str, Any]]

Lists objects of this Dataset.

list_tag

list_tag(self) ‑> List[Dict[str, Any]]

Lists tags of this Dataset.

update

update(self, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None

Updates the metadata of this Dataset.

If none of the args is provided, do nothing.

Args
  • name (Optional[str])

    New name of this Dataset.

  • labels (Optional[Sequence[str]])

    New labels of this Dataset.

  • description (Optional[str])

    New description of this Dataset.

t9k.ah.core.Folder

Folder(path: str, id_: str, owner: str, asset_kind: str, name: str, labels: List[str], description: str, extra: str)

Represents a Asset Hub Folder in server.

Attributes

  • path (str)

    Path of the Folder.

  • id (str)

    ID of the Folder in server.

  • owner (str)

    Owner of the Folder.

  • kind (str)

    Kind of the Folder, is a string 'Model' or 'Dataset'.

  • name (str)

    Name of the Folder.

  • labels (List[str])

    Labels of the Folder.

  • description (str)

    Description of the Folder.

  • extra (str)

    Extra information about the Folder.

  • alive (bool)

    Whether the Folder is alive.

Methods

create_asset

create_asset(self, name: str, labels: Optional[Sequence[str]] = None, description: str = '', exist_ok: bool = False) ‑> Union[t9k.ah.core.Model, t9k.ah.core.Dataset]

Creates an Asset in this Folder.

Args
  • name (str)

    Name of the Asset.

  • labels (Optional[Sequence[str]])

    Labels of the Asset.

  • description (str)

    Description of the Asset.

  • exist_ok (bool)

    If True and Asset with name already exists, return a Model or Dataset instance representing this Asset; if False and Asset exists, raise a RuntimeError.

Returns

A Model or Dataset instance representing created Model or Dataset, depending on Asset kind of this Folder.

delete

delete(self) ‑> None

Deletes this Folder.

get_asset

get_asset(self, name: str) ‑> Union[t9k.ah.core.Model, t9k.ah.core.Dataset]

Gets an Asset in this Folder.

If you want to get Asset directly by its path, use ah.get_asset().

Args
  • name (str)

    Name of the Asset.

Returns

A Model or Dataset instance representing retrieved Model or Dataset, depending on Asset kind of this Folder.

list_asset

list_asset(self) ‑> List[Dict[str, Any]]

Lists Assets in this Folder.

update

update(self, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None

Updates the metadata of this Folder.

If none of the args is provided, do nothing.

Args
  • name (Optional[str])

    New name of this Folder.

  • labels (Optional[Sequence[str]])

    New labels of this Folder.

  • description (Optional[str])

    New description of this Folder.

t9k.ah.core.Model

Model(id_: str, folder: t9k.ah.core.Folder, name: str, labels: List[str], description: str, extra: str)

Represents a Model in server.

Attributes

  • path (str)

    Path of the Model in server.

  • id (str)

    ID of the Model in server.

  • folder (t9k.ah.core.Folder)

    A Folder instance corresponding to the Folder that the Model belongs to.

  • kind (str)

    A string 'Model'.

  • name (str)

    Name of the Model.

  • labels (List[str])

    Labels of the Model.

  • description (str)

    Description of the Model.

  • extra (str)

    Extra information about the Model.

  • alive (bool)

    Whether the Model is alive.

Ancestors

  • t9k.ah.core._Model

Methods

create_branch

create_branch(self, name: str) ‑> t9k.ah.core.Branch

Creates an empty branch of this Model.

Args
  • name (str)

    Name of the branch.

Returns

A Branch instance representing created branch.

delete

delete(self) ‑> None

Deletes this Model.

download

download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None

Downloads objects of this Model.

Args
  • paths (Optional[Sequence[str]])

    Files or directories to download from this Dataset, is a sequence of paths in Dataset. Here format a/.../b signifies a file while a/.../b/ signifies a directory. Defaults to all objects.

  • save_dir (str)

    Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.

get_branch

get_branch(self, name: str, verbose: bool = True) ‑> t9k.ah.core.Branch

Gets a branch of this Model.

Args
  • name (str)

    Name of the branch.

  • verbose (bool)

    Whether to log error.

Returns

A Branch instance representing retrieved branch.

get_commit

get_commit(self, id: str) ‑> t9k.ah.core.Commit

Gets a commit of this Model.

If no commit matches id, or two or more commits matche id, raise a RuntimeError.

Args
  • id (str)

    A prefix of ID of the commit.

Returns

A Commit instance representing retrieved commit.

get_tag

get_tag(self, name: str, verbose: bool = True) ‑> t9k.ah.core.Tag

Gets a tag of this Model.

Args
  • name (str)

    Name of the tag.

  • verbose (bool)

    Whether to log error.

Returns

A Tag instance representing retrieved tag.

list_branch

list_branch(self) ‑> List[Dict[str, Any]]

Lists branches in this Model.

list_object

list_object(self) ‑> List[Dict[str, Any]]

Lists objects of this Model.

list_tag

list_tag(self) ‑> List[Dict[str, Any]]

Lists tags of this Model.

update

update(self, name: Optional[str] = None, labels: Optional[Sequence[str]] = None, description: Optional[str] = None) ‑> None

Updates the metadata of this Model.

If none of the args is provided, do nothing.

Args
  • name (Optional[str])

    New name of this Model.

  • labels (Optional[Sequence[str]])

    New labels of this Model.

  • description (Optional[str])

    New description of this Model.

t9k.ah.core.Tag

Tag(asset: Union[t9k.ah.core.Model, t9k.ah.core.Dataset], name: str, commit_id: str)

Represents a tag of Asset.

Attributes

  • path (str)

    Path of the tag.

  • asset (Union[t9k.ah.core.Model, t9k.ah.core.Dataset])

    A Model or Dataset instance corresponding to the Asset that the tag belongs to.

  • kind (str)

    A string 'tag'.

  • name (str)

    Name of the tag.

  • commit_id (str)

    ID of the commit that the tag points to.

  • alive (bool)

    Whether the tag is alive.

Ancestors

  • t9k.ah.core._Ref

Methods

create_tag

create_tag(self, name: str) ‑> t9k.ah.core.Tag

Creates another tag that points to this tag.

Args
  • name (str)

    Name of the tag.

Returns

A Tag instance representing created tag.

delete

delete(self) ‑> None

Deletes this tag.

download

download(self, paths: Optional[Sequence[str]] = None, save_dir: str = '.') ‑> None

Downloads objects of this tag.

Args
  • paths (Optional[Sequence[str]])

    Files or directories to download from this tag, is a sequence of paths in tag. Here format a/.../b signifies a file while a/.../b/ signifies a directory. Defaults to all objects.

  • save_dir (str)

    Local directory which objects are downloaded to. If the directory does not exist, create it. Defaults to current working directory.

list_commit

list_commit(self) ‑> List[Dict[str, Any]]

Lists commits of this tag.

list_object

list_object(self) ‑> List[Dict[str, Any]]

Lists objects of this tag.

t9k.config

t9k.config.Config

Config()

SDK config.

Methods

get

get(self, key: str, default: Any = None) ‑> Any

items

items(self) ‑> ItemsView[str, Any]

to_dict

to_dict(self) ‑> Dict[str, Any]

update

update(self, new_config: Dict[str, Any]) ‑> None

t9k.config.ConfigItem

ConfigItem(name: str, value: Optional[Any] = None, processor: Union[Callable, Sequence[Callable], None] = None, validator: Union[Callable, Sequence[Callable], None] = None, hook: Union[Callable, Sequence[Callable], None] = None)

SDK config item.

Attributes

  • name (str)

    Name of config item.

  • value (Any)

    Value of config item.

t9k.em

t9k.em.artifact.Artifact

Artifact(metadata: Dict[str, Any], objects: Optional[Dict[str, Dict[str, Any]]] = None)

Implementation of Artifact, a set of files that a Run inputs or outputs.

Args

  • metadata (Dict[str, Any])

    Metadata to initialize a new Artifact.

  • objects (Optional[Dict[str, Dict[str, Any]]])

    Data of objects of the Artifact.

Attributes

  • name (str)

    Name of the Artifact.

  • labels (List[str])

    Labels of the Artifact.

  • description (str)

    Description of the Artifact.

  • created_timestamp (str)

    Created timestamp of the Artifact.

  • alternative_name (str)

    Alternative name of the Artifact.

  • objects (List[Dict[str, str]])

    Data of objects of the Artifact.

  • remote (List[Dict[str, str]])

    Upload and download history of the Artifact.

  • local (str)

    Local directory of the Artifact.

Methods

add_dir

add_dir(self, dir_path: str, obj_path: Optional[str] = None) ‑> None

Adds all files under a local directory as objects of the Artifact.

The directory will be copied to local directory of the Artifact, the specific subpath depends on its obj_path, for example:

# dir copied to `<local-dir>/a`
artifact.add_dir(dir_path='a/')
# or
artifact.add_dir(dir_path='a')
# or
artifact.add_dir(dir_path='a/', obj_path='a')

# dir copied to `<local-dir>/b/a`
artifact.add_dir(dir_path='a/', obj_path='b/')
# or
artifact.add_dir(dir_path='a/', obj_path='b/a')

add_file

add_file(self, file_path: str, obj_path: Optional[str] = None) ‑> None

Adds a local file as an object of the Artifact.

The file will be copied to local directory of the Artifact, the specific subpath depends on its object path, for example:

# file copied to `<local-dir>/1.png`
artifact.add_file(file_path='1.png')
# or
artifact.add_file(file_path='1.png', obj_path='1.png')

# file copied to `<local-dir>/a/1.png`
artifact.add_file(file_path='1.png', obj_path='a/')
# or
artifact.add_file(file_path='1.png', obj_path='a/1.png')

add_reference

add_reference(self, uri: str, obj_path: Optional[str] = None) ‑> None

Adds a URI as an object reference to the Artifact.

parse_from_dict

parse_from_dict(self, data: Dict[str, Any]) ‑> None

Parses an Artifact instance from a dict.

to_dict

to_dict(self) ‑> Dict[str, Any]

Converts Artifact instance to a dict and returns it.

upload

upload(self, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> None

Uploads this Artifact to server.

Args
  • folder (str)

    Path of the Folder to which the Artifact is uploaded. If the provided path does not start with '/', /<current-user>/ is prepended to it.

  • make_folder (bool)

    If True and Folder with path folder does not exist, make the Folder and parent Folders as needed.

  • conflict_strategy (str)

    Strategy adopted when an Artifact with the same name as the Artifact to be uploaded already exists in the Folder, must be 'skip', 'error', 'new' or 'replace'. If 'skip', skip the upload; if 'error', error out; if 'new', upload with the alternative name of Artifact; if 'replace', delete the existing Artifact and upload.

t9k.em.containers.Params

Params(upload: Callable, init_hparams: Dict[str, Union[str, int, float, bool, None, List[~T], Tuple[], Dict[~KT, ~VT]]] = None)

Container class to hold hyperparameters of Run.

It is recommended to set all hyperparameters by calling update method once before building the model. Nevertheless, you are free to operate hyperparameters like items of a dict or attributes of an object.

Examples

Recommended method of setting hyperparameters:

run.update({
    'batch_size': 32,
    'epochs': 10,
})

Assign parameter like an item of dict or attribute of object:

run.params['batch_size'] = 32
run.params.epochs = 10

Args

  • upload (Callable)

    Function that is called to upload hyperparameters every time hyperparameters are updated.

  • init_hparams (Dict[str, Union[str, int, float, bool, None, List[~T], Tuple[], Dict[~KT, ~VT]]])

    Initial hyperparameters.

Ancestors

  • collections.abc.MutableMapping

Methods

as_dict

as_dict(self)

items

items(self)

D.items() -> a set-like object providing a view on D's items

keys

keys(self)

D.keys() -> a set-like object providing a view on D's keys

parse

parse(self, dist_tf_strategy=None, dist_torch_model=None, dist_hvd=None)

Parses hyperparameters from various objects of various frameworks.

Args
  • dist_tf_strategy

    TensorFlow distribution strategy instance if tf.distribute is used for distributed training.

  • dist_torch_model

    PyTorch model wrapped with DP or DDP if torch.distributed is used for distributed training.

  • dist_hvd

    Used module such as horovod.keras and horovod.torch if Horovod is used for distributed training.

update

update(self, new_params: Dict[str, Any], override: bool = True)

Updates with new params.

Args
  • new_params (Dict[str, Any])

    New params to be updated with.

  • override (bool)

    Whether to override current params.

values

values(self)

D.values() -> an object providing a view on D's values

t9k.em.create_artifact

create_artifact(name: str, labels: Optional[Sequence[str]] = None, description: str = '') ‑> t9k.em.artifact.Artifact

Creates and initializes a new Artifact.

The local files of Artifact are placed under the parent directory specified by the environment variable EM_ARTIFACT_PARENT_DIR (default is relative path .em/artifacts).

Examples

tensorboard_artifact = em.create_artifact(name='tensorboard_logs')

Args

  • name (str)

    Name of the Artifact.

  • labels (Optional[Sequence[str]])

    Labels of the Artifact.

  • description (str)

    Description of the Artifact.

Returns

An Artifact instance created and initialized.

t9k.em.create_run

create_run(config_path: Optional[str] = None, name: str = 'default', hparams: Optional[Dict[str, Any]] = None, labels: Optional[Sequence[str]] = None, description: str = '', auto_upload: bool = False, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> t9k.em.run.Run

Creates and initializes a new Run.

The local files of Run are placed under the parent directory specified by the environment variable EM_RUN_PARENT_DIR (default is relative path .em/runs).

Examples

Basic usage:

from t9k import em

run = em.create_run(name='cnn_keras',
                    folder='cv/image-classification/mnist')

Provide initial parameters of Run:

hparams = {
    'batch_size': 32,
    'epochs': 1,
    'learning_rate': 0.001,
    'conv_channels1': 32,
    'conv_channels2': 64,
    'conv_channels3': 64,
    'conv_kernel_size': 3,
    'maxpool_size': 2,
    'linear_features1': 64,
}

run = em.create_run(name='cnn_keras',
                    hparams=hparams,
                    folder_path='cv/image-classification/mnist')

Provide a Run config file:

run = em.create_run(config_path='./run_config.yaml')

where the config file run_config.yaml is like:

name: cnn_keras
hparams:
  batch_size: 32
  epochs: 1
  learning_rate: 0.001
  conv_channels1: 32
  conv_channels2: 64
  conv_channels3: 64
  conv_kernel_size: 3
  maxpool_size: 2
  linear_features1: 64
labels:
- Keras
description: Train a simple CNN model that classifies images of handwritten digits.

Args

  • config_path (Optional[str])

    Local path of the Run config file. For all of the following args, the values parsed from the config file take precedence over values passed in.

  • name (str)

    Name of the Run.

  • hparams (Optional[Dict[str, Any]])

    Initial hyperparameters of the Run.

  • labels (Optional[Sequence[str]])

    Labels of the Run.

  • description (str)

    Description of the Run.

  • auto_upload (bool)

    Whether to upload the Run and its data automatically and asynchronously. If False, all of the following args will not be used.

  • folder (str)

    Path of the Folder to which the Run is uploaded. If the provided path does not start with '/', /<current-user>/ is prepended to it. If auto_upload is False, this arg will not be used.

  • make_folder (bool)

    If True and Folder with path folder does not exist, make the Folder and parent Folders as needed. If auto_upload is False, this arg will not be used.

  • conflict_strategy (str)

    Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be 'skip', 'error', 'new' or 'replace'. If 'skip', skip the upload; if 'error', error out; if 'new', upload with the alternative name of Run; if 'replace', delete the existing Run and upload. If auto_upload is False, this arg will not be used.

Returns

A Run instance created and initialized.

t9k.em.load_artifact

load_artifact(path: str) ‑> t9k.em.artifact.Artifact

Loads an Artifact from local or server.

This function will first search for the corresponding local directory, followed by remote path. If the path is not found in either location, raise a RuntimeError.

In the case of the remote path, if the provided path does not start with '/', /<current-user>/ is prepended to it.

Examples

Load by local path:

em.load_artifact(path=
    '.em/artifacts/tensorboard_logs_220823_194728_4e48t2')

Load by remote path:

em.load_artifact(path='/user/path/to/tensorboard_logs')

Args

  • path (str)

    Local directory of the Artifact, or path of the Artifact in server.

Returns

An Artifact instance loaded.

t9k.em.load_run

load_run(path: str, auto_upload: bool = False, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> t9k.em.run.Run

Loads a Run from local or server.

This function will first search for the corresponding local path, followed by remote path. If the path is not found in either location, raise a RuntimeError.

In the case of the remote path, if the provided path does not start with '/', /<current-user>/ is prepended to it.

Examples

Load by local path:

em.load_run(path='.em/runs/cnn_keras_220823_194728_4e48t2')

Load by remote path:

em.load_run(path='/user/path/to/cnn_keras')

Args

  • path (str)

    Local directory of the Run, or path of the Run in server.

  • auto_upload (bool)

    Whether to upload the Run and its data automatically and asynchronously. If False, all of the following args will not be used.

  • folder (str)

    Path of the Folder to which the Run is uploaded. If the provided path does not start with '/', /<current-user>/ is prepended to it. If auto_upload is False, this arg will not be used.

  • make_folder (bool)

    If True and Folder with path folder does not exist, make the Folder and parent Folders as needed. If auto_upload is False, this arg will not be used.

  • conflict_strategy (str)

    Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be 'skip', 'error', 'new' or 'replace'. If 'skip', skip the upload; if 'error', error out; if 'new', upload with the alternative name of Run; if 'replace', delete the existing Run and upload. If auto_upload is False, this arg will not be used.

Returns

A Run instance loaded.

t9k.em.login

login(ais_host: Optional[str] = None, api_key: Optional[str] = None, timeout: Optional[int] = None) ‑> None

Logs in to AIStore server.

Sets up the client that corresponds with AIStore server.

Args

  • ais_host (Optional[str])

    URL of AIStore server. Defaults to t9k.CONFIG['aistore_host'].

  • api_key (Optional[str])

    API Key for requesting server. Defaults to t9k.CONFIG['api_key'].

  • timeout (Optional[int])

    How many seconds to wait for server to send data before giving up.

Raises

  • requests.HTTPError

    Unable to connect to the server and unable_to_connect_ok is False.

t9k.em.logout

logout() ‑> None

Logs out from the current AIStore server.

The client is unset, it can no longer correspond with AIStore server until it is set up again.

t9k.em.run.Run

Run(metadata: Dict[str, Any], hparams: Optional[Dict[str, Any]] = None, metrics: Optional[Dict[str, List[Dict[str, Dict[str, Union[str, int, float]]]]]] = None, platform: Optional[Dict[str, Any]] = None, git: Optional[Dict[str, Any]] = None)

Implementation of Run, a run of a specific model for certain ML task.

Args

  • metadata (Dict[str, Any])

    Metadata to initialize a new Run.

  • hparams (Optional[Dict[str, Any]])

    Hyperparameters of the Run.

  • metrics (Optional[Dict[str, List[Dict[str, Dict[str, Union[str, int, float]]]]]])

    Metrics of the Run.

  • platform (Optional[Dict[str, Any]])

    Platform information of the Run.

  • git (Optional[Dict[str, Any]])

    Git information of the Run.

Attributes

  • name (str)

    Name of the Run.

  • labels (List[str])

    Labels of the Run.

  • description (str)

    Description of the Run.

  • start_timestamp (str)

    Start timestamp of the Run.

  • end_timestamp (str)

    End timestamp of the Run.

  • status (str)

    Status of the Run.

  • alternative_name (str)

    Alternative name of the Run.

  • associations (Dict[str, List[Dict[str, str]]])

    Input and output resources of the Run.

  • hparams (Any)

    Hyperparameters of the Run.

  • metrics (Dict[str, List[Dict[str, Dict[str, Union[str, int, float]]]]])

    Metrics produced in the Run.

  • platform (Dict[str, Any])

    Platform information of the Run.

  • git (Dict[str, Any])

    Git information of the Run.

  • remote (List[Dict[str, str]])

    Upload and download history of the Run.

  • local (str)

    Local directory of the Run.

Methods

finish

finish(*args, **kwargs)

log

log(self, type: str, metrics: Dict[str, float], step: int, epoch: Optional[int] = None) ‑> None

Logs a set of metrics of Run.

Args
  • type (str)

    Type of the metrics, 'train' (or 'training'), 'val' (or 'validate', 'validation') and 'test' (or 'testing', 'eval', 'evaluate', 'evaluation') for training, validation and testing metrics respectively. Besides, you can also use other arbitrary string as custom type of the metrics.

  • metrics (Dict[str, float])

    Additional metrics to be logged.

  • step (int)

    Number of the step that the metrics belong to.

  • epoch (Optional[int])

    Number of the epoch that the metrics belong to.

mark_input

mark_input(self, resource: Union[t9k.em.artifact.Artifact, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag, t9k.ah.core.Commit]) ‑> None

Marks an Artifact, Model or Dataset as an input of this Run.

mark_output

mark_output(self, resource: Union[t9k.em.artifact.Artifact, t9k.ah.core.Model, t9k.ah.core.Dataset, t9k.ah.core.Branch, t9k.ah.core.Tag, t9k.ah.core.Commit]) ‑> None

Marks an Artifact, Model or Dataset as an output of this Run.

parse_from_dict

parse_from_dict(self, data: Dict[str, Any]) ‑> None

Parses a Run instance from a dict.

to_dict

to_dict(self) ‑> Dict[str, Any]

Converts Run instance to a dict and returns it.

upload

upload(self, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> None

Uploads this Run to server.

If this Run has input or output Artifacts, these Artifacts are uploaded as well if they have not been uploaded, and these associations are uploaded.

Args
  • folder (str)

    Path of the Folder to which the Run is uploaded. If the provided path does not start with '/', /<current-user>/ is prepended to it.

  • make_folder (bool)

    If True and Folder with path folder does not exist, make the Folder and parent Folders as needed.

  • conflict_strategy (str)

    Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be 'skip', 'error', 'new' or 'replace'. If 'skip', skip the upload; if 'error', error out; if 'new', upload with the alternative name of Run; if 'replace', delete the existing Run and upload.

t9k.em.upload

upload(path: str, folder: str = 'default', make_folder: bool = False, conflict_strategy: str = 'new') ‑> None

Upload local Runs or Artifacts.

Examples

Upload a Run by its local directory:

em.upload(path='.em/runs/cnn_keras_220823_194728_4e48t2')

Upload all Artifact under the parent directory:

em.upload(path='.em/artifacts')

Specify the path of Folder to which the Run is uploaded:

em.upload(path='.em/runs/cnn_keras_220823_194728_4e48t2',
              folder='image_classification/mnist')

Args

  • path (str)

    Local directory of the Run to be uploaded, or parent directory that contains one or more Runs.

  • folder (str)

    Path of the Folder to which the Run is uploaded. If the provided path does not start with '/', /<current-user>/ is prepended to it.

  • make_folder (bool)

    If True and Folder with path folder does not exist, make the Folder and parent Folders as needed.

  • conflict_strategy (str)

    Strategy adopted when a Run with the same name as the Run to be uploaded already exists in the Folder, must be 'skip', 'error', 'new' or 'replace'. If 'skip', skip the upload; if 'error', error out; if 'new', upload with the alternative name of Run; if 'replace', delete the existing Run and upload.

t9k.tuner

t9k.tuner.get_current_parameter

get_current_parameter(tag: Optional[str] = None)

Gets current hyper parameters generated by tuner. It returns the same group of hyper parameters as the last call of get_next_parameter returns.

Args

  • tag (Optional[str])

    hyper parameter key.

t9k.tuner.get_experiment_id

get_experiment_id()

Gets experiment ID.

Returns

Identifier of current experiment.

t9k.tuner.get_next_parameter

get_next_parameter()

Gets the hyper paremeters generated by tuner. For a multiphase experiment, it returns a new group of hyper parameters at each call of get_next_parameter. For a non-multiphase (multiPhase is not configured or set to False) experiment, it returns hyper parameters only on the first call for each trial job, it returns None since second call. This API should be called only once in each trial job of an experiment which is not specified as multiphase.

Returns

A dict object contains the hyper parameters generated by tuner, the keys of the dict are defined in search space. Returns None if no more hyper parameters can be generated by tuner.

t9k.tuner.get_sequence_id

get_sequence_id()

Gets trial job sequence nubmer. A sequence number is an integer value assigned to each trial job base on the order they are submitted, incremental starting from 0. In one experiment, both trial job ID and sequence number are unique for each trial job, they are of different data types.

Returns

Sequence number of current trial job which is calling this API.

t9k.tuner.get_trial_id

get_trial_id()

Gets trial job ID which is string identifier of a trial job, for example 'MoXrp'. In one experiment, each trial job has an unique string ID.

Returns

Identifier of current trial job which is calling this API.

t9k.tuner.report_final_result

report_final_result(metric: Any)

Reports final result to TUNER.

Args

  • metric (Any)

    Usually (for built-in tuners to work), it should be a number, or a dict with key "default" (a number), and any other extra keys.

t9k.tuner.report_intermediate_result

report_intermediate_result(metric: Any, step: int)

Reports intermediate result to TUNER.

Args

  • metric (Any)

    serializable object.

Codepack

Codepack 以简洁明了的形式定义在平台上开发、运行、部署一个机器学习项目所需要的全部信息,例如代码、配置文件、各种参数等。其相关工具能够根据这些信息自动地执行相应的操作,从而大幅减少用户的操作量,显著改善实验的可重复性。

例如对于 MNIST 手写数字图像分类任务,在已经准备好了训练代码、数据集和资源配置文件的情况下,你只需要再创建一个 Codepack 定义文件,然后使用 Codepack CLI 执行一条命令,就可以在平台上启动分布式训练:

这里 Codepack 定义文件的内容如下:

apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
default: prepare-env
targets:
  - name: prepare-env        # Prepare running env
    actions:
      - name: workspace-for-training
        verb: apply
        files: [pvc.yaml]
  - name: copy-file          # Copy training code and dataset to PVC
    deps: ["prepare-env"]
    actions:
      - name: copy-code
        verb: copy
        src: .
        dst: codepack-example:.
  - name: run-distributed-training    # Run a distributed training
    deps: ["prepare-env", "copy-file"]
    actions:
      - name: trainingjob
        verb: create
        files: [trainingjob.yaml]

整个 Codepack 的文件结构如下:

mnist-keras
├── codepack.yaml
├── main.py
├── mnist.npz
├── pvc.yaml
└── trainingjob.yaml

由于 Codepack 的全部信息都维护在一个定义文件中,用户创建一个新的 Codepack 或者将既有的机器学习项目修改为 Codepack 都非常容易,并且用户可以使用 Git 来轻松地对 Codepack 进行版本控制和分发。

Codepack 的相关工具包括命令行工具和集群内组件,前者负责读取 Codepack 定义并执行用户指定的 action,后者负责进行安全访问控制以及为命令行工具执行 action 提供支持。

下一步

概念

Codepack

Codepack 是对用户想要在平台上运行的机器学习项目的抽象,其实质上是一个包含项目文件(模型代码、资源配置文件等)以及 Codepack 定义文件的文件系统的目录,该定义文件包含了 Codepack 的基本信息(版本、名称、描述等)和运行信息(target 和 action 的定义),见 Codepack 定义

target

target 是对 Codepack 的一个具体任务的抽象,例如在平台上完成模型训练、部署模型为推理服务等。每个 target 可以指定其依赖的其他 target(例如创建推理服务需要先完成模型训练),命令行工具在运行一个 target 时,将递归地解析依赖,然后运行一个工作流。

action

action 是对 target 的一个具体的可执行的操作的抽象,例如在平台中创建一个 PVC、创建一个进行分布式训练的 TrainingJob 等。action 定义了多个动词(verb),每个动词针对某一类的具体操作,由命令行工具和集群内组件提供实现。

Codepack 定义

一个包含机器学习代码及相关文件的文件系统目录,加上 Codepack 的定义文件就构成了一个 Codepack。Codepack 定义文件是一个通常名为 codepack.yaml 的 YAML 文件,其包含 Codepack 的版本、名称、描述等基本信息以及 target 定义、action 定义等运行相关的信息。

下面将具体介绍 Codepack 定义文件中的各个字段以及它们的作用,从而指导用户如何创建一个 Codepack。

创建 Codepack 定义文件

下面是一个基本的 Codepack 定义文件的示例:

apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
targets:
  - name: prepare-env    # target definition
    actions:
      - name: workspace-for-training    # action definition
        verb: apply
        files: [pvc.yaml]
      - name: copy-code
        verb: copy
        src: .
        dst: codepack-pvc:.

在该例中:

  • 指定 Codepack 的版本、名称和详细描述(分别由 apiVersionnamedescription 字段指定)。
  • targets 字段定义一个 target,这个 target 又通过 actions 字段定义两个 action。这里 target 的 name 字段是必需的;action 的 name 字段不是必需的,但 verb 字段以及相应动词需要提供的字段是必需的(请参阅 action 动词)。

指定默认项目和 target

可以通过 projectdefault 字段指定 Codepack 的默认项目和 target,这样在使用命令行工具运行 Codepack 时如果不提供相应的参数,则会使用这些默认值。

apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo           # default project to run in
default: prepare-env    # default target to run
targets:
  - name: prepare-env
    actions:
      - name: workspace-for-training
        verb: apply
        files: [pvc.yaml]
      - name: copy-code
        verb: copy
        src: .
        dst: codepack-pvc:.

工作流机制

target 是对 Codepack 的一个具体任务的抽象,多个 target 之间可能存在依赖关系,例如负责从本地复制文件到 PVC 的 target 需要依赖负责创建 PVC 的 target 运行完毕。每一个 target 可以通过 deps 字段传入一个 target 名称列表来指定其依赖的其他 target。

在使用命令行工具运行某一个 target 时,命令行工具会递归地解析所有依赖的 target,动态地构建一个有向无环图,然后串行或者并行地运行图中当前没有依赖或依赖已经运行完毕的 target,直到所有 target 全部运行。

利用工作流机制,可以将上面示例中的 target prepare-env 拆分为具有依赖关系的两个 target,并且在此基础上再创建一个依赖它们的负责启动分布式训练的 target。

apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
default: prepare-env
targets:
  - name: prepare-env        # Prepare running env
    actions:
      - name: workspace-for-training
        verb: apply
        files: [pvc.yaml]
  - name: copy-file          # Copy the Codepack to PVC
    deps: ["prepare-env"]
    actions:
      - name: copy-code
        verb: copy
        src: .
        dst: codepack-pvc:.
  - name: run-distributed-training    # Run a distributed training
    deps: ["prepare-env", "copy-file"]
    actions:
      - name: trainingjob
        verb: create
        files: [trainingjob.yaml]

action 动词

action 的动词通过 verb 字段指定,表示其操作类型,目前定义了下列值。

apply

应用配置到资源,类似于 kubectl apply。若同名资源已经存在,则更新其配置,否则创建该资源。

需要提供以下字段:

  • files:定义资源的 YAML 配置文件的路径、文件路径的列表或者包含 YAML 配置文件的目录的路径。

示例:

actions:
  - name: workspace-for-training
    verb: apply
    files: [pvc.yaml]

copy

将文件或目录从源位置复制到目标位置,具体实现取决于源和目标的类型:

  1. 若都为本地路径,则直接在本地进行 rsync 操作。
  2. 若一个为本地路径,一个为 PVC 路径,则在集群中创建一个挂载这个 PVC 并且运行 sshd 服务的 Pod,在本地进行远程 rsync 操作。
  3. 若都为 PVC 路径,则在集群中创建一个挂载这两个 PVC 的 Pod,在 Pod 中进行 rsync 操作。

需要提供以下字段:

  • src:文件或目录的源位置,可以是本地路径或 PVC 路径,格式如下:

    • 本地路径:

      • .(Codepack 的全部文件)
      • ./data(Codepack 的子目录)
      • ./data/(Codepack 的子目录下的全部文件)
      • ./train.py(Codepack 的文件)
    • PVC 路径:

      • <pvc-name>:.(PVC 的根目录)
      • <pvc-name>:data(PVC 的子目录)
      • <pvc-name>:data/(PVC 的子目录下的全部文件)
      • <pvc-name>:data/mnist.npz(PVC 的文件)
  • dst:文件或目录的目标位置,可以是本地路径或 PVC 路径,格式同上。

示例:

actions:
  - name: copy-code
    verb: copy
    src: .
    dst: codepack-pvc:.

create

创建资源,类似于 kubectl create。若同名资源已经存在,则错误退出,或为名称添加随机后缀再进行创建。

需要提供以下字段:

  • files:定义资源的 YAML 配置文件的路径、文件路径的列表或者包含 YAML 配置文件的目录的路径。
  • new:若为 True,并且同名资源已经存在,则为名称添加随机后缀再进行创建;若为 False 则错误退出。默认为 True。

示例:

actions:
  - name: trainingjob
    verb: create
    files: [trainingjob.yaml]

命令行工具

Codepack CLI(命令行工具)用于在命令行终端中运行 Codepack。

安装

前置条件

Codepack CLI 使用 Python 3 编写,在安装之前请确保你的本地环境安装了 3.6 或以上版本的 Python 以及 pip 工具。

为使 Codepack CLI 提供的文件复制功能正常运行,还需要安装 3.1.0 及以上版本的 rsync。macOS 执行以下命令安装:

brew install rsync

基于 Debian 的 Linux 发行版执行以下命令安装:

apt-get install rsync

基于 rpm 的 Linux 发行版执行以下命令安装:

yum install rsync

然后你可以执行以下命令来验证安装完成,并且确认安装的 rsync 版本。

rsync --version

安装

目前 TensorStack SDK 仅提供用于本地安装的 Python 包,你可以从平台首页下载。

然后使用以下命令进行安装:

pip install codepack-<version>.tar.gz [-i <pypi-mirror-url>]

命令

check

检查 Codepack 的有效性。

使用

codepack check [CODEPACK_PATH]

CODEPACK_PATH    Codepack 或 Codepack 定义文件的路径, 默认为当前路径

示例

$ codepack check examples/mnist-keras
Checked, no errors found in codepack mnist-keras

config

查看、修改 Codepack CLI 的配置。

Codepack CLI 各项配置的含义如下:

配置项含义默认值
api_key用于身份验证的 API KeyNone
copy_pod_imagecopy 动词创建的 Pod 所使用的镜像None

使用

$ codepack config [--list] [--get KEY] [--set KEY=VALUE]

--list, -l             列出所有 CLI 配置项
--get=KEY, -g          获取 CLI 配置项
--set=KEY=VALUE, -s    设置 CLI 配置项

示例

$ codepack config --list
api_key=None
copy_pod_image=t9kpublic/sshd-rsync:0.0.0.6

$ codepack config --get api_key
api_key=None

$ codepack config --set api_key=5b398842-7c92-4922-a472-c905553beefd
api_key=5b398842-7c92-4922-a472-c905553beefd
config items set

$ codepack config --get api_key
api_key=5b398842-7c92-4922-a472-c905553beefd

describe

查看 Codepack 的详细信息。

使用

codepack describe [CODEPACK_PATH]

CODEPACK_PATH    Codepack 或 Codepack 定义文件的路径, 默认为当前路径

示例

$ codepack describe examples/mnist-keras 
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
targets:
  - prepare-env
  - copy-file
  - create-notebook
  - run-distributed-training
  - run-e2e-workflow

run

运行 Codepack 的指定 target。

使用

codepack run [--project PROJECT_NAME] [--target TARGET_NAME] [--verbose] [--wait-timeout INTEGER] [CODEPACK_PATH]

--project=PROJECT_NAME, -p    项目名称, 运行在该项目下
--target=TARGET_NAME, -t      target 名称, 运行该 target
--verbose, -v                 打印更多信息
--wait-timeout=INT, -W        设定以秒为单位的 Pod 超时等待时间
CODEPACK_PATH                 Codepack 或 Codepack 定义文件的路径, 默认为当前路径

示例

$ codepack run examples/mnist-keras -t run-distributed-training -p demo
RUN target run-distributed-training of codepack mnist-keras in project demo
Running sequence: prepare-env -> copy-file -> run-distributed-training

Target 1/3: prepare-env
APPLY by files ['pvc.yaml']
PersistentVolumeClaim with the name codepack-example already exists, skip
Target 2/3: copy-file
COPY from . to codepack-example:.
copied
Target 3/3: run-distributed-training
CREATE by files ['trainingjob.yaml']
TensorFlowTrainingJob codepack-example created

配置

配置文件

Codepack CLI 没有单独的配置文件,而是使用 TensorStack CLI 的配置文件。在执行 codepack 命令时,会自动读取位于路径 ~/.t9k/t9k-config.yaml 的配置文件(如果设置了环境变量 T9K_CONFIG,则读取其值给出的路径)。如果配置文件不存在或缺少部分配置项,则缺少的这些配置项会被设置为 None,这可能导致 Codepack CLI 的部分功能不能正常工作。

扩展配置

配置文件中的 contexts[*].extension.codepack 字段是 Codepack CLI 的扩展配置,其包含以下字段:

字段功能
copy-pod-image用于复制文件的 Pod 使用的镜像

查看配置

使用 codepack config -l 命令以查看所有配置项的值。

身份验证

Codepack CLI 支持下列身份验证方式,你可以选择其中的一种进行相应的配置。

平台内运行(incluster)

用户需要在平台资源内(平台所在 Kubernetes 集群的 Pod 内)使用 Codepack CLI,例如在 Notebook 的终端中使用。

注意在运行 target 时只能指定当前项目(不指定则默认为当前项目)。

在此方式下,Codepack CLI 直接利用 Kubernetes 提供给 Pod 的 Service Account 向 kube-apiserver 发送请求以执行各 action。

kubeconfig 文件

用户需要持有平台所在 Kubernetes 集群的 kubeconfig 文件,并将其放置在路径 ~/.kube/config 下(如果设置了环境变量 KUBECONFIG,则放置在其值给出的路径下)。

在此方式下,Codepack CLI 直接利用 kubeconfig 文件向 kube-apiserver 发送请求以执行各 action。

t9kconfig 文件

用户持有的配置文件需要提供 API Key 或 token。

在此方式下,Codepack CLI 向平台的各服务器发送请求,再由它们向 kube-apiserver 转发请求以执行各 action。

示例

下面是一个简单但完整的创建和运行 Codepack 的示例。

创建 Codepack

这里以进行 MNIST 手写数字图像分类的 Keras 模型为例,在工作路径下创建一个名为 mnist-keras 的目录。

准备代码、数据集和资源配置文件

首先编写一个进行模型构建、训练和测试的 Python 脚本,使用 Keras 框架和简单的卷积神经网络结构。为了在平台上进行分布式训练,训练过程采用 tf.distribute.MultiWorkerMirroredStrategy 分布式策略。具体代码如下:

import argparse
import json
import logging
import os
import shutil

import tensorflow as tf
from tensorflow.keras import callbacks, datasets, layers, models, optimizers

parser = argparse.ArgumentParser(
    description='Distributed training of Keras model for MNIST with '
    'MultiWorkerMirroredStrategy.')
parser.add_argument('--aimd',
                    action='store_true',
                    default=False,
                    help='Use AIMD to record training data.')
parser.add_argument('--api_key',
                    type=str,
                    help='API Key for requesting AIMD server. '
                    'Required if --aimd is set.')
parser.add_argument(
    '--folder_path',
    type=str,
    default='aimd-example',
    help='Path of AIMD folder in which trial is to be created. '
    'Required if --aimd is set.')
parser.add_argument('--log_dir',
                    type=str,
                    help='Path of the TensorBoard log directory.')
parser.add_argument('--no_cuda',
                    action='store_true',
                    default=False,
                    help='Disable CUDA training.')
parser.add_argument(
    '--server_url',
    type=str,
    default='https://proxy.nc201.kube.tensorstack.net/t9k/aimd/server',
    help='URL of AIMD server. Required if --aimd is set.')
parser.add_argument('--save_path',
                    type=str,
                    default=None,
                    help='Save path of the trained model.')
parser.add_argument('--trial_name',
                    type=str,
                    default='mnist_keras_distributed',
                    help='Name of AIMD trial to create. '
                    'Required if --aimd is set.')
args = parser.parse_args()
logger = logging.getLogger('print')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())
logger.propagate = False

if args.no_cuda:
    # Sets all GPUs invisible
    tf.config.set_visible_devices([], 'GPU')
gpus = tf.config.get_visible_devices('GPU')
if gpus:
    # Print GPU info
    logger.info('NVIDIA_VISIBLE_DEVICES: {}'.format(
        os.getenv('NVIDIA_VISIBLE_DEVICES')))
    logger.info('T9K_GPU_PERCENT: {}'.format(os.getenv('T9K_GPU_PERCENT')))
    logger.info('Visible GPUs: {}'.format(
        tf.config.get_visible_devices('GPU')))
    # Set memory growth
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(gpu, True)
    # # Set GPU memory limit
    # tf.config.set_logical_device_configuration(
    #     gpus[0], [tf.config.LogicalDeviceConfiguration(memory_limit=1024)])

    strategy = tf.distribute.MultiWorkerMirroredStrategy()

# Get information for current worker.
tf_config = json.loads(os.environ['TF_CONFIG'])
world_size = len(tf_config['cluster']['worker'])
task_index = tf_config['task']['index']

if args.aimd and task_index == 0:
    from t9k import aimd
    trial = aimd.init(server_url=args.server_url,
                    trial_name=args.trial_name,
                    folder_path=args.folder_path,
                    api_key=args.api_key)

params = {
    'batch_size': 32 * world_size,
    'epochs': 10,
    'learning_rate': 0.001 * world_size,
    'conv_channels1': 32,
    'conv_channels2': 64,
    'conv_channels3': 64,
    'conv_kernel_size': 3,
    'maxpool_size': 2,
    'linear_features1': 64,
    'seed': 1,
}

if args.aimd and task_index == 0:
    trial.params.update(params)
    trial.params.parse(dist_tf_strategy=strategy)

with strategy.scope():
    model = models.Sequential([
        layers.Conv2D(params['conv_channels1'],
                    params['conv_kernel_size'],
                    activation='relu',
                    input_shape=(28, 28, 1)),
        layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
        layers.Conv2D(params['conv_channels2'],
                    params['conv_kernel_size'],
                    activation='relu'),
        layers.MaxPooling2D((params['maxpool_size'], params['maxpool_size'])),
        layers.Conv2D(params['conv_channels3'],
                    params['conv_kernel_size'],
                    activation='relu'),
        layers.Flatten(),
        layers.Dense(params['linear_features1'], activation='relu'),
        layers.Dense(10, activation='softmax'),
    ])
    model.compile(
        optimizer=optimizers.Adam(learning_rate=params['learning_rate']),
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy'])

print(os.path.join(os.getcwd(), 'mnist.npz'))
(train_images, train_labels), (test_images,
                            test_labels) = datasets.mnist.load_data(
                                path=os.path.join(os.getcwd(), 'mnist.npz'))
train_images = train_images.reshape((60000, 28, 28, 1)).astype("float32") / 255
test_images = test_images.reshape((10000, 28, 28, 1)).astype("float32") / 255
train_images, val_images = tf.split(train_images, [48000, 12000], axis=0)
train_labels, val_labels = tf.split(train_labels, [48000, 12000], axis=0)
train_dataset = tf.data.Dataset.from_tensor_slices(
    (train_images, train_labels)).shuffle(
        48000, seed=params['seed']).repeat().batch(params['batch_size'])
val_dataset = tf.data.Dataset.from_tensor_slices(
    (val_images, val_labels)).batch(400)
test_dataset = tf.data.Dataset.from_tensor_slices(
    (test_images, test_labels)).batch(1000)

train_callbacks = []
test_callbacks = []

if args.aimd and task_index == 0:
    from t9k.aimd.keras import AIMDFitCallback, AIMDEvalCallback
    train_callbacks.append(AIMDFitCallback(trial))
    test_callbacks.append(AIMDEvalCallback(trial))

if args.log_dir and task_index == 0:
    log_dir = args.log_dir
    if os.path.exists(log_dir):
        shutil.rmtree(log_dir, ignore_errors=True)
    tensorboard_callback = callbacks.TensorBoard(log_dir=log_dir)
    train_callbacks.append(tensorboard_callback)

model.fit(train_dataset,
        epochs=params['epochs'],
        steps_per_epoch=48000 // params['batch_size'],
        validation_data=val_dataset,
        callbacks=train_callbacks,
        verbose=2)

if args.save_path:
    if task_index == 0:
        save_path = args.save_path
    else:
        dirname = os.path.dirname(args.save_path)
        basename = os.path.basename(
            args.save_path) + '_temp_' + str(task_index)
        save_path = os.path.join(dirname, basename)
    if os.path.exists(save_path):
        shutil.rmtree(save_path, ignore_errors=True)
    model.save(save_path)
    if task_index != 0:
        shutil.rmtree(save_path, ignore_errors=True)

model.evaluate(test_dataset, callbacks=test_callbacks, verbose=2)

if args.aimd and task_index == 0:
    trial.finish()

编写一个下载数据集的脚本并运行,以将数据集文件 mnist.npz 下载到 Codepack 中。具体代码如下:

import os
import tensorflow as tf

_, _ = tf.keras.datasets.mnist.load_data(
os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mnist.npz'))

考虑在平台上运行时需要创建 PVC、Notebook(可选,便于进一步开发或对 PVC 中的文件进行修改)和 TensorFlowTrainingJob,分别编写相应的资源配置文件如下:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: codepack-example
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 2Gi
apiVersion: tensorstack.dev/v1beta1
kind: Notebook
metadata:
  name: codepack-example
spec:
  template:
    spec:
      containers:
        - name: notebook
          image: 'registry.tensorstack.cn/t9k/tensorflow-2.8.0-notebook-cpu:1.50.0'
          resources:
            limits:
              cpu: '1'
              memory: 1Gi
            requests:
              cpu: 500m
              memory: 500Mi
          volumeMounts:
            - name: workingdir
              mountPath: /t9k/mnt
      volumes:
        - name: workingdir
          persistentVolumeClaim:
            claimName: codepack-example
apiVersion: batch.tensorstack.dev/v1beta1
kind: TensorFlowTrainingJob
metadata:
  name: codepack-example
spec:
  scheduler:
    t9kScheduler:
      queue: default
      priority: 50
  runPolicy:
    cleanUpPolicy: Unfinished
    backoffLimit: 20           # 所有Pod最多共重启20次
  tensorboardSpec:
    trainingLogFilesets:
      - t9k://pvc/codepack-example/mnist-keras/log
    image: t9kpublic/tensorflow-2.7.0:cpu
  replicaSpecs:
    - type: worker
      replicas: 4
      restartPolicy: OnFailure
      template:
        spec:
          securityContext:
            runAsUser: 1000
          containers:
            - command:
                - python        # 运行脚本的命令
                - main.py
                - "--no_cuda"
                - "--log_dir"
                - "log"
                - "--save_path"
                - "saved-model"
              workingDir: /mnt/mnist-keras/    # 工作路径,与定义文件中Codepack的
              imagePullPolicy: IfNotPresent    # 复制路径一致
              image: t9kpublic/tensorflow-2.7.0:cpu
              name: tensorflow
              resources:
                requests:
                  cpu: 2000m
                  memory: 2Gi
                limits:
                  cpu: 4000m
                  memory: 4Gi
              volumeMounts:
                - mountPath: /mnt
                  name: data
          volumes:
            - name: data
              persistentVolumeClaim:
                claimName: codepack-example

现在 Codepack 的文件结构如下:

mnist-keras
├── download_dataset.py
├── main.py
├── mnist.npz
├── notebook.yaml
├── pvc.yaml
└── trainingjob.yaml

编写 Codepack 定义文件

然后编写 Codepack 的定义文件。考虑在平台中运行该 Codepack 的过程,将其拆分为 4 个具体的任务,分别是:

  1. 准备环境,这里只包含创建 PVC。使用 verb apply 并提供 pvc.yaml 文件的路径。
  2. 复制整个 Codepack 到 PVC。使用 verb copy 并提供源和目标位置的路径。
  3. 创建 Notebook。使用 verb create 并提供 notebook.yaml 文件的路径。需要依赖 1 和 2。
  4. 进行分布式训练,即创建 TrainingJob。使用 verb create 并提供 trainingjob.yaml 文件的路径。需要依赖 1 和 2。

据此完成的定义文件如下:

apiVersion: codepack.tensorstack.dev/v1beta1
name: mnist-keras
description: A simple image classifier based on CNN using tf2.
project: demo
default: prepare-env
targets:
  - name: prepare-env        # Prepare running env
    actions:
      - name: workspace-for-training
        verb: apply
        files: [pvc.yaml]
  - name: copy-file          # Copy training code and dataset to PVC
    deps: ["prepare-env"]
    actions:
      - name: copy-code
        verb: copy
        src: .
        dst: codepack-example:.
  - name: create-notebook    # Create a notebook with the codepack in it
    deps: ["prepare-env", "copy-file"]
    actions:
      - name: notebook
        verb: create
        files: [notebook.yaml]
  - name: run-distributed-training    # Run a distributed training
    deps: ["prepare-env", "copy-file"]
    actions:
      - name: trainingjob
        verb: create
        files: [trainingjob.yaml]

最终 Codepack 的文件结构如下:

mnist-keras
├── codepack.yaml
├── download_dataset.py
├── main.py
├── mnist.npz
├── notebook.yaml
├── pvc.yaml
└── trainingjob.yaml

对 Codepack 进行版本控制(可选)

将 Codepack 创建为一个 Git 仓库以进行版本控制,之后你就可以使用任意的本地或远程仓库方便地进行版本控制和分发。

运行 Codepack

使用 Codepack CLI 运行 Codepack。

配置身份验证信息

Codepack CLI 支持多种身份验证方式,你可以选择其中一种并进行相应的配置。详细步骤请参阅身份验证

使用命令行工具运行 Codepack

先使用以下命令运行 target create-notebook

$ codepack run examples/mnist-keras -t create-notebook -p demo
RUN target create-notebook of codepack mnist-keras in project demo
Running sequence: prepare-env -> copy-file -> create-notebook

Target 1/3: prepare-env
APPLY by files ['pvc.yaml']
PersistentVolumeClaim codepack-example created
Target 2/3: copy-file
COPY from . to codepack-example:.
copied
Target 3/3: create-notebook
CREATE by files ['notebook.yaml']
Notebook codepack-example created

再使用以下命令运行 target run-distributed-training

$ codepack run examples/mnist-keras -t run-distributed-training -p demo
RUN target run-distributed-training of codepack mnist-keras in project demo
Running sequence: prepare-env -> copy-file -> run-distributed-training

Target 1/3: prepare-env
APPLY by files ['pvc.yaml']
PersistentVolumeClaim with the name codepack-example already exists, skip
Target 2/3: copy-file
COPY from . to codepack-example:.
copied
Target 3/3: run-distributed-training
CREATE by files ['trainingjob.yaml']
TensorFlowTrainingJob codepack-example created

可以看到在运行这两个 target 的过程中,Codepack CLI 自动解析了工作流并顺序运行各个依赖的 target,按照 YAML 配置文件创建了各资源以及复制整个 Codepack 到 PVC。在运行 target run-distributed-training 的过程中,Codepack CLI 跳过了第一个 target(因为 PVC 已经创建),第二个 target 也实际上没有更新 PVC 中的文件(因为背后调用的是 rsync)。

参考

术语表

本术语表记录了 TensorStack AI 平台的一些专有名词,方便用户随时查阅。

API Key

API Key 是一种 TensorStack AI 平台的安全认证方式,主要应用场景为非交互式程序化身份认证,例如自动化脚本等;或者受限制的交互式场景,例如命令行工具。详见 API Key 文档

Assessor 算法

Assessor 算法是一系列训练评估算法的统称,用于在 AutoTune 中判断当前超参数的训练中间结果是否符合预期。详见 AutoTune 文档

AutoTune

AutoTune 是 TensorStack AI 平台提供的自动化机器学习工具,用于自动地进行特征工程、神经网络架构搜索、超参调优和模型压缩。详见 AutoTune 文档

AutoTuneExperiment

AutoTuneExperiment 是一种 TensorStack 资源,用于自动化机器学习超参数调优。详见 AutoTuneExperiment 文档

BeamJob

BeamJob 是一种 TensorStack 资源,用于通过 Apache Beam 框架和 Apache Flink 等底层计算引擎运行分布式计算任务。详见 BeamJob 文档

ClusterRole

与 Role 类似,但 Role 只能指定某个命名空间范围内的权限,ClusterRole 是整个集群范围。

ClusterRoleBinding

与 RoleBinding 类似,但 RoleBinding 只能指定某个命名空间范围内的权限,ClusterRoleBinding 是整个集群范围。

ConfigMap

ConfigMap 是一种以键值对的形式存储非机密信息的 Kubernetes 资源。Pod 可以挂载 ConfigMap,并以环境变量、命令行参数或配置文件的形式使用 ConfigMap 中的信息。详见 ConfigMap管理 ConfigMap

Container(容器)

容器是可移植、可执行的轻量级的镜像,包含其中的软件及其相关依赖。容器使应用和底层的主机基础设施解耦,降低了应用在不同云环境或者操作系统上的部署难度,便于应用扩展。

Controller(控制器)

控制器负责监控集群中某种 Kubernetes 资源的所有实例,并设法将资源的当前状态转变为期望状态。

CRD(Custom Resource Definition,定制资源定义)

CRD 是 Kubernetes 提供的一种扩展机制,允许开发者定制自己的资源,并开发对应的控制器。TensorStack AI 平台定义了一系列资源,以方便你在 Kubernetes 集群上构建机器学习应用。

CronWorkflowRun

CronWorkflowRun 是一种 TensorStack 资源,用于方便地定时执行 WorkflowRun。详见 CronWorkflowRun 文档

Docker

Docker 是一个提供操作系统级别的虚拟化技术的软件,用于将软件应用及其相关依赖打包成所谓的容器(Container),能够在一个操作系统实例中运行多个其他操作系统中构建的容器。Kubernetes 支持使用 Docker 作为容器运行时。详见 Docker 文档

Explorer

Explorer 是一种 TensorStack 资源,用于通过浏览器访问文件管理器和集成开发环境(IDE)。详见 Explorer 文档

GenericJob

GenericJob 是一种 TensorStack 资源,用于统一协调多个 Pod 共同完成一项任务。详见 GenericJob 文档

Image(镜像)

镜像是保存的容器实例,它打包了应用运行所需的一组软件。你可以将镜像存储在容器镜像仓库、拉取到本地系统并作为应用来运行。

Job

在 TensorStack AI 平台中,Job 是一类统一协调多个 Pod 共同完成一项任务的资源,包括 GenericJob、TensorFlowTrainingJob、PyTorchTrainingJob、XGBoostTrainingJob、MPIJob、BeamJob 等。

Kubernetes(K8s)

Kubernetes 是一个开源的容器编排引擎,用来对容器化应用进行自动化部署、 扩缩和管理。TensorStack AI 平台构建在 Kubernetes 的坚实基础之上。详见 Kubernetes 文档

Label(标签)

标签是附属在资源上的键值对,用于标明资源的属性。你可以通过标签来选取一组资源的某个子集。

MLService

MLService 是一种 TensorStack 资源,用于部署机器学习模型预测服务,以供外部用户使用。详见 MLService 文档

MPIJob

MPIJob 是一种 TensorStack 资源,用于通过 OpenMPI 协议进行分布式机器学习训练。详见 MPIJob 文档

Namespace(命名空间)

命名空间是一组资源所属的工作空间,提供了一种划分集群、隔离资源的方式。同一命名空间内的资源名称必须不同,不同命名空间的资源名称可以相同。

Node(节点)

节点是 Kubernetes 中的工作机器。通常,Kubernetes 集群由一系列节点组成,少则一个,多则上千个。

Notebook

Notebook 是一种 TensorStack 资源,用于在集群中运行 Jupyter Notebook,同时提供 GPU 支持、SSH 访问支持等补充功能。详见 Notebook 文档

Pod

Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。Pod 是一组(一个或多个)容器,这些容器共享存储、网络以及怎样运行这些容器的声明。详见 Kubernetes 文档

PodGroup

PodGroup 是一组 Pod 的集合,它们需要协同工作、一起被调度。详见 PodGroup 文档

Project

Project 是 TensorStack AI 平台对计算集群的抽象,建立在 Kubernetes 命名空间(namespace)之上。不同的用户通常在不同的 Project 下工作,并且可以互相分享自己 Project。详见 Project 文档

PVC(PersistentVolumeClaim,持久卷申领)

PVC 是一种持久化的存储资源,可以被 Pod 挂载、作为 Pod 的卷被访问。你可以在 TensorStack AI 平台的模型构建控制台中创建一个 PVC,并指定它的存储空间(例如 100M、1G)和访问模式(例如只读、可读写、可运行),详见 PVC管理 PVC

PyTorchTrainingJob

PyTorchTrainingJob 是一种 TensorStack 资源,用于通过 PyTorch 框架进行分布式机器学习训练。详见 PyTorchTrainingJob 文档

Queue(队列)

队列是一种 TensorStack 资源,用于存放 PodGroup 并根据它们的优先级进行调度。详见队列文档

RBAC(Role Based Access Control)

RBAC 是一种管理访问控制的方式,详见 Kubernetes 文档。你可以通过 ServiceAccount、Role、RoleBinding、ClusterRole、ClusterRoleBinding 等资源来管理访问控制。

Role

Role 中包含一组代表相关权限的规则,例如获取 Pod、创建 Pod、删除 Pod、获取 Secret、创建 Secret、删除 Secret 等。

RoleBinding

RoleBinding 将 Role 中定义的权限赋予一个用户或者一个 ServiceAccount,这样绑定 ServiceAccount 的 Pod 就能进行 Role 中定义的操作。

Scheduler(调度器)

调度器负责将 Pod 分配到合适的节点上,保证节点满足 Pod 声明的计算资源(CPU、内存、GPU等)、亲和度偏好(希望与其他 Pod 一起运行、希望运行在拥有某个标签的节点上等)等需求。

Secret

Secret 是一种存储密码、令牌、SSH Key 等敏感信息的 Kubernetes 资源。Pod 可以将 Secret 挂载为一个文件,并读取其中的信息。详见 Secret管理 Secret

ServiceAccount

ServiceAccount 为 Pod 提供一个身份凭证。当你创建一个 Pod 时,如果没有指定 ServiceAccount,该 Pod 会默认绑定一个名为 default 的 ServiceAccount。

SimpleMLService

SimpleMLService 是一种 TensorStack 资源,用于部署机器学习模型预测服务,以供内部开发者快速测试。详见 SimpleMLService 文档

TensorBoard

TensorBoard 是 TensorFlow 提供的机器学习可视化工具。TensorStack AI 平台提供在集群中一键部署 TensorBoard 的功能,详见 TensorBoard 文档

TensorFlowTrainingJob

TensorFlowTrainingJob 是一种 TensorStack 资源,用于通过 TensorFlow 框架进行分布式机器学习训练。详见 TensorFlowTrainingJob 文档

Tuner 算法

Tuner 算法是一系列超参数调优算法的统称,用于在 AutoTune 中选取合适的超参数组合。详见 AutoTune 文档

Volume(卷)

卷是一个包含数据的文件夹,可以被 Pod 中的容器访问。详见 Kubernetes 文档

WorkflowRun

WorkflowRun 是一种 TensorStack 资源,用于实例化 WorkflowTemplate 并提供 WorkflowTemplate 运行时所需的参数、工作空间等资源。详见 WorkflowRun 文档

WorkflowTemplate

WorkflowTemplate 是一种 TensorStack 资源,用于在 Kubernetes 中有序、高效、方便地组织运行各类工作负载。详见 WorkflowTemplate 文档

XGBoostTrainingJob

XGBoostTrainingJob 是一种 TensorStack 资源,用于通过 XGBoost 框架进行分布式机器学习训练。详见 XGBoostTrainingJob 文档

API 参考

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

EventControllerStatus

Appears in:

FieldDescription
deployment EventDeploymentStatus

EventDeploymentStatus

Appears in:

FieldDescription
name string
readyReplicas integer
podStatus EventPodStatus

EventPodStatus

Appears in:

FieldDescription
name string
uid UID
phase PodPhase

NetworkPolicy

Appears in:

FieldDescription
useDefaultTemplate booleanIf true, the default NetworkPolicy defined by the administrator will be applied.
template NetworkPolicyTemplateA NethworkPolicy defined for this project.

NetworkPolicyTemplate

Appears in:

FieldDescription
spec NetworkPolicySpec

Project

Project is the Schema for the projects API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringProject
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec ProjectSpec
status ProjectStatus

ProjectCondition

Appears in:

FieldDescription
type ProjectConditionTypeType is the type of the condition.
status ConditionStatusStatus is the status of the condition. Can be True, False, Unknown.
lastUpdateTime TimeLast time we probed the condition.
lastTransitionTime TimeLast time the condition transitioned from one status to another.
reason stringUnique, one-word, CamelCase reason for the condition's last transition.
message stringHuman-readable message indicating details about last transition.

ProjectConditionType

Underlying type: string

Appears in:

ProjectList

ProjectList contains a list of Project

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringProjectList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items Project array

ProjectSpec

ProjectSpec defines the desired state of Project

Appears in:

FieldDescription
resourceQuota ResourceQuota
networkPolicy NetworkPolicy
quotaProfile string
defaultScheduler SchedulePolicyDefaultScheduler defines the default scheduler and queue information for the project. It is just a configuration information, the controller does not need to do anything.

ProjectStatus

ProjectStatus defines the observed state of Project

Appears in:

FieldDescription
conditions ProjectCondition array
eventController EventControllerStatus
resourceQuota ResourceQuotaStatus

QuotaProfile

QuotaProfile is the Schema for the quotaprofiles API. This API resource represents a template for project/namespace resource quota specifications, defined as an instance of corev1.ResourceQuotaSpec.

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringQuotaProfile
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec ResourceQuotaSpec

QuotaProfileList

QuotaProfileList contains a list of QuotaProfile

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringQuotaProfileList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items QuotaProfile array

ResourceQuota

Appears in:

FieldDescription
template ResourceQuotaTemplateA corev1.ResourceQuota defined for this project.

ResourceQuotaStatus

Appears in:

FieldDescription
name string
ResourceQuotaStatus ResourceQuotaStatus

ResourceQuotaTemplate

Appears in:

FieldDescription
spec ResourceQuotaSpec

SchedulePolicy

SchedulePolicy specifies preferences for resource allocation requests, including the name of the preferred scheduler and additional configuration parameters.

Appears in:

FieldDescription
t9kScheduler T9kScheduler

T9kScheduler

Appears in:

FieldDescription
queue stringName of the resource Queue of a T9kScheduler.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

Aggregate

Aggregate records the number of replica pods at each phase.

Appears in:

FieldDescription
creating integerPod has been created, but resources have not been scheduled.
pending integerPod has been accepted by the system, but one or more of the containers has not been started. This includes time before being bound to a node, as well as time spent pulling images onto the host.
running integerPod has been bound to a node and all of the containers have been started. At least one container is still running or is in the process of being restarted.
succeeded integerAll containers in the pod have voluntarily terminated with a container exit code of 0, and the system is not going to restart any of these containers.
failed integerAll containers in the pod have terminated, and at least one container has terminated in failure (exited with a non-zero exit code or was stopped by the system).
unknown integerFor some reason the state of the pod could not be obtained, typically due to an error in communicating with the host of the pod.
deleted integerPod has been deleted.

CleanUpPolicy

Underlying type: string

CleanUpPolicy specifies the collection of replicas that are to be deleted upon job completion.

Appears in:

ContainerStatus

ContainerStatus defines the observed state of the container.

Appears in:

DebugMode

DebugMode configs whether and how to start a job in debug mode.

Appears in:

FieldDescription
enabled booleanWhether to enable debug mode.
replicaSpecs ReplicaDebugSet arrayIf provided, these specs provide overwriting values for job replicas.

FinishRule

A finishRule is a condition used to check if the job has finished. A finishRule identifies a set of replicas, and the controller determines the job's status by checking the status of all of these replicas.

Appears in:

GenericJob

GenericJob represents the schema for a general-purpose batch job API. While it offers less automation compared to specialized APIs like PyTorchTrainingJob, it allows for greater flexibility in specifying parallel replicas/pods. This design serves as a comprehensive job definition mechanism when more specialized APIs are not applicable or available.

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringGenericJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec GenericJobSpec
status GenericJobStatus

GenericJobList

GenericJobList contains a list of GenericJob

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringGenericJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items GenericJob array

GenericJobSpec

GenericJobSpec defines the desired state of GenericJob

Appears in:

FieldDescription
successRules FinishRule arrayRules used to check if a generic job has succeeded. The job succeeded when any one of the successRules is fulfilled. Each item of successRules may refer to a series of replicas, and the job succeeded only if all of the replicas referred in this series are completed successfully.
failureRules FinishRule arrayRules used to check if a generic job has failed. The job failed when any one of failureRules is fulfilled. Each item of failureRules refers to a series of replicas, and the job failed only if all of the replicas in this series failed.
service ServiceOptionDetails of v1/Service for replica pods. Optional: Defaults to empty and no service will be created.
runMode RunModeJob running mode. Defaults to Immediate mode.
cleanUpPolicy CleanUpPolicyTo avoid wasting resources on completed tasks, controller will reclaim resource according to the following policies: None: (default) no resources reclamation; Unfinished: only finished pods is to be deleted; All: all the pods are to be deleted.
scheduler SchedulePolicyIf specified, the pod will be dispatched by the specified scheduler. Otherwise, the pod will be dispatched by the default scheduler.
replicaSpecs ReplicaSpec arrayList of replica specs belonging to the job. There must be at least one replica defined for a Job.

GenericJobStatus

GenericJobStatus defines the observed state of GenericJob

Appears in:

FieldDescription
tasks Tasks arrayAn array of status of individual tasks.
phase JobPhaseProvides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine.
aggregate AggregateRecords the number of replicas at each phase.
conditions JobCondition arrayThe latest available observations of a job's current state.

JobCondition

JobCondition describes the current state of a job.

Appears in:

FieldDescription
type JobConditionTypeType of job condition: Complete or Failed.
status ConditionStatusStatus of the condition, one of True, False, Unknown.
lastTransitionTime TimeLast time the condition transited from one status to another.
reason stringBrief reason for the condition's last transition.
message stringHuman readable message indicating details about last transition.

JobConditionType

Underlying type: string

JobConditionType defines all possible types of JobStatus. Can be one of: Initialized, Running, ReplicaFailure, Completed, or Failed.

Appears in:

JobPhase

Underlying type: string

Appears in:

PauseMode

PauseMode configs whether and how to start a job in pause mode.

Appears in:

FieldDescription
enabled booleanWhether to enable pause mode.
resumeSpecs ResumeSpec arrayIf provided, these specs provide overwriting values for job replicas when resuming.

ReplicaDebugSet

ReplicaDebugSet describes how to start replicas in debug mode.

Appears in:

FieldDescription
type stringReplica type.
skipInitContainer booleanSkips creation of initContainer, if true.
command stringEntrypoint array. Optional: Default to ["sleep", "inf"]

ReplicaSpec

ReplicaSpec defines the desired state of replicas.

Appears in:

FieldDescription
type stringReplica type.
replicas integerThe desired number of replicas of this replica type. Defaults to 1.
restartPolicy RestartPolicyRestart policy for replicas of this replica type. One of Always, OnFailure, Never. Optional: Default to OnFailure.
template PodTemplateSpecDefines the template used to create pods.

ReplicaStatus

ReplicaStatus defines the observed state of the pod.

Appears in:

FieldDescription
name stringPod name.
uid UIDPod uid.
phase PodPhasePod phase. The phase of a Pod is a simple, high-level summary of where the Pod is in its lifecycle.
containers ContainerStatus arrayContainers status.

RestartPolicy

RestartPolicy describes how the replica should be restarted.

Appears in:

FieldDescription
policy RestartPolicyTypeThe policy to restart finished replica.
limit integerThe maximum number of restarts. Optional: Default to 0.

RestartPolicyType

Underlying type: string

Appears in:

ResumeSpec

ResumeSpec describes how to resume replicas from pause mode.

Appears in:

FieldDescription
type stringReplica type.
skipInitContainer booleanSkips creation of initContainer, if true.
command stringEntrypoint array. Provides overwriting values if provided; otherwise, values in immediate mode are used.
args stringArguments to the entrypoint. Arguments in immediate mode are used if not provided.

RunMode

RunMode defines the job's execution behavior: Immediate mode: (Default) Tasks are executed immediately upon submission. Debug mode: Job pods are created, but regular executions are replaced with null operations (e.g., sleep) for convenient debugging purposes. Pause mode: Job execution is halted, and pods are deleted to reclaim resources. A graceful pod termination process is initiated to allow pods to exit cleanly.

Appears in:

FieldDescription
debug DebugModeDebug mode.
pause PauseModePause mode.

SchedulePolicy

SchedulePolicy signals to K8s how the job should be scheduled.

Appears in:

FieldDescription
t9kScheduler T9kSchedulerT9k Scheduler. TODO: link to t9k scheduler docs.

ServiceOption

Details of a replicas' servivce.

Appears in:

FieldDescription
ports ServicePort arrayThe list of ports that are exposed by this service.

T9kScheduler

T9kScheduler provides additonal configurations needed for the scheduling process.

Appears in:

FieldDescription
queue stringSpecifies the name of the queue should be used for running this workload. TODO: link to t9k scheduler docs.
priority integerIndicates the priority of the PodGroup; valid range: [0, 100]. Optional: Default to 0.

Tasks

Task defines the observed state of the task.

Appears in:

FieldDescription
type stringReplica type.
restartCount integerThe number of restarts that have been performed.
replicas ReplicaStatus arrayReplicas status array.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

ReplicaSpec

ReplicaSpec describes the spec of a replica.

Appears in:

FieldDescription
type ReplicaTypeReplicaType is the type of the replica, one of "chief", "worker", "ps", or "evaluator".
replicas integerThe desired number of replicas created for the current replica type. If unspecified, defaults to 1.
template PodTemplateSpecDescribes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will create new pods if restart is required.
restartPolicy RestartPolicyThe restart policy for this replica, one of Always, OnFailure, Never, or ExitCode.

ReplicaType

Underlying type: string

ReplicaType is the type of the replica, one of "chief", "worker", "ps", or "evaluator".

Appears in:

RestartPolicy

Underlying type: string

RestartPolicy describes how the replicas should be restarted. Can be one of: Always, OnFailure, Never, or ExitCode.

Appears in:

RunPolicy

RunPolicy encapsulates various runtime policies of the distributed training job, for example how to clean up resources and how long the job can stay active.

Appears in:

FieldDescription
activeDeadlineSeconds integerSpecifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer.
backoffLimit integerOptional number of retries before marking this job failed.
cleanUpPolicy CleanUpPolicyClean the tasks after the training job finished.

TensorFlowTrainingJob

TensorFlowTrainingJob is the Schema for the TensorFlowTrainingJob API.

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringTensorFlowTrainingJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec TensorFlowTrainingJobSpec
status TensorFlowTrainingJobStatus

TensorFlowTrainingJobList

TensorFlowTrainingJobList contains a list of TensorFlowTrainingJob

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringTensorFlowTrainingJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items TensorFlowTrainingJob array

TensorFlowTrainingJobSpec

TensorFlowTrainingJobSpec outlines the intended configuration and execution parameters for a TensorFlowTrainingJob.

Appears in:

FieldDescription
replicaSpecs ReplicaSpec arrayDescribes the spec of the replicas of the job.
runMode RunModeJob's execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission.
tensorboardSpec TensorBoardSpecDescribes the Tensorboard to be created for showing training logs.
runPolicy RunPolicyExecution policy configurations governing the behavior of the TensorFlowTrainingJob.
scheduler SchedulePolicyIdentifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler.

TensorFlowTrainingJobStatus

TensorFlowTrainingJobStatus defines the observed state of TensorFlowTrainingJob

Appears in:

FieldDescription
tasks Tasks arrayThe statuses of individual tasks.
tensorboard DependentStatusThe status of tensorboard.
backoffCount integerThe number of restarts being performed.
aggregate Aggregate
conditions JobCondition arrayRepresents the latest available observations of a TensorFlowTrainingJob's current state.
phase JobPhasePhase is the phase-style status of the TensorFlowTrainingJob.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

ElasticConfig

Configuration governing the elastic scaling behavior of the job.

Appears in:

FieldDescription
enabled booleanSet true to use elastic training.
minReplicas integerThe minimum number of replicas to start to run this elastic compute. The autoscaler cannot scale down an elastic job below this number. This value cannnot be changed once the job is created.
maxReplicas integerThe maximum number of replicas to start to run this elastic compute. The autoscaler cannot scale up an elastic job over this number. This value cannnot be changed once the job is created.
expectedReplicas integerNumber of replicas to be created. This number can be set to an initial value upon creation. This value can be modified dynamically by an external entity, such as a user or an autoscaler, to scale the job up or down.

PyTorchTrainingJob

PyTorchTrainingJob is the Schema for the pytorchtrainingjobs API.

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringPyTorchTrainingJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec PyTorchTrainingJobSpec
status PyTorchTrainingJobStatus

PyTorchTrainingJobList

PyTorchTrainingJobList contains a list of PyTorchTrainingJob

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringPyTorchTrainingJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items PyTorchTrainingJob array

PyTorchTrainingJobSpec

PyTorchTrainingJobSpec outlines the intended configuration and execution parameters for a PyTorchTrainingJo.

Appears in:

FieldDescription
replicaSpecs ReplicaSpec arrayAn array of ReplicaSpec. Specifies the pytorch cluster configuration.
elastic ElasticConfigConfigurations for how to launch an elastic training. Elastic training is effective only in torchrun mode.
torchrunConfig TorchrunConfigWhether and how to use torchrun to launch a training process.
runMode RunModeJob's execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission.
runPolicy RunPolicyExecution policy configurations governing the behavior of a PytorchTrainingJob.
tensorboardSpec TensorBoardSpecIf specified, controller will create a Tensorboard for showing training logs.
scheduler SchedulePolicyIdentifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler.

PyTorchTrainingJobStatus

PyTorchTrainingJobStatus defines the observed state of PyTorchTrainingJob.

Appears in:

FieldDescription
tasks Tasks arrayThe status details of individual tasks.
tensorboard DependentStatusThe status of the tensorboard.
backoffCount integerThe number of restarts having been performed.
aggregate AggregateThe number of tasks in each state.
conditions JobCondition arrayThe latest available observations of an object's current state.
phase JobPhaseProvides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine.

ReplicaSpec

ReplicaSpec is a description of the job replica.

Appears in:

FieldDescription
type stringReplicaType is the type of the replica.
replicas integerThe desired number of replicas of the current template. Defaults to 1.
scalingWeight integerScaling weight of the current replica used in elastic training.
template PodTemplateSpecDescribes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will decide if restarts are desired.
restartPolicy RestartPolicyRestart policy for all replicas within the job. One of Always, OnFailure, Never, or ExitCode.

TorchrunConfig

Describes how to launch pytorch training with torchrun.

Appears in:

FieldDescription
enabled booleanSet true to use torchrun launch pytorch training.
maxRestarts integer
procPerNode stringNumber of processes to be started on every replica.
rdzvBackend stringCommunication backed used for the group. Defaults to c10d.
extraOptions string arrayExtra options for torchrun.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

ReplicaSpec

ReplicaSpec outlines the intended configuration and execution parameters for a XGBoostTrainingJob.

Appears in:

FieldDescription
type ReplicaTypeReplicaType is the type of the replica, one of "master" or "worker".
replicas integerThe desired number of replicas of the current template. If unspecified, defaults to 1.
template PodTemplateSpecDescribes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will decide if restarts are desired.
restartPolicy RestartPolicyRestart policy for all replicas within the job. One of Always, OnFailure, Never, or ExitCode. Defaults to OnFailure.

ReplicaType

Underlying type: string

ReplicaType is the type of the replica, one of "master" or "worker".

Appears in:

XGBoostTrainingJob

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringXGBoostTrainingJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec XGBoostTrainingJobSpec
status XGBoostTrainingJobStatus

XGBoostTrainingJobList

XGBoostTrainingJobList contains a list of XGBoostTrainingJob.

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringXGBoostTrainingJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items XGBoostTrainingJob array

XGBoostTrainingJobSpec

Appears in:

FieldDescription
replicaSpecs ReplicaSpec arrayAn array of ReplicaSpec. Specifies the XGBoost replica configurations.
runMode RunModeJob's execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission.
runPolicy RunPolicyExecution policy configurations governing the behavior of the XGBoostTrainingJob.
scheduler SchedulePolicyIdentifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler.

XGBoostTrainingJobStatus

XGBoostTrainingJobStatus defines the observed state of XGBoostTrainingJob.

Appears in:

FieldDescription
tasks Tasks arrayThe status details of individual tasks.
backoffCount integerThe number of restarts being performed.
aggregate Aggregate
conditions JobCondition arrayThe latest available observations of an object's current state.
phase JobPhaseProvides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

ColossalAIJob

ColossalAIJob is the Schema for the colossalaijobs API

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringColossalAIJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec ColossalAIJobSpec
status ColossalAIJobStatus

ColossalAIJobList

ColossalAIJobList contains a list of ColossalAIJob.

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringColossalAIJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items ColossalAIJob array

ColossalAIJobSpec

ColossalAIJobSpec defines the configurations of a ColossalAI training job.

Appears in:

FieldDescription
ssh SSHConfigSSH configs.
runMode RunModeThe desired running mode of the job, defaults to Immediate.
runPolicy RunPolicyControls the handling of completed replicas and other related processes.
scheduler SchedulePolicySpecifies the scheduler to request for resources. Defaults to cluster default scheduler.
launcher LauncherSpecication for the launcher replica.
worker WorkerSpecication for the launcher replica.

ColossalAIJobStatus

ColossalAIJobStatus describes the observed state of ColossalAIJob.

Appears in:

FieldDescription
tasks Tasks arrayThe statuses of individual tasks.
aggregate AggregateThe number of replicas in each phase.
phase JobPhaseProvides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine.
conditions JobCondition arrayThe latest available observations of an object's current state.

Launcher

Specification of replica launcher.

Appears in:

FieldDescription
image stringContainer image name.
workingDir stringWorking directory of container launcher. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated.
env EnvVar arrayList of environment variables set for the container. Cannot be updated.
resources ResourceRequirementsCompute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

RunPolicy

RunPolicy dictates specific actions to be taken by the controller upon job completion.

Appears in:

FieldDescription
cleanUpWorkers booleanDefaults to false.

SSHConfig

SSHConfig specifies various configurations for running the SSH daemon (sshd).

Appears in:

FieldDescription
authMountPath stringSSHAuthMountPath is the directory where SSH keys are mounted. Defaults to "/root/.ssh".
sshdPath stringThe location of the sshd executable file.

Worker

Specification of the worker replicas.

Appears in:

FieldDescription
replicas integerNumber of replicas to launch. Defaults to 1.
procPerWorker integerThe number of processes of a worker. Defaults to 1.
command string arraySpecifies the command used to start the workers.
torchArgs string arrayArgs of torchrun.
template PodTemplateSpecTemplate defines the workers that will be created from this pod template.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

Config

Configuration information for running a DeepSpeed job. Details are outlined in the official DeepSpeed documentation (https://www.deepspeed.ai/getting-started/) for comprehensive guidance.

Appears in:

FieldDescription
customCommand stringCustom launch commands, when enabled, other options in Config except for slotsPerWorker will not take effect.
slotsPerWorker integerThe number of slots for each worker/replica. This is normally set to the number of GPUs requested for each replica.
localRank booleanIf parameter local_rank should be passed to training programs.
autotune AutotuneTypeParameters for running the autotuning process to find configurations for a training job on a particular cluster/machine.
run RunTypeMechanism to start the training program.
otherArgs string arraySeting up other command line args for the deepspeed job.

DeepSpeedJob

DeepSpeedJob defines the schema for the DeepSpeedJob API.

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringDeepSpeedJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec DeepSpeedJobSpec
status DeepSpeedJobStatus

DeepSpeedJobList

DeepSpeedJobList contains a list of DeepSpeedJob

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringDeepSpeedJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items DeepSpeedJob array

DeepSpeedJobSpec

DeepSpeedJobSpec outlines the intended configuration and execution parameters for a DeepSpeedJob.

Appears in:

FieldDescription
scheduler SchedulePolicyIdentifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler.
runPolicy RunPolicyExecution policy configurations governing the behavior of the distributed training job.
runMode RunModeJob's execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission.
elastic ElasticConfigConfigurations for how to launch an elastic training.
config ConfigKey configurations for executing DeepSpeed training jobs.
disableCustomEnv booleanSetting environment variables during DeepSpeed training necessitates creating an env file to store the desired variables. The launcher will then distribute these variables to each worker process. Nevertheless, certain scenarios require disabling this automated behavior, and this flag enables control over this functionality.
false: (default) The environment variables set in job specs are used in the training processes. The controller will automatically put the environment variables into the env file so that the launcher can send them to each worker;
true: The environment variables set in the job specs are only used to start the container entrypoint program, and the training program does not need these environment variables.
worker WorkerSpecifications for the worker replicas.

DeepSpeedJobStatus

DeepSpeedJobStatus represents the observed state of a DeepSpeedJob.

Appears in:

FieldDescription
tasks Tasks array
aggregate Aggregate
phase JobPhaseProvides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine.
backoffCount integerThe number of restarts being performed.
conditions JobCondition arrayThe latest available observations of an object's current state.

ElasticConfig

Configuration governing the elastic scaling behavior of the job.

Appears in:

FieldDescription
enabled booleanSet true to use elastic training.
minReplicas integerThe minimum number of replicas to start to run this elastic compute. The autoscaler cannot scale down an elastic job below this number. This value cannnot be changed once the job is created.
maxReplicas integerThe maximum number of replicas to start to run this elastic compute. The autoscaler cannot scale up an elastic job over this number. This value cannnot be changed once the job is created.
expectedReplicas integerNumber of replicas to be created. This number can be set to an initial value upon creation. This value can be modified dynamically by an external entity, such as a user or an autoscaler, to scale the job up or down.

RunPolicy

RunPolicy encapsulates various runtime policies of the distributed training job, for example how to clean up resources and how long the job can stay active.

Appears in:

FieldDescription
activeDeadlineSeconds integerSpecifies the duration in seconds relative to the startTime that the job may be active before the system tries to terminate it; value must be positive integer.
backoffLimit integerOptional number of retries before marking this job failed.
cleanUpPolicy CleanUpPolicyClean the tasks after the training job finished.

RunType

How the training program should be started. Exactly one of the 3 choices should be set.

Appears in:

FieldDescription
python string arrayUsing a python script
module string arrayUsing a python module
exec string arrayUsing an executable program

Worker

Worker defines the configurations for DeepSpeedJob worker replicas.

Appears in:

FieldDescription
replicas integerThe number of workers to launch.
template PodTemplateSpecDescribes the pod that will be created for this replica. Note that RestartPolicy in PodTemplateSpec will always be set to Never as the job controller will decide if restarts are desired.
restartPolicy RestartPolicyRestart policy for all replicas owned by the job. One of Always, OnFailure, Never, or ExitCode. Defaults to OnFailure.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

MPIJob

MPIJob is the Schema for the mpijobs API

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringMPIJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec MPIJobSpec
status MPIJobStatus

MPIJobList

MPIJobList contains a list of MPIJob

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringMPIJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items MPIJob array

MPIJobSpec

MPIJobSpec outlines the intended configuration and execution parameters for a MPIJob.

Appears in:

FieldDescription
worker WorkerConfigSpecifications for the worker replicas.
mca object (keys:string, values:string)Open MPI uses Modular Component Architecture (MCA) parameters to provide a way to tune your runtime environment.
ssh SSHConfigSSH configs.
runPolicy RunPolicyExecution policy configurations governing the behavior of the MPI job.
runMode RunModeJob's execution behavior. If omitted, defaults to Immediate mode, and tasks are executed immediately upon submission.
mpiHome stringOpen MPI installation path.
scheduler SchedulePolicyIdentifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler. Use k8s default scheduler by default.

MPIJobStatus

MPIJobStatus represents the observed state of a MPIJob.

Appears in:

FieldDescription
tasks Tasks arrayIndividual task status details of the job.
aggregate Aggregate
phase JobPhaseProvides a simple, high-level summary of where the Job is in its lifecycle. Note that this is NOT indended to be a comprehensive state machine.
conditions JobCondition arrayThe latest available observations of an object's current state.

RunPolicy

RunPolicy encapsulates various runtime policies of the MPI job, for example how to clean up resources.

Appears in:

FieldDescription
cleanUpWorkers booleanIf worker replicas should be cleand up after they finish. Defaults false.

SSHConfig

SSHConfig specifies various configurations for running the SSH daemon (sshd).

Appears in:

FieldDescription
sshAuthMountPath stringSSHAuthMountPath is the directory where SSH keys are mounted. Defaults to "/root/.ssh".
sshdPath string

WorkerConfig

WorkerConfig defines the configurations for MPI worker replicas.

Appears in:

FieldDescription
replicas integerThe number of workers to launch. Default 1.
extraMPIArgs string arrayExtra args for mpirun.
cmd string arrayCommand line to start the MPI programs inside a worker pod. This is invoked by the launcher after all the worker pods have been created and entered ready state.
template PodTemplateSpecDefines the pod template used to create workers. Users are responsible for ensuring that container images and configurations are properly set to guarantee the worker operates in the state anticipated by the launcher.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the batch v1beta1 API group

Resource Types

BeamJob

BeamJob is the Schema for the beamjobs API

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringBeamJob
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec BeamJobSpec
status BeamJobStatus

BeamJobList

BeamJobList contains a list of BeamJob

FieldDescription
apiVersion stringbatch.tensorstack.dev/v1beta1
kind stringBeamJobList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items BeamJob array

BeamJobSpec

BeamJobSpec defines the desired state of BeamJob

Appears in:

FieldDescription
flinkClusterTemplate FlinkClusterTemplateSpecSpecifies the FlinkCluster that will be created when executing a BeamJob.
jobTemplate JobTemplateSpecSpecifies the Job that will be created when executing a BeamJob.
runPolicy RunPolicyRuntime policies governing the behavior of the BeamJob.
scheduler SchedulePolicyIdentifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler.
runMode RunModeNormal mode and debug mode are supported now.

BeamJobStatus

BeamJobStatus defines the observed state of BeamJob

Appears in:

FieldDescription
phase JobPhasePhase is a label for the condition of the job at the current time.
conditions JobCondition arrayThe latest available observations of the BeamJob's current state.
tasks Tasks arrayThe statuses of individual tasks.
aggregate Aggregate
jobURL stringThe URL to Web UI of the cluster where details of the job is displayed.

FlinkClusterTemplateSpec

FlinkClusterTemplateSpec describes the data a FlinkCluster should have when created from a template

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec FlinkClusterSpecSpecification of the desired behavior of the FlinkCluster.

RunPolicy

RunPolicy encapsulates runtime policies governing the behavior of the BeamJob.

Appears in:

FieldDescription
cleanUpCluster booleanWhether or not delete cluster after the job finished. Default false.

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

HttpDataSource

Details of HTTP data source.

Appears in:

FieldDescription
url string arrayUrl pointing to the log files.

PVCDataSource

Details of PVC data source.

Appears in:

FieldDescription
name stringPVC name.
subPath string arrayThe relative paths of logs in the PVC.

PodReference

PodReference references to a v1.pod.

Appears in:

FieldDescription
name stringName of the Pod.
uid stringUID of the Pod.

PodStatus

Pod defines the observed state of a replica.

Appears in:

FieldDescription
reference PodReferenceReferences to the subordinate v1.Pod.
phase PodPhaseReplicated from the corresponding field in the subordinate v1.Pod.

S3DataSource

Details of S3 data source.

Appears in:

FieldDescription
secretRef SecretRefS3 data source uses a secret to transmit access/secret key and service enpoint.
uri string arrayS3 object uri.

SchedulePolicy

SchedulePolicy specifies the preferred scheduler responsible for handling resource allocation requests.

Appears in:

FieldDescription
t9kScheduler T9kScheduler

SecretRef

Appears in:

FieldDescription
name stringSecret name.

T9kScheduler

Appears in:

FieldDescription
queue stringName of the queue to use with the T9kScheduler.

TensorBoard

TensorBoard is the Schema for the tensorboards API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringTensorBoard
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec TensorBoardSpec
status TensorBoardStatus

TensorBoardCondition

TensorBoardCondition defines the observed condition of TensorBoard

Appears in:

FieldDescription
type TensorBoardConditionTypeType is the type of the condition. Possible values are Idle, etc
status ConditionStatusStatus is the status of the condition type. Possible values of type Idle are True
message stringMessage is the reason of the status
lastTransitionTime TimeLastTransitionTime is the last time the status was changed
lastProbeTime TimeLastProbeTime is the last time the condition was probed

TensorBoardConditionType

Underlying type: string

Appears in:

TensorBoardDataSource

TensorBoardDataSource represents the location and type of the tensorboard data source. It includes three types of data sources: PVC, S3, and HTTP. In a tensorboard service, these three types of data sources can be used simultaneously.

Appears in:

FieldDescription
pvc PVCDataSource arrayPVC represents PVCs that are mounted to workload as directories to provide log data.
s3 S3DataSourceS3 represents a s3 service and access/secret key to access the service.
http HttpDataSourceHTTP provides several urls.

TensorBoardList

TensorBoardList contains a list of TensorBoard

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringTensorBoardList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items TensorBoard array

TensorBoardPhase

Underlying type: string

Appears in:

TensorBoardSpec

TensorBoardSpec defines the desired state of TensorBoard

Appears in:

FieldDescription
trainingLogFilesets string arrayTrainingLogFilesets is the list of filesets containing training log. The format of fileset: t9k://pvc/[pvc-name]/[subpath] t9k://minio/[secret-name]/[bucket]/[subpath] To be deprecated: Use spec.logDir instead.
logDir TensorBoardDataSourceLogDir is a series of data source containing training log.
image stringThe container image used to run the tensorboard.
suspend booleansuspend specifies whether the TensorBoard controller should delete Pods or not. If true, the associated v1.Pod can be terminated. However, other API resources, such as ConfigMaps and Services, will be preserved for use upon resuming the TensorBoard. Defaults to false.
scheduler SchedulePolicy
resources ResourceRequirementsCompute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

TensorBoardStatus

TensorBoardStatus defines the observed state of TensorBoard

Appears in:

FieldDescription
phase TensorBoardPhase
pod PodStatus
conditions TensorBoardCondition arrayConditions is an array of current conditions
url stringThe URL to Web UI of the tensorboard

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

Notebook

Notebook is the Schema for the notebooks API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringNotebook
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec NotebookSpec
status NotebookStatus

NotebookCondition

NotebookCondition defines the observed condition of notebook

Appears in:

FieldDescription
type NotebookConditionTypeType is the type of the condition. Possible values are Idle, etc
status ConditionStatusStatus is the status of the condition type. Possible values of type Idle are `True
message stringMessage is a human-readable message for the reason of the status.
lastTransitionTime TimeLastTransitionTime is the last time the status was changed.
lastProbeTime TimeLastProbeTime is the last time the condition was probed.

NotebookConditionType

Underlying type: string

Appears in:

NotebookList

NotebookList contains a list of Notebook

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringNotebookList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items Notebook array

NotebookPhase

Underlying type: string

Appears in:

NotebookSSHSpec

NotebookSSHSpec defines the ssh template spec of Notebook

Appears in:

FieldDescription
enabled booleanIf true, SSH service will be started for this Notebook instance.
serviceType ServiceType
authorized_keys string arrayA list of names of v1.Secret containing SSH public keys authorized for access to this SSH service.

NotebookSSHStatus

NotebookSSHStatus defines the observed state of the SSH service associated with the Notebook.

Appears in:

FieldDescription
serviceName stringThe v1.Service name of the SSH service.
port integerThe port number of the SSH server daemon.
clusterIp string
nodePort integer
protocol Protocol
lastSshClientActivity TimeLastSshClientActivity is the last time an SSH client is active.

NotebookSpec

NotebookSpec defines the desired state of a Notebook.

Appears in:

FieldDescription
template NotebookTemplateSpec
scheduler SchedulePolicy
ssh NotebookSSHSpec
type NotebookType
suspend booleansuspend specifies whether the Notebook controller should delete Pods or not. If true, the associated v1.Pod can be terminated. However, other API resources, such as ConfigMaps and Services, will be preserved for use upon resuming the notebook. Defaults to false.

NotebookStatus

NotebookStatus defines the observed state of a Notebook.

Appears in:

FieldDescription
phase NotebookPhase
pod PodStatus
ssh NotebookSSHStatus
conditions NotebookCondition arrayConditions is an array of current conditions
url stringThe URL to Web UI of the notebook

NotebookTemplateSpec

NotebookTemplateSpec defines the pod template to run a Notebook.

Appears in:

FieldDescription
spec PodSpec

NotebookType

Underlying type: string

Appears in:

PodReference

PodReference references a K8s v1.Pod.

Appears in:

FieldDescription
name stringName of the Pod.
uid stringUID of the Pod.

PodStatus

Pod defines the observed state of the Pod running the notebook.

Appears in:

FieldDescription
reference PodReferenceReferences to the subordinate v1.Pod.
phase PodPhaseReplicated from the corresponding field in the subordinate v1.Pod.

SchedulePolicy

SchedulePolicy specifies the preferred scheduler responsible for handling resource allocation requests.

Appears in:

FieldDescription
t9kScheduler T9kScheduler

T9kScheduler

Appears in:

FieldDescription
queue stringName of the queue to use with the T9kScheduler.

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

AIStoreConfig

AIStoreConfig represents the configuration for using AIStore as a data storage for experiments.

Appears in:

FieldDescription
secret stringSecret specifies the secret containing the API Key authorized to upload data to AIStore.
folder stringFolder indicates the destination folder where the experiment data will be stored.

AdvisorConfig

AdvisorConfig represents the configuration for the advisor algorithm and its parameters.

Appears in:

FieldDescription
builtinAdvisorName stringBuiltInAdvisorName specifies the name of the built-in advisor algorithm to be used. Available options include: Hyperband, BOHB.
classArgs stringClassArgs defines the parameters specific to the chosen advisor algorithm. Different algorithms may require distinct parameters.

AssessorConfig

AssessorConfig represents the configuration for the assessor algorithm and its parameters.

Appears in:

FieldDescription
builtinAssessorName stringBuiltInAssessorName specifies the name of the built-in assessor algorithm to be used. Available options include: Medianstop, Curvefitting.
classArgs stringClassArgs defines the parameters specific to the chosen assessor algorithm. Different algorithms may require distinct parameters.

AutoTuneExperiment

AutoTuneExperiment is the Schema for the autotune API.

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/apis
kind stringAutoTuneExperiment
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec AutoTuneExperimentSpec
status AutoTuneExperimentStatus

AutoTuneExperimentList

AutoTuneExperimentList contains a list of AutoTuneExperiment.

FieldDescription
apiVersion stringtensorstack.dev/apis
kind stringAutoTuneExperimentList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items AutoTuneExperiment array

AutoTuneExperimentSpec

AutoTuneExperimentSpec defines the desired state of the AutoTuneExperiment.

Appears in:

FieldDescription
aistore AIStoreConfigAIStore configures an AIStore as storage for experiment data. If this field is set, data will be uploaded to the AIStore.
maxExecSeconds integerMaxExecSeconds is the time limit (in seconds) for the AutoTuneExperiment, If this limit is exceeded, the AutoTuneExperiment reaches phase TIMEOUT.
maxTrialNum integerMaxTrialNum specifies the maximum number of trials for the AutoTuneExperiment. Once this number of trials is reached, the AutoTuneExperiment reaches phase DONE.
trialConcurrency integerTrialConcurrency is the maximum number of trials running simultaneously.
searchSpace stringSearchSpace defines the hyperparameter search space as a JSON string. It specifies the range for searching optimized hyperparameters. Example: { "batch_size": {"_type": "choice", "_value": [16, 32, 64, 128]}, "learning_rate": {"_type": "choice", "_value": [0.0001, 0.001, 0.01, 0.1]}, "conv_channels1": {"_type": "choice", "_value": [16, 32, 64, 128]} }
storage QuantityStorage specifies the size of PVC for storing configurations and training metrics.
trainingConfig TrainingConfigTrainingConfig represents the configuration for creating Jobs, which evaluate the performance of different hyperparameters.
tuner TunerConfigTuner configures a tuner for optimizing hyperparameter.
assessor AssessorConfigAssessor configures an assessor for filtering hyperparameters and interrupting training when hyperparameters are deemed unqualified. Note that this field is ignored if Tuner is not set.
advisor AdvisorConfigAdvisor configures an advisor for optimizing hyperparameter. Note that when both Tuner and Advisor are set, Tuner takes precedence.

AutoTuneExperimentStatus

AutoTuneExperimentStatus defines the observed state of the AutoTuneExperiment.

Appears in:

FieldDescription
OwnerStatus OwnerStatus
nextCheckedTime TimeNextCheckedTime indicates the scheduled time for the next status check of the experiment process by the controller.
phase ExperimentStatusPhase provides a simple, high-level summary of where the AutoTuneExperiment is in its lifecycle. Note that it is NOT intended to serve as a comprehensive state machine. This field is optional.
serverNote stringServerNote contains the current status of the experiment process.

ExperimentStatus

Underlying type: string

Appears in:

TunerConfig

TunerConfig represents the configuration for the tuner algorithm and its parameters.

Appears in:

FieldDescription
builtinTunerName stringBuiltInTunerName specifies the name of the built-in tuner algorithm to be used. Available options include: Random, Anneal, TPE, Evolution, Batch, GridSearch, MetisTuner, GPTuner, PPOTuner, PBTTuner.
classArgs stringClassArgs defines the parameters specific to the chosen tuner algorithm. Different algorithms may require distinct parameters.

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

Explorer

Explorer is the Schema for the explorers API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringExplorer
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec ExplorerSpec
status ExplorerStatus

ExplorerCondition

ExplorerCondition defines the observed condition of Explorer resource

Appears in:

FieldDescription
type ExplorerConditionTypeType is the type of the condition. Possible values are Idle, etc
status ConditionStatusStatus is the status of the condition type. Possible values of type Idle are True
message stringMessage is the reason of the status
lastTransitionTime TimeLastTransitionTime is the last time the status was changed
lastProbeTime TimeLastProbeTime is the last time the condition was probed

ExplorerConditionType

Underlying type: string

Appears in:

ExplorerList

ExplorerList contains a list of Explorer

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringExplorerList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items Explorer array

ExplorerSpec

ExplorerSpec defines the desired state of Explorer

Appears in:

FieldDescription
storageType StorageTypeType of storage, only pvc is supported for now.
storageName stringName of the StorageType instance.
suspend booleansuspend specifies whether the Explorer controller should delete Pods or not. If true, the associated v1.Pod can be terminated. However, other API resources, such as ConfigMaps and Services, will be preserved for use upon resuming the Explorer. Defaults to false.
scheduler SchedulePolicy

ExplorerStatus

ExplorerStatus defines the observed state of Explorer

Appears in:

FieldDescription
conditions ExplorerCondition arrayConditions is an array of current conditions
codeServer ResourceStatus
fileBrowser ResourceStatus

PodReference

PodReference refers to a replica.

Appears in:

FieldDescription
name stringName of the Pod.
uid stringUID of the Pod.

PodStatus

Pod defines the observed state of a replica.

Appears in:

FieldDescription
reference PodReferenceReferences to the subordinate v1.Pod.
phase PodPhaseReplicated from the corresponding field in the subordinate v1.Pod.

ResourcePhase

Underlying type: string

Appears in:

ResourceStatus

Appears in:

FieldDescription
phase ResourcePhase
pod PodStatus

SchedulePolicy

SchedulePolicy specifies preferences for resource allocation requests, including the name of the preferred scheduler and additional configuration parameters.

Appears in:

FieldDescription
t9kScheduler T9kScheduler

StorageType

Underlying type: string

StorageType is the type of storage volume.

Appears in:

T9kScheduler

Appears in:

FieldDescription
queue stringName of the resource Queue of a T9kScheduler.

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

S3Config

S3Config defines the config of s3

Appears in:

FieldDescription
uri string

SecretReference

SecretReference defines a Secret Reference

Appears in:

FieldDescription
name string

StorageShim

StorageShim is the Schema for the storageshims API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringStorageShim
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec StorageShimSpec
status StorageShimStatus

StorageShimCondition

StorageShimCondition contains details for the current condition of this StorageShim

Appears in:

FieldDescription
type StorageShimConditionTypeType is the type of the condition
status ConditionStatusStatus is the status of the condition. Can be True, False, Unknown.
message stringHuman-readable message indicating details about last transition.
lastTransitionTime TimeLast time the condition transitioned from one status to another.

StorageShimConditionType

Underlying type: string

StorageShimConditionType is a valid value for StorageShimCondition.Type

Appears in:

StorageShimList

StorageShimList contains a list of StorageShim

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringStorageShimList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items StorageShim array

StorageShimSpec

StorageShimSpec defines the desired state of StorageShim

Appears in:

FieldDescription
s3 S3ConfigS3 defines the config of s3, such as uri
readOnly booleanSpecifies a read-only configuration. Defaults to false.
secretRef SecretReferenceSpecifies a secret reference, must be in the same namespace of this StorageShim currently

StorageShimStatus

StorageShimStatus defines the observed state of StorageShim

Appears in:

FieldDescription
phase PersistentVolumeClaimPhaseThe phase of this StorageShim
conditions StorageShimCondition arrayConditions is an array of current conditions

tensorstack.dev/v1beta2

Package v1beta2 contains API Schema definitions for the v1beta2 API group

Resource Types

CephFSClient

CephFSClient defines the client configurations to connnect to the cephfs server.

Appears in:

FieldDescription
secretRef SecretReferenceSecretRef references a Kubernetes v1.Secret object that securely stores the CephFS client configurations.

CephFSConfig

CephFSConfig defines configuration details for a cephfs storage system.

Appears in:

FieldDescription
path stringPath specifies the absolute path within a CephFS volume to be mounted. It should be a valid directory path within the mounted volume. For example, /path/to/directory.
server CephFSServerServer provides the configuration details for the CephFS cluster. This includes information such as the Ceph monitor IP addresses and the CephFS volume name.
client CephFSClientClient defines the details of a cephFS client.

CephFSServer

CephFSServer defines the configuration details for the CephFS cluster.

Appears in:

FieldDescription
configMapRef ConfigMapReferenceConfigMapRef defines a reference to a K8s v1/configmap that stores CephFS cluster details such as the Ceph monitor IP addresses and the CephFS volume name.

ConfigMapReference

ConfigMapReference defines a Kubernetes v1.ConfigMap reference.

Appears in:

FieldDescription
name stringName of the configmap.
namespace stringNamespace where the configmap resides in.

S3Config

S3Config defines the configuration details for an S3 object storage service.

Appears in:

FieldDescription
readOnly booleanSpecifies that this S3 service can only be used as read-only. Defaults to false.
uri stringThe S3 prefix to mount, specified as s3://<bucket>[/path].
secretRef SecretReferenceReferences a Kubernetes v1.Secret object. The referenced Secret must reside in the same namespace as the referencing StorageShim.

SecretReference

SecretReference defines a reference to a Kubernetes v1.Secret object.

Appears in:

FieldDescription
name stringThe name of a Kubernetes v1.Secret object that holds the CephFS client configurations. This Secret must reside within the same namespace as the referencing StorageShim.

StorageShim

StorageShim is the Schema for the storageshims API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta2
kind stringStorageShim
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec StorageShimSpec
status StorageShimStatus

StorageShimCondition

StorageShimCondition contains details for the current condition of this StorageShim

Appears in:

FieldDescription
type StorageShimConditionTypeType is the type of the condition
status ConditionStatusStatus is the status of the condition. Can be True, False, Unknown.
message stringHuman-readable message indicating details about last transition.
lastTransitionTime TimeLast time the condition transitioned from one status to another.

StorageShimConditionType

Underlying type: string

StorageShimConditionType is a valid value for StorageShimCondition.Type

Appears in:

StorageShimList

StorageShimList contains a list of StorageShim

FieldDescription
apiVersion stringtensorstack.dev/v1beta2
kind stringStorageShimList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items StorageShim array

StorageShimSpec

StorageShimSpec defines the desired state of StorageShim

Appears in:

FieldDescription
type StorageShimTypeType specifies the type of storage system to be integrated with. One of the supported values is required, and currently cephfs, s3 are supported. More storage system types will be added in the future.
s3 S3ConfigS3 defines the configuration details for an s3 object store service.
cephfs CephFSConfigCephFS defines the configuraitons for a cephfs.

StorageShimStatus

StorageShimStatus defines the observed state of StorageShim

Appears in:

FieldDescription
phase PersistentVolumeClaimPhaseThe phase of this StorageShim.
conditions StorageShimCondition arrayConditions represent an array of current conditions observed within the system.

StorageShimType

Underlying type: string

Appears in:

API Reference

Packages

scheduler.tensorstack.dev/v1beta1

Package v1beta1 is the v1beta1 version of the API.

Resource Types

PodGroup

PodGroup represents a collection of Pods to be scheduled together to facilicate with parallel computing. PodGroup is usually automatically created by workload controllers to manage parallel batch workloads such as machine learning training and to enable coscheduling/gang-scheduling strategies. Users can also manually create a PodGroup and associates Pods with it if desired.

Appears in:

FieldDescription
apiVersion stringscheduler.tensorstack.dev/v1beta1
kind stringPodGroup
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec PodGroupSpecSpecification of the desired behavior of the pod group. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
status PodGroupStatusStatus represents the current status of a pod group. This data may not be up to date.

PodGroupCondition

PodGroupCondition contains details for the current state of this pod group.

Appears in:

FieldDescription
type PodGroupConditionTypeThe type of the condition.
status ConditionStatusThe status of the condition.
transitionID stringThe ID of condition transition.
lastTransitionTime TimeLast time of condition transition(s).
reason stringUnique, one-word, CamelCase, machine-readable reason for the condition's last change.
message stringHuman-readable message indicating details about last change.

PodGroupInQueueStatus

Appears in:

FieldDescription
total integer

PodGroupList

PodGroupList is a collection of pod groups.

FieldDescription
apiVersion stringscheduler.tensorstack.dev/v1beta1
kind stringPodGroupList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items PodGroup arrayThe list of PodGroup.

PodGroupSpec

PodGroupSpec represents the desired specification of a pod group.

Appears in:

FieldDescription
roles Role array
minMember integerMinMember defines the minimal number of pods to run the PodGroup. If there less than minMember of pods joining the PodGroup, none of the existing pods in the group will be scheduled. After minMember of pods joined, the scheduler will only schedule them if there are sufficient resources to allow minMember of pods start together.
queue stringQueue defines the queue from which resources for pods of the PodGroup should be allocated. If queue is not specified, the PodGroup will be scheduled to queue "default".
priority integerIf specified, indicates the PodGroup's priority; groups with larger priority values will be considered for scheduling first; range is [0,100].
topologyPolicy TopologyPolicyTypeTopologyPolicy declares the topology policy PodGroup needs.

PodGroupStatus

PodGroupStatus represents the current state of a pod group.

Appears in:

FieldDescription
conditions PodGroupCondition arrayThe conditions of PodGroup.
allocated object (keys:ResourceName, values:Quantity)Allocated represents resources and their qunatities allocated to the PodGroup.
pending integerThe number of pods in phase Pending.
running integerThe number of pods in phase running.
succeeded integerThe number of pods in phase Succeeded.
failed integerThe number of pods in phase Failed.
unknown integerThe number of pods in phase Unknown.

PodInQueueStatus

Appears in:

FieldDescription
pending integerThe number of 'Pending' Pods in this queue.
running integerThe number of 'Running' Pods in this queue.
succeeded integerThe number of 'Succeeded' Pods in this queue.
failed integerThe number of 'Failed' Pods in this queue
unknown integerThe number of 'Unknown' Pods in this queue.

Queue

Queue is an API-resource to reprenent a sub-set of cluster compute resources and associated administrative policies, such as allowed users, resource quota, allowed workload types, max duration of workload runtime and etc.

Appears in:

FieldDescription
apiVersion stringscheduler.tensorstack.dev/v1beta1
kind stringQueue
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec QueueSpecSpecification of the desired behavior of the queue. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
status QueueStatusThe status of queue.

QueueCondition

Appears in:

FieldDescription
type QueueConditionTypeType is the type of the condition. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
status ConditionStatusStatus is the status of the condition. Can be True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
lastTransitionTime TimeLast time the condition transitioned.
reason stringUnique, one-word, CamelCase reason for the condition's last transition.
message stringHuman-readable message indicating details about last transition.

QueueConditionType

Underlying type: string

Appears in:

QueueList

QueueList is a collection of queues.

FieldDescription
apiVersion stringscheduler.tensorstack.dev/v1beta1
kind stringQueueList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items Queue arrayThe list of Queue.

QueueSpec

QueueSpec represents the desired specification of a Queue.

Appears in:

FieldDescription
quota QuotaRequirements
priority integerIf specified, indicates the Queue's priority. range is [0,100] The higher value of priority, workloads in this queue will be scheduled with resources with higher preferences.
preemptible booleanPreemptible indicate whether the queue can be preempted by other queue when cluster resources are in short. Queue can be preempted if Preemptible is not set.
closed booleanAfter queue is closed, new workloads (pods) will not be allocated with resources and no new workloads will be accepted either.
maxDuration DurationDefine the max lifetime of Pod using the Queue. Supported units: y, w, d, h, m, s, ms. Examples: 30s, 1m, 1h20m15s, 15d.
resourceShapeProfile stringSpecify ResourceShape profile used by the Queue.
nodeSelector LabelSelectorNodeSelector specifies the nodes whoses resource can be used by a Queue. This provides a machanism to restrict workloads submitted to a particular queue to a sub-set of nodes in the cluster. if nil, all nodes are eligible.
namespaceSelector LabelSelectorNamespaceSelector specifies the set of namespaces from which workloads are allowed to use this Queue. if nil, no namespaces are selected. Note: There may be other authorization procedures that permit workloads in a queue. They are OR'ed with this selector.

QueueStatus

QueueStatus represents the status of Queue.

Appears in:

FieldDescription
allocated object (keys:ResourceName, values:Quantity)Count of resource allocated to the queue.
conditions QueueCondition arrayCurrent service state of Queue.
podGroups PodGroupInQueueStatusPodGroup Status in Queue.
pods PodInQueueStatusPod Status in Queue.

QuotaRequirements

Appears in:

FieldDescription
requests object (keys:ResourceName, values:Quantity)Requests describes max amount of resources pods in the Queue can potentially request. However, these are the upper limits for resources, not necessarily always available for use. This can be used by cluster administrators to control the upper bounds of resources submitted to a particular queue. Togethe with allowed users of queues, this provides a mechanism for admins to set policies to constrain some aspects of user resource usages.

Role

Role describes pod's role and minMember constraint for this role.

Appears in:

FieldDescription
name stringRole Name
minMember integerMinMember defines minimal number of pods of the role.

API Reference

Packages

batch.tensorstack.dev/v1beta1

Package v1beta1 defines the CRD types.

Resource Types

BeamJobWorkflowTemplate

BeamJobWorkflowTemplate creates a t9k beam job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec BeamJobSpecSpec of the beam job.

ColossalAIJobWorkflowTemplate

ColossalAIJobWorkflowTemplate creates a t9k colossalai job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec ColossalAIJobSpecSpec of the colossalai job.

ConcurrencyPolicy

Underlying type: string

ConcurrencyPolicy describes how the WorkflowRun will be handled. Only one of the following concurrent policies may be specified. If none of the following policies is specified, the default one is AllowConcurrent.

Appears in:

ConditionSelector

ConditionSelector selects a k8s resource if its status.conditions contains a condition whose type and status are exactly the same as those of the condition selector.

Appears in:

FieldDescription
type stringType of the condition.
status ConditionStatusStatus of the condition, one of True, False, or Unknown.

CronWorkflowRun

CronWorkflowRun is the Schema for the CronWorkflowRun API

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/apis
kind stringCronWorkflowRun
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec CronWorkflowRunSpec
status CronWorkflowRunStatus

CronWorkflowRunCondition

CronWorkflowRunCondition is an observation of the condition of the CronWorkflowRun.

Appears in:

FieldDescription
type CronWorkflowRunConditionTypeType of CronWorkflowRun condition.
status ConditionStatusStatus of the condition, one of True, False, or Unknown.
reason stringThe reason for the condition's last transition.
message stringA readable message indicating details about the transition.
lastTransitionTime TimeLast time the condition transitioned from one status to another.

CronWorkflowRunConditionType

Underlying type: string

CronWorkflowRunConditionType defines all possible types of CronWorkflowRunCondition. Can be one of: HasStarted, IsRunning, HasSuccessfulRun, HasFailedRun.

Appears in:

CronWorkflowRunList

CronWorkflowRunList contains a list of CronWorkflowRun

FieldDescription
apiVersion stringbatch.tensorstack.dev/apis
kind stringCronWorkflowRunList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items CronWorkflowRun array

CronWorkflowRunSpec

CronWorkflowRunSpec defines the desired state of CronWorkflowRun.

Appears in:

FieldDescription
schedule stringSchedule defines the schedule for the running of WorkflowRuns.
concurrencyPolicy ConcurrencyPolicySpecifies how to treat concurrent executions of a WorkflowRun. Valid values are: - "Allow" (default): allows WorkflowRuns to run concurrently; - "Forbid": forbids concurrent runs, skipping next run if previous run hasn't finished yet; - "Replace": cancels currently running WorkflowRun and replaces it with a new one
successfulRunsHistoryLimit integerThe number of successful finished WorkflowRuns to retain. This is a pointer to distinguish between explicit zero and not specified.
failedRunsHistoryLimit integerThe number of failed finished WorkflowRuns to retain. This is a pointer to distinguish between explicit zero and not specified.
startingDeadlineSeconds integerDeadline in seconds for starting the WorkflowRuns if it misses scheduled time for any reason. Missed WorkflowRun runs will be counted as failed ones.
suspend booleanThis flag tells the controller to suspend subsequent runs, it does not apply to already started runs. Defaults to false.
workflowRun WorkflowRunTemplateSpecSpecifies the WorkflowRun that will be created when executing a CronWorkflowRun.

CronWorkflowRunStatus

CronWorkflowRunStatus defines the observed state of CronWorkflowRun.

Appears in:

FieldDescription
active ObjectReference arrayA list of pointers to currently running WorkflowRuns.
lastScheduleTime TimeThe last time when the WorkflowRun was successfully created.
conditions CronWorkflowRunCondition arrayThe latest available observations of the CronWorkflowRun's current state.

DAGNode

DAGNode represents a node in the graph during DAG execution.

Appears in:

FieldDescription
name stringName is the name of this node within the DAG.
workflowTemplateRef stringWorkflowTemplateRef is a reference to a workflowTemplate definition.
when WhenExpression arrayWhenExpressions is a list of when expressions that need to be true for the node to run
retries integerRetries represents how many times this node should be retried in case of failure: Condition Succeeded set to False
dependencies string arrayDependencies are name of other nodes which this depends on, to force a specific ordering in graph execution.
params Param arrayParameters declares parameters passed to this node.
workspaces WorkspaceDAGBinding arrayWorkspaces maps workspaces from the DAG WorkflowTemplate spec to the workspaces declared in the node.

DAGWorkflowTemplate

DAGWorkflowTemplate creates a dag consisting of other WorkflowTemplates.

Appears in:

FieldDescription
templates DAGNode arrayTemplates are a list of DAG nodes.
failureStrategy FailureStrategyFailureStrategy is the strategy when a node in DAG fails.

DeepSpeedJobWorkflowTemplate

DeepSpeedJobWorkflowTemplate creates a t9k deepspeed job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec DeepSpeedJobSpecSpec of the deepspeed job.

FailureStrategy

Underlying type: string

FailureStrategy defines the failure strategy of DAGWorkflowTemplate.

Appears in:

GenericJobWorkflowTemplate

GenericJobWorkflowTemplate creates a t9k generic job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec GenericJobSpecSpec of the generic job.

MPIJobWorkflowTemplate

MPIJobWorkflowTemplate creates a t9k mpi job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec MPIJobSpecSpec of the mpi job.

NodePhase

Underlying type: string

NodePhase is the current state of a node. Node means the node in a DAG. PodWorkflowTemplate, SeqPodWorkflowTemplate and ResourceWorkflowTemplate are also considered as an independent node. DAGWorkflowTemplate itself is considered as a parent node.

Appears in:

NodeStatus

NodeStatus is the status of a node in DAG

Appears in:

FieldDescription
workflowRunName stringWorkflowRunName is the name of WorkflowRun created from the node.
phase NodePhasePhase is the phase of the node.
whenExpressions WhenExpression arrayWhenExpressions show why if the node is skipped.

Param

Param declares a string to use for the parameter called name.

Appears in:

FieldDescription
name string
value string

ParamSpec

ParamSpec defines values that are provided by users as inputs on a WorkflowRun.

Appears in:

FieldDescription
name stringName declares the name by which a parameter is referenced.
description stringDescription is a user-facing description of the parameter that may be used to populate a UI.
default stringDefault is the value a parameter takes if no input value is supplied. If default is set, a WorkflowTemplate may be executed without a supplied value for the parameter. It serves as a pointer to distinguish between setting no default and setting empty string as default.

PodSpecWithoutContainers

PodSpecWithoutContainers is a helper struct for SeqPodWorkflowTemplate forked from https://github.com/kubernetes/api/blob/v0.20.0/core/v1/types.go#L2914

Appears in:

FieldDescription
volumes Volume arrayList of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes
initContainers Container arrayList of initialization containers belonging to the pod. Init containers are executed in order prior to containers being started. If any init container fails, the pod is considered to have failed and is handled according to its restartPolicy. The name for an init container or normal container must be unique among all containers. Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. The resourceRequirements of an init container are taken into account during scheduling by finding the highest request/limit for each resource type, and then using the max of of that value or the sum of the normal containers. Limits are applied to init containers in a similar fashion. Init containers cannot currently be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
ephemeralContainers EphemeralContainer arrayList of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. This field is alpha-level and is only honored by servers that enable the EphemeralContainers feature.
restartPolicy RestartPolicyRestart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
terminationGracePeriodSeconds integerOptional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.
activeDeadlineSeconds integerOptional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.
dnsPolicy DNSPolicySet DNS policy for the pod. Defaults to "ClusterFirst". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'.
nodeSelector object (keys:string, values:string)NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
serviceAccountName stringServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
serviceAccount stringDeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.
automountServiceAccountToken booleanAutomountServiceAccountToken indicates whether a service account token should be automatically mounted.
nodeName stringNodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.
hostNetwork booleanHost networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.
hostPID booleanUse the host's pid namespace. Optional: Default to false.
hostIPC booleanUse the host's ipc namespace. Optional: Default to false.
shareProcessNamespace booleanShare a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false.
securityContext PodSecurityContextSecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.
imagePullSecrets LocalObjectReference arrayImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod
hostname stringSpecifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.
subdomain stringIf specified, the fully qualified Pod hostname will be "...svc.". If not specified, the pod will not have a domainname at all.
affinity AffinityIf specified, the pod's scheduling constraints
schedulerName stringIf specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler.
tolerations Toleration arrayIf specified, the pod's tolerations.
hostAliases HostAlias arrayHostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts file if specified. This is only valid for non-hostNetwork pods.
priorityClassName stringIf specified, indicates the pod's priority. "system-node-critical" and "system-cluster-critical" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.
priority integerThe priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.
dnsConfig PodDNSConfigSpecifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.
readinessGates PodReadinessGate arrayIf specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md
runtimeClassName stringRuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md This is a beta feature as of Kubernetes v1.14.
enableServiceLinks booleanEnableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. Optional: Defaults to true.
preemptionPolicy PreemptionPolicyPreemptionPolicy is the Policy for preempting pods with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. This field is beta-level, gated by the NonPreemptingPriority feature-gate.
overhead object (keys:ResourceName, values:Quantity)Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. This field will be autopopulated at admission time by the RuntimeClass admission controller. If the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. The RuntimeClass admission controller will reject Pod create requests which have the overhead already set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md This field is alpha-level as of Kubernetes v1.16, and is only honored by servers that enable the PodOverhead feature.
topologySpreadConstraints TopologySpreadConstraint arrayTopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed.
setHostnameAsFQDN booleanIf true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters to FQDN. If a pod does not have FQDN, this has no effect. Default to false.

PodWorkflowTemplate

PodWorkflowTemplate creates a pod.

Appears in:

FieldDescription
PodSpec PodSpec

PyTorchTrainingJobWorkflowTemplate

PyTorchTrainingJobWorkflowTemplate creates a t9k pytorch training job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec PyTorchTrainingJobSpecSpec of the pytorch training job.

ResourceWorkflowTemplate

ResourceWorkflowTemplate creates a k8s resource.

Appears in:

FieldDescription
successRules RulesSuccessRules is an expression which describes the state of the k8s resource in which the task was considered succeeded.
failureRules RulesFailureRules is an expression which describes the state of the k8s resource in which the task was considered failed.
manifest stringManifest is the full spec of the k8s resource to create.

Result

Result used to describe the results of a task

Appears in:

FieldDescription
name stringName the given name
description stringDescription is a human-readable description of the result
value stringValue is a expression to generate DAG result by combining node results Only required for DAG WorkflowTemplate

Rules

Rules describe the state of the k8s resource.

Appears in:

FieldDescription
fieldSelector stringFieldSelector selects k8s resources based on the value of one or more resource fields, examples: metadata.name=my-service metadata.namespace!=default status.phase!=Running,spec.restartPolicy=Always
conditionSelector ConditionSelectorConditionSelector selects k8s resources based on .status.conditions.

SchedulePolicy

SchedulePolicy defines how k8s schedules the WorkflowRun.

Appears in:

FieldDescription
t9kScheduler T9kSchedulerT9k Scheduler.

SeqPodWorkflowTemplate

SeqPodWorkflowTemplate creates a pod whose containers run sequentially. The spec of SeqPodWorkflowTemplate is almost the same with corev1.PodSpec, except that the field Containers is replaced by Steps, to emphasize the sequential execution pattern.

Appears in:

FieldDescription
PodSpecWithoutContainers PodSpecWithoutContainers
steps Step arraySteps are the sequentially running containers of the SeqPodWorkflowTemplate

Step

Step embeds the Container type, which allows it to include fields not provided by Container.

Appears in:

FieldDescription
Container Container
script stringScript is the contents of an executable file to execute. If Script is not empty, the Step cannot have an Command and the Args will be passed to the Script.

T9kScheduler

T9kScheduler provides additonal configurations needed for the scheduling process.

Appears in:

FieldDescription
queue stringSpecifies the name of the queue should be used for running this workload.

TensorFlowTrainingJobWorkflowTemplate

TensorFlowTrainingJobWorkflowTemplate creates a t9k training job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec TensorFlowTrainingJobSpecSpec of the training job.

WhenExpression

WhenExpression allows a node in DAG to declare expressions to be evaluated before the node is run to determine whether the node should be executed or skipped.

Appears in:

FieldDescription
input stringInput is the string for guard checking which can be a static input or an output from a parent node
operator OperatorOperator that represents an Input's relationship to the values
values string arrayValues is an array of strings, which is compared against the input, for guard checking It must be non-empty

WorkflowRun

WorkflowRun is the Schema for the workflowrun API

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/apis
kind stringWorkflowRun
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec WorkflowRunSpec
status WorkflowRunStatus

WorkflowRunCondition

WorkflowRunCondition is an observation of the condition of the WorkflowRun.

Appears in:

FieldDescription
type WorkflowRunConditionTypeType of WorkflowRun condition.
status ConditionStatusStatus of the condition, one of True, False, or Unknown.
reason stringThe reason for the condition's last transition.
message stringA readable message indicating details about the transition.
lastTransitionTime TimeLast time the condition transitioned from one status to another.

WorkflowRunConditionType

Underlying type: string

WorkflowRunConditionType defines all possible types of WorkflowRunConditionType. Can be one of: Running, Completed.

Appears in:

WorkflowRunList

WorkflowRunList contains a list of WorkflowRun

FieldDescription
apiVersion stringbatch.tensorstack.dev/apis
kind stringWorkflowRunList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items WorkflowRun array

WorkflowRunResult

WorkflowRunResult used to describe the results of a workflowTemplate

Appears in:

FieldDescription
name stringName the given name
value stringValue the given value of the result

WorkflowRunSpec

WorkflowRunSpec defines the desired state of WorkflowRun

Appears in:

FieldDescription
workspaces WorkspaceBinding arrayWorkspaces is a list of mappings from volumes to workspace names that will be supplied to WorkflowTemplate.
params Param arrayParams is a list of input parameters that will be supplied to WorkflowTemplate.
serviceAccountName stringServiceAccountName is the name of the service account that the created pod will use.
workflowTemplateRef stringWorkflowTemplateRef is the name of the WorkflowTemplate that WorkflowRun will use. No more than one of the WorkflowTemplateRef and WorkflowTemplateSpec may be specified.
workflowTemplateSpec WorkflowTemplateSpecWorkflowTemplateSpec is an embedded spec of WorkflowTemplate that WorkflowRun will use. No more than one of the WorkflowTemplateRef and WorkflowTemplateSpec may be specified.
timeout DurationTime after which the build times out. Defaults to never. Refer Go's ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration
depth integerDepth indicates the depth of the WorkflowRun in DAG. If Depth exceeds limit, the WorkflowRun will not be created.
scheduler SchedulePolicyIdentifies the preferred scheduler for allocating resources to replicas. Defaults to cluster default scheduler.

WorkflowRunStatus

WorkflowRunStatus defines the observed state of WorkflowRun

Appears in:

FieldDescription
WorkflowRunStatusFields WorkflowRunStatusFieldsWorkflowRunStatusFields inlines the status fields.
retriedStatus WorkflowRunStatusFields arrayRetriedStatus contains the history of WorkflowRunStatus in case of a retry in order to keep record of failures.

WorkflowRunStatusFields

WorkflowRunStatusFields are the main fields of WorkflowRunStatus

Appears in:

FieldDescription
phase NodePhasePhase is a simple, high-level summary of where the WorkflowRun is in its lifecycle.
message stringA human readable message indicating details about why the WorkflowRun is in this condition.
nodes object (keys:string, values:NodeStatus)Nodes is a map of DAG nodes status, with the node name as the key.
startTime TimeStartTime is the time the build is actually started.
completionTime TimeCompletionTime is the time the build completed.
results WorkflowRunResult arrayResults are the list of results written out by the workflowTemplate's containers
workflowTemplateSpec WorkflowTemplateSpecWorkflowTemplateSpec contains the Spec from the dereferenced WorkflowTemplate definition used to instantiate this WorkflowRun.
podName stringPodName is the name of the pod created by WorkflowRun.
conditions WorkflowRunCondition arrayThe latest available observations of the WorkflowRun's current state.

WorkflowRunTemplateSpec

WorkflowRunTemplateSpec describes the data a WorkflowRun should have when created from a template

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec WorkflowRunSpecSpecification of the desired behavior of the WorkflowRun.

WorkflowTemplate

WorkflowTemplate is the Schema for the WorkflowTemplate API

Appears in:

FieldDescription
apiVersion stringbatch.tensorstack.dev/apis
kind stringWorkflowTemplate
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec WorkflowTemplateSpec
status WorkflowTemplateStatus

WorkflowTemplateList

WorkflowTemplateList contains a list of WorkflowTemplate

FieldDescription
apiVersion stringbatch.tensorstack.dev/apis
kind stringWorkflowTemplateList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items WorkflowTemplate array

WorkflowTemplateSpec

WorkflowTemplateSpec defines the desired state of WorkflowTemplate.

Appears in:

FieldDescription
description stringDescription is a user-facing description of the task that may be used to populate a UI.
workspaces WorkspaceDeclaration arrayWorkspaces are the volumes that this WorkflowTemplate requires. Workspaces must be supplied as inputs in WorkflowRuns unless they are declared as optional.
params ParamSpec arrayParams is a list of input parameters required to run the task. Params must be supplied as inputs in WorkflowRuns unless they declare a default value.
results Result arrayResults are values that this WorkflowTemplate can output
type WorkflowTemplateTypeType defines the type of WorkflowTemplate. If empty, the first non-nil field in (pod, seqPod, resource, dag) will be the type.
pod PodWorkflowTemplatePod is the spec of pod which WorkflowTemplate will create.
seqPod SeqPodWorkflowTemplateSeqPod is the spec of pod with sequentially running containers which WorkflowTemplate will create.
resource ResourceWorkflowTemplateResource is the spec of k8s resource which WorkflowTemplate will create.
dag DAGWorkflowTemplateDAG is the spec of DAG which WorkflowTemplate will create.
genericJob GenericJobWorkflowTemplateGenericJob is the spec of t9k generic job which WorkflowTemplate will create.
tensorflowTrainingJob TensorFlowTrainingJobWorkflowTemplateTensorFlowTrainingJob is the spec of t9k training job which WorkflowTemplate will create.
pytorchTrainingJob PyTorchTrainingJobWorkflowTemplatePyTorchTrainingJob is the spec of t9k pytorch training job which WorkflowTemplate will create.
xgboostTrainingJob XGBoostTrainingJobWorkflowTemplateXGBoostTrainingJob is the spec of t9k xgboost training job which WorkflowTemplate will create.
colossalaiJob ColossalAIJobWorkflowTemplateColossalAIJob is the spec of t9k colossalai job which WorkflowTemplate will create.
deepspeedJob DeepSpeedJobWorkflowTemplateDeepSpeedJob is the spec of t9k deepspeed job which WorkflowTemplate will create.
mpiJob MPIJobWorkflowTemplateMPIJob is the spec of t9k mpi job which WorkflowTemplate will create.
beamJob BeamJobWorkflowTemplateBeamJob is the spec of t9k beam job which WorkflowTemplate will create.

WorkflowTemplateType

Underlying type: string

WorkflowTemplateType defines the type of WorkflowTemplate.

Appears in:

WorkspaceBinding

WorkspaceBinding maps a WorkflowTemplate's declared workspace to a Volume.

Appears in:

FieldDescription
name stringName is the name of the workspace populated by the volume.
subPath stringSubPath is optionally a directory on the volume which should be used for this binding (i.e. the volume will be mounted at this sub directory).
persistentVolumeClaim PersistentVolumeClaimVolumeSourcePersistentVolumeClaimVolumeSource represents a reference to a PersistentVolumeClaim in the same namespace. Either this OR EmptyDir can be used.
emptyDir EmptyDirVolumeSourceEmptyDir represents a temporary directory that shares a WorkflowTemplate's lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir Either this OR PersistentVolumeClaim can be used.
configMap ConfigMapVolumeSourceConfigMap represents a configMap that should populate this workspace.
secret SecretVolumeSourceSecret represents a secret that should populate this workspace.

WorkspaceDAGBinding

WorkspaceDAGBinding describes how a workspace passed into a DAG WorkflowTemplate should be mapped to a node's declared workspace.

Appears in:

FieldDescription
name stringName is the name of the workspace as declared by the node
workspace stringWorkspace is the name of the workspace declared by the DAG WorkflowTemplate
subPath stringSubPath is optionally a directory on the volume which should be used for this binding (i.e. the volume will be mounted at this sub directory).

WorkspaceDeclaration

WorkspaceDeclaration is a declaration of a volume that a WorkflowTemplate requires.

Appears in:

FieldDescription
name stringName is the name by which you can bind the volume at runtime.
description stringDescription is an optional human readable description of this volume.
mountPath stringMountPath overrides the directory that the volume will be made available at.
readOnly booleanReadOnly dictates whether a mounted volume is writable. By default this field is false and so mounted volumes are writable.
optional booleanOptional marks a Workspace as not being required in WorkflowRuns. By default this field is false and so declared workspaces are required.

XGBoostTrainingJobWorkflowTemplate

XGBoostTrainingJobWorkflowTemplate creates a t9k xgboost training job.

Appears in:

FieldDescription
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec XGBoostTrainingJobSpecSpec of the xgboost training job.

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

Condition

Condition contains details about resource state

Appears in:

FieldDescription
type ConditionTypeCondition type.
status ConditionStatusCondition status, True, False or Unknown.
lastTransitionTime TimeLast time the condition transitioned from one status to another.
message stringHuman-readable message indicating details about last transition.

ConditionType

Underlying type: string

ConditionType is a valid value of Condition.Type

Appears in:

EventListener

EventListener is the Schema for the eventlisteners API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringEventListener
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec EventListenerSpec
status EventListenerStatus

EventListenerAddress

The access address for in-cluster and out-cluster

Appears in:

FieldDescription
url stringThe access address for out-cluster
inClusterURL stringThe access address for in-cluster

EventListenerList

EventListenerList contains a list of EventListener

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringEventListenerList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items EventListener array

EventListenerSpec

EventListenerSpec defines the desired state of EventListener

Appears in:

FieldDescription
replicas integerNumber of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.
resources ResourceRequirementsCompute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

EventListenerStatus

EventListenerStatus defines the observed state of EventListener

Appears in:

FieldDescription
address EventListenerAddressThe access address for in-cluster and out-cluster
conditions Condition arrayRepresents the latest available observations of a eventListener's current state.

EventSource

The source that events come from.

Appears in:

FieldDescription
eventListenerName stringName of an existing EventListener.
filters Filter arrayList of filters to filter events from the EventListener.

Filter

Filter defines how to filter events from the EventListener.

Appears in:

FieldDescription
path stringPath is the JSONPath of the event's (JSON decoded) data key Path is a series of keys separated by a dot. A key may contain wildcard characters '*' and '?'. To access an array value use the index as the key. The dot and wildcard characters can be escaped with '\'. See https://github.com/tidwall/gjson#path-syntax for more information on how to use this.
type JSONTypeType contains the JSON type of the data
values string arrayValues is the allowed string values for this key Booleans are passed using strconv.ParseBool() Numbers are parsed using as float64 using strconv.ParseFloat() Strings are taken as is Nils this value is ignored

JSONType

Underlying type: string

JSONType contains the supported JSON types for data filtering

Appears in:

WorkflowTrigger

WorkflowTrigger is the Schema for the workflowtriggers API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringWorkflowTrigger
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec WorkflowTriggerSpec
status WorkflowTriggerStatus

WorkflowTriggerList

WorkflowTriggerList contains a list of WorkflowTrigger

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringWorkflowTriggerList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items WorkflowTrigger array

WorkflowTriggerSpec

WorkflowTriggerSpec defines the desired state of WorkflowTrigger

Appears in:

FieldDescription
replicas integerNumber of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1.
eventSources EventSource arrayList of sources that events come from.
serviceAccountName stringName of a service account used by WorkflowTrigger to create WorkflowRuns.
resources ResourceRequirementsCompute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
workflowRunSpec WorkflowRunSpecSpec of WorkflowRun to be created by WorkflowTrigger.

WorkflowTriggerStatus

WorkflowTriggerStatus defines the observed state of WorkflowTrigger

Appears in:

FieldDescription
conditions Condition arrayRepresents the latest available observations of a eventListener's current state.

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

Address

Appears in:

FieldDescription
url stringthe service's in-cluster url, e.g. managed-simplemlservice-41309.demo.svc.cluster.local
ports AddressPort arrayan array of serivce port & protocol

AddressPort

AddressPort stores ports defined in service of simplemlservice

Appears in:

FieldDescription
port integerThe port that will be exposed by this service.
nodePort integerThe port on each node on which this service is exposed when type=NodePort or LoadBalancer. Usually assigned by the system. If specified, it will be allocated to the service if unused or else creation of the service will fail. Default is to auto-allocate a port if the ServiceType of this Service requires one. More info: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
protocol ProtocolThe IP protocol for this port. Supports "TCP", "UDP", and "SCTP". Default is TCP.

Condition

Condition for simpleMLService

Appears in:

FieldDescription
lastTransitionTime Time
type SimpleMLServiceConditionType
status ConditionStatus
reason string
message string

CustomSpec

CustomSpec defines a pod template to run model serving

Appears in:

FieldDescription
spec PodSpec

DeploymentSpec

DeploymentSpec defines the configuration for replicas & scheduler

Appears in:

FieldDescription
scheduler SchedulePolicyScheduler responsible for handling resource allocation requests. default is default-scheduler
replicas integerReplicas of pods running model serving
strategy DeploymentStrategyThe deployment strategy to use to replace existing pods with new ones

PVCStorage

PVCStorage defines infos of pvc

Appears in:

FieldDescription
name stringPVC name
subPath stringDirectory path where model is located in PVC. Must be a relative path. e.g. "model/mnist"
mountPath stringDirectory path where model locates in container. Must be absolute path, default is "/var/lib/t9k/model"

PyTorchSpec

PyTorchSpec defines arguments for configuring PyTorch model serving

Appears in:

FieldDescription
modelsFlag stringValue of torchserve's flag --models
image stringImage of torchserve
resources ResourceRequirementsCompute Resources required by a replica

S3Storage

S3Storage defines infos of s3

Appears in:

FieldDescription
secretRef LocalObjectReferenceSecretRef is reference to the secret storing s3cmd config
uri stringDirectory path where model locates in s3. e.g. "s3://<bucket>/<dir>/"
mountPath stringDirectory path where model locates in container, default is "/var/lib/t9k/model"

SchedulePolicy

SchedulePolicy defines which scheduler is responsible for handling resource allocation requests

Appears in:

FieldDescription
t9kScheduler T9kSchedulerUse t9k-scheduler

ServiceSpec

ServiceSpec defines the desired state of Service created by Controller

Appears in:

FieldDescription
ports ServicePort arrayThe list of ports that are exposed by this service. More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies
type ServiceTypetype determines how the Service is exposed. Defaults to ClusterIP. Valid options are ExternalName, ClusterIP, NodePort, and LoadBalancer. "ExternalName" maps to the specified externalName. "ClusterIP" allocates a cluster-internal IP address for load-balancing to endpoints. Endpoints are determined by the selector or if that is not specified, by manual construction of an Endpoints object. If clusterIP is "None", no virtual IP is allocated and the endpoints are published as a set of endpoints rather than a stable IP. "NodePort" builds on ClusterIP and allocates a port on every node which routes to the clusterIP. "LoadBalancer" builds on NodePort and creates an external load-balancer (if supported in the current cloud) which routes to the clusterIP. More info: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types

SimpleMLService

SimpleMLService is the Schema for the simplemlservices API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringSimpleMLService
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec SimpleMLServiceSpec
status SimpleMLServiceStatus

SimpleMLServiceConditionType

Underlying type: string

SimpleMLServiceConditionType is a type

Appears in:

SimpleMLServiceList

SimpleMLServiceList contains a list of SimpleMLService

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringSimpleMLServiceList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items SimpleMLService array

SimpleMLServiceSpec

SimpleMLServiceSpec defines the desired state of SimpleMLService

Appears in:

FieldDescription
tensorflow TensorflowSpecSpec for Tensorflow Serving (https://github.com/tensorflow/serving)
pytorch PyTorchSpecSpec for TorchServe
custom CustomSpecCustom Spec
storage StorageStorage of model
DeploymentSpec DeploymentSpecConfiguration for replicas & scheduler
service ServiceSpecConfiguration for service. Controller will create default service if spec.service not set

SimpleMLServiceStatus

SimpleMLServiceStatus defines the observed state of SimpleMLService

Appears in:

FieldDescription
address Address
conditions Condition array

Storage

Storage defines the storage where the model locates

Appears in:

FieldDescription
s3 S3StorageModel locates in S3
pvc PVCStorageModel locates in pvc

T9kScheduler

T9kScheduler defines SimpleMLService use t9k-scheduler.

Appears in:

FieldDescription
queue stringName of queue which SimpleMLService's pod belongs to

TensorflowSpec

TensorflowSpec defines arguments for configuring Tensorflow model serving

Appears in:

FieldDescription
image stringImage of Tensorflow Serving
resources ResourceRequirementsCompute Resources required by a replica

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

AddressStatus

AddressStatus store state of serving address

Appears in:

FieldDescription
url stringURL used for predictor.

ContainerResources

Appears in:

FieldDescription
name stringName of container
resources ResourceRequirementsResource requirements

DeploymentSpec

DeploymentSpec defines the configuration for knative service

Appears in:

FieldDescription
minReplicas integerMinimum number of replicas, pods won't scale down to 0 in case of no traffic
maxReplicas integerThis is the up bound for autoscaler to scale to
template PatchTemplateSpecCustom template of knative service
logger LoggerSpecLogger spec

EditableMetadata

Metadata includes the editable part of metav1.ObjectMeta. Now only contains labels and annotations

Appears in:

FieldDescription
labels object (keys:string, values:string)Labels
annotations object (keys:string, values:string)Annotations

LoggerMode

Underlying type: string

Appears in:

LoggerSpec

Appears in:

FieldDescription
urls string arrayLogger sink url array
mode LoggerModeLogger mode
resources ResourceRequirementsResource requirements

MLService

MLService is the Schema for the mlservices API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringMLService
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec MLServiceSpec
status MLServiceStatus

MLServiceCondition

Appears in:

FieldDescription
type MLServiceConditionTypeType of condition.
status ConditionStatusStatus of the condition, one of True, False, Unknown.
lastTransitionTime TimeLast time the condition transitioned from one status to another.
reason stringThe reason for the condition's last transition.
message stringA human readable message indicating details about the transition.

MLServiceConditionType

Underlying type: string

Appears in:

MLServiceList

MLServiceList contains a list of MLService

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringMLServiceList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items MLService array

MLServiceRuntime

MLServiceRuntime is the Schema for the mlserviceruntimes API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringMLServiceRuntime
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec MLServiceRuntimeSpec
status MLServiceRuntimeStatus

MLServiceRuntimeList

MLServiceRuntimeList contains a list of MLServiceRuntime

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringMLServiceRuntimeList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items MLServiceRuntime array

MLServiceRuntimeSpec

Appears in:

FieldDescription
enabled booleanSet true if enabled
template RuntimeTemplateSpecTemplate defines the knative revision that will be created from this pod template.

MLServiceSpec

MLServiceSpec defines the desired state of MLService

Appears in:

FieldDescription
releases ReleaseSpec arrayReleases define multiple versions of predictor
transformer TransformerSpecTransformer will pre-process and post-process data
default stringDefault specifies the release name which will be used as default version.
canary stringCanary specifies the release name which will be used as canary version.
canaryTrafficPercent integerCanaryTrafficPercent specifies traffic percent of canary version, range is (0,100).
scheduler SchedulePolicyDefault Scheduler is default-scheduler
runMode RunModeMLService RunMode

MLServiceStatus

MLServiceStatus defines the observed state of MLService

Appears in:

FieldDescription
defaultRelease stringDefault release name
canaryRelease stringCanary release name
conditions MLServiceCondition arrayConditions
releases ReleaseStatus arrayThe observed statuses of MLService releases
transformer TransformerStatusThe observed statuses of transformers.
address AddressStatusAddress

ModelSpec

Appears in:

FieldDescription
parameters object (keys:string, values:string)Model parameters
runtime stringSpecific ServingRuntime name to use for deployment.

PVCStorage

PVCStorage defines infos of pvc

Appears in:

FieldDescription
name stringPVC name
subPath stringDirectory path where model is located in PVC. Must be a relative path. e.g. "model/mnist" Defaults to "" (volume's root).
mountPath stringDirectory path where model locates in container, default is "/var/lib/t9k/model"

PatchTemplateSpec

podSpec and containers are optional. This will be patched to runtime

Appears in:

FieldDescription
metadata EditableMetadataRefer to Kubernetes API documentation for fields of metadata.
spec PodSpecPod Spec with optional containers

PodSpec

PodSpec is a description of a pod.

Appears in:

FieldDescription
volumes Volume arrayList of volumes that can be mounted by containers belonging to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes
initContainers Container arrayList of initialization containers belonging to the pod. Init containers are executed in order prior to containers being started. If any init container fails, the pod is considered to have failed and is handled according to its restartPolicy. The name for an init container or normal container must be unique among all containers. Init containers may not have Lifecycle actions, Readiness probes, Liveness probes, or Startup probes. The resourceRequirements of an init container are taken into account during scheduling by finding the highest request/limit for each resource type, and then using the max of of that value or the sum of the normal containers. Limits are applied to init containers in a similar fashion. Init containers cannot currently be added or removed. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/
containers Container arrayList of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated.
ephemeralContainers EphemeralContainer arrayList of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. This field is alpha-level and is only honored by servers that enable the EphemeralContainers feature.
restartPolicy RestartPolicyRestart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
terminationGracePeriodSeconds integerOptional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.
activeDeadlineSeconds integerOptional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.
dnsPolicy DNSPolicySet DNS policy for the pod. Defaults to "ClusterFirst". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'.
nodeSelector object (keys:string, values:string)NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
serviceAccountName stringServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
serviceAccount stringDeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.
automountServiceAccountToken booleanAutomountServiceAccountToken indicates whether a service account token should be automatically mounted.
nodeName stringNodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.
hostNetwork booleanHost networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.
hostPID booleanUse the host's pid namespace. Optional: Default to false.
hostIPC booleanUse the host's ipc namespace. Optional: Default to false.
shareProcessNamespace booleanShare a single process namespace between all of the containers in a pod. When this is set containers will be able to view and signal processes from other containers in the same pod, and the first process in each container will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both be set. Optional: Default to false.
securityContext PodSecurityContextSecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.
imagePullSecrets LocalObjectReference arrayImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod
hostname stringSpecifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.
subdomain stringIf specified, the fully qualified Pod hostname will be "...svc.". If not specified, the pod will not have a domainname at all.
affinity AffinityIf specified, the pod's scheduling constraints
schedulerName stringIf specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler.
tolerations Toleration arrayIf specified, the pod's tolerations.
hostAliases HostAlias arrayHostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts file if specified. This is only valid for non-hostNetwork pods.
priorityClassName stringIf specified, indicates the pod's priority. "system-node-critical" and "system-cluster-critical" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.
priority integerThe priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.
dnsConfig PodDNSConfigSpecifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.
readinessGates PodReadinessGate arrayIf specified, all readiness gates will be evaluated for pod readiness. A pod is ready when all its containers are ready AND all conditions specified in the readiness gates have status equal to "True" More info: https://git.k8s.io/enhancements/keps/sig-network/0007-pod-ready%2B%2B.md
runtimeClassName stringRuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md This is a beta feature as of Kubernetes v1.14.
enableServiceLinks booleanEnableServiceLinks indicates whether information about services should be injected into pod's environment variables, matching the syntax of Docker links. Optional: Defaults to true.
preemptionPolicy PreemptionPolicyPreemptionPolicy is the Policy for preempting pods with lower priority. One of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset. This field is beta-level, gated by the NonPreemptingPriority feature-gate.
overhead object (keys:ResourceName, values:Quantity)Overhead represents the resource overhead associated with running a pod for a given RuntimeClass. This field will be autopopulated at admission time by the RuntimeClass admission controller. If the RuntimeClass admission controller is enabled, overhead must not be set in Pod create requests. The RuntimeClass admission controller will reject Pod create requests which have the overhead already set. If RuntimeClass is configured and selected in the PodSpec, Overhead will be set to the value defined in the corresponding RuntimeClass, otherwise it will remain unset and treated as zero. More info: https://git.k8s.io/enhancements/keps/sig-node/20190226-pod-overhead.md This field is alpha-level as of Kubernetes v1.16, and is only honored by servers that enable the PodOverhead feature.
topologySpreadConstraints TopologySpreadConstraint arrayTopologySpreadConstraints describes how a group of pods ought to spread across topology domains. Scheduler will schedule pods in a way which abides by the constraints. All topologySpreadConstraints are ANDed.
setHostnameAsFQDN booleanIf true the pod's hostname will be configured as the pod's FQDN, rather than the leaf name (the default). In Linux containers, this means setting the FQDN in the hostname field of the kernel (the nodename field of struct utsname). In Windows containers, this means setting the registry value of hostname for the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters to FQDN. If a pod does not have FQDN, this has no effect. Default to false.

PredictorSpec

PredictorSpec defines the configuration for a predictor, The following fields follow a "1-of" semantic. Users must specify exactly one spec.

Appears in:

FieldDescription
model ModelSpecModel info
storage StorageModel storage spec
DeploymentSpec DeploymentSpecModel deploy spec
containersResources ContainerResources arrayContainer's resources

ReleaseSpec

ReleaseSpec defines the specific spec of release

Appears in:

FieldDescription
name stringName is the release name
predictor PredictorSpecPredictor defines the model serving spec

ReleaseStatus

ReleaseStatus defines the observed status of one MLService release

Appears in:

FieldDescription
name stringRelease name
ready booleanTrue if release service ready
trafficPercent integerTraffic percent of this release
url stringService url
reason stringReason for not ready, empty if ready
message stringMessage for not ready, empty if ready
readyReplicas integerReady replicas numbers
totalReplicas integerTotal replicas numbers

RunMode

Underlying type: string

Appears in:

RuntimeTemplateSpec

this will be applied to RevisionTemplateSpec

Appears in:

FieldDescription
metadata EditableMetadataRefer to Kubernetes API documentation for fields of metadata.
spec PodSpecPod Spec with optional containers

S3Storage

S3Storage defines infos of s3

Appears in:

FieldDescription
secretRef LocalObjectReferenceSecretRef is reference to the secret storing s3cmd config
uri stringDirectory path where model locates in s3. e.g. "s3://<bucket>/<dir>/"
mountPath stringDirectory path where model locates in container, default is "/var/lib/t9k/model"

SchedulePolicy

SchedulePolicy defines how k8s to schedule the replicas.

Appears in:

FieldDescription
t9kScheduler T9kSchedulerTensorStack scheduler spec

Storage

Storage defines the storage where the model locates

Appears in:

FieldDescription
s3 S3StorageModel locates in S3
pvc PVCStorageModel locates in pvc

T9kScheduler

Appears in:

FieldDescription
queue stringQueue name

TransformerSpec

TransformerSpec defines the transformer

Appears in:

FieldDescription
DeploymentSpec DeploymentSpecTransformer deployment spec
storage StorageTransformer model storage spec

TransformerStatus

TransformerStatus defines the observed status of transformer

Appears in:

FieldDescription
ready booleanTrue if transformer service ready
url stringTransformer url
reason stringReason for not ready, empty if ready
message stringMessage for not ready, empty if ready
readyReplicas integerReady replicas numbers
totalReplicas integerTotal replicas numbers

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

AdditionalDiskConfig

Appears in:

FieldDescription
name string
bus DiskBusBus indicates the type of disk device to emulate. supported values: virtio, sata, scsi.
serial stringThe system-serial-number in SMBIOS
VolumeSource VolumeSourceVolumeSource represents the location and type of the mounted volume. Defaults to Disk, if no type is specified.

CPURequirements

CPU resources info, including cpu model and count.

Appears in:

FieldDescription
model stringvirt-handler detects cpus on nodes and add cpu-model.node.kubevirt.io/[model-name] labels to nodes. Set this filed to filter nodes by model. optional
cores QuantityCount of cpu.

FileSystemConfig

Appears in:

FieldDescription
name string
VolumeSource VolumeSourceVolumeSource represents the location and type of the mounted volume. Defaults to Disk, if no type is specified.

GPURequirements

GPU resources info, including device name and count.

Appears in:

FieldDescription
type stringkubevirt-gpu-device-plugin detects gpus on nodes and add extended resources to k8s cluster. Type is the name of gpu extended resource, it is usually related to gpu device name.
count integerCount of gpus in use.

Network

Appears in:

FieldDescription
tcp integer arrayThe ports exposed with TCP protocol.
udp integer arrayThe ports exposed with UDP protocol.
macAddress stringInterface MAC address. For example: de:ad:00:00:be:af or DE-AD-00-00-BE-AF.
dnsConfig PodDNSConfigSpecifies the DNS parameters of a VM. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.
dnsPolicy DNSPolicySet DNS policy for the VM. Defaults to "ClusterFirst". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'.

PVCTemplate

Appears in:

FieldDescription
size QuantityPVC Size
volumeMode PersistentVolumeModevolumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.
accessModes PersistentVolumeAccessMode arrayAccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1
storageClassName stringName of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1

ResourceRequirements

Resources allocated to VirtualMachine.

Appears in:

FieldDescription
gpu GPURequirementsGPU resources allocated to VirtualMachine. optional
cpu CPURequirementsCPU required by this VirtualMachine.
memory QuantityMemory required by this VirtualMachine.

RootDisk

Appears in:

FieldDescription
ephemeral booleanNot to record the data generated in the virtual machine to the root disk. Defaults to false.
pvc PVCTemplateCreate and bind a new pvc to DataVolume.
source DataVolumeSourceThe src of the data for the requested DataVolume.
bus DiskBusBus indicates the type of disk device to emulate. supported values: virtio, sata, scsi.

SchedulePolicy

SchedulePolicy specifies the preferred scheduler responsible for handling resource allocation requests.

Appears in:

FieldDescription
t9kScheduler T9kScheduler

Storage

Appears in:

FieldDescription
root RootDiskRoot disk.
additionalDisks AdditionalDiskConfig arrayAttach a volume as a disk to the VM.
filesystems FileSystemConfig arrayFilesystems describes filesystem which is connected to the VM.

T9kScheduler

Appears in:

FieldDescription
queue stringName of the queue to use with the T9kScheduler.

VMRef

Appears in:

FieldDescription
name string

VirtualServer

VirtualServer is the Schema for the virtualservers API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringVirtualServer
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec VirtualServerSpec
status VirtualServerStatus

VirtualServerCondition

VirtualServerCondition defines the observed condition of VirtualServer.

Appears in:

FieldDescription
type VirtualServerConditionTypeType is the type of the condition.
status ConditionStatusStatus is the status of the condition type. Possible values of are `True
message stringMessage is a human-readable message for the reason of the status.
reason stringUnique, one-word, CamelCase reason for the vm's last transition.
lastTransitionTime TimeLastTransitionTime is the last time the status was changed.

VirtualServerConditionType

Underlying type: string

VirtualServerConditionType defines all possible types of VirtualServerCondition. Can be one of: DataImported, Ready, Failure or Paused.

Appears in:

VirtualServerList

VirtualServerList contains a list of VirtualServer

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringVirtualServerList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items VirtualServer array

VirtualServerSpec

VirtualServerSpec defines the desired state of VirtualServer

Appears in:

FieldDescription
resources ResourceRequirementsCompute Resources required by this VM.
storage StorageDisks and filesystems attached to the VM.
firmware FirmwareFirmware.
network NetworkVM network config.
runStrategy VirtualMachineRunStrategyRunning state indicates the requested running state of the VirtualMachineInstance
useVirtioTransitional booleanFall back to legacy virtio 0.9 support if virtio bus is selected on devices. This is helpful for old machines like CentOS6 or RHEL6 which do not understand virtio_non_transitional (virtio 1.0).
scheduler SchedulePolicySpecifies the preferred scheduler responsible for handling resource allocation requests.
cloudInit stringCloudInit represents a cloud-init NoCloud user-data source. The NoCloud data will be added as a disk to the vmi. A proper cloud-init installation is required inside the guest. More info: http://cloudinit.readthedocs.io/en/latest/topics/datasources/nocloud.html

VirtualServerStatus

VirtualServerStatus defines the observed state of VirtualServer

Appears in:

FieldDescription
conditions VirtualServerCondition arrayThe latest available observations of a VirtualServer's current state.
printableStatus VirtualMachinePrintableStatusPrintableStatus is a human readable, high-level representation of the status of the virtual machine
vm VMRefRefers to VirtualMachine created by this VirtualServer.
runStrategy VirtualMachineRunStrategyRunning state indicates the requested running state of the VirtualMachineInstance mutually exclusive with Running

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

DataCube

DataCube is the Schema for the datacubes API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringDataCube
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec DataCubeSpec
status DataCubeStatus

DataCubeCondition

DataCubeCondition contains details for the current condition of this datacube

Appears in:

FieldDescription
type DataCubeConditionTypeType is the type of the condition.
status ConditionStatusStatus is the status of the condition. Can be True, False, Unknown.
lastProbeTime TimeLast time we probed the condition.
lastTransitionTime TimeLast time the condition transitioned from one status to another.
reason stringUnique, one-word, CamelCase reason for the condition's last transition.
message stringHuman-readable message indicating details about last transition.

DataCubeConditionType

Underlying type: string

DataCubeConditionType defines all possible types of DataCubeStatus. Can be one of: Initialized, Complete, or Failed.

Appears in:

DataCubeList

DataCubeList contains a list of DataCube

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringDataCubeList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items DataCube array

DataCubePhase

Underlying type: string

Appears in:

DataCubeSpec

DataCubeSpec defines the desired state of DataCube

Appears in:

FieldDescription
source DataReferenceSource defines where the data is stored
sink DataReferenceSink defines where the data will be transferred to
executor ExecutorReferenceExecutor defines how the data will be transferred

DataCubeStatus

DataCubeStatus defines the observed state of DataCube

Appears in:

FieldDescription
phase DataCubePhaseThe phase of this datacube.
conditions DataCubeCondition arrayConditions represent an array of current conditions observed within the system.
pod PodStatusThe status of the underlying Pod

DataReference

Appears in:

FieldDescription
type DataTypeType of the data
options EnvVar arrayOptions for the data
pvc PVCReferenceData in pvc

DataType

Underlying type: string

Appears in:

ExecutorOptions

Appears in:

FieldDescription
sync booleanWhether to sync data, if false, use copy
backoffLimit integerSpecifies the number of retries before marking this datacube failed. Defaults to 0.
activeDeadlineSeconds integerSpecifies the duration in seconds relative to the startTime that the datacube may be active before the system tries to terminate it; value must be positive integer
extraArgs string arrayExtra args appended to executed command

ExecutorReference

Appears in:

FieldDescription
options ExecutorOptionsOptions of executor
env EnvVar arrayEnv of executor's contianer
securityContext PodSecurityContextSecurityContext of executor's container

PVCReference

Appears in:

FieldDescription
name stringName of PVC
subPath stringPath within PVC
template PersistentVolumeClaimTemplateTemplate to create pvc if not exist, only avaliable when uploading

PodReference

PodReference references a K8s v1.Pod.

Appears in:

FieldDescription
name stringName of the Pod.
uid stringUID of the Pod.

PodStatus

PodStatus defines the observed status of the Pod running file transfer.

Appears in:

FieldDescription
reference PodReferenceReferences to the subordinate v1.Pod.
phase PodPhaseReplicated from the corresponding field in the subordinate v1.Pod.
status string

API Reference

Packages

tensorstack.dev/v1beta1

Package v1beta1 contains API Schema definitions for the v1beta1 API group

Resource Types

SecretReference

SecretReference defines a reference to a Kubernetes v1.Secret object.

Appears in:

FieldDescription
name stringThe name of a Kubernetes v1.Secret object that holds the token and kubeconfig.

ServiceAccountToken

ServiceAccountToken is the Schema for the serviceaccounttokens API

Appears in:

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringServiceAccountToken
metadata ObjectMetaRefer to Kubernetes API documentation for fields of metadata.
spec ServiceAccountTokenSpec
status ServiceAccountTokenStatus

ServiceAccountTokenCondition

ServiceAccountTokenCondition contains details for the current condition of ServiceAccountToken

Appears in:

FieldDescription
type ServiceAccountTokenConditionTypeType is the type of the condition.
status ConditionStatusStatus is the status of the condition. Can be True, False, Unknown.
lastTransitionTime TimeLast time the condition transitioned from one status to another.
reason stringUnique, one-word, CamelCase reason for the condition's last transition.
message stringHuman-readable message indicating details about last transition.

ServiceAccountTokenConditionType

Underlying type: string

ServiceAccountTokenConditionType defines all possible types for ServiceAccountTokenCondition.Type

Appears in:

ServiceAccountTokenList

ServiceAccountTokenList contains a list of ServiceAccountToken

FieldDescription
apiVersion stringtensorstack.dev/v1beta1
kind stringServiceAccountTokenList
metadata ListMetaRefer to Kubernetes API documentation for fields of metadata.
items ServiceAccountToken array

ServiceAccountTokenSpec

ServiceAccountTokenSpec defines the desired state of ServiceAccountToken

Appears in:

FieldDescription
duration stringDuration defines the requested token lifetime. The server may return a token with a longer or shorter lifetime.

ServiceAccountTokenStatus

ServiceAccountTokenStatus defines the observed state of ServiceAccountToken

Appears in:

FieldDescription
expirationTime TimeExpirationTime is the time of expiration of the returned token.
secretRef SecretReferenceSecretRef references a Kubernetes v1.Secret object.
conditions ServiceAccountTokenCondition arrayConditions represent an array of current conditions observed within the system.

标准镜像

部分 CRD,如 Notebook、T9k Job 和 MLService,需要 Docker 镜像来提供模型开发、训练或推理所需的具体运行环境。平台提供并维护了一系列镜像以满足你的基本使用需求,这些镜像被称为标准镜像。

你也可以构建自定义镜像,以满足更加特定的需求。

Notebook 标准镜像列表

每个 Notebook 标准镜像包含特定的机器学习框架,同时预装了一些 Python 包、命令行工具和最新版本的平台工具

当前正在维护的 Notebook 标准镜像如下表所示:

名称环境
tensorflow-2.14.0-notebook-cpuTensorFlow 2(仅支持 CPU)
tensorflow-2.14.0-notebook-gpuTensorFlow 2(支持 GPU)
torch-2.1.0-notebookPyTorch 2,conda
miniconda-22.11.1-notebookconda

说明:

  1. 你可以在创建 Notebook 时选择以使用这些镜像,也可以直接从 Docker Hub 的 t9kpublic Namespace 下拉取这些镜像以使用。
  2. 这些镜像会持续更新,直到相应机器学习框架的小版本更新后被新镜像替代,此时旧镜像会被移除。镜像的标签(tag)是它的版本号,其跟随平台的版本号进行更新;镜像的每一次更新可能包含修复问题、更新包或工具、更新 Notebook 的扩展程序等内容。
  3. 标签中包含 -sudo 的镜像包含 sudo 命令,其中用户(t9kuser)的密码为 tensorstack
  4. 所有镜像包含以下命令行工具:
名称介绍
curl用于从或向服务器传输数据,支持多种协议。
git分布式版本控制系统,用于跟踪和协作开发软件项目的源代码。
htop一个交互式的系统监视器,用于实时查看和管理运行中的进程。
rclone用于在本地和云存储之间同步、管理文件的命令行程序,支持多种云存储服务。
rsync用于高效同步和传输文件,支持本地和远程文件。
s3cmd用于管理 Amazon S3 云存储服务。
ssh用于安全地远程访问和管理服务器。
unzip用于解压缩 ZIP 文件。
vim一款高效、可定制的文本编辑器,常用于编程和文本编辑。
wget用于从网络上下载文件,支持 HTTP、HTTPS 和 FTP 协议。
zip用于创建和管理 ZIP 压缩文件。

背景

人工智能(AI)技术的发展已经取得了显著的成果,并对各行业的发展产生了深远的影响。其中最为突出的成就是以深度学习为基础在计算机视觉、LLM 等领域的突破性成果。

AI 计算平台对于 AI 技术的开发和应用具有重要意义。它提供了一个集成化、高效的环境,让开发者和企业能够轻松地构建、训练和部署机器学习模型。这种便捷性极大地降低了 AI 技术的门槛,使得更多的组织和个人能够利用先进的 AI 能力。

  1. AI 计算平台通过提供高级的 AI 开发工具和预构建的模型,简化了 AI 开发流程。开发者不需要从头开始构建复杂的模型,而是可以基于现有的模型进行定制和优化,这加速了从概念到实现的过程。
  2. AI 计算平台提供了大规模的计算资源和数据管理能力,这对于处理大量数据和运行复杂的 AI 模型至关重要。用户可以根据需要轻松扩展资源,以适应不断变化的需求。
  3. 平台还包含丰富的协作和集成工具,使得团队可以更有效地合作开发。此外,它们还提供了严格的安全和隐私保护措施,保证了数据的安全性和合规性。

新的范式

AI 是一种崭新的计算范式,它具有数据驱动、基于实验的特点,并且经常需要进行大规模的计算。

  • 在传统软件开发中,程序员编写明确的指令或规则,来告诉计算机如何处理数据和执行任务。这种方法依赖于开发者对问题的深入理解以及能够准确预测所有可能的情况并据此编写代码。
  • 相比之下,AI 的开发更多地依赖于数据而不是预设的规则。在这种模式下,AI 系统通过大量数据来学习和识别模式,然后基于这些学习成果做出判断或预测。开发者不是直接编写处理每种情况的代码, 而是设计算法来让计算机自我学习和适应。这意味着 AI 系统在面对新数据时可以持续改进其性能和准确性。
  • 此外,AI 开发通常需要更多关注于数据的收集、处理和分析。数据的质量和量直接影响到模型的性能,因此数据预处理成为 AI 开发中的一个重要步骤。而在传统软件开发中,主要关注的是逻辑的构建和代码的优化。

总的来说,AI 的数据驱动计算范式更加强调数据本身和从数据中学习的能力,而不是像传统软件那样依赖于硬编码的指令和规则。 这种方法使得 AI 在处理复杂、动态和模糊的问题时更加有效,但也带来了对数据质量和巨大计算处理能力的依赖。

computation-paradigm-for-ai
图 1: AI 计算的要素。模型架构程序 + 数据集经过训练(模型参数优化)后产生 AI 模型。

系统需求

由于 AI 技术的特性,用户在开发和使用 AI 过程中,在系统方面提出了多方面的需求,希望能够:

  • 方便地构建、使用和迭代数据集、模型架构和参数,以及
  • 简单、可靠地使用大规模分布式并行、异构和加速计算等技术来快速、高效地运行大规模的数据处理、训练和推理计算等。

数据

AI 计算过程中读取或者产生的数据可以分为两类:主干数据、元数据。

  • 主干数据:训练数据集、模型等大体量数据。
  • 元数据:计算过程中的各种配置、超参数、指标等。
ai-data
图 2:AI 计算在数据方面的核心需求。1)针对大规模的数据(训练数据集、模型等)提供高性能、大容量和完善的生命周期管理支持;2)对 AI 实验过程中的各种配置、超参数、指标等进行方便地记录、存取、查询等,并提供丰富的可视化支持。

用户希望通过一致、多维度高度可扩展的机制来支持对数据的各种操作。例如,训练数据无论是100KiB 还是 100TiB,都能够使用同一套工具、SDK,API:

  1. 方便地使用数据:能够在探索、实验、训练过程中,简单、快速地使用不同的数据;
  2. 高性能地使用数据:支持训练过程中对数据的高速读取(训练数据集)、写入(checkpoint,模型本身);
  3. 可靠地维护数据:
    • 像代码一样维护数据版本 (versioning);
    • 记录数据的变化历史 (commits and logs);
    • 隔离 (branches)。
  4. 对 AI 计算过程中的配置、超参数、脚本、各种指标等,提供方便、完善的支持:
    • 元数据管理系统为基础底座;
    • SDK 支持在各种场景进行集成;
    • 可视化工具方便地跟踪、展示、比较、分析多个实验过程。

计算

用户希望能够通过便捷的方式使用大规模分布式并行、异构、加速计算等技术以快速、高效地运行大规模的数据处理、训练和推理计算等。

scalable-ai-compute
图 3: 方便地进行计算。系统支持以同样的方式定义、运行、调试 AI 领域的各种计算任务。例如,使用 1 张 GPU 的训练任务和使用 1000 张 GPU 的训练任务可以使用一致的方式来完成。

AI 计算场景的典型需求:

类别需求说明
软件包依赖清晰、一致、方便地管理对 Pyhton 脚本、GPU 驱动程序、网络驱动程序等各种软件包的依赖
计算环境支持在 dev、 train、test、deploy 等环境方便地切换、迭代
数据、代码高效、便捷地使用数据、脚本、配置及跟踪它们的变化
计算资源快速、简单、方便地请求和使用各种计算资源:CPU、RAM、GPU、高速网络、存储...
运行计算可靠、简单、方便地运行个各种类型的计算:开发环境、并行训练、微调、数据处理、推理服务...

Kubernetes

Kubernetes 是一个灵活、可扩展的容器集群管理平台,它通过 Master 节点的集中控制和调度,工作节点(Worker Nodes) 负责运行应用工作负载。工作节点可方便地动态伸缩规模。

k8s-arch
图 4:Kubernetes 架构图。Source: https://en.wikipedia.org/wiki/Kubernetes

如上图所示,Kubernetes 的整体架构主要包含以下组件:

Master 节点: Master 节点负责整个集群的控制和管理。主要包含以下组件:

  • kube-apiserver:提供了资源操作的统一入口,以 RESTful API 方式提供服务。
  • etcd:负责存储集群的配置信息和资源状态。
  • kube-scheduler:负责资源的调度,按照预定的调度策略将 Pod 调度到相应的节点上。
  • kube-controller-manager: 负责管理控制器,确保集群处于预期的状态。

Node节点:Node 节点是 Kubernetes 集群中的工作节点,由 Master 节点管理,主要包含以下组件:

  • kubelet:负责管理 Node 节点上的 Pod 和容器的生命周期。
  • kube-proxy:负责为 Service 提供 cluster 内部的服务发现和负载均衡。
  • 容器运行时(containerd,CRI-O,Docker 等): 负责真正运行容器的软件。

Kubernetes 还包括其他辅助模块(Add-ons),例如:

  • DNS 模块:负责为集群中的主机提供 DNS 解析服务。
  • 网络插件:负责提供底层的网络实现,例如 flannel 和 calico。
  • 参数模块:提供配置管理功能。
  • 仪表板插件:提供 GUI。
  • 存储插件:提供持久化存储实现,例如 Ceph 和 Luster 。
  • 日志模块:提供日志收集、存储功能。
  • 安全模块:提供认证、授权、准入控制等安全功能。

TensorStack AI 计算平台

TensorStack AI 计算平台构建于以 Kubernetes 为核心的云原生技术,采用开放的、标准的、被普遍采用的、无厂商锁定风险的技术和协议,并能够:

  1. 长期稳定迭代、不断进步;
  2. 提供高度可靠性;
  3. 提供高度安全性;
  4. 支持在多个维度(计算规模、数据规模、硬件架构等)方便进行扩展。
ai-infra
图 5:TensorStack AI 计算平台。 平台采用开放的、标准的、被普遍采用的、无厂商锁定风险的技术和协议;并在稳定性、可靠性、扩展性、安全性多方面具备优异的能力。

TensorStack 对 AI 计算中的主要系统问题及解决方法:

  1. 软件包依赖

    采用容器镜像清晰、一致、方便地管理对 Pyhton 脚本、GPU 驱动程序、网络驱动程序等各种软件包的依赖:

     - 稳定的基础镜像:跟随框架(PyTorch)等主要依赖发布;
     - 镜像全流程支持:制作、发布到 Registry、运行。
    
  2. 计算环境

    采用 Infrastructure As Code 原则 + 容器镜像 + 网络存储的机制支持在 dev、 train、test、deploy 等环境方便地切换、迭代数据、代码。

  3. 数据、代码

    通过网络存储 + 服务(Version Control,AI DB,Experiment Management 等)支持高效、便捷地使用数据、脚本、配置及跟踪它们的变化。

  4. 计算资源

    通过 CRD controller + resource scheduler,实现快速、简单、方便地请求和使用各种计算资源:CPU、RAM、GPU、高速网络、存储...

  5. 运行计算

    T9k Jobs + Services 等实现可靠、简单、方便地运行个各种类型的计算:开发环境、并行训练、微调、数据处理、推理服务...

TensorStack AI 计算平台将在推动 AI 技术的普及和应用方面发挥着关键作用,为各行各业提供实现 AI 驱动创新的关键工具和资源。

参考

Infrastructure for deep learning, 2016
https://openai.com/research/infrastructure-for-deep-learning

Scaling Kubernetes to 2,500 nodes, 2018
https://openai.com/research/scaling-kubernetes-to-2500-nodes

Scaling Kubernetes to 7,500 nodes, 2021
https://openai.com/research/scaling-kubernetes-to-7500-nodes

Borg, Omega, and Kubernetes - Lessons learned from three container-management systems over a decade, 2016
https://queue.acm.org/detail.cfm?id=2898444

Large-scale cluster management at Google with Borg, 2015
https://research.google/pubs/pub43438/

Omega: flexible, scalable schedulers for large compute clusters, 2013
https://research.google/pubs/pub41684/

Kubernetes as a Platform for building Platforms with Mario-Leander Reimer, 2022
https://www.youtube.com/watch?v=wDMbBSVNzWY

Cloud-native computing
https://en.wikipedia.org/wiki/Cloud-native_computing

Cloud Native Computing Foundation
https://www.cncf.io/

Infrastructure As Code
https://en.wikipedia.org/wiki/Infrastructure_as_code

HyperMLService

HyperMLService 用于实现多集群的推理服务自动化部署。

架构

整体架构如下图所示:

architecture

其中集群分为以下几类:

  1. 主集群(hub cluster):用于运行 HyperMLService 控制器、创建 HyperMLService 实例
  2. 子集群(spoke cluster):用于运行具体的 MLService 工作负载
  3. 流量入口集群(ingress cluster):用于运行 HeadIngress,分发流量到各个子集群,实现负载均衡

工作流程如下:

  1. 发布工程师(release engineers)在主集群中通过定义/修改 HyperMLService 实现自动化的多集群高可靠部署模型推理服务。
  2. HyperMLService 控制器在各个子集群中自动化部署 MLService
  3. 发布工程师在流量入口集群中创建 HeadIngress,用于分发流量到各个子集群中的 MLService,实现负载均衡策略。

注:

  • 主集群、子集群、流量入口集群只是功能上的区分,一个物理集群可以同时是主集群、子集群或流量入口集群
  • 目前 HeadIngress 由发布工程师手动创建,后续可实现自动化部署。

使用

准备工作

首先,你需要准备好以下几个 kubeconfig(均为 cluster-admin 权限):

  1. hub.kubeconfig:主集群的 kubeconfig
  2. spoke.kubeconfig:每个子集群的 kubeconfig
  3. ingress.kubeconfig:流量入口集群的 kubeconfig
  4. karmada.kubeconfig:主集群中运行的 Karmada API Server 的 kubeconfig,获取方式如下:
$ kubectl --kubeconfig hub.kubeconfig get secret -n karmada-system karmada-kubeconfig -o jsonpath={.data.kubeconfig} | base64 -d > karmada.kubeconfig

然后,你需要在本地安装 kubectl karmada plugin:

$ curl -s https://raw.githubusercontent.com/karmada-io/karmada/master/hack/install-cli.sh | sudo bash -s kubectl-karmada

最后,你需要在 Karmada 中注册各个子集群,其中需要为每个子集群选取一个名称 <spoke-cluster-name>

$ kubectl karmada join <spoke-cluster-name> \
    --kubeconfig=./karmada.kubeconfig \
    --cluster-kubeconfig=./spoke.kubeconfig

创建 HyperMLService

在主集群的 namespace demo 中创建一个 HyperMLService hmls-sample

$ kubectl --kubeconfig hub.kubeconfig create -f ./hmls-sample.yaml

其中 hmls-sample.yaml 文件的内容如下:

# hmls-sample.yaml
apiVersion: tensorstack.dev/v1beta1
kind: HyperMLService
metadata:
  name: hmls-sample
  namespace: demo
spec:
  workloads:
  - clusters:
    - spoke1
    - spoke2
    manifests:
    - apiVersion: tensorstack.dev/v1beta1
      kind: MLServiceRuntime
      metadata:
        name: t9k-torchserve
        namespace: demo
      spec:
        ...
    - apiVersion: v1
      kind: Secret
      metadata:
        name: s3-secret
        namespace: demo
      spec:
        ...
    - apiVersion: tensorstack.dev/v1beta1
      kind: MLService
      metadata:
        name: torch-mnist-s3
        namespace: demo
      spec:
        ...
  - clusters:
    - spoke3
    - spoke4
    manifests:
    - apiVersion: tensorstack.dev/v1beta1
      kind: MLService
      metadata:
        name: t9k-torchserve
        namespace: demo
      spec:
        ...

其中:

  • spec.workloads 是一个数组,其中每个元素包括一组子集群的名称和一组资源的定义,表示要在这些子集群中创建这些资源。
  • 具体的资源定义根据子集群的情况不同有差别,实际创建时再填充完整

查看 HyperMLService 的状态:

$ kubectl --kubeconfig hub.kubeconfig get hmls -n demo hmls-sample -o yaml
apiVersion: tensorstack.dev/v1beta1
kind: HyperMLService
metadata:
  creationTimestamp: "2024-04-15T10:11:48Z"
  finalizers:
  - tensorstack.dev/hypermlservice-controller
  generation: 2
  name: hmls-sample
  namespace: demo
  resourceVersion: "60156093"
  uid: 4f4bd6c7-911e-4cb4-9f6a-ce541fe16654
spec:
  ...
status:
  aggregatedStatus:
  - applied: true
    appliedMessage: Manifest has been successfully applied
    cluster: spoke1
    resource:
      apiVersion: tensorstack.dev/v1beta1
      kind: MLService
      name: torch-mnist-s3
      namespace: default
    status:
      address:
        url: http://torch-mnist-s3.default.ksvc.spoke1.t9kcloud.cn
      conditions:
      - lastTransitionTime: "2024-04-16T02:45:26Z"
        status: "False"
        type: Paused
      - lastTransitionTime: "2024-04-16T02:45:52Z"
        status: "True"
        type: Ready
      defaultRelease: origin
      releases:
      - name: origin
        ready: true
        readyReplicas: 1
        totalReplicas: 1
        trafficPercent: 100
        url: http://torch-mnist-s3-predict-origin.default.ksvc.spoke1.t9kcloud.cn
  - applied: true
    appliedMessage: Manifest has been successfully applied
    cluster: spoke1
    resource:
      apiVersion: tensorstack.dev/v1beta1
      kind: MLServiceRuntime
      name: t9k-torchserve
      namespace: default
  - applied: true
    appliedMessage: Manifest has been successfully applied
    cluster: spoke1
    resource:
      apiVersion: v1
      kind: Secret
      name: nfs-pek
      namespace: default
  - applied: true
    appliedMessage: Manifest has been successfully applied
    cluster: spoke2
    resource:
      apiVersion: tensorstack.dev/v1beta1
      kind: MLService
      name: torch-mnist-s3
      namespace: default
    status:
      address:
        url: http://torch-mnist-s3.default.ksvc.spoke2.t9kcloud.cn
      conditions:
      - lastTransitionTime: "2024-04-19T02:23:52Z"
        status: "False"
        type: Paused
      - lastTransitionTime: "2024-04-19T02:24:09Z"
        status: "True"
        type: Ready
      defaultRelease: origin
      releases:
      - name: origin
        ready: true
        readyReplicas: 1
        totalReplicas: 1
        trafficPercent: 100
        url: http://torch-mnist-s3-predict-origin.default.ksvc.spoke2.t9kcloud.cn
  - applied: true
    appliedMessage: Manifest has been successfully applied
    cluster: spoke2
    resource:
      apiVersion: tensorstack.dev/v1beta1
      kind: MLServiceRuntime
      name: t9k-torchserve
      namespace: default
  - applied: true
    appliedMessage: Manifest has been successfully applied
    cluster: spoke2
    resource:
      apiVersion: v1
      kind: Secret
      name: nfs-pek
      namespace: default
  conditions:
  - lastTransitionTime: "2024-04-19T02:23:51Z"
    message: All manifests have been successfully applied
    status: "True"
    type: FullyApplied

其中:

  • status.aggregatedStatus 是一个数组,其中每个元素对应一个子集群中的一个资源的运行状态。例如,从中可以获取每个子集群中 MLService 的推理 API 地址。
  • status.conditions 表示 HyperMLService 的总体状态,如果有资源未能在子集群中创建成功,这里会显示相关报错信息。

创建 HeadIngress

从 HyperMLService 的 status 中获取每个子集群的 MLService 的推理 API 地址,例如:

  • http://torch-mnist-s3-predict-origin.default.ksvc.spoke1.t9kcloud.cn
  • http://torch-mnist-s3-predict-origin.default.ksvc.spoke2.t9kcloud.cn

对于上述每个推理 API 地址,在流量入口集群中创建一个 ServiceEntry:

$ kubectl --kubeconfig ingress.kubeconfig create -f ./serviceentry.yaml

其中 serviceentry.yaml 文件的内容如下:

# serviceentry.yaml
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
 name: mlservice-spoke1
spec:
 hosts:
 - torch-mnist-s3-predict-origin.default.ksvc.spoke1.t9kcloud.cn
 location: MESH_EXTERNAL
 ports:
 - number: 80
   name: example-http
   protocol: HTTP
 resolution: DNS
---
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
 name: mlservice-spoke2
spec:
 hosts:
 - torch-mnist-s3-predict-origin.default.ksvc.spoke2.t9kcloud.cn
 location: MESH_EXTERNAL
 ports:
 - number: 80
   name: example-http
   protocol: HTTP
 resolution: DNS

然后创建一个 VirtualService,用于负载均衡:

$ kubectl --kubeconfig ingress.kubeconfig create -f ./virtualservice.yaml

其中 virtualservice.yaml 文件的内容如下:

# virtualservice.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: lb
spec:
  gateways:
  - t9k.t9k-system
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /t9k/hypermlservices/namespaces/demo/hmls-sample/
    route:
    - destination:
        host: torch-mnist-s3-predict-origin.default.ksvc.spoke1.t9kcloud.cn
      headers:
        request:
          set:
            Host: torch-mnist-s3-predict-origin.default.ksvc.spoke1.t9kcloud.cn
      weight: 30
    - destination:
        host: torch-mnist-s3-predict-origin.default.ksvc.spoke2.t9kcloud.cn
      headers:
        request:
          set:
            Host: torch-mnist-s3-predict-origin.default.ksvc.spoke2.t9kcloud.cn
      weight: 70

其中:

  • 设置了 url path 为 /t9k/hypermlservices/namespaces/demo/hmls-sample/
  • 设置了两个推理 API 地址的权重为 30 和 70

因此,你可以通过以下地址访问 HyperMLService:

<ingress-nginx-domain-name>/t9k/hypermlservices/namespaces/demo/hmls-sample/

其中 30% 的请求将转发到第一个子集群,70% 的请求将转发到第二个子集群。