在 Kubernetes 上部署 GLM-4.7 2bit量化模型

本文记录了在多节点 Kubernetes 集群上部署大模型 GLM-4.7-UD-Q2_K_XL 并调用的完整实践过程,包括资源调优、容器调度、NUMA 优化、Pod 调试以及模型调用示例。
hg下载 合计135g
https://huggingface.co/unsloth/GLM-4.7-GGUF?show_file_info=UD-Q2_K_XL%2FGLM-4.7-UD-Q2_K_XL-00001-of-00003.gguf
https://huggingface.co/unsloth/GLM-4.7-GGUF?show_file_info=UD-Q2_K_XL%2FGLM-4.7-UD-Q2_K_XL-00002-of-00003.gguf
https://huggingface.co/unsloth/GLM-4.7-GGUF?show_file_info=UD-Q2_K_XL%2FGLM-4.7-UD-Q2_K_XL-00003-of-00003.gguf


一、背景

我们有一台多节点集群,目标是部署一个单实例大模型(GGUF 文件,约 135GB),让模型充分利用整个节点的 CPU 和内存资源,同时通过 REST API 提供文本生成服务。

硬件环境(以 k8s-worker2 为例)

1
2
3
4
5
6
7
8
9
10
11
lscpu
````

输出核心信息:

* CPU: 128 核(2 Socket × 32 核 × 2 线程/核)
* NUMA 节点: 8
* 内存: 1.8TB

```bash
free -h
  • 总内存: 1.8T
  • 已用: 86G
  • 可用: 1.6T

说明内存和 CPU 资源都非常充裕,适合单实例部署大模型。


二、初始部署尝试

最初我们使用以下 Deployment YAML 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
apiVersion: apps/v1
kind: Deployment
metadata:
name: glm-server
spec:
replicas: 1
selector:
matchLabels:
app: glm-server
template:
metadata:
labels:
app: glm-server
spec:
containers:
- name: glm-server
image: ghcr.io/ggml-org/llama.cpp:server
args:
- "-m"
- "/models/GLM-4.7-UD-Q2_K_XL-00001-of-00003.gguf"
- "--port"
- "8181"
- "--ctx-size"
- "4096"
- "--mmap"
- "--chat-template"
- "glm4"
- "-c"
- "32"
ports:
- containerPort: 8181
volumeMounts:
- name: model-volume
mountPath: /models
resources:
limits:
memory: "200Gi"
cpu: "32"
volumes:
- name: model-volume
hostPath:
path: /home/mnt/192.168.1.60/data/models/unsloth
type: Directory

1️⃣ 问题一:Pod Pending

1
kubectl get pods -w

输出显示:

1
glm-server-xxx   0/1   Pending   ...

kubectl describe pod glm-server-xxx 显示:

1
Warning  FailedScheduling  ...  0/3 nodes are available: 1 Insufficient cpu ...

原因:Pod 请求 CPU/内存资源过高,或者 NodeSelector 限制了节点,导致调度失败。


2️⃣ 问题二:Pod CrashLoopBackOff

当尝试将 CPU、内存调大,或者启用 NUMA 绑定时:

1
2
3
4
5
6
7
8
9
10
11
12
args:
- "numactl"
- "--interleave=all"
- "./server"
- "-m" ...
resources:
limits:
cpu: 128
memory: 500Gi
requests:
cpu: 8
memory: 32Gi

Pod 状态变为:

1
2
CrashLoopBackOff
Exit Code: 127

原因:容器内缺少 numactl 或命令路径错误,需要确保镜像内已经安装 numactl,并且 server 路径正确。


三、优化部署策略

根据节点资源与模型需求,采取以下措施:

  1. 增加 CPU 核数和内存限制

    • 单实例请求 64 核、200Gi 内存
    • 限制可用 128 核、300-400Gi 内存
    • 保证单实例可以加载完整 GGUF 模型
  2. NUMA 优化

    • 对大模型推荐使用 numactl --interleave=all,在多 NUMA 节点之间均匀分配内存
    • 或者绑定部分核心和内存,保证性能稳定
  3. HostPath 挂载模型文件

    • 模型文件过大(135G),直接挂载宿主机目录
    • 避免使用容器镜像内嵌模型,减小镜像体积

最终 YAML 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
apiVersion: apps/v1
kind: Deployment
metadata:
name: glm-server
spec:
replicas: 1
selector:
matchLabels:
app: glm-server
template:
metadata:
labels:
app: glm-server
spec:
containers:
- name: glm-server
image: ghcr.io/ggml-org/llama.cpp:server
command:
- "/bin/bash"
- "-c"
args:
- |
echo "====== CPU ======"; lscpu
echo "====== MEM ======"; free -h
echo "====== STARTING GLM ======";
numactl --interleave=all /app/server \
-m /models/GLM-4.7-UD-Q2_K_XL-00001-of-00003.gguf \
--port 8181 --host 0.0.0.0 --ctx-size 4096 --mmap \
--chat-template glm4 -c 128
ports:
- containerPort: 8181
volumeMounts:
- name: model-volume
mountPath: /models
resources:
limits:
cpu: "128"
memory: "500Gi"
requests:
cpu: "64"
memory: "200Gi"
volumes:
- name: model-volume
hostPath:
path: /home/mnt/192.168.1.60/data/models/unsloth
type: Directory

四、Pod 调试

  1. 检查 Pod 状态:
1
2
3
kubectl get pods
kubectl describe pod glm-server-xxxx
kubectl logs -f glm-server-xxxx
  1. 确认模型服务健康:
1
2
curl http://<pod-ip>:8181/health
# 返回 {"status":"ok"} 表示模型启动成功

五、调用模型 API

1️⃣ 使用 curl 调用 completions

1
2
3
4
5
6
7
curl -X POST http://10.244.126.56:8181/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "GLM-4.7-UD-Q2_K_XL",
"prompt": "介绍一下自己",
"max_tokens": 100
}'

返回示例:

1
2
3
4
5
6
7
8
9
{
"choices":[
{
"text":"我是一个喜欢写代码的人,写代码对我来说不仅仅是工作,更是一种乐趣...",
"index":0
}
],
"model":"GLM-4.7-UD-Q2_K_XL-00001-of-00003.gguf"
}

2️⃣ 长文本请求示例

1
2
3
4
5
6
7
curl -X POST http://10.244.126.56:8181/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "GLM-4.7-UD-Q2_K_XL",
"prompt": "用python写一个俄罗斯方块游戏",
"max_tokens": 1000
}'

返回完整代码片段,支持直接执行。

注意:/chat 接口在该版本中不可用,会返回 404。


六、总结经验

  1. 资源调优

    • 根据硬件资源调整 CPU、内存、NUMA 策略
    • 大模型单实例可以充分利用多 NUMA 节点
  2. 镜像与依赖

    • 确认容器内有 numactl 等必要工具
    • 模型文件直接挂载宿主机,避免拉取大镜像
  3. 调试技巧

    • kubectl describe pod 查看调度和事件
    • kubectl logs 查看容器启动信息
    • /health 检查模型是否可用
  4. 调用方式

    • /v1/completions 是通用接口
    • 大模型生成长文本时,需要适当增加 max_tokens

经过多次尝试,最终成功在单实例中跑满 CPU 并加载 135G 模型,提供可用的 REST API 调用。