Skip to content

系统基础速查

本页速览 模型部署工程师必备的系统知识速查:Linux、容器与 Docker、Kubernetes、网络与进程模型、GPU 环境与性能工具——部署排障时随手可查。

系统基础速查

使用建议

本文是一张「排障速查卡」:每节按 场景 → 命令 → 怎么读输出 组织。遇到「服务起不来、GPU 打不开、延迟莫名高」这类问题时先翻对应小节,再回到正文链接里补系统知识。

Linux 常用命令速查

场景命令怎么看输出
看进程在不在、占用多少ps aux | grep python第 3 列 CPU、第 4 列 RSS(内存),看 PID 用于后续 killtop -p
实时看资源占用top(或 htop%CPU/%MEM 高的进程;load average 超核数说明排队。top -p PID 单看目标进程。
看内存还剩多少free -havailable 才是真可用;buff/cache 可回收。swap 飙升 = 内存告急。
看磁盘还剩多少df -hUse% 接近 100% 会引发写失败;模型仓库目录单独挂载要重点看。
看端口谁在监听ss -tlnp(旧系统用 netstat -tlnpLISTEN 行才是服务就绪;PID/Program 列确认是不是自己的进程。
看某个端口被谁占lsof -i :8000排查「端口被占用」时直接定位到进程,然后决定 kill 或换端口。
看进程打开了哪些文件lsof -p PID定位「文件被删了但进程还握着句柄」导致的磁盘不释放问题。
看日志尾部tail -f /path/to/log实时跟踪错误;grep -i error 过滤关键字。
后台运行服务nohup cmd > log 2>&1 &断开 SSH 后仍运行;日志重定向避免占用终端。

容器与 Docker

镜像构建最佳实践(直接影响镜像体积、构建速度与安全性):

  • 分层与缓存Dockerfile 每一条 RUN/COPY 生成一层,变更靠前的层会使后续缓存全部失效。把很少变化的依赖安装放前面(如 apt-get installpip install),把频繁变化的源码 COPY 放最后
  • 合并指令:多个 RUN&& 合并,减少层数(如 RUN apt-get update && apt-get install -y curl)。
  • 非 root 运行USER nonroot(或创建专用用户),生产容器绝不用 root——这是镜像安全扫描的头号告警项。
  • 多阶段构建FROM ... AS builder 编译、FROM ... 只拷贝产物,把编译工具链留在构建阶段。
  • 指定基础镜像 tag(python:3.11-slim),不要用 latest

docker run 常用参数

参数作用例子
-d后台运行docker run -d -p 8000:8000 my-svc
-p 宿主机:容器端口映射-p 8000:8000
-v 宿主机:容器挂载目录(模型权重、日志)-v /models:/models
--gpus all透传全部 GPU(需 nvidia-container-toolkit)--gpus '"device=0,1"' 指定卡
--name容器命名--name triton-server
--restart=unless-stopped异常退出自动重启生产服务必备
--shm-size加大共享内存(多进程/NCCL 需要)--shm-size 1g
--network host用宿主机网络(高性能/调试场景)注意端口冲突

docker composedocker-compose.yml):用 YAML 声明「服务 + 网络 + 卷」多容器编排。常用命令:docker compose up -d(启动)、docker compose logs -f(看日志)、docker compose down(停止)。推理服务 + Prometheus + Grafana 一套起在 compose 里是最快的本地模拟环境。

排障场景:容器内看不到 GPU 现象:宿主机 nvidia-smi 正常,容器里报 CUDA driver version is insufficient 或找不到设备。 排查链:nvidia-smi(驱动 OK?)→ 宿主装了 nvidia-container-toolkitsudo nvidia-ctk runtime configure --runtime=dockersystemctl restart docker?→ docker run --gpus all nvidia/cuda:... nvidia-smi 验证。详见 NVIDIA 官方安装文档

Kubernetes 核心概念

对象一句话定位与推理服务的关系
Pod最小调度单元,一个或多个容器共享网络/IP模型服务的实例,Pod 内通常「一个推理进程」
Deployment声明式管理 Pod 副本数(ReplicaSet)与滚动更新推理服务无状态副本的标准载体
Service稳定的集群内访问入口(ClusterIP/DNS)负载均衡到各 Pod,配合 kubectl port-forward 调试
Ingress集群外部的 HTTP(S) 入口路由对外暴露 /v1/models 等 API,可挂 TLS
HPA(Horizontal Pod Autoscaler)按 CPU/自定义指标自动扩缩副本按 QPS 或 GPU 利用率扩缩推理副本
ConfigMap / Secret配置与密钥注入模型路径、HF Token、环境变量
PVC持久化存储声明挂载模型权重避免每次冷启动下载

资源请求与限制resources.requests/limits)——推理服务最容易踩的坑:

yaml
resources:
  requests: { cpu: "4", memory: 16Gi, nvidia.com/gpu: 1 }
  limits:   { cpu: "4", memory: 24Gi, nvidia.com/gpu: 1 }
  • requests 决定调度与 QoS(不设 requests 的 Pod 是 BestEffort,最容易被驱逐);limits 防止进程吃光节点内存触发 OOMKill。
  • 给推理容器 limits.cpurequests.cpu 相等(Guaranteed QoS)可避免被抢占,代价是预留。
  • GPU 用 nvidia.com/gpu 声明(设备插件),GPU 的 requests 必须等于 limits

健康探针——决定「流量切给它还是摘掉它」:

探针用途推理场景建议
livenessProbe进程僵死时重启容器探测 /healthz,失败自动重启
readinessProbe就绪后才接流量模型加载完成前应返回失败,防止流量打进「模型还没起来」的副本
startupProbe慢启动保护大模型加载要几十秒,用 startup 放宽,避免 liveness 误杀

排障场景:服务起来了但请求 503/Connection Refusedkubectl get pods 看状态 → kubectl logs 看模型是否加载完 → 查 readinessProbe 路径与返回码;Pod 反复 CrashLoop 则先 kubectl describe pod 看 Events 里的 OOMKilled/ImagePullBackOff。

网络基础

HTTP 状态码速记(排障第一直觉):

状态码含义常见触发点
200成功正常推理响应
4xx客户端错误400 参数错、401/403 鉴权、404 路径、429 限流
5xx服务端错误500 推理异常、502 网关连不上后端、503 服务未就绪、504 超时
  • 502/503 在推理场景:先分清是「负载均衡器连不上 Pod」(看 Ingress/网关日志)还是「Pod 内服务没就绪」(看探针)。
  • 429(限流):动态批处理积压或副本数不足时常见,配合 Retry-After 头重试。

TCP 三次握手与超时

  • 三次握手(SYN → SYN-ACK → ACK)建立连接;抓包可用 tcpdump -i any port 8000 观察握手是否完成。
  • 常见超时参数:客户端连接超时 connect_timeout、服务端处理超时 read_timeout、总体超时 total_timeout。推理服务建议分别设置:连接 5s、首字节 60s+(模型推理可能慢)、总超时按最大单请求时长放大。
  • 连接池与 keep-alive:推理是高频小请求场景,务必复用连接(HTTP keep-alive、gRPC channel 复用),否则每次请求都在付握手成本——ab -k(keep-alive)与不带 -k 压测的差距往往就是性能瓶颈。

gRPC:基于 HTTP/2 的高性能 RPC,适合吞吐优先的推理(Triton 的 gRPC 端口就是典型)。特征:二进制协议、流式支持、连接长期复用。选型上「延迟敏感 + 内部系统」用 gRPC,「对外 + 简单调试」用 REST。

进程 / 线程 / 异步模型

概念定义对推理服务的影响
进程(Process)资源隔离的执行单元,各占独立内存空间多进程部署(如 Gunicorn/Uvicorn workers)可并行利用多核,但每份都要加载一份模型(显存翻倍)
线程(Thread)进程内的执行流,共享内存Python 中受 GIL 限制
GIL(全局解释器锁)CPython 同一时刻只允许一个线程执行字节码CPU 密集型 Python 代码多线程不加速;但推理的密集计算发生在 C/CUDA 库内部,会释放 GIL,所以「Python + 推理引擎」场景多线程仍有效
协程(Coroutine)用户态协作式调度,单线程内切换FastAPI 的 async defasyncio 事件循环模型,适合 IO 密集(网络等待、流式转发)
事件循环(Event Loop)单线程管理 IO 事件回调LLM 流式输出场景,事件循环让一个进程同时服务大量在途流

关键结论(推理服务并发模型)

  • CPU 密集的模型计算 → 交给推理引擎(释放 GIL 的 C/CUDA 代码),用线程/批处理榨干硬件。
  • IO 密集的请求处理 → 用 asyncio/FastAPI async 处理并发,一个 worker 扛大量长连接。
  • 需要多核并行时再上多进程,但要算清「进程数 × 每进程模型显存」是否放得下。

GPU 环境

nvidia-smi 输出解读

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 550.54.15    Driver Version: 550.54.15    CUDA Version: 12.4     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  A100-SXM4-40GB       On  | 00000000:00:04.0 On  |                    0 |
|  0%   47C    P0    68W / 400W |   3640MiB / 40960MiB |     44%      Default |
+-----------------------------------------------------------------------------+
含义排障关注
Driver Version / CUDA Version驱动版本 / 驱动支持的最高 CUDA驱动「支持」12.4 ≠ 运行时装了 CUDA 12.4,容器内报 libcudart 错先查这层
Memory-Usage已用/总显存GPU-Util 低但显存占满 = 模型卡在加载/泄漏
GPU-UtilSM 利用率持续接近 0 但服务有请求 = CPU/带宽瓶颈或没真正用 GPU
Temp / Pwr温度 / 当前功耗撞功耗墙或温度墙会性能骤降
Ecc Errors显存 ECC 错误计数持续增长是硬件故障信号

CUDA / cuDNN 版本匹配(部署排障第一大坑):

  • 三层要匹配:NVIDIA 驱动CUDA 运行时推理框架(PyTorch/TensorRT 等)编译时用的 CUDA 版本
  • 驱动是「向下兼容」的:驱动 ≥ 框架需要的 CUDA 版本即可。查法:nvidia-smi 看驱动支持的 CUDA 版本,python -c "import torch; print(torch.version.cuda)" 看 PyTorch 绑定的版本。
  • 首选容器方案:直接用官方镜像(nvidia/cuda:12.4-runtime-ubuntu22.04、NGC 的 PyTorch/Triton 镜像),框架与 CUDA 版本已配对,别再手工装。

驱动与容器(nvidia-container-toolkit):容器要访问 GPU 必须装 toolkit 并把运行时配置给 Docker/containerd,见上文容器小节链接。

显存泄漏排查

场景命令/手段怎么判断
显存被吃光但不释放nvidia-smi 连续观察 Memory-Usage服务空闲时显存还在涨 = 泄漏(推理引擎/框架 bug 常见)
定位谁在占显存nvidia-smi --query-compute-apps=pid,used_memory --format=csv看到残留的僵尸 Python 进程,kill
容器内看不到进程占用nvidia-smi 只显示当前容器--display 或宿主直接 fuser -v /dev/nvidia* 排查
PyTorch 缓存导致误报torch.cuda.empty_cache()显存被 PyTorch 缓存池占着不释放,属正常,压力测试才见真峰值

性能排查命令

工具看什么推理服务场景怎么用
vmstat 1进程/内存/IO/CPU 总览r(运行队列)长期大于核数 = CPU 排队;si/so 非零 = 内存吃紧开始换页
iostat -x 1磁盘吞吐与利用率模型冷启动/权重加载慢时看 %utilawaitawait 高 = 磁盘慢
pidstat 1单进程 CPU/内存定位是哪个进程在吃 CPU(如 tokenizer 线程 vs 推理线程)
perf top / perf record热点函数采样Python 服务先 py-spy top --pid 看 Python 栈,底层热点再上 perf
flamegraph(火焰图)调用栈耗时可视化perf/py-spy 数据生成,一眼看出「时间花在哪个调用栈」
sar -n DEV 1网卡流量与错误判断是否网络成为吞吐瓶颈
nload / iftop实时流量与连接排查大模型流式输出的带宽占用

排障思路:延迟高先分层 客户端耗时 = 网络往返 + 服务端排队 + 推理计算 + 后处理。用 time curl 分开测网络;用服务端指标(如 Triton/vLLM 的请求级指标)看「排队 vs 执行」占比;用火焰图看执行内部热点。分层定位比在单一层面瞎猜高效得多。

延伸阅读