容器镜像控制
控制器操作数据库和worker节点的工作流程被封装为一系列Python脚本
容器控制
初始化容器
脚本名称 |
container_init.py |
输入内容 |
iid(镜像编号),uid(用户编号),name(容器名称),cpu(容器CPU需求),mem(容器内存需求),gid(GPU编号,可选) |
- 核验身份:查询数据库,确保镜像存在,并且用户有权限使用该镜像。如果没有相应的镜像记录,返回错误信息。
- 查询数据库,获取容器所使用的设备(
did
)的 IP 地址、CPU、内存及其他资源信息,并获取设备的相关目录路径(如数据目录、公共目录)。
- 查询数据库,获取该设备已运行容器所占用的 CPU 和内存资源,如果新容器所需资源加上现有资源超出设备总资源,则返回错误信息。
- 检查 GPU 可用性:如果容器请求使用 GPU,查询指定 GPU 是否已被其他容器占用。如果 GPU 不可用,则返回错误信息。
- 获取端口信息:通过执行远程脚本获取容器所需的 SSH、Jupyter 和 TensorBoard 端口。远程脚本会尝试绑定三个随机端口,如果成功绑定,就将端口号返回
- 生成16位的随机密码,作为容器的ssh和jupyter登录密码
- 启动容器:构造并执行 Docker 命令,通过 SSH 启动容器,并映射资源(如挂载卷、暴露端口等)。
- 更新
containers
表,记录新容器的状态(running
)、资源配置、端口和密码。
- 如果容器使用了 GPU,更新
container_gpu
表,标记该 GPU 已被容器使用。
- 返回结果:如果容器启动成功,返回容器的随机密码、SSH 端口、Jupyter 端口和 TensorBoard 端口信息。
查询容器状态
脚本名称 |
container_status.py |
输入内容 |
cid(容器编号),uid(用户编号) |
- 查询数据库,验证容器是否属于用户,以及容器是否存在
- 查询数据库中旧的容器状态
- 查询数据库获取容器所在worker的ip,用于启动ssh控制连接
- ssh连接到容器所在worker,执行查询容器状态的指令
- 比较新旧状态,如果不同,则更新数据库中的容器状态
启动容器
脚本名称 |
container_start.py |
输入内容 |
cid(容器编号),uid(用户编号) |
- 验证用户身份:查询数据库,验证指定容器是否属于用户,以及容器是否存在。
- 检查容器状态:调用
container_status
函数查询容器当前的状态。如果容器已经在运行,直接返回错误信息,表示容器已经启动。
- 获取容器资源信息:查询数据库,获取容器的 CPU 和内存需求。
- 获取设备资源信息:查询容器所在设备的资源情况(如 CPU、内存等)以及已分配的资源。
- 检查资源是否足够:计算当前设备已使用的 CPU 和内存,并与设备的总资源进行比较。如果容器需求超出设备剩余资源,返回错误信息。
- 检查 GPU 可用性:查询容器是否使用 GPU,如果有 GPU 使用需求,则检查该 GPU 是否已被其他容器占用。如果 GPU 不可用,返回错误信息。
- 启动容器:通过 SSH 连接到容器所在的设备,并执行 Docker 启动命令来启动容器。
- 更新容器状态:如果容器启动成功,更新数据库中容器的状态为 "running"。
- 更新 GPU 使用情况:如果容器分配了 GPU,则更新数据库中
container_gpu
表的状态,标记该 GPU 为正在使用。
停止容器
脚本名称 |
container_stop.py |
输入内容 |
cid(容器编号),uid(用户编号,可选) |
- 查询数据库,验证指定容器是否属于该用户,确保容器存在且用户有权限访问该容器。
- 获取容器当前状态,如果容器已经停止(
exited
),直接返回错误信息,表示容器已处于停止状态。
- 获取容器 GPU 信息:查询数据库获取容器是否分配了 GPU。如果容器有 GPU 资源,记录该 GPU ID。
- 查询容器所在设备的 IP 地址,以便通过 SSH 连接到该设备。
- 停止容器:通过 SSH 命令执行
docker stop
来停止容器。
- 更新容器状态:如果容器成功停止,更新数据库中容器的状态为 "exited"。
- 更新 GPU 使用情况:如果容器分配了 GPU,则更新数据库中
container_gpu
表,标记该 GPU 为未使用状态。
删除容器
脚本名称 |
container_rm.py |
输入内容 |
cid(容器编号),uid(用户编号) |
- 验证用户身份:查询数据库,验证容器是否属于指定用户,并且容器是否存在。确保用户有权限删除该容器。
- 获取容器当前状态:获取容器当前状态。如果容器正在运行,先调用
container_stop
函数停止容器。
- 查询容器所在设备的 IP 地址,通过 SSH 连接到该设备,执行删除操作。
- 更新数据库,删除
containers
表中的容器记录。
镜像控制
创建镜像
脚本名称 |
image_create.py |
输入内容 |
cid(容器编号),name(镜像名称),uid(用户编号),public(是否公开) |
- 查询数据库,确认用户是否有权限访问指定的容器。如果用户没有访问权限或容器不存在,则返回错误信息。
- 获取设备信息:查询数据库,获取容器所属设备的
did
和设备的 IP 地址,用于后续通过 SSH 连接到设备。
- 容器转镜像:使用
docker commit
命令通过 SSH 连接到设备,创建一个新的镜像。镜像的 ID 会通过命令的标准输出返回,并从输出中提取出镜像的 real_id
(SHA256 哈希)。
- 从数据库获取一个新的镜像 ID (
iid
),该 ID 是数据库中 images
表的下一个可用 ID。
- 再次SSH 连接到设备,获取刚刚创建的镜像的大小。
- 在
images
表中插入新镜像的记录,包括镜像的 iid
、所属设备 did
、镜像名称、real_id
、是否公开和镜像大小。
- 在
user_images
表中插入记录,表示用户拥有该镜像。
删除镜像
脚本名称 |
image_rm.py |
输入内容 |
iid(镜像ID),uid(用户ID) |
实现细节如下:
- 查询数据库
user_images
表,验证用户是否拥有该镜像。如果用户没有访问权限或者镜像不存在,返回错误信息。
- 验证镜像是否关联容器:通过查询
containers
表,检查是否有容器依赖于该镜像。如果存在依赖的容器,则无法删除镜像,返回错误信息。
- 获取设备IP:通过查询
images
表,找到该镜像所在设备的 IP 地址。镜像对应的设备是通过 did
关联的。
- 获取镜像真实ID:查询
images
表,获取该镜像的真实 ID(real_id
),这是 Docker 用来标识镜像的实际哈希值。
- 删除镜像:使用
docker rmi
命令通过 SSH 连接到设备,删除指定的镜像
- 从
images
表中删除该镜像记录。
- 从
user_images
表中删除用户与该镜像的关联记录。