10 | 云上 AI 推理服务:把 scikit-learn 模型塞进 K8s,纯 CPU 也能跑
10 | 云上 AI 推理服务把 scikit-learn 模型塞进 K8s纯 CPU 也能跑系列目录《基于华为云 FlexusX 四节点集群的云计算全栈实操》PaaS 篇本篇对应课程模块云上 AI / 云原生应用引子上一篇我们把 K3s 集群跑起来了也验证了它「负载均衡、自愈、弹性、滚动更新」的四大能力。但集群本身不产生价值——跑在上面的工作负载才产生价值。这一篇我们让集群干一件「很 AI」的事部署一个在线情感分析推理服务。模型是 scikit-learn 的 TF-IDF 逻辑回归框架用 FastAPI uvicorn 封装成 HTTP API全程纯 CPU、不用 GPU。为什么选这么「朴素」的组合因为现实里 80% 的 AI 落地需求根本用不到大模型情感分析、垃圾邮件分类、风险评分、文本相似度……这些中小模型在 CPU 上几毫秒就能出结果却要吃掉一整张几千块的 GPU 卡账怎么算都不划算。本文会带你走完一条完整链路模型训练 → 容器封装 → 镜像分发 → K8s 编排 → HTTP 在线推理并重点讲清楚一个很多人会卡住的真实难题——K8s 用的是 containerd不是 Docker本地镜像怎么交付到集群。背景与理论CPU 推理的成本逻辑《深入浅出云计算》反复强调一个观点云的价值不在「算力最大」而在「算力刚好匹配需求」。AI 推理正是这一观点的试金石。维度GPU 推理如 T4/A10CPU 推理如 FlexusX 8vCPU单卡/实例成本高GPU 溢价明显低通用算力按需付费吞吐适合大模型 / 高并发批量中小模型单请求毫秒级足够适用模型LLM、CV 大模型、嵌入向量传统 ML、轻量分类/回归部署复杂度需 nvidia-docker、device-plugin普通容器零额外依赖我们的情感分析模型是一个TfidfVectorizer(ngram_range(1,2))LogisticRegression的 Pipeline参数量极小一次predict_proba在 CPU 上亚毫秒级完成。把它放在 8vCPU 的 FlexusX 上单实例即可稳定撑起中小流量成本只有 GPU 方案的零头。这正是云原生 AI 落地的「群众路线」——不必人人都上大模型。架构┌─────────────────────────────────────────────────────────────┐ │ K3s Cluster (containerd runtime, 3 nodes) │ │ │ │ NodePort 30800 ──┐ │ │ ▼ │ │ kube-proxy (iptables) │ │ / | \ │ │ ▼ ▼ ▼ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ sentiment │ │ sentiment │ │ sentiment │ │ │ │ -ai Pod │ │ -ai Pod │ │ -ai Pod │ │ │ │ (node1) │ │ (node3) │ │ (node4) │ │ │ │ FastAPI │ │ FastAPI │ │ FastAPI │ │ │ │ :8000 │ │ :8000 │ │ :8000 │ │ │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │ │ │ (imagePullPolicy: Never, 本地镜像) │ │ └───────────────┴────────────────┘ │ │ │ │ 镜像来源docker save → ctr import → 内网 scp 分发 │ └─────────────────────────────────────────────────────────────┘链路关键点镜像不走公网 Registry而是本地构建后通过内网分发到各节点 containerd——这是没有私有 Registry 时的务实方案生产建议改用 Harbor/SWR后文详述。环境与准备节点弹性公网IP私有IP规格系统K8s角色node1113.47.6.41192.168.0.2528vCPU/16GiBUbuntu 24.04.4control-planenode31.94.220.182192.168.0.2418vCPU/16GiBUbuntu 24.04.4workernode4124.70.102.139192.168.0.1508vCPU/16GiBUbuntu 24.04.4worker沿用上篇的 K3s v1.36.2k3s1 containerd 2.3.2 集群。由于 node2 未纳入集群镜像分发只需在 n1、n3、n4 三节点间进行。实操步骤1. 编写推理服务 app.py服务启动时用内置中英混合语料训练模型对外暴露三个端点/元信息、/healthz探针、/predict推理。关键片段完整见../ai-service/app.py# 启动时即在模块加载阶段训练模型CPU毫秒级modelPipeline([(tfidf,TfidfVectorizer(ngram_range(1,2),min_df1)),(clf,LogisticRegression(max_iter1000)),])model.fit([tfort,_inTRAIN],[yfor_,yinTRAIN])app.get(/healthz)defhealthz():return{status:ok,pod:HOSTNAME}app.post(/predict)defpredict(req:Req):probamodel.predict_proba([req.text])[0]labelpositiveifproba[1]0.5elsenegativereturn{text:req.text,label:label,score_positive:round(float(proba[1]),4),score_negative:round(float(proba[0]),4),served_by_pod:HOSTNAME,}设计要点训练放在进程启动期而非首次请求时避免冷启动抖动语料小CPU 上训练几乎无感。/healthz与/predict分离探针走轻量端点推理走重端点互不干扰。served_by_pod字段用于验证负载均衡——能看到请求究竟落到哪个 Pod。2. 编写 DockerfilePyPI 清华镜像加速FROM python:3.11-slim WORKDIR /app # 使用国内 PyPI 镜像加速依赖安装 RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . EXPOSE 8000 CMD [uvicorn, app:app, --host, 0.0.0.0, --port, 8000]requirements.txt固定版本保证可复现fastapi0.115.6 uvicorn0.34.0 scikit-learn1.6.1 pydantic2.10.43. 构建镜像在 node1 上构建最终镜像sentiment-ai:1.0体积约 600MB含 python:3.11-slim 基础镜像与 scikit-learn 依赖cdai-servicedockerbuild-tsentiment-ai:1.0.4. 把镜像交付到 K8s关键难点这是全文最关键的工程点。很多人以为docker build完kubectl apply就能用——错。K3s 用的是containerd它不读 Docker 的本地镜像库。如果你在 YAML 里写imagePullPolicy: IfNotPresent却没配可访问的 RegistryPod 会一直ImagePullBackOff。我们的务实方案无私有 Registry 时# 1) node1: 把 Docker 镜像导出成 tardockersave sentiment-ai:1.0-osentiment-ai.tar# 约 133 MiB# 2) node1: 导入到本机 containerdK3s 自带 ctrsudok3s ctr imagesimportsentiment-ai.tar# 3) 内网 scp 分发 tar 到 worker 节点scpsentiment-ai.tar node3:/tmp/scpsentiment-ai.tar node4:/tmp/# 4) node3 / node4: 各自导入 containerdsshnode3sudo k3s ctr images import /tmp/sentiment-ai.tarsshnode4sudo k3s ctr images import /tmp/sentiment-ai.tar三节点 containerd 都持有镜像后Deployment 里必须显式声明imagePullPolicy: Never告诉 K3s「别去远程拉就用本地镜像」containers:-name:sentiment-aiimage:docker.io/library/sentiment-ai:1.0imagePullPolicy:Never5. 部署到 K8sai-service.yaml完整见../k8s/ai-service.yaml关键片段apiVersion:apps/v1kind:Deploymentmetadata:name:sentiment-aispec:replicas:3template:spec:containers:-name:sentiment-aiimage:docker.io/library/sentiment-ai:1.0imagePullPolicy:Neverports:-containerPort:8000resources:requests:cpu:100mmemory:128Milimits:cpu:500mmemory:512MireadinessProbe:httpGet:path:/healthzport:8000initialDelaySeconds:3periodSeconds:5livenessProbe:httpGet:path:/healthzport:8000initialDelaySeconds:5periodSeconds:10topologySpreadConstraints:-maxSkew:1topologyKey:kubernetes.io/hostnamewhenUnsatisfiable:ScheduleAnywaylabelSelector:matchLabels:app:sentiment-ai---apiVersion:v1kind:Servicemetadata:name:sentiment-ai-svcspec:type:NodePortselector:app:sentiment-aiports:-port:8000targetPort:8000nodePort:30800sudokubectl apply-fai-service.yamlsudokubectl get pods-owide真实输出实测以下来自results/15_ai_inference.txt。Pod 跨 3 节点均衡分布sentiment-ai-7f878749b7-9whd9 Running ecs-71b9-0003 sentiment-ai-7f878749b7-p8fnx Running ecs-71b9-0004 sentiment-ai-7f878749b7-rxdf5 Running ecs-71b9-0001topologySpreadConstraints再次生效3 副本精确落到 n3/n4/n1 三个节点。服务元信息 GET /{service:sentiment-inference,framework:scikit-learn FastAPI, pod:sentiment-ai-7f878749b7-p8fnx}推理测试 POST /predict请求被负载均衡到不同 PodIN : this is absolutely wonderful, i love it OUT: labelpositive score_pos0.5604 served_by...-p8fnx IN : terrible quality, total waste of money OUT: labelnegative score_pos0.4265 served_by...-rxdf5 IN : the delivery was fast and the product works great OUT: labelpositive score_pos0.5844 served_by...-9whd9 IN : it broke after one day, very disappointed OUT: labelnegative score_pos0.4104 served_by...-p8fnx4/4 样本情感分类全部正确且返回了正负类概率分数如score_pos0.5604。更关键的是served_by_pod字段——请求被负载均衡到了p8fnx、rxdf5、9whd9三个不同的 Pod证明 Service 的流量分发真实生效。深度解读探针对 AI 服务的特殊意义这篇的 YAML 里我特意给 AI 服务配了readinessProbe和livenessProbe这比普通 Web 服务更有讲究readinessProbe就绪探针AI 服务启动时要加载/训练模型可能需要几秒才能接流量。在就绪前若放流量进来要么报错要么超时。探针失败期间kube-proxy 不会把该 Pod 加入 Endpoint避免「启动期裸奔」。livenessProbe存活探针如果模型推理时死锁、或内存泄漏把进程拖死存活探针持续失败会触发 kubelet重启该 Pod配合 ReplicaSet 实现自愈对线上推理可用性至关重要。对大模型/GPU 服务探针还要加startupProbe给足冷启动时间否则大模型加载慢会被误杀——这是我们这套小模型不必、但大模型必做的细节。踩坑与排障重点坑 1containerd 看不到 Docker 镜像现象Pod 一直ImagePullBackOffdescribe显示ErrImageNeverPull或拉取 timeout。根因docker和k3s ctr是两套独立的镜像存储。Docker 构建的镜像只在 Docker 的 graph driver 里containerd 不会自动看到。解决docker save→k3s ctr images import→ 各节点分发 →imagePullPolicy: Never。且三个节点都必须有镜像否则调度到没镜像的节点就会 Pending/ErrImagePull。坑 2镜像标签要带仓库前缀ai-service.yaml里写的是docker.io/library/sentiment-ai:1.0。导入时若只标sentiment-ai:1.0containerd 内部会规范化为docker.io/library/sentiment-ai:1.0YAML 里最好写全避免命名空间不匹配导致找不到。坑 3镜像体积python:3.11-slim scikit-learn 让镜像到 600MB。生产可换python:3.11-alpine 多阶段构建压到 200MB 以内分发更快、启动更轻。生产建议与延伸当前方案的定位本地docker savectr import 内网分发是没有私有 Registry 时的最佳过渡方案适合实验、PoC、离线环境。但它有明显的生产短板每加一个节点都要手动分发镜像不可扩展无法做镜像版本管理、签名、漏洞扫描。生产应升级为私有 Registry华为云 SWR 或自建 HarborYAML 改成image: swr.cn-xxx.myhuaweicloud.com/team/sentiment-ai:1.0imagePullPolicy: IfNotPresent配合ImagePullSecret。更大模型的路线模型服务化框架KServe / Triton Inference Server——统一推理协议、动态批处理dynamic batching、模型版本灰度GPU 推理需安装 NVIDIA device-plugin节点打nvidia.com/gpu资源标签Pod 声明limits: nvidia.com/gpu: 1大模型LLMvLLM / TGIS 等推理引擎配合 K8s 的HPA GPU 共享如 volcano做弹性。小结我们打通了一条完整的「云上 CPU AI 推理」链路模型训练——scikit-learn TF-IDF 逻辑回归启动即训容器封装——FastAPI uvicorn镜像 600MB镜像交付——docker save→ctr import→ 内网分发 →imagePullPolicy: NeverK8s 编排——3 副本跨 3 节点NodePort 30800在线推理——4/4 分类正确请求负载均衡到不同 Pod。最值得记住的工程经验K8s 用 containerdDocker 构建的镜像必须显式导入 containerd否则 Pod 拉不到镜像。这条坑踩过一次就忘不掉了。下一篇我们给这个 AI 服务加上HPA 自动伸缩让它在流量洪峰时自动扩容、低谷时缩容——真正体验 Serverless 式的弹性。配置与实测引用推理实测../results/15_ai_inference.txt部署清单../k8s/ai-service.yaml服务代码../ai-service/app.py构建文件../ai-service/Dockerfile、../ai-service/requirements.txt

相关新闻

HTML5 Audio/Video 标签,属性,方法,事件汇总

HTML5 Audio/Video 标签,属性,方法,事件汇总

一、标签介绍 1、<audio> 标签属性&#xff1a; src&#xff1a;音乐的URL preload&#xff1a;预加载 autoplay&#xff1a;自动播放 loop&#xff1a;循环播放 controls&#xff1a;浏览器自带的控制条 Html代码 <audio id”media” src”http://www.abc.com/test.m…

2026/7/28 16:03:41阅读更多 →
报错:'str' object has no attribute 'decode'

报错:'str' object has no attribute 'decode'

进入报错的文件夹operations.py&#xff0c;修改 query query.decode(errors‘replace’) 为 query query.encode(errors‘replace’)

2026/7/28 16:03:41阅读更多 →
HttpClient源码解析系列一:概括及使用

HttpClient源码解析系列一:概括及使用

一、简单介绍下Http, tcp/ip和socket区别&#xff1a;首先看一下无处不在的OSI七层传输模型&#xff1a;第一层&#xff1a;应用层。定义了用于在网络中进行通信和传输数据的接口&#xff1b;&#xff08;Http协议位于该层&#xff09;第二层&#xff1a;表示层。定义不同的系统…

2026/7/28 16:03:41阅读更多 →
600万年薪抢疯了!大模型人才火爆,小白也能入局,速收藏!

600万年薪抢疯了!大模型人才火爆,小白也能入局,速收藏!

大厂争抢AI人才&#xff0c;大模型算法成热招岗位第一&#xff0c;AI科学家月薪破10万。企业看重实干能力&#xff0c;博士实习日薪超千元。AI人才分三类&#xff1a;A类核心技术人才&#xff0c;B类应用开发人才&#xff0c;C类AI使用者。普通理工科学生可切入B类&#xff0c;…

2026/7/28 17:19:57阅读更多 →
##将一个字符的前n个字符左旋##判断一个字符串是否为另外一个字符串旋转之后的字符串。

##将一个字符的前n个字符左旋##判断一个字符串是否为另外一个字符串旋转之后的字符串。

实现一个函数&#xff0c;可以左旋字符串中的k个字符。 ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 思路如下&#xff1a;先将要左旋的k个字符逆置&#xff0c;然后将k个字符之后的字符逆置&#xff0c;左后将整个字符串逆置。1.逆置字符串的函数void reverse(char …

2026/7/28 17:19:57阅读更多 →
基于线段树的RMQ

基于线段树的RMQ

每个节点维护的是区间的最小值#include <cstdio> #include <iostream> #include <vector> #include <cmath> #include <queue> #include <algorithm> #include <cstring>typedef long long ll; const int INF 1e6; const int maxn…

2026/7/28 17:19:57阅读更多 →
基础Demo_02数据运算符(学习笔记)

基础Demo_02数据运算符(学习笔记)

算术运算图中代码 public class Demo01_YurnSuan {public static void main(String[] args){System.out.println(10 20); // 30System.out.println(10 - 20); // -10System.out.println(10 * 20); // 200System.out.println(10 / 20); // 整数与整数运算,结果还是整数System.o…

2026/7/28 17:19:57阅读更多 →
如何选择适合自己的编程语言?这个操作厉害了

如何选择适合自己的编程语言?这个操作厉害了

Twitter上流传的《编程语言选择指导图》&#xff0c;非常具有参考性。大家可以通过这张图做个小测试&#xff0c;看看自己更适合哪种编程语言。 学习编程&#xff0c;首先要选择一门编程语言&#xff0c;但是初学者往往在这个环节产生迷茫&#xff0c;不知道该如何选择。 下面的…

2026/7/28 17:19:57阅读更多 →
开源一套.NET平台的Excel COM 组件二次封装库

开源一套.NET平台的Excel COM 组件二次封装库

开源一套.NET平台的Excel COM 组件二次封装库 在日常的企业级开发中&#xff0c;Excel 文件的读写是一个高频需求。虽然 .NET 平台提供了多种方式操作 Excel&#xff0c;如 NPOI、EPPlus 或 OpenXML&#xff0c;但在某些场景下&#xff08;如调用 VBA 宏、保留复杂格式、与旧系…

2026/7/28 17:17:57阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

&#x1f539; 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具&#xff0c;凭借本地离线运行、可视化图形操作和任务自动化三大核心特性&#xff0c;赢得了众多用户的青睐。与普通在线对话AI工具不同&#xff0c;它属于能够直接操控本机软硬件的智能数字员工…

2026/7/28 4:06:39阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接&#xff0c;是用激光束对阀座壳体&#xff08;通常为不锈钢或铝合金&#xff09;进行密封焊接&#xff0c;使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/28 2:08:06阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX&#xff1a;三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/28 1:38:28阅读更多 →
告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿&#xff01;3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:29阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑&#xff1a;把几百页的财报、法规、技术手册扔给向量库&#xff0c;问一个具体问题&#xff0c;搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了&#xff0c;要么藏在几十条结果的最下面。语义相似≠真正相关&#xff0c;这个…

2026/7/28 0:00:29阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营&#xff0c;从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候&#xff0c;每天刷半小时抖音&#xff0c;手动把爆款视频的口播敲进备忘录&#xff0c;一条2分钟的视频得花十来分钟&#xff0c;碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:29阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/27 16:57:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/28 3:17:03阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/28 2:35:58阅读更多 →