返回

解决 K8s 中 NVIDIA NIM 部署 driver/library version mismatch 错误

Ai

解决本地 K8s 环境下部署 NVIDIA NIM 遭遇的 Driver/Library Version Mismatch 错误

最近在尝试将一个基于 Hugging Face 的 multilingual-e5-small 模型,通过 NVIDIA NIM 部署到本地 Kubernetes 集群,目标是提供一个文本向量化服务。但在实际部署过程中遇到了一个常见的错误:nvidia-container-cli.real: initialization error: nvml error: driver/library version mismatch。 这篇文章就来仔细说说这个问题,还有怎么解决。

问题原因分析

先看看报错信息,核心是 "driver/library version mismatch", 这说明驱动和库的版本不匹配。这通常发生在以下几种情况:

  1. 宿主机驱动版本与容器内 CUDA Toolkit 版本不兼容: NVIDIA 驱动程序(安装在宿主机上)需要与 CUDA Toolkit(通常打包在容器镜像内)版本兼容。如果版本差异过大,就会出问题。

  2. Kubernetes 集群节点间的驱动版本不一致: 如果集群中有多个节点,并且这些节点的 NVIDIA 驱动版本不同,调度到不同节点的 Pod 可能会因为驱动不兼容而失败。

  3. 容器内残留旧版本 CUDA 库: 有时候,构建 Docker 镜像时,可能会意外地将旧版本的 CUDA 库打包进去,导致运行时版本冲突。

  4. nvidia-container-runtime 安装或配置问题: nvidia-container-runtime 负责在容器内正确设置 NVIDIA GPU 环境。如果它本身安装不正确,或配置有误,也可能导致问题。

解决步骤

针对以上原因,咱一步步排查并解决:

1. 检查和更新驱动程序

先看看宿主机的驱动:

nvidia-smi

记下驱动版本号(你的是: 560.35.03)。 接下来看看NVIDIA 官网上的驱动兼容性矩阵,查查这个驱动能支持的最高的 CUDA Toolkit 版本。
你的driver 和cuda版本匹配。 看下一步。

2. 统一 Kubernetes 集群节点驱动版本

如果你的 Kubernetes 集群有多个节点,并且你无法确保driver version 一致,可以使用 nodeSelector。将应用程序 pod 限制到特定driver版本的node 上.

部署 YAML 可以这么改:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sentence-embedding-app
spec:
  selector:
    matchLabels:
      app: sentence-embedding
  replicas: 1
  template:
    metadata:
      labels:
        app: sentence-embedding
    spec:
      nodeSelector:
        nvidia-driver-version: "560.35.03" # <--- 增加这一行,选择指定driver version
      containers:
      - name: sentence-embedding
        image: <your-image-name>:<your-image-tag> # 换成你自己的镜像
        resources:
          limits:
            cpu: '32'
            ephemeral-storage: 30Gi
            memory: 12Gi
            nvidia.com/gpu: '1'
          requests:
            cpu: '4'
            ephemeral-storage: 3Gi
            memory: 8Gi
            nvidia.com/gpu: '1'

上面加了一行 nodeSelector,意思是只把这个 Pod 调度到 nvidia-driver-version 标签是 "560.35.03" 的节点上。
在应用 nodeSelector 之前,请先给 node 加上 Label:

kubectl label nodes <your-node-name> nvidia-driver-version=560.35.03

<your-node-name> 换成你实际的节点名字。

3. 精简和重建 Docker 镜像

有时 Dockerfile 写得不好,或者基础镜像太大,可能会导致意料之外的问题。试试换个更小、更干净的基础镜像。还有就是确保 pip install 时候不会装上一些不必要的库,产生干扰。

鉴于你已经使用了nvcr.io/nvidia/pytorch:24.08-py3,这个基础镜像理论上应该包含了与 CUDA 12.6 兼容的 PyTorch 及相关库。但还是建议仔细审查一下 requirements.txt 文件,避免安装与 CUDA 或 NVIDIA 驱动相关的包(除非你确定需要特定版本,且明确知道自己在干什么)。

下面是个可能更精简的 Dockerfile(你可以参考):

FROM nvcr.io/nvidia/pytorch:24.08-py3

WORKDIR /app

# 只拷贝必要的文件
COPY requirements.txt ./
COPY src/search-llm-svc.py ./

# 安装依赖, 加上 --no-cache-dir
RUN pip install --no-cache-dir -r requirements.txt

# 设置非 root 用户,更安全
USER nobody

CMD ["python", "search-llm-svc.py"]

改进点:

  • 使用 nobody 用户: 默认以 root 用户运行容器不太安全。改成 nobody 用户能减少潜在风险。

  • ** 更严格的依赖: ** 查看一下你的requirement.txt , 把没必要的删除.

  • 使用更小的模型: 如果模型很大, 下载或者load 很费时间。 可以使用这个docker file 来优化load 时间。

    FROM nvcr.io/nvidia/pytorch:24.08-py3
    
    # Set a working directory
    WORKDIR /app
    
    # Copy only the necessary files to keep the image lean
    COPY requirements.txt .
    
    # Install dependencies first to leverage Docker caching
    RUN pip install --no-cache-dir -r requirements.txt
    
    # Copy the model files into the container's filesystem
    COPY models/ /app/models/
    # Copy the service script
    COPY src/search-llm-svc.py .
    
    # Run the service with uvicorn
    CMD ["uvicorn", "search-llm-svc.py:app", "--host", "0.0.0.0", "--port", "8000"]
    

    模型加载和处理的修改,请考虑以下Python代码:

    from fastapi import FastAPI, HTTPException
    from pydantic import BaseModel
    from sentence_transformers import SentenceTransformer
    import uvicorn
    import os
    
    app = FastAPI()
    
    # Define the request body model
    class EmbeddingRequest(BaseModel):
        sentences: str
    
    # Define the path to the pre-downloaded model
    model_path = '/app/models/'
    
    # Check if the model exists and load it
    if os.path.exists(model_path):
        try:
            model = SentenceTransformer(model_path, device='cuda')
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))
    else:
        raise HTTPException(status_code=404, detail="Model not found")
    @app.post("/embeddings")
    async def get_embeddings(request: EmbeddingRequest):
        try:
            # Encode the sentences to get embeddings
            embeddings = model.encode(request.sentences)
            return embeddings.tolist()[0]
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))
    
    if __name__ == "__main__":
       uvicorn.run(app, host="0.0.0.0", port=8000)
    

4. 检查 nvidia-container-runtime

确认 nvidia-container-runtime 装好了, 而且配置正确。

# 检查 nvidia-container-runtime 是否安装
dpkg -l | grep nvidia-container-runtime

# 查看 containerd 配置(如果使用 containerd)
cat /etc/containerd/config.toml

# 查看 Docker 配置(如果使用 Docker)
cat /etc/docker/daemon.json
  • 如果没装,赶紧装:

     distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
     && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
     && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
        sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
        sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
      sudo apt-get update
      sudo apt-get install -y nvidia-container-toolkit
      sudo nvidia-ctk runtime configure --runtime=docker
      sudo systemctl restart docker
    
  • 看看 /etc/containerd/config.toml (如果你用的 containerd)里面,有没有类似下面的配置:

    [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia]
      runtime_type = "io.containerd.runc.v2"
      [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.nvidia.options]
        BinaryName = "/usr/bin/nvidia-container-runtime"
    
  • 看看 /etc/docker/daemon.json (如果你用的 Docker)里面有没有:

    {
      "default-runtime": "nvidia",
      "runtimes": {
        "nvidia": {
          "path": "/usr/bin/nvidia-container-runtime",
          "runtimeArgs": []
        }
      }
    }
    

配置改了之后,记得重启 containerd 或 Docker:

sudo systemctl restart containerd  # 或 docker

5.查看GPU设备信息

运行'nvidia-smi -q' 并查看 “Driver/library version mismatch” 这条log之前的部分,会有关于gpu 的具体报错信息。

nvidia-smi -q

其他建议

  • 日志: 多看日志!除了 nvidia-smi, 还可以看看 Kubernetes 的事件:

    kubectl describe pod <your-pod-name>
    kubectl logs <your-pod-name> -c <your-container-name>
    

<your-pod-name><your-container-name> 替换成你实际的名字。

按这几步走,大部分版本不匹配的问题都能搞定。关键还是细心排查,一步步来,祝你好运!