弹性部署¶
该功能仅面向企业用户,认证入口: 控制台 -> 左侧菜单-账号安全 -> 实名认证。API文档:阅读API文档
弹性部署是专为企业AIGC等场景设计的批量调度和启动若干容器、以及管理容器生命周期的功能。
调度模式介绍¶
算力调度单元¶
在系统资源池中管理有N台不同配置的物理主机。主机在GPU型号及数量、CPU型号及数量、内存大小配置上有差异,系统将主机的CPU和内存按GPU数量(N)等比例划分为N个算力调度单元,不支持修改和拆分该调度单元。
例如主机A的配置为8卡3090、128核CPU、720GB内存,那么该主机每个算力调度单元为:3090 * 1;16 vCPU;90GB内存
。在该主机上创建容器时,容器的算力配置只能为该调度单元的 1~8倍,不可调整CPU、内存与GPU之间的数量比例。
容器的调度与启动¶
容器根据您指定的调度条件进行创建,由于以上算力调度单元的不可拆分性和不同主机之间算力单元的差异性,指定的调度条件可以有:GPU的型号和数量、CPU数量范围、内存大小范围、价格范围等。当某主机满足该调度条件时,即在该主机上创建和启动容器。例如:
有机器A、B、C。空闲的算力分别为:
8卡3090、128核CPU、720GB内存
、8卡3090、64核CPU、720GB内存
、8卡3090、128核CPU、360GB内存
设置调度条件为:GPU数量=8,CPU数量范围=[100, 200],内存大小范围=[224, 1024]。
那么系统最终会在A或者C主机上创建实例,如果在A主机上创建实例,则实例的配置规格为
8卡3090、128核CPU、720GB内存
、如果在C主机上创建实例,则实例的配置规格为8卡3090、128核CPU、360GB内存
ReplicaSet类型的调度¶
AutoDL的ReplicaSet指创建和维护一组在任何时候都处于运行状态,且容器数量达到指定副本数量的稳定集合。每个容器副本都根据您设置的容器调度条件进行调度与启动。
如果修改调度条件,系统将会销毁不满足条件的已存在运行中的容器,并启动符合条件的新容器。修改容器副本数量将立即创建新容器或销毁已存在运行中的容器,直到运行中的容器数量=您设置的副本数量。
Job类型的调度¶
AutoDL的Job指创建一个或多个容器,直到指定数量的容器执行结束并退出。和ReplicaSet不同的地方是,Job不会为了维持指定的容器副本数量,而在某个容器结束后启动新容器(启动新容器仅因为已经完成的容器数量未达到设置的目标容器数量)。而是容器结束后就将其记录为完成,直到完成的容器数量达到设置的目标值,此时整个调度结束,不再启动新容器。
Container类型的调度¶
AutoDL的Container指仅创建一个容器,直到该容器结束并退出,即结束调度。等价于目标容器数量=1的Job调度。
容器生命周期¶
容器的生命周期取决于您设置的cmd命令执行生命周期。cmd执行结束那么该容器将会退出关机,因此如果您的cmd中启动应用程序的命令做了后台运行处理,则在cmd的最后添加sleep infinity
,防止父进程退出导致容器关机以及所有其他进程结束。即以下两种方式均可(以下具体命令只是示例):
# 方式一:
python app.py
# 方式二:
nohup python app.py & && sleep infinity
以上方式二应用程序后台运行,通过sleep infinity阻断cmd结束,这样会使得app.py应用程序的生命周期和容器的生命周期两者独立,需要您独立管理应用程序的生命周期(即假设app.py运行结束,实际上容器仍然在正常运行中,不能通过容器状态推知应用状态)。如果您需要自行管理应用程序的生命周期,则推荐使用这种方式,否则推荐方式一。
此外您可以调用停止弹性部署的接口或者停止某一具体容器的接口完成容器的停止。
计费¶
弹性部署的容器计费方式为按量计费,单价同算力市场相同(接近)配置的价格。例如算力市场典型配置的A5000价格(会员价)为1.18元/小时,那么弹性部署同样配置的容器单价同样为1.18元/小时。
弹性部署中的容器和容器实例的差异¶
差异1:数据的保留规则不同
在算力市场租用的容器实例,当实例关机后有一段数据保留期(参考文档),弹性部署的容器在关机后立即释放数据,不会保留
最佳实践¶
镜像与文件存储¶
在启动时系统会pull镜像启动容器,如果静态的、不需要经常变更的环境与其他数据文件可以存放于镜像中,避免镜像的频繁更新,由于每次更新后有一个重新缓存镜像到每台主机的过程,因此会影响第一次启动容器的时间。
如果经常变更的文件,如代码和模型文件,推荐存放于文件存储,文件存储作为跨实例的共享存储会挂载到同地区每个容器中,因此可以加以利用该特点简化管理和部署。但是文件存储也有缺点:性能相比本地盘慢,特别是对于非常多的小文件读写(kb级别的文件)性能较差,大文件的读写带宽约为100MB/s。如需增加性能请联系客服处理。
启动命令¶
- 容器在启动后就会立即执行您设置的启动命令,命令结束容器也会停止并释放,即命令执行的生命周期=容器的生命周期。因此以
python app.py
命令为例,请勿将该命令以后台的方式执行,比如python app.py &
,这样命令(父进程)会立即执行完成并将程序(子进程)挂在后台运行,但是此时由于命令已结束系统会停止容器导致所有进程一起终止,未能达到期望的效果。如果特殊原因需要以这种方式执行,那么trick为:python app.py &; sleep infinity
- 如果您在启动时执行的命令非常多且复杂,建议您在镜像或文件存储中写一个shell脚本,将这些命令放于一个脚本中,这样容器的启动命令改为执行该脚本,让启动命令得到简化,避免出错。
- 启动命令的执行相对路径:建议先切换到相应目录下再执行脚本。比如
python app.py
命令,app.py
脚本在/root目录,那么命令最好写为cd /root/ && python app.py
- 对于Conda使用虚拟环境的情况,在命令中这样写
conda activate my-env && python xxx.py
,一般会由于无法切换环境而执行失败,推荐您改为/root/miniconda3/envs/my-env/bin/python xxx.py
,即直接使用虚拟环境的python解释器
异常调试¶
场景举例:容器的启动命令为python app.py
,开始调度后容器开机运行但立即异常结束,原因未知。
调试方法:编辑部署,将容器的启动命令由python app.py
改为sleep infinity
,目的是用sleep
命令阻塞容器使得它一直保持运行状态,此时等待容器运行后,用容器的ssh命令登录,手动在容器中执行python app.py
命令来查看是否执行异常进行调试,如此可以以交互的方式高效定位问题。调试完成后编辑部署将命令改为正确的命令。