基于k8s job执行推理

利用 Kubernetes (K8S) 原生 Job 负载实现离线执行推理任务,可以在提交任务后关闭开发机,任务将自动在 GPU 集群中异步执行,并在完成后自动释放资源,确保计算资源的高效利用。

首先需要准备集群,并用kubectl连接成功。 具体步骤可以参考这里。(使用的分区为:华北二区

准备推理脚本

准备一个共享存储

在英博云的控制台:存储 -> 共享存储卷 -> 创建存储卷,建立一个存储卷,命名为temptest,如下所示:

这是一张图片

开启一个开发机并挂载共享存储

在开发机列表页面,选择一个开发机,点击更多 -> 更改实例配置,在接下来的页面中的存储配置部分为开发机挂载存储卷,选择建好的共享存储卷temptest, 256 GB,并输入挂载路径,这里输入/root/data ,点击确定

这是一张图片

编辑推理脚本

返回开发机列表页面,开启挂载共享存储卷的开发机,点击此开发机的JupyterLab链接,进入指定的共享存储卷路径(示例为/root/data),在左侧空白栏右键创建inference.py文件和output文件夹,也可以在JupyterLabLauncher页,点击Terminal进入终端,使用指令创建。

这是一张图片

inference.py中写入以下内容:

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

def run_inference():
    model_path = "/public/huggingface-models/Qwen/Qwen2.5-7B-Instruct-1M"
    print("正在加载分词器...")
    tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True, use_fast=False)
    print("正在加载模型(使用 BF16 精度)...")
    # 4090 支持 BF16,建议优先使用 BF16
    model = AutoModelForCausalLM.from_pretrained(
        model_path,
        torch_dtype=torch.bfloat16,
        device_map="auto",
        trust_remote_code=True
    )
    prompt = "请详细解释一下什么是大语言模型的量化技术?"
    messages = [
        {"role": "system", "content": "你是一个严谨的 AI 助手。"},
        {"role": "user", "content": prompt}
    ]
    # 使用 Qwen 特有的 chat 模板
    text = tokenizer.apply_chat_template(
        messages,
        tokenize=False,
        add_generation_prompt=True
    )
    model_inputs = tokenizer([text], return_tensors="pt").to(model.device)
    print("--- 开始生成 ---")
    generated_ids = model.generate(
        **model_inputs,
        max_new_tokens=2048,
        do_sample=True,
        temperature=0.7,
        top_p=0.9
    )
    generated_ids = [
        output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
    ]  # 过滤掉输入部分,只保留生成部分
    response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
    output_file = "/root/data/output/qwen_response.txt"
    with open(output_file, "w", encoding="utf-8") as f:
         f.write(f"Response:\n{response}\n")
if __name__ == "__main__":
    run_inference()
关闭开发机

此时所有准备都已经做好,可以关闭开发机。

返回开发机列表页面,选择开发机,点击更多 -> 关机

部署 Job 服务

获取推理需要的镜像

在英博云控制台左侧边栏镜像服务中点击预置镜像,点击预置镜像列表中的镜像仓库名称pytorch,选择适合的版本复制镜像地址。

这是一张图片

准备 Job yaml文件

Job 配置文件定义了资源需求、节点亲和性及自动清理策略。

准备如下的 job.yaml 文件:

apiVersion: batch/v1
kind: Job
metadata:
  name: pytorch-official-job
spec:
  ttlSecondsAfterFinished: 60 # 任务完成后60秒自动清理
  template:
    metadata:
      annotations:
        cloud.ebtech.com/resource-flavor: "bob-eci.4090-slim.5large" 
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: cloud.ebtech.com/gpu
                operator: In
                values:
                - RTX_4090
      containers:
      - name: worker
        # 使用前面复制的镜像地址
        image: registry-cn-huabei2-internal.ebcloud.com/ebsys/pytorch:2.5.1-cuda12.2-python3.10-ubuntu22.04-v09
        command: ["/bin/bash", "-c"]
        args:
          - |
            pip install accelerate -i https://pypi.tuna.tsinghua.edu.cn/simple
            echo "Starting inference script..."
            python3 /root/data/inference.py
        resources:
          limits:
            nvidia.com/gpu: 1
          requests:
            nvidia.com/gpu: 1
        volumeMounts:
        - name: data-volume
          mountPath: /root/data  # 开发机共享存储卷路径
        - name: public-volume 
          mountPath: /public # 挂载宿主机的 /public 目录
          readOnly: true
      volumes:
      - name: data-volume
        persistentVolumeClaim:
          claimName: temptest # 共享存储卷名称
      - name: public-volume  # --- hostPath 方式连接预置模型 ---
        hostPath:
          path: /public
          type: Directory
      restartPolicy: Never
执行部署命令
# 提交任务,之后直接关机
kubectl apply -f job.yaml
查看进度
# 查看任务是否已成功创建
kubectl get jobs
kubectl get pobs
获取模型产出

重新启动开发机,进入/root/data/output目录,查看qwen_response.txt的内容

这是一张图片