解决 K8s 中 NVIDIA NIM 部署 driver/library version mismatch 错误
2025-03-12 17:52:02
解决本地 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", 这说明驱动和库的版本不匹配。这通常发生在以下几种情况:
-
宿主机驱动版本与容器内 CUDA Toolkit 版本不兼容: NVIDIA 驱动程序(安装在宿主机上)需要与 CUDA Toolkit(通常打包在容器镜像内)版本兼容。如果版本差异过大,就会出问题。
-
Kubernetes 集群节点间的驱动版本不一致: 如果集群中有多个节点,并且这些节点的 NVIDIA 驱动版本不同,调度到不同节点的 Pod 可能会因为驱动不兼容而失败。
-
容器内残留旧版本 CUDA 库: 有时候,构建 Docker 镜像时,可能会意外地将旧版本的 CUDA 库打包进去,导致运行时版本冲突。
-
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>
替换成你实际的名字。
按这几步走,大部分版本不匹配的问题都能搞定。关键还是细心排查,一步步来,祝你好运!