使用Docker和Kubernetes部署机器学习模型

容器化将应用程序打包为轻量级、可移植的单元。对于机器学习(ML)来说,这确保了环境的可重复性和易于部署。例如,容器将机器学习模型代码与其确切的依赖项捆绑在一起,因此其结果可以在不同机器上保持一致,然后它们可以在任何Docker主机或云平台上运行,从而提高了可移植性。像Kubernetes这样的编排平台增加了可扩展性,可以根据需要自动启动或关闭容器。容器还将机器学习环境与其他应用程序隔离开来,从而防止依赖冲突。简而言之,将机器学习模型封装到Docker容器中,可以使其更容易在生产环境中可靠地迁移、运行和扩展。

  • 可重复性: 容器映像捆绑了模型、库和运行时(例如Python、scikit-learn),因此机器学习服务在任何系统上的行为都保持一致。
  • 可移植性:同一个容器可以在开发人员的笔记本电脑、持续集成(CI)管道或云计算虚拟机上运行,而无需更改。
  • 可扩展性:容器平台(Docker+Kubernetes)可以在负载下复制实例。Kubernetes可以自动扩展运行机器学习服务的Pod以满足需求。
  • 隔离性: 每个容器与其他容器和主机操作系统隔离,避免版本冲突或"在我的机器上能运行"的问题。

有了这些优势,可以通过具体示例进行演示:使用Python训练一个简单模型,通过Flask API提供服务,然后将其容器化并部署到AWS EKS Kubernetes集群上。

构建和提供示例机器学习模型

首先,创建一个简单的Scikit-Learn模型。使用Iris数据集训练一个决策树,然后用joblib保存模型。代码如下:

ini 复制代码
1 # train_model.py
2 from sklearn.datasets import load_iris
3 from sklearn.tree import DecisionTreeClassifier
4 import joblib
5
6 iris = load_iris()
7 X, y = iris.data, iris.target
8 model = DecisionTreeClassifier()
9 model.fit(X, y)
10 joblib.dump(model, 'model.pkl')

这将生成model.pkl。接下来,编写一个REST API来提供预测服务。例如,使用Flask加载模型并根据JSON输入进行预测:

ini 复制代码
1 # app.py
2 from flask import Flask, request, jsonify
3 import joblib
4
5 app = Flask(__name__)
6 model = joblib.load('model.pkl')
7
8 @app.route('/predict', methods=['POST'])
9 def predict():
10 data = request.get_json()
11 features = data.get('features')
12 prediction = model.predict([features])
13 return jsonify({'prediction': int(prediction[0])})
14
15 if __name__ == '__main__':
16 app.run(host='0.0.0.0', port=5000)

在这里,客户端发送类似{"features": 5.1, 3.5, 1.4, 0.2}的 JSON,服务器返回预测的类。

将机器学习服务Docker化

为了实现容器化,需要编写一个Dockerfile。Docker使用客户端**-** 服务器架构:Docker CLI与Docker守护进程交互,以构建镜像,从注册表中获取层,并运行容器。下图说明了这种架构:

Docker使用客户端-服务器模型,Docker CLI与管理镜像和容器的Docker守护进程进行通信。每个Docker映像都是一个分层的文件系统,其中包括应用程序代码和依赖项。在这里,将把Flask API和模型打包到一个映像中。

在项目目录中创建一个Dockerfile:

sql 复制代码
1 # Dockerfile
2 FROM python:3.9-slim
3 WORKDIR /app
4 COPY requirements.txt ./
5 RUN pip install -r requirements.txt
6 COPY model.pkl app.py ./
7 EXPOSE 5000
8 CMD ["python", "app.py"]

还包括一个requirements.txt,其中列出Python依赖项:

复制代码
1 flask
2 scikit-learn
3 joblib

在本地构建Docker镜像:(bash)。

perl 复制代码
Docker build -t my-ml-app:latest

这将创建一个包含模型服务器的映像my-ml-app:latest,可以通过运行(bash)来验证:

bash 复制代码
curl -X POST -H "Content-Type: application/json" \ 
-d '{"features": [5.1, 3.5, 1.4, 0.2]}' \ http://localhost:5000/predict

你可以得到一个JSON响应,如下所示:

json 复制代码
1 {"prediction":0}

这样,机器学习模型就实现了容器化,可以在任何Docker可用的地方运行。

Kubernetes 基础概念:Pod、Deployments和Services

Kubernetes集群由一个控制平台和多个工作节点组成。控制平台(有时称为Master)管理基本组件,例如如etcd(用于存储状态)、API服务器、调度程序、控制器管理器。工作节点在Pod中运行容器。其架构如下:

Kubernetes集群架构包括控制平台和工作节点。Kubernetes集群遵循master-worker模型。控制平台(图左)保存集群状态(etcd、API服务器、调度程序、控制器管理器)。工作节点(图右)运行kubelet和代理,并采用容器托管Pod。

关键概念:

  • Pod:Pod是最小的可部署单元。一个Pod封装一个或多个共享网络/存储的容器。Pod在节点上运行,并被视为单个单元。
  • Deployment:Deployment负责监督和维护一组Pod的控制器,确保所需数量的Pod正在运行和更新。声明一个Deployment,指定需要多少个副本,Kubernetes确保有许多Pod正在运行。
  • Service:Service是一种抽象,它对一组Pod进行分组,并为访问它们建立一致的策略,无论其各自的IP地址或生命周期如何。Service为Pod提供稳定的网络端点(ClusterIP 或LoadBalancer),支持负载均衡和发现。

在实践中,将创建一个Deployment来保持模型服务器的两个副本的运行,并创建一个Service来公开它们。

部署到AWS EKS

现在将Docker映像推送到注册表中,并部署到AWS EKS(Elastic Kubernetes Service)上的Kubernetes。首先,标记和推送映像(使用Docker Hub或ECR)。例如,使用Docker Hub:(bash)

perl 复制代码
docker tag my-ml-app:latest your_dockerhub_user/my-ml-app:latest docker push your_dockerhub_user/my-ml-app:latest

将your_dockerhub_user替换为Docker Hub用户名。

接下来,设置一个EKS集群(需要配置eksctl和AWS CLI)。如果还没有集群,AWS提供了创建集群的指南。例如:(bash)

lua 复制代码
create cluster -name ml-model-cluster -region us-west-2 -nodes

这将创建一个具有两个工作节点的基本EKS集群。确保kubectl上下文指向新的集群(AWS文档解释了如何连接)。

创建一个使用容器映像的Kubernetes部署清单(deploy.yaml):

yaml 复制代码
1 apiVersion: apps/v1
2 kind: Deployment
3 metadata:
4 name: ml-model-deployment
5 spec:
6 replicas: 2
7 selector:
8 matchLabels:
9 app: ml-model
10 template:
11 metadata:
12 labels:
13 app: ml-model
14 spec:
15 containers:
16 - name: ml-model
17 image: your_dockerhub_user/my-ml-app:latest
18 ports:
19 - containerPort: 9000

以及一个Service(Service.yaml),用于在外部公开它(在EKS上使用LoadBalancer类型): YAML

yaml 复制代码
1 apiVersion: v1
2 kind: Service
3 metadata:
4 name: ml-model-service
5 spec:
6 type: LoadBalancer
7 selector:
8 app: ml-model
9 ports:
10 - protocol: TCP
11 port: 80
12 targetPort: 9000

将这些应用于集群:(bash)

复制代码
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

检查状态:

arduino 复制代码
kubectl get deployments
kubectl get pods
kubectl get svc ml-model-service

当LoadBalancer配置完成之后,其Service将获得外部IP(或 AWS DNS)。一旦准备就绪,可以向该地址的80端口发送请求,它将转发到端口9000上的Pod。

结论

现在已经将scikit-learn模型实现容器化,使用Flask为其提供服务,并将其部署在Kubernetes上。为了生产就绪,可以考虑以下最佳实践:

  • 扩展: 使用kubectl scale或Kubernetes自动扩展根据CPU/内存或请求率调整副本。
  • 监控: 部署监控以跟踪Pod运行状况和模型性能。收集日志(例如使用Fluentd/Elasticsearch)用于故障排除。
  • CI/CD 使用管道(例如GitHub Actions、Jenkins或AWS CodePipeline)自动化工作流,这些管道可以重建映像并在新模型版本上更新部署(Deployment)。
  • 安全性: 使用Kubernetes RBAC和网络策略来保护访问。考虑扫描映像以查找漏洞,并使用与IAM集成的私有注册表(AWS ECR)。
  • 高级机器学习运维: 探索Kubeflow或Seldon等专用模型服务工具,以及MLflow或 Neptune等模型跟踪工具。如果模型需要这些工具,可以使用GPU或多架构映像。
相关推荐
IT_陈寒1 分钟前
Redis的SETNX并发问题让我加了三天班
前端·人工智能·后端
demo007x17 分钟前
Docling 文档转换以及技术架构分析
前端·后端·程序员
用户5191495848452 小时前
Windows 渗透测试载荷加载器 POC 工具集
人工智能·aigc
袋鱼不重2 小时前
我的神奇同事,AI 用多了居然写了个 Open In Codex
前端·后端·ai编程
大树882 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
用户8356290780512 小时前
使用 Python 操作 Word 内容控件
后端·python
像我这样帅的人丶你还2 小时前
啥? 前端也要会干Java?🛵🛵🛵
后端
Hommy882 小时前
【剪映小助手】添加贴纸接口(Add Sticker)
后端·github·剪映小助手·视频剪辑自动化·剪映api
通信小呆呆2 小时前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人
施小赞2 小时前
普通 RAG vs GraphRAG 核心对比
人工智能·ai