Kubernetes + Docker 部署一个yolov5检测服务(基于FastDeploy)

Kubernetes + Docker 从零部署一个yolov5检测服务,服务基于PaddlePaddle/FastDeploy的服务化部署;所有软件从零安装。

1.说明

  • 基于k8s的minikube部署一个单节点服务,重了解在部署流程和细节。
  • 服务基于CPU部署。

2.环境

WSL2 Ubuntu 18.04
kubernetes v1.23.8
Docker 23.0.0
PaddlePaddle/FastDeploy

3.安装过程

· 3.1安装 Docker

#1. 新软件列表和允许使用https
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
#2.添加阿里源的GPG
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

#3.设置阿里源的docker仓库
 echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

#4.安装docker:

#4.1更新apt-get
sudo apt-get update

#4.2安装最新的docker版本
sudo apt-get install docker-ce docker-ce-cli containerd.io

#4.3启动docker
sudo service docker start

#4.4查看docker服务状态
sudo service docker status

· 3.2安装 minikube

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
  • 这里启动大约要5分钟
#启动k8s,使用docker为引擎.
minikube start --force --driver=docker --kubernetes-version=v1.23.8
  • 验证minikube启动情况
minikube kubectl get ns
#显示一下说明成功
root@DESKTOP-4J64IFF:~# minikube kubectl get ns
NAME                   STATUS   AGE
default                Active   8d
kube-node-lease        Active   8d
kube-public            Active   8d
kube-system            Active   8d
kubernetes-dashboard   Active   8d

· 3.3安装 Kubectl

  • 安装
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl 
chmod +x ./kubectl 
sudo mv ./kubectl /usr/local/bin/kubectl 
kubectl version --client
  • 测试
kubectl get pod -A

4.部署过程

· 4.1 Docker相关

  • 下载CPU镜像,仅支持Paddle/ONNX模型在CPU上进行服务化部署,支持的推理后端包括OpenVINO、Paddle Inference和ONNX Runtime。
docker pull registry.baidubce.com/paddlepaddle/fastdeploy:1.0.2-cpu-only-21.10
  • 下载部署代码,及模型等
#下载部署示例代码
git clone https://github.com/PaddlePaddle/FastDeploy.git
cd FastDeploy/examples/vision/detection/yolov5/serving/

#下载yolov5模型文件和测试图片
wget https://gitee.com/paddlepaddle/PaddleDetection/raw/release/2.4/demo/000000014439.jpg
wget https://bj.bcebos.com/paddlehub/fastdeploy/yolov5s.onnx

# 将模型放入 models/runtime/1目录下, 并重命名为model.onnx
mv yolov5s.onnx models/runtime/1/model.onnx
  • 启动docker测试服务(可跳过)
######################### 服务端 ##############################
cd FastDeploy/examples/vision/detection/yolov5/serving/
# 手动启动docker
docker run -it --net=host --name fd_serving -v `pwd`/:/yolov5_serving registry.baidubce.com/paddlepaddle/fastdeploy:x.y.z-cpu-only-21.10  bash
#启动服务
fastdeployserver --model-repository=/yolov5_serving/models --backend-config=python,shm-default-byte-size=10485760

#服务启动成功后, 会有以下输出:
#I0928 04:51:15.784517 206 grpc_server.cc:4117] Started GRPCInferenceService at 0.0.0.0:8001
#I0928 04:51:15.785177 206 http_server.cc:2815] Started HTTPService at 0.0.0.0:8000
#I0928 04:51:15.826578 206 http_server.cc:167] Started Metrics Service at 0.0.0.0:8002
######################### 客户端 ##############################
cd FastDeploy/examples/vision/detection/yolov5/serving/
#安装端依赖
python3 -m pip install tritonclient[all]
# 发送请求
python3 yolov5_grpc_client.py

#发送请求成功后,会返回json格式的检测结果并打印输出:
#output_name: detction_result
#{'boxes': [[268.48028564453125, 81.05305480957031, 298.69476318359375, 169.43902587890625], [104.73116302490234, 45.66197204589844, 127.58382415771484, 93.44938659667969], [378.9093933105469, 39.75013732910156, 395.6086120605469, 84.24342346191406], [158.552978515625, 80.36149597167969, 199.18576049804688, 168.18191528320312], [414.37530517578125, 90.94805908203125, 506.3218994140625, 280.40521240234375], [364.00341796875, 56.608917236328125, 381.97857666015625, 115.96823120117188], [351.7251281738281, 42.635345458984375, 366.9103088378906, 98.04837036132812], [505.8882751464844, 114.36674499511719, 593.1248779296875, 275.99530029296875], [327.7086181640625, 38.36369323730469, 346.84991455078125, 80.89302062988281], [583.493408203125, 114.53289794921875, 612.3546142578125, 175.87353515625], [186.4706573486328, 44.941375732421875, 199.6645050048828, 61.037628173828125], [169.6158905029297, 48.01460266113281, 178.1415557861328, 60.88859558105469], [25.81019401550293, 117.19969177246094, 59.88878631591797, 152.85012817382812], [352.1452941894531, 46.71272277832031, 381.9460754394531, 106.75212097167969], [1.875, 150.734375, 37.96875, 173.78125], [464.65728759765625, 15.901412963867188, 472.512939453125, 34.11640930175781], [64.625, 135.171875, 84.5, 154.40625], [57.8125, 151.234375, 103.0, 174.15625], [165.890625, 88.609375, 527.90625, 339.953125], [101.40625, 152.5625, 118.890625, 169.140625]], 'scores': [0.8965693116188049, 0.8695310950279236, 0.8684297800064087, 0.8429877758026123, 0.8358422517776489, 0.8151364326477051, 0.8089362382888794, 0.801361083984375, 0.7947245836257935, 0.7606497406959534, 0.6325908303260803, 0.6139386892318726, 0.5906146764755249, 0.505328893661499, 0.40457233786582947, 0.3460320234298706, 0.33283042907714844, 0.3325657248497009, 0.2594234347343445, 0.25389009714126587], 'label_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 24, 33, 24], 'masks': [], 'contain_masks': False}

  • 编写Dockerfile
	FROM registry.baidubce.com/paddlepaddle/fastdeploy:1.0.2-cpu-only-21.10
	## 编写人
	MAINTAINER xxx
	# 在docker容器构建时拷贝程序
	ADD ./FastDeploy-develop  /opt/FastDeploy-develop
	# 容器暴露的端口号,需要在容器中运行使用端口号一致
	EXPOSE 8000
	EXPOSE 8001
	# 容器启动之后执行的命令, java -jar ROOT.jar
	CMD ["cd /opt/FastDeploy-develop/examples/vision/detection/yolov5/serving"]
	CMD ["fastdeployserver","--model-repository=/opt/FastDeploy-develop/examples/vision/detection/yolov5/serving/models","--backend-config=python,shm-default-byte-size=10485760"]
  • 打包images
docker build -t k8s_yolo_demo:latest .

· 4.2 k8s相关

  • 生成Deployment yaml
kubectl create deployment demo --image=k8s_yolo_demo:latest -o yaml --dry-run=client > demo.yaml
#在本地路径下会生成demo.yaml
  • 修改demo.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: demo
  name: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: demo
    spec:
      containers:
      - image: k8s_yolo_demo
        imagePullPolicy: IfNotPresent
        name: k8s_yolo_demo
        resources: {} 
     ports:
     - containerPort: 8001
status: {}
  • 编写server yaml
apiVersion: v1
kind: Service
metadata:
 name: demo
spec:
 type: NodePort      #这里代表是NodePort类型的,另外还有ingress,LoadBalancer(这里映射到本机IP)
 ports:
 - port: 8001          #这里的端口和clusterIP(kubectl describe service service-hello中的IP的port)对应,即在集群中所有机>器上curl 10.98.166.242:80可访问发布的应用服务。
   targetPort: 8001  #端口一定要和container暴露出来的端口对应,nodejs暴露出来的端口是8081,所以这里也应是8081
   nodePort: 31111   # 所有的节点都会开放此端口30000--32767,此端口供外部调用。
 selector:
   app: demo         #这里选择器一定要选择容器的标签,之前写name:kube-node是错的。

· 4.3 启动服务

# 首先启动
kubectl apply -f demo.yaml
# 可能会报错 获取不到images
# 这里demo.yaml 中添加   imagePullPolicy: IfNotPresent    (已添加过了)
# 这里使用cache方式获取images

# 1.添加环境变量  使得k8s 使用docker
eval $(minikube docker-env)
# 2.把images添加到k8s的cache中去
minikube cache add  k8s_yolo_demo
# 3.从新加载启动
kubectl apply -f demo.yaml
# 4.查看启动的pod 是否running
kubectl get pods
# 5.把images从k8s的cache中删掉
minikube cache delete k8s_yolo_demo

# 6.启动server
kubectl apply -f demo_server.yaml

如图这里看到pod和server都正常启动了:
在这里插入图片描述

· 4.4 客户端测试

# 查看本机IP
ifconfig

在这里插入图片描述

#修改客户端代码中的url
url = "192.168.49.1:31111"
python3 yolov5_grpc_client.py

#发送请求成功后,会返回json格式的检测结果并打印输出:
#output_name: detction_result
#{'boxes': [[268.48028564453125, 81.05305480957031, 298.69476318359375, 169.43902587890625], [104.73116302490234, 45.66197204589844, 127.58382415771484, 93.44938659667969], [378.9093933105469, 39.75013732910156, 395.6086120605469, 84.24342346191406], [158.552978515625, 80.36149597167969, 199.18576049804688, 168.18191528320312], [414.37530517578125, 90.94805908203125, 506.3218994140625, 280.40521240234375], [364.00341796875, 56.608917236328125, 381.97857666015625, 115.96823120117188], [351.7251281738281, 42.635345458984375, 366.9103088378906, 98.04837036132812], [505.8882751464844, 114.36674499511719, 593.1248779296875, 275.99530029296875], [327.7086181640625, 38.36369323730469, 346.84991455078125, 80.89302062988281], [583.493408203125, 114.53289794921875, 612.3546142578125, 175.87353515625], [186.4706573486328, 44.941375732421875, 199.6645050048828, 61.037628173828125], [169.6158905029297, 48.01460266113281, 178.1415557861328, 60.88859558105469], [25.81019401550293, 117.19969177246094, 59.88878631591797, 152.85012817382812], [352.1452941894531, 46.71272277832031, 381.9460754394531, 106.75212097167969], [1.875, 150.734375, 37.96875, 173.78125], [464.65728759765625, 15.901412963867188, 472.512939453125, 34.11640930175781], [64.625, 135.171875, 84.5, 154.40625], [57.8125, 151.234375, 103.0, 174.15625], [165.890625, 88.609375, 527.90625, 339.953125], [101.40625, 152.5625, 118.890625, 169.140625]], 'scores': [0.8965693116188049, 0.8695310950279236, 0.8684297800064087, 0.8429877758026123, 0.8358422517776489, 0.8151364326477051, 0.8089362382888794, 0.801361083984375, 0.7947245836257935, 0.7606497406959534, 0.6325908303260803, 0.6139386892318726, 0.5906146764755249, 0.505328893661499, 0.40457233786582947, 0.3460320234298706, 0.33283042907714844, 0.3325657248497009, 0.2594234347343445, 0.25389009714126587], 'label_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 24, 24, 33, 24], 'masks': [], 'contain_masks': False}

五.总结

  • 最有问题的还是pod IP映射的问题,没搞清k8s的端口映射逻辑。
  • 本机由于虚拟机启动IP会变动为 192.168.49.1,实际服务是之前启动的,已经映射到了192.168.49.2上,这里需要从新启动下server,就会从新映射到当前IP。
  • 这里k8s获取docker image的方式也有问题,这是测试无所谓了;正式部署不会存在这种问题。
  • GPU方式还没尝试,有空了再试试,主要是搭建环境比较麻烦。

六.引用

https://github.com/PaddlePaddle/FastDeploy/blob/develop/examples/vision/detection/yolov5/serving/README_CN.md
https://www.jianshu.com/p/c8b42d5cda2d

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年3月4日 上午10:41
下一篇 2023年3月4日 上午10:44

相关推荐