本文最后更新于:2025年1月12日 凌晨
                  
                
              
            
            
              
                
                最近需要做一次面向公司的算法团队的k8s培训,算法的同事对于docker和gpu的使用还是比较熟悉的,随着大模型的发展,很多训练、测试、数据处理的任务都需要在k8s上进行,所以需要对k8s有一个基本的了解,基于这样的背景,我结合docker的使用,对k8s的一些概念进行了类比,希望能够帮助大家更好的理解k8s。
对于熟悉Docker的用户,在迁移到Kubernetes时,将某些概念进行类比可以帮助加快对Kubernetes的理解。本文将通过一个示例,阐述Docker和Kubernetes在容器编排方面的异同。

Docekr
Docker 是一个群众们喜闻乐见的容器技术,在过去10年中,它对传统的软件部署方式进行了革命式的颠覆(ps:截止 2023 年,Docker公司在K8s抛弃了Docekr的同时,对其仅有的护城河 Docker hub采取了一系列的收费政策,标志着昔日的屠龙少年,已经成为了一条暮年的巨龙)。言归正传,我们这里直接用时下热门的text-generation-inference大模型推理容器做个 docker 的例子。
| 12
 3
 4
 
 | model=tiiuae/falcon-7b-instructvolume=$PWD/data
 
 docker run --gpus all --shm-size 1g -p 8080:80 -v $volume:/data ghcr.io/huggingface/text-generation-inference:1.0.1 --model-id $model
 
 | 
大道至简,上面的命令已经完成了一个PPT大模型部署演示最低要求🤣🤣🤣
Docker Compose 编排
当然事情远没有这么简单,一个相对完整的最小化大模型应用,需要包含以下几个部分:
- 负责对话的web UI界面——HTML+CSS+JS ON NGINX
- 用户对话的后端服务——FastAPI
- 模型推理的后端服务——Text Generation Inference
- 数据库服务——MySQL
 Docker Compose允许在一个文件中声明多个服务的容器化部署,使用docker-compose up可以方便地启动这些服务。
| 12
 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
 47
 48
 49
 
 | version: '3'services:
 
 nginx:
 image: nginx:latest
 ports:
 - "80:80"
 depends_on:
 - web
 
 web:
 image: python:3.7-alpine
 command: uvicorn main:app --host 0.0.0.0 --port 5000
 ports:
 - "5000:5000"
 depends_on:
 - db
 - tgi
 
 tgi:
 image: ghcr.io/huggingface/text-generation-inference:0.9.4
 ports:
 - "8080:8080"
 command: --model-id meta-llama/Llama-2-70b-hf
 volumes:
 - models_data:/data
 deploy:
 resources:
 reservations:
 devices:
 - driver: nvidia
 count: 8
 capabilities: [gpu] // 声明需要使用的GPU数量
 
 db:
 image: mysql:5.7
 volumes:
 - db_data:/var/lib/mysql
 restart: always
 environment:
 MYSQL_ROOT_PASSWORD: password
 MYSQL_DATABASE: appdb
 ports:
 - "3306:3306"
 
 volumes:
 db_data:
 models_data:
 
 
 | 
服务启动也很简单:
这非常适合本地开发和小规模部署。但对于复杂环境,Compose的功能有限。这需要一个更强大的编排平台,比如Kubernetes,来解决一些我们会关注的问题:
- gpu资源的分配
- 推理服务的负载均衡
- 模型的版本管理
- 模型弹性伸缩
Kubernetes编排
Kubernetes提供了比Docker Compose更广泛的编排功能。我们可以参考类似的概念,编写Kubernetes配置来部署这个应用:
- Pod vs 容器:Pod可以包含一个或多个紧耦合的容器。
- Deployment vs Compose:用于部署无状态应用的规范。
- Service vs 网络:提供服务发现和负载均衡的抽象。
- Volume vs 数据卷:用于存储抽象,可以通过PVC和PV实现。
- ConfigMap vs 环境变量:配置应用参数。
- HPA类似Docker的自动扩缩容,可以根据指标自动增加或减少Pod数量。
- Kubectl类似Docker Compose命令,用于部署和管理Kubernetes应用资源。
- Kubernetes也有镜像管理、密钥管理、日志查询等类似Docker的功能。
等等。这些概念对熟悉Docker的用户来说很亲切。组合使用这些资源,我们可以编排这个应用:
deployment.yaml 用用于部署应用:
| 12
 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
 47
 48
 49
 50
 51
 
 | apiVersion: apps/v1kind: Deployment
 metadata:
 annotations:
 kompose.cmd: kompose convert -f docekr-compose.yml
 kompose.version: 1.30.0 (9d8dcb518)
 creationTimestamp: null
 labels:
 io.kompose.service: tgi
 name: tgi
 namespace: default
 spec:
 replicas: 1
 selector:
 matchLabels:
 io.kompose.service: tgi
 strategy:
 type: Recreate
 template:
 metadata:
 annotations:
 kompose.cmd: kompose convert -f docekr-compose.yml
 kompose.version: 1.30.0 (9d8dcb518)
 creationTimestamp: null
 labels:
 io.kompose.network/compose-k8s-default: "true"
 io.kompose.service: tgi
 spec:
 containers:
 - args:
 - --model-id
 - meta-llama/Llama-2-70b-hf
 image: ghcr.io/huggingface/text-generation-inference:0.9.4
 name: tgi
 ports:
 - containerPort: 8080
 hostPort: 8080
 protocol: TCP
 resources:
 limits:
 nvidia.com/gpu: 1
 volumeMounts:
 - mountPath: /data
 name: models-data
 restartPolicy: Always
 volumes:
 - name: models-data
 persistentVolumeClaim:
 claimName: models-data
 status: {}
 
 
 | 
PV和PVC的配置文件,用于存储模型数据:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | apiVersion: v1kind: PersistentVolumeClaim
 metadata:
 creationTimestamp: null
 labels:
 io.kompose.service: models-data
 name: models-data
 namespace: default
 spec:
 accessModes:
 - ReadWriteOnce
 resources:
 requests:
 storage: 100Mi
 status: {}
 
 | 
service.yaml 用于暴露服务:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | apiVersion: v1kind: Service
 metadata:
 annotations:
 kompose.cmd: kompose convert -f docekr-compose.yml
 kompose.version: 1.30.0 (9d8dcb518)
 creationTimestamp: null
 labels:
 io.kompose.service: tgi
 name: tgi
 namespace: default
 spec:
 ports:
 - name: "8080"
 port: 8080
 targetPort: 8080
 selector:
 io.kompose.service: tgi
 status:
 loadBalancer: {}
 
 | 
访问应用
可以通过NodePort或者更推荐的Ingress来访问部署的应用。Ingress提供负载均衡、SSL终止等高级功能。
展望
Docker Compose非常适合本地和小规模容器编排。对于大规模生产,Kubernetes提供了更丰富的功能,类比Docker概念可以帮助理解。组合使用两者可以发挥它们各自的优势。
在后续的实际应用的中我们会采用基于kserve的模型服务框架,基于kserve 对算法服务的抽象封装,算法工程师只需要提供相应的模型文件即可实现算法服务的上线,可以快速的反向运用于数据挖掘和自动化标注等。

参考