在Kubernetes (K8S)上托管Aim
由于Aim可以通过FastAPI作为本地服务器运行,因此可以部署到K8S集群!在K8S上托管Aim具有以下优势:
您组织的多个用户可以在一个地方访问Aim,这样ML从业者就不需要自己运行Aim了
Aim运行可以集中在一个远程存储卷上,这为远程模型训练和监控提供了额外的支持和便利
部署到K8S抽象了Aim CLI,使用户能够专注于Aim提供的价值(可视化/应用程序 vs. 理解CLI
up和repo)
以下部分说明如何在K8S上部署和运行Aim。这些部分假设:
访问云服务提供商,例如GCP、AWS或Azure
可以托管Dockerfile的代码仓库,例如Google Artifact Registry或Dockerhub
具备配置
ReadWriteMany卷的权限/能力,或将现有卷绑定到K8S部署
Dockerfile
以下Dockerfile镜像足以让Aim在容器中运行:
# python3.7 should be sufficient to run Aim
FROM python:3.7
# install the `aim` package on the latest version
RUN pip install --upgrade aim
# make a directory where the Aim repo will be initialized, `/aim`
RUN mkdir /aim
ENTRYPOINT ["/bin/sh", "-c"]
# have to run `aim init` in the directory that stores aim data for
# otherwise `aim up` will prompt for confirmation to create the directory itself.
# We run aim listening on 0.0.0.0 to expose all ports. Also, we run
# using `--dev` to print verbose logs. Port 43800 is the default port of
# `aim up` but explicit is better than implicit.
CMD ["echo \"N\" | aim init --repo /aim && aim up --host 0.0.0.0 --port 43800 --workers 2 --repo /aim"]
假设你将上述内容保存在当前目录中,可以使用docker build . -t my-aim-container:1命令构建容器,并通过docker push my-docker-repository.dev/deployments/aim:1将其推送到你的代码仓库。
数据量
使用K8S卷存储Aim运行记录的核心优势在于,其他K8S部署可以挂载同一个卷并在其上存储运行记录!这样,核心Aim K8S部署就能读取新的运行记录,并将其展示给想要可视化结果的用户。例如,可以设置一个执行模型训练并记录Aim运行的部署,该部署使用与Aim部署挂载相同的卷!该模型如下图所示:
通常来说,支持ReadWriteMany属性的存储卷需要手动配置,例如Google Cloud上的Filestore实例,或者通用的GlusterFS卷。一旦磁盘配置完成,就可以通过IP地址将其绑定到持久卷。假设您可以在云服务提供商上配置这样的磁盘并获取IP地址,我们就可以创建一个存储卷表示及其对应的声明。持久卷(aim-pv.yaml)可以这样定义:
apiVersion: v1
kind: PersistentVolume
metadata:
name: aim-runs
spec:
capacity:
storage: 1Ti # or whatever size disk you provisioned
accessModes:
- ReadWriteMany
nfs:
path: /aim
server: 123.12.123.12 # add your own IP here
持久卷声明 (aim-pvc.yaml) 内容如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: aim-runs-claim
spec:
accessModes:
- ReadWriteMany
storageClassName: "" # if you have a custom storage class, use it! Otherwise, it's `default`
volumeName: aim-runs
resources:
requests:
storage: 1Ti
这些可以通过以下方式提供:
> kubectl apply -f aim-pv.yaml
> kubectl apply -f aim-pvc.yaml
一旦卷被配置完成,我们就可以将其挂载到我们的部署中!
部署
主要的Aim部署将包含一个运行Aim的独立容器。该部署会挂载之前配置的存储卷,主Aim仓库将在存储卷挂载路径下初始化。例如,如果存储卷挂载到/aim路径,那么部署将从该路径初始化和读取Aim运行记录。对应的K8S部署如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-aim-deployment
name: my-aim-deployment
namespace: default
spec:
selector:
matchLabels:
app: my-aim-deployment
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: my-aim-deployment
spec:
containers:
image: my-docker-repository.dev/deployments/aim:1
name: my-aim-deployment
ports:
- containerPort: 43800
protocol: TCP
resources:
limits:
cpu: "1"
memory: 2Gi
requests:
cpu: 100m
memory: 1Gi
volumeMounts:
- mountPath: /aim
name: aim-runs
volumes:
- name: aim-runs
persistentVolumeClaim:
claimName: aim-runs-claim
这个K8S部署:
定义一个包含单个副本的pod,运行由Dockerfile定义的Aim服务器
通过持久卷声明
aim-run-claim挂载持久卷aim-runDockerfile 将
/aim目录初始化为 Aim 代码仓库。请注意,如果仓库已初始化(首次部署创建后就会出现这种情况,因为仓库只需初始化一次),Dockerfile 已自动向确认提示传递N参数以避免手动操作在端口43800上启动Aim服务器,该服务器读取存储在
/aim中的所有运行记录
服务
现在部署已经完成,Aim服务器可以通过K8S服务暴露出来!根据您的集群设置,您有多种方式来暴露该部署。其中一个选项是运行:
> kubectl expose deployment my-aim-deployment --type=LoadBalancer --name=my-aim-service
另一种选择是自行创建服务定义并应用它。定义文件 (aim-svc.yaml) 可以是:
apiVersion: v1
kind: Service
metadata:
name: my-aim-service
spec:
selector:
app: my-aim-deployment
ports:
- protocol: TCP
port: 80
targetPort: 43800
服务定义可以通过以下方式应用:
> kubectl apply -f aim-svc.yaml
结论
就这样!现在您已拥有以下结构来服务用户的Aim运行:
假设您的用户可以向某个运行模型训练的pod/deployment提交训练任务,并且该部署中包含正确的aim代码来在路径/aim记录运行信息,那么您的Aim部署在下一次执行实时更新时就能显示该运行记录!