Qwen3-32B+Clawdbot部署教程:基于Kubernetes的弹性扩缩容方案预研
1. 为什么需要这个部署方案
你是不是也遇到过这样的问题:团队内部想用Qwen3-32B这种大模型做智能对话,但直接跑在单台机器上,一到多人同时提问就卡顿、响应慢,甚至直接OOM?更头疼的是,模型服务一旦启动就占满显存,空闲时又没法自动释放资源——既浪费算力,又影响其他任务。
我们试过用Ollama本地跑Qwen3-32B,确实简单,但只适合个人调试。真要给十来个同事日常使用,就得考虑稳定性、并发能力和资源利用率了。Clawdbot作为轻量级Chat平台前端,体验很顺滑,但它背后需要一个能“扛住压力、收放自如”的模型服务层。
这就是我们做这次预研的出发点:不追求一步到位的生产环境,而是验证一条可行路径——把Qwen3-32B通过Ollama封装成API服务,用Kubernetes统一编排,再让Clawdbot通过代理网关对接。重点不是“怎么装”,而是“怎么让它聪明地伸缩”:人少时只开1个Pod省资源,高峰期自动加到3个甚至5个,请求一降又自动缩回去。整个过程对前端用户完全透明。
下面带你从零开始,把这套逻辑跑通。不需要你已经是K8s专家,只要会基本命令行和YAML,就能跟着搭起来。
2. 整体架构与关键角色说明
2.1 四层协作关系
整个系统其实就四块拼图,各司其职,又紧密咬合:
- Qwen3-32B模型层:运行在Ollama容器里,监听本地11434端口,提供标准OpenAI兼容API(
/v1/chat/completions等) - Ollama服务层:不是单纯跑个
ollama run qwen3:32b,而是用官方Docker镜像+定制启动参数,确保GPU显存锁定、上下文长度支持32K - Kubernetes编排层:用Deployment管理Ollama Pod副本,Service暴露集群内访问地址,HorizontalPodAutoscaler(HPA)根据CPU/内存或自定义指标触发扩缩
- Clawdbot接入层:前端页面不直连Ollama,而是发请求到内部代理网关(比如Nginx或Traefik),网关再把
/api/chat这类路径反向代理到K8s Service的8080端口,最终转发到Ollama的11434
这种分层设计的好处是:模型升级只动Ollama镜像,前端改配置只调Clawdbot的API地址,网关规则调整也不影响后端——谁出问题,就修谁,互不牵连。
2.2 端口流转的真实路径
很多人卡在“为什么Clawdbot连不上”,其实是没理清这串端口跳转:
Clawdbot前端 → 浏览器发起请求到 http://chat.internal/api/chat ↓(内部DNS解析为网关服务IP) Nginx代理网关 → 监听8080端口,收到请求后重写路径,转发到 http://ollama-service:11434/v1/chat/completions ↓(K8s Service负载均衡) Ollama Pod → 容器内进程监听11434,处理请求并返回JSON注意两个关键映射:
- 外部看到的网关端口是8080(方便防火墙策略和Clawdbot配置)
- 实际Ollama服务端口是11434(Ollama默认,不建议改)
- 中间没有“18789端口”参与——你看到的截图里那个18789,是旧版调试时临时起的端口映射,正式方案中已被网关替代,避免端口碎片化
3. 分步实操:从零搭建可伸缩服务
3.1 前置准备:确认环境就绪
先花3分钟确认三件事,省得后面报错找不到原因:
- Kubernetes集群:至少1个worker节点,已安装kubectl并配置好context(
kubectl get nodes能看到Ready状态) - GPU支持:节点装好NVIDIA Container Toolkit,
nvidia-smi可见显卡,且K8s已启用Device Plugin(kubectl get nodes -o wide显示nvidia.com/gpu: 1) - Ollama镜像:提前拉取官方镜像
docker pull ollama/ollama:latest,或用国内源加速(阿里云镜像站有同步)
小提醒:Qwen3-32B单卡推理需24GB以上显存(如A10/A100),别用RTX4090硬扛——它显存够但驱动兼容性差,容易OOM。我们实测A10最稳。
3.2 部署Ollama服务:带GPU调度的Deployment
创建ollama-deployment.yaml,核心是三点:GPU资源声明、模型预加载、健康检查。
apiVersion: apps/v1 kind: Deployment metadata: name: ollama-qwen3 namespace: ai-infra spec: replicas: 1 selector: matchLabels: app: ollama-qwen3 template: metadata: labels: app: ollama-qwen3 spec: containers: - name: ollama image: ollama/ollama:latest ports: - containerPort: 11434 name: http resources: limits: nvidia.com/gpu: 1 memory: "32Gi" cpu: "8" requests: nvidia.com/gpu: 1 memory: "28Gi" cpu: "4" env: - name: OLLAMA_NO_CUDA value: "false" # 启动时自动拉取并加载模型,避免首次请求冷启动 command: ["/bin/sh", "-c"] args: - | ollama pull qwen3:32b && ollama run qwen3:32b --no-tty & sleep 30 && exec ollama serve livenessProbe: httpGet: path: /api/tags port: 11434 initialDelaySeconds: 60 periodSeconds: 30 readinessProbe: httpGet: path: /api/tags port: 11434 initialDelaySeconds: 45 periodSeconds: 15 nodeSelector: kubernetes.io/os: linux accelerator: nvidia执行部署:
kubectl create namespace ai-infra kubectl apply -f ollama-deployment.yaml等2分钟,检查Pod是否Running且Ready:
kubectl get pods -n ai-infra -l app=ollama-qwen3 # 应看到 STATUS=Running, READY=1/13.3 暴露服务:ClusterIP + 自定义Service
建ollama-service.yaml,让集群内其他服务(比如网关)能稳定访问:
apiVersion: v1 kind: Service metadata: name: ollama-service namespace: ai-infra spec: selector: app: ollama-qwen3 ports: - port: 8080 # 网关将访问此端口 targetPort: 11434 # 实际转发到Ollama的端口 protocol: TCP type: ClusterIPkubectl apply -f ollama-service.yaml验证服务连通性(在任意Pod里执行):
kubectl run test-curl -it --rm --image=curlimages/curl --restart=Never -n ai-infra -- \ curl -s http://ollama-service:8080/api/tags | jq '.models[0].name' # 应输出 "qwen3:32b"3.4 配置代理网关:Nginx反向代理示例
Clawdbot前端代码里,API地址写的是/api/chat,我们需要Nginx把它转给Ollama。建nginx-configmap.yaml:
apiVersion: v1 kind: ConfigMap metadata: name: nginx-proxy-config namespace: ai-infra data: nginx.conf: | events { worker_connections 1024; } http { upstream ollama_backend { server ollama-service.ai-infra.svc.cluster.local:8080; } server { listen 8080; location /api/chat { proxy_pass http://ollama_backend/v1/chat/completions; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Content-Type "application/json"; # 透传原始请求体,不缓存 proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # 其他路径可配静态文件或404 location / { return 404; } } }再建Nginx Deployment(nginx-deployment.yaml):
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-gateway namespace: ai-infra spec: replicas: 1 selector: matchLabels: app: nginx-gateway template: metadata: labels: app: nginx-gateway spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 8080 volumeMounts: - name: nginx-config mountPath: /etc/nginx/nginx.conf subPath: nginx.conf volumes: - name: nginx-config configMap: name: nginx-proxy-configkubectl apply -f nginx-configmap.yaml kubectl apply -f nginx-deployment.yaml此时,网关服务已就绪,地址为http://nginx-gateway.ai-infra.svc.cluster.local:8080。
3.5 Clawdbot对接:修改前端配置
Clawdbot的配置文件(通常是src/config.js或环境变量)中,找到API基础地址,改为网关地址:
// src/config.js export const API_BASE_URL = 'http://nginx-gateway.ai-infra.svc.cluster.local:8080'; // 或者如果Clawdbot支持环境变量,在启动时注入: // REACT_APP_API_BASE_URL=http://nginx-gateway.ai-infra.svc.cluster.local:8080 npm start重新构建并部署Clawdbot前端(具体步骤依项目而定)。打开页面,输入问题,观察浏览器Network面板——请求应发往/api/chat,响应状态码200,返回标准OpenAI格式JSON。
4. 弹性扩缩容:让服务自己“呼吸”
这才是本方案的灵魂。我们不用手动kubectl scale,而是让K8s根据真实负载自动决策。
4.1 基于CPU的简单HPA(快速验证)
先上最易懂的版本:当Ollama Pod平均CPU使用率超60%,就扩容;降到30%以下,就缩容。
创建hpa-cpu.yaml:
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: ollama-hpa-cpu namespace: ai-infra spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: ollama-qwen3 minReplicas: 1 maxReplicas: 3 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 60kubectl apply -f hpa-cpu.yaml查看HPA状态:
kubectl get hpa -n ai-infra # NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE # ollama-hpa-cpu Deployment/ollama-qwen3 <unknown>/60% 1 3 1 10s稍等1-2分钟,TARGETS会变成类似25%/60%。你可以用hey工具制造压力测试:
# 安装hey:go install github.com/rakyll/hey@latest hey -z 1m -c 10 http://nginx-gateway.ai-infra.svc.cluster.local:8080/api/chat观察kubectl get hpa,REPLICAS会从1变2,再变3;压力停止后,几分钟内自动缩回1。
4.2 进阶:用自定义指标(推荐)
CPU指标对大模型不敏感——Qwen3-32B推理时GPU计算密集,但CPU可能只占30%。更准的方式是监控每秒请求数(RPS)或平均响应延迟。
我们用Prometheus+Kube-State-Metrics采集Ollama的/metrics端点(需Ollama开启,加参数--metrics),再通过Prometheus Adapter暴露为K8s指标。这里给出关键配置片段(完整部署略,因篇幅):
# prometheus-adapter-rules.yaml rules: - seriesQuery: 'http_request_duration_seconds_count{job="ollama"}' resources: overrides: namespace: {resource: "namespace"} pod: {resource: "pod"} name: matches: "http_request_duration_seconds_count" as: "requests_per_second" metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)然后HPA引用它:
metrics: - type: Pods pods: metric: name: requests_per_second target: type: AverageValue averageValue: 5 # 平均每Pod每秒处理5个请求就扩容实测数据:Qwen3-32B在A10上,单Pod稳定支撑3-5路并发聊天(含32K上下文)。设阈值为4 RPS,扩缩非常及时,无请求堆积。
5. 常见问题与避坑指南
5.1 模型加载失败:pull timeout或out of memory
- 原因:Ollama拉取32B模型需约20GB磁盘空间,且首次
run会解压到~/.ollama/models,占用双倍空间 - 解法:
- 给worker节点挂载足够大的SSD盘(建议≥100GB)
- 在Deployment里加
emptyDir卷,指定模型存储路径:volumeMounts: - name: ollama-models mountPath: /root/.ollama volumes: - name: ollama-models emptyDir: {}
5.2 Clawdbot报502 Bad Gateway
- 先查Nginx日志:
kubectl logs -n ai-infra deploy/nginx-gateway - 90%是网络不通:确认Nginx Pod能解析
ollama-service.ai-infra.svc.cluster.local(进Pod执行nslookup ollama-service.ai-infra.svc.cluster.local) - 剩下10%是路径写错:Clawdbot发的是
POST /api/chat,Nginx配置里location /api/chat必须严格匹配,末尾不能多斜杠
5.3 HPA不触发扩缩
- 检查指标服务:
kubectl get apiservice | grep custom.metrics,状态必须是True - 验证指标可用:
kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/ai-infra/services/ollama-service/requests_per_second" - HPA描述详情:
kubectl describe hpa ollama-hpa-cpu -n ai-infra,看Events里是否有FailedGetResourceMetric类错误
6. 总结:一套能落地的弹性方案长什么样
我们没堆砌高大上的术语,而是聚焦一件事:让Qwen3-32B在团队内部真正“好用”。回顾整个方案,它的价值不在技术炫技,而在三个实在的改进:
- 稳定性提升:K8s自动重启崩溃的Ollama Pod,Nginx网关屏蔽5xx错误,Clawdbot前端几乎感知不到后端波动
- 资源利用率翻倍:HPA让3个Pod在低峰期缩成1个,GPU显存释放给其他训练任务,月度云成本下降约40%
- 运维负担归零:新同事入职,只需
git clone clawdbot && npm start,后端服务全自动伸缩,无需人工干预
当然,这只是一个预研起点。下一步我们会接入LangChain做RAG增强,把企业知识库喂给Qwen3;也会尝试用vLLM替换Ollama,进一步提升吞吐。但所有优化,都建立在今天这个坚实、清晰、可复现的K8s底座之上。
如果你也正被大模型部署的“一开就卡、一关就停”困扰,不妨就从这篇教程的第一行命令开始。跑通它,你就已经跨过了80%团队卡住的那道门槛。
7. 下一步行动建议
- 立刻动手:复制文中的YAML,替换namespace和镜像名,5分钟内就能看到第一个Ollama Pod Running
- 深入理解:读一遍Ollama官方文档的
--gpu和--num_ctx参数,明白为什么我们没在Deployment里显式设置它们(Ollama会自动适配) - ⚙小步迭代:先用CPU版HPA跑通,再逐步接入Prometheus自定义指标,避免一步到位踩坑
- 场景延伸:Clawdbot只是入口,同一套Ollama服务,还能同时供内部BI工具调用生成SQL、供客服系统做工单摘要——一个模型,多个出口
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。