一种镜像构建的方法及设备与流程

专利2024-03-09  115



1.本发明涉及计算机软件技术领域,特别涉及一种镜像构建的方法及设备。


背景技术:

2.人工智能(ai)算法训练平台是面对ai训练任务的大规模分布式计算平台,计算节点通常是基于gpu的云主机集群,利用分布式计算优势,提高模型训练效率。为了提供统一的人工智能运行环境,通常会采用docker技术容器化与虚拟化计算资源,分别构建以tensorflow、pytorch、caffe等为主的ai算法训练框架镜像,同时安装多种高性能计算库加速矩阵计算。
3.算法人员使用该平台的一般流程为:准备数据集和训练脚本,在平台选择特定版本的训练镜像,指定启动脚本和参数并提交任务,平台接到任务后通过调度算法分配任务到一台或多台计算节点,节点的服务器根据传递的参数准备数据集、训练脚本,然后从docker镜像仓库中拉取(pull)镜像并启动训练。
4.由于目前ai算法训练平台的docker训练镜像的体积很大,占用节点的存储空间,导致节点的服务器从docker镜像仓库中拉取镜像时耗时较长,并且复杂的开发调试软件版本依赖关系,也容易导致镜像的兼容性较差。


技术实现要素:

5.本发明提供一种镜像构建的方法及设备,用于梳理整个在用软件技术栈构建多层级的镜像,能够充分复用基础镜像节省harbor仓库和计算节点的存储空间,固化版本后也能够增强镜像的兼容性。
6.第一方面,本发明实施例提供的一种镜像构建的方法,该方法包括:
7.获取软件资源列表,所述软件资源列表中的软件资源包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;
8.基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;
9.根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。
10.本实施例通过梳理整个在用软件技术栈构建多层级的镜像,基于各层级对应的镜像间的依赖关系实现对较低层级的镜像的复用,节省harbor仓库和计算节点的存储空间,由于是按照整个在用软件技术栈进行软件版本配套表的选择,固化版本后能够增强镜像的兼容性,防止安装软件包时自动安装的依赖版本不合适问题,使得整个镜像环境对于训练程序的运行具有较好的兼容性。
11.作为一种可选的实施方式,所述基于所述软件资源列表生成树状拓扑图,包括:
12.根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图;
13.其中所述树状拓扑图中第i+1个层级包含的节点对应的软件资源中最长的生命周期,小于第i个层级包含的节点对应的软件资源中最短的生命周期。
14.作为一种可选的实施方式,所述根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图,包括:
15.响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;
16.根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图。
17.作为一种可选的实施方式,所述树状拓扑图包括至少3个层级,其中:
18.根据所述第一软件资源中与编译能力相关的软件资源确定第一层级;
19.根据所述第一软件资源中与驱动、通信、加速运算以及编程语言中的至少一种相关的软件资源确定第二层级;
20.根据所述第二软件资源确定第三层级;
21.其中所述层级从低到高依次为第一层级、第二层级、第三层级。
22.作为一种可选的实施方式,所述树状拓扑图还包括最底层级,通过如下方式确定所述最底层级:
23.根据与硬件无关的运行库和开发编译工具链,生成所述树状拓扑图中的最底层级;其中所述最底层级低于所述第一软件资源对应的节点所在的层级。
24.作为一种可选的实施方式,所述获取软件资源列表,包括:
25.根据计算机集群使用的硬件资源,确定第一软件资源;
26.根据至少一种应用任务所需的软件资源,确定第二软件资源;
27.根据所述第一软件资源、所述第二软件资源以及各个软件资源之间的依赖关系,确定软件资源列表。
28.作为一种可选的实施方式,依次构建与各个层级对应的镜像之后,还包括:
29.将构建的各个层级对应的镜像上传到镜像仓库;
30.当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像,其中所述预设层级包括所述第一软件资源对应的节点所在的层级。
31.作为一种可选的实施方式,所述依次构建与各个层级对应的镜像,还包括:
32.当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。
33.作为一种可选的实施方式,所述第i+1个层级对应的镜像基于所述树状拓扑图中第i个层级对应的镜像构建;其中,第1个层级对应的镜像基于公共镜像构建。
34.第二方面,本发明实施例提供的一种镜像构建的设备,包括处理器和存储器,所述存储器用于存储所述处理器可执行的程序,所述处理器用于读取所述存储器中的程序并执行如下步骤:
35.获取软件资源列表,所述软件资源列表中的软件资源包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;
36.基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;
37.根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。
38.作为一种可选的实施方式,所述处理器具体被配置为执行:
39.根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图;
40.其中所述树状拓扑图中第i+1个层级包含的节点对应的软件资源中最长的生命周期,小于第i个层级包含的节点对应的软件资源中最短的生命周期。
41.作为一种可选的实施方式,所述处理器具体被配置为执行:
42.响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;
43.根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图。
44.作为一种可选的实施方式,所述树状拓扑图包括至少3个层级,所述处理器具体被配置为执行:
45.根据所述第一软件资源中与编译能力相关的软件资源确定第一层级;
46.根据所述第一软件资源中与驱动、通信、加速运算以及编程语言中的至少一种相关的软件资源确定第二层级;
47.根据所述第二软件资源确定第三层级;
48.其中所述层级从低到高依次为第一层级、第二层级、第三层级。
49.作为一种可选的实施方式,所述树状拓扑图还包括最底层级,所述处理器具体被配置为执行通过如下方式确定所述最底层级:
50.根据与硬件无关的运行库和开发编译工具链,生成所述树状拓扑图中的最底层级;其中所述最底层级低于所述第一软件资源对应的节点所在的层级。
51.作为一种可选的实施方式,所述处理器具体被配置为执行:
52.根据计算机集群使用的硬件资源,确定第一软件资源;
53.根据至少一种应用任务所需的软件资源,确定第二软件资源;
54.根据所述第一软件资源、所述第二软件资源以及各个软件资源之间的依赖关系,确定软件资源列表。
55.作为一种可选的实施方式,依次构建与各个层级对应的镜像之后,所述处理器具体还被配置为执行:
56.将构建的各个层级对应的镜像上传到镜像仓库;
57.当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像,其中所述预设层级包括所述第一软件
资源对应的节点所在的层级。
58.作为一种可选的实施方式,所述处理器具体还被配置为执行:
59.当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。
60.作为一种可选的实施方式,所述第i+1个层级对应的镜像基于所述树状拓扑图中第i个层级对应的镜像构建;其中,第1个层级对应的镜像基于公共镜像构建。
61.第三方面,本发明实施例还提供一种镜像构建的装置,该装置包括:
62.获取软件单元,用于获取软件资源列表,所述软件资源列表包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;
63.生成拓扑图单元,用于基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;
64.构建镜像单元,用于根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。
65.作为一种可选的实施方式,所述生成拓扑图单元具体用于:
66.根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图;
67.其中所述树状拓扑图中第i+1个层级包含的节点对应的软件资源中最长的生命周期,小于第i个层级包含的节点对应的软件资源中最短的生命周期。
68.作为一种可选的实施方式,所述生成拓扑图单元具体用于:
69.响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;
70.根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图。
71.作为一种可选的实施方式,所述树状拓扑图包括至少3个层级,所述生成拓扑图单元具体用于:
72.根据所述第一软件资源中与编译能力相关的软件资源确定第一层级;
73.根据所述第一软件资源中与驱动、通信、加速运算以及编程语言中的至少一种相关的软件资源确定第二层级;
74.根据所述第二软件资源确定第三层级;
75.其中所述层级从低到高依次为第一层级、第二层级、第三层级。
76.作为一种可选的实施方式,所述树状拓扑图还包括最底层级,所述生成拓扑图单元具体用于通过如下方式确定所述最底层级:
77.根据与硬件无关的运行库和开发编译工具链,生成所述树状拓扑图中的最底层级;其中所述最底层级低于所述第一软件资源对应的节点所在的层级。
78.作为一种可选的实施方式,所述获取软件单元具体用于:
79.根据计算机集群使用的硬件资源,确定第一软件资源;
80.根据至少一种应用任务所需的软件资源,确定第二软件资源;
81.根据所述第一软件资源、所述第二软件资源以及各个软件资源之间的依赖关系,确定软件资源列表。
82.作为一种可选的实施方式,依次构建与各个层级对应的镜像之后,还包括复用镜像单元具体用于:
83.将构建的各个层级对应的镜像上传到镜像仓库;
84.当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像,其中所述预设层级包括所述第一软件资源对应的节点所在的层级。
85.作为一种可选的实施方式,所述构建镜像单元具体还用于:
86.当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。
87.作为一种可选的实施方式,所述第i+1个层级对应的镜像基于所述树状拓扑图中第i个层级对应的镜像构建;其中,第1个层级对应的镜像基于公共镜像构建。
88.第四方面,本发明实施例还提供一种计算机存储介质,其上存储有计算机程序,该程序被处理器执行时用于实现上述第一方面所述方法的步骤。
89.本技术的这些方面或其他方面在以下的实施例的描述中会更加简明易懂。
附图说明
90.为了更清楚地说明本发明实施例中的技术方案,下面将对实施例描述中所需要使用的附图作简要介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域的普通技术人员来讲,在不付出创造性劳动性的前提下,还可以根据这些附图获得其他的附图。
91.图1为本发明实施例提供的一种镜像构建的方法实施流程图;
92.图2为本发明实施例提供的一种树状拓扑图的层级结构示意图;
93.图3为本发明实施例提供的一种镜像构建的具体实施方法流程图;
94.图4为本发明实施例提供的一种基于树状拓扑图的镜像层级结构图;
95.图5为本发明实施例提供的一种镜像构建的设备示意图;
96.图6为本发明实施例提供的一种镜像构建的装置示意图。
具体实施方式
97.为了使本发明的目的、技术方案和优点更加清楚,下面将结合附图对本发明作进一步地详细描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其它实施例,都属于本发明保护的范围。
98.本发明实施例中术语“和/或”,描述关联对象的关联关系,表示可以存在三种关系,例如,a和/或b,可以表示:单独存在a,同时存在a和b,单独存在b这三种情况。字符“/”一般表示前后关联对象是一种“或”的关系。
99.本发明实施例中术语“docker”,是一个开源的虚拟化技术,旨在提供一种应用的自动化部署解决方案,能够让开发者打包他们的应用及依赖包到一个可移植的容器中。
100.本发明实施例中术语“容器”,可以视为一种轻量级虚拟机,由docker镜像(image)进行实例化而得到,是镜像创建的运行实例,docker利用容器来运行应用,每个容器都是相互隔离的、保证安全的平台,其中容器可视为一个轻量级的linux运行环境。
101.本发明实施例中术语“镜像”,是一个只读的模板,一个镜像可以包含一个完整的操作系统环境,里面仅安装了用户需要的应用程序,镜像不包含任何动态数据,其内容在构建之后也不会被改变。镜像可以用来创建docker容器,用户可以使用设备上已有的镜像来安装多个相同的docker容器。
102.本发明实施例中术语“docker镜像”,是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含为运行时准备的配置参数。
103.本发明实施例中术语“镜像仓库”,是集中存放镜像文件的地方。用户创建完镜像后,可以将其上传到公共镜像仓库或者私有镜像仓库,需要在另一台主机上使用该镜像时,只需要从镜像仓库上下载即可。
104.本发明实施例中术语“依赖”,表示软件开发存在的依赖关系,每个软件都有不同的功能提供和调用,通过依赖关系描述不同软件相互之间的功能需求。
105.本发明实施例描述的应用场景是为了更加清楚的说明本发明实施例的技术方案,并不构成对于本发明实施例提供的技术方案的限定,本领域普通技术人员可知,随着新应用场景的出现,本发明实施例提供的技术方案对于类似的技术问题,同样适用。其中,在本发明的描述中,除非另有说明,“多个”的含义是两个或两个以上。
106.实施例1、目前,docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的linux机器上,也可以实现虚拟化。使用docker容器,应用可以对平台和硬件无感知。如果在应用程序中使用了gpu(图形处理器,graphics processing unit),由于需要安装nvidia driver(英伟达驱动),docker引擎并没有原生支持,因此也就无法直接在容器中访问gpu资源。为了解决容器中无法访问gpu资源的问题,通常可以在容器中重新安装nvidia driver,容器启动的时候将nvidia gpu作为符号设备传递进来。但是这种方案的问题在于宿主机和容器内安装的nvidia driver版本可能不一致,因此docker image无法在多机间共享,这就丧失了docker的主要优势。因此,为了在保持docker image迁移性的同时可以方便的使用gpu,nvidia提出了nvidia docker的方案。nvidia docker整体工作架构包含如下部分:
107.硬件,服务器上安装有nvidia gpu;
108.宿主机,安装了操作系统和cuda driver,以及docker引擎;
109.容器,包含容器os用户空间,cuda toolkit,以及用户应用程序;
110.其中,宿主机上需要安装cuda driver,容器内需要安装cuda toolkit,无需安装cuda driver,nvidia提供了预安装不同版本cuda toolkit的官方镜像。
111.人工智能(ai)算法训练平台是面对ai训练任务的大规模分布式计算平台,计算节点通常是基于gpu的云主机集群,利用分布式计算优势,提高模型训练效率。为了提供统一的人工智能运行环境,通常会采用docker技术容器化与虚拟化计算资源,分别构建以tensorflow、pytorch、caffe等为主的ai算法训练框架镜像,同时安装多种高性能计算库加
速矩阵计算。算法人员使用该平台的一般流程为:准备数据集和训练脚本,在平台选择特定版本的训练镜像,指定启动脚本和参数并提交任务,平台接到任务后通过调度算法分配任务到一台或多台计算节点,节点的服务器根据传递的参数准备数据集、训练脚本,然后从docker镜像仓库中拉取(pull)镜像并启动训练。如果预设的ai算法训练镜像不满足用户的需求,则用户需要定制训练环境,基于已有镜像或从头开始构建镜像,安装配置需要的软件后上传镜像到镜像仓库。由于目前ai算法训练平台的docker训练镜像的体积很大,占用节点的存储空间,导致节点的服务器从docker镜像仓库中拉取镜像时耗时较长,并且复杂的开发调试软件版本依赖关系,也容易导致镜像的兼容性较差。
112.其他常见的现有设计是nvidia提供的ngc镜像,以ngc-pytorch镜像为例,其设计的主要缺点是按月份构建新镜像时,选择当前最新cuda toolkit版本,编译的pytorch版本不是标准的发布版本tag,而是在github上master分支下最新commitid,其它nvidia gpu配套软件也是最新版本。通常计算集群节点的驱动版本、通信配件和其它软件版本在相当长时间内是不会更新的,造成的结果就是最新cuda toolkit和底层配套软件不一定能在节点机器上正常运行;由于采用了pytorch非正式发布版本commitid构建镜像,训练代码在各个pytorch版本之间做兼容性适配也会出现问题。
113.为了解决上述问题,本实施例提供一种镜像构建的方法,通过梳理在用技术栈,分多个层次构建镜像,充分复用多个基础镜像,能够节省harbor仓库和计算节点的存储空间,并降低计算节点拉取新镜像的耗时。并根据梳理出的镜像间的依赖关系,固化底层软件版本,能够增强镜像的兼容性,使得部分在用的老版本代码也可以较好的运行。
114.如图1所示,本实施例提供一种镜像构建的方法,该方法的具体实施流程如下所示:
115.步骤100、获取软件资源列表,所述软件资源列表包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;
116.在一些实施例中,本实施例通过如下方式获取软件资源列表:
117.根据计算机集群使用的硬件资源,确定第一软件资源;根据至少一种应用任务所需的软件资源,确定第二软件资源;根据第一软件资源和第二软件资源,以及各个软件资源之间的依赖关系,确定软件资源列表。
118.在一些实施例中,本实施例中的软件资源列表还包括各个软件资源之间的依赖关系。
119.实施中,首先梳理出高性能计算机集群所使用的硬件资源、软件资源、软件资源和硬件资源间的依赖关系、不同版本的软件资源间的依赖关系、驱动版本、驱动版本和硬件资源间的依赖关系等;其次,梳理出各种类型的应用任务所使用的软件资源,软件版本以及各软件版本间的依赖关系等。
120.下面对本实施例中的硬件资源和软件资源进行详细描述:
121.计算机集群通常采用的硬件资源如nvidia gpu卡,包括但不限于如下任一或任多种型号:titan-v(7.0)、p4(6.1)、t4(7.5)、1080ti(6.1)、2080ti(7.5)、v100(7.0)、a40(8.6)、a30(8.0)、a100(8.0)。
122.由硬件资源确定cuda算子编译计算能力集,其中cuda依赖于硬件资源确定,不同的硬件型号支持不同的cuda算子编译计算能力,cuda算子编译计算能力包括但不限于如下
任一或任多种编译能力:5.2、6.0、6.1、7.0、7.5、8.0、8.6+ptx;其中,ptx(并行线程执行)表示具体向后兼容的编译能力。
123.由硬件资源确定驱动版本,由于硬件随时间更新,计算机集群中的驱动版本不会经常改变,为了确保之前的硬件依然能够运行,例如选择的驱动版本包括但不限于cuda版本10.2和11.1+(ampere架构的gpu需要cuda版本最低为11.x);
124.驱动和通信软件通常打包在一起,用于多机多卡训练的通信软件,本实施例涉及到的驱动和通信软件包括但不限于如下任一或任多种:mlnx-ofed、nccl、openmpi、openucx、hpcx、gdrcopy、nv_peer_memory。
125.本实施例还涉及高性能计算软件,用于加速运算等,包括但不限于如下任一或任多种:cudatoolkit、cudnn,mkl、openblas、atlas、opencv。
126.本实施例还涉及ai框架软件资源,用于进行算法训练、模型的转换和验证等,包括但不限于:用于算法训练的pytorch,模型转换验证的caffe。
127.本实施例还涉及应用软件,包括但不限于目标检测,跟踪,分类,分割,识别,nlp等领域常用的开源仓库代码软件。
128.步骤101、基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;
129.实施中,本实施例基于梳理出的计算机集群中使用的硬件资源、软件资源以及与应用任务相关的软件资源等,生成树状拓扑图,将软件资源进行层级划分,使得将与硬件资源相关的第一软件资源和与应用业务相关的第二软件资源进行划分,由于与硬件资源相关的第一软件资源不容易进行变化,更容易作为基础镜像进行复用,因此通过该层级关系构建多层级的镜像,使得利用低层级的软件资源构建的镜像进行复用,节省计算节点和镜像仓库的存储资源。
130.在一些实施例中,本实施例通过如下方式基于所述软件资源列表生成树状拓扑图:
131.根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图;其中所述树状拓扑图中第i+1个层级包含的节点对应的软件资源中最长的生命周期,小于第i个层级包含的节点对应的软件资源中最短的生命周期,即生命周期较长的软件资源的层级低于生命周期较短的软件资源的层级。
132.其中,本实施例中的软件资源的生命周期是指软件的产生直到报废或停止使用的过程,一个软件具体要使用多久在项目中根据实际业务需求定义,本实施例将版本不需要经常变动的软件作为生命周期较长的软件资源,比如一个镜像分阶段构建时包含的cuda、cudnn的父镜像通常不会变动,除非在构建时存在缺陷需要生成新版本,则将该父镜像作为生命周期较长的软件资源。
133.其中,linux中的软件依赖关系为拓扑树结构,比如a直接或间接依赖b,b又依赖于c和d等。软件依赖比较复杂,目前一般是通过包管理软件自动安装依赖,本实施例主要考虑关键软件间的依赖关系,比如cuda、cudnn、pytorch、caffe等常用或关键软件间的依赖关系。如果重点关注的软件间共同依赖的多个版本间发生冲突,则选择能够兼容更多软件版本对应的共同依赖的版本,或者手动修改重点关注的代码进行适配解决。
134.在一些实施例中,本实施例通过如下方式根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图:
135.响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;
136.根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图。
137.实施中,本实施例可以基于用户关注的信息生成树状拓扑图,用户关注的信息是指用户在系统入口选择的信息,通常包括硬件资源和应用任务,例如用户选择硬件资源,根据该硬件资源确定对应的软件资源为cuda版本,用户还可以选择应用任务,根据训练任务确定与用户训练代码直接相关的训练框架版本,例如选择pytorch1.7、pytorch1.8、pytorch1.9、pytorch1.10、pytorch1.11中的一种。其中用户对使用镜像操作系统版本,如python版本,以及相关依赖版本等并不关注,因此,用户在实际操作中只需要指定硬件资源和应用任务,本实施例可以根据用户指定的硬件资源和应用任务,从软件列表中筛选出对应的目标软件资源,从而利用目标软件资源生成树状拓扑图。
138.步骤102、根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。
139.在一些实施例中,所述第i+1个层级对应的镜像基于所述树状拓扑图中第i个层级对应的镜像构建;其中,第1个层级对应的镜像基于公共镜像构建。
140.实施中,按照所述树状拓扑图中的层级顺序,根据每个层级包含的节点表征的软件资源,依次构建与各个层级对应的镜像,其中相邻层级中较高层级对应的镜像依赖于较低层级对应的镜像。
141.在一些实施例中,本实施例中的述树状拓扑图包括至少3个层级,从低到高依次为第一层级、第二层级、第三层级,其中:
142.根据所述第一软件资源中与编译能力相关的软件资源确定第一层级;实施中,可以根据cuda和cudnn版本确定第一层级;
143.根据所述第一软件资源中与驱动、通信、加速运算以及编程语言中的至少一种相关的软件资源确定第二层级;实施中,可以根据ai开发训练平台需要用到软件包和基础python3编码语言确定第二层级;
144.根据所述第二软件资源确定第三层级;实施中,可以根据cudatoolkit和pytorch版本确定第三层级;
145.其中所述层级从低到高依次为第一层级、第二层级、第三层级。
146.在一些实施例中,本实施例中的树状拓扑图还包括最底层级,通过如下方式确定所述最底层级:
147.根据与硬件无关的运行库和开发编译工具链,生成所述树状拓扑图中的最底层级;其中所述最底层级低于所述第一软件资源对应的节点所在的层级。
148.实施中,如图2所示,本实施例提供一种树状拓扑图的层级结构,共包括五个层级,从低到高依次是最底层级、第一层级、第二层级、第三层级、顶层;其中:
149.最底层级对应的镜像为base镜像,依赖于公共镜像,base镜像包含与硬件无关的
运行库和开发编译工具链,在构建成功后相当长时间不会变;其中公共镜像是由开发厂商提供的。
150.第一层级对应的镜像为cuda镜像,cuda镜像依赖base镜像,根据cuda和cudnn版本的不同存在多个版本;
151.第二层级对应的镜像为basic镜像,basic镜像依赖cuda镜像,包含ai开发训练平台需要用到软件包和基础python3编码语言;
152.第三层级对应的镜像为pytorch镜像,pytorch镜像依赖basic镜像,由于pytorch存在多个正式发布版本,且每个版本所支持的最高最低cudatoolkit版本是确定的,不同型号显卡的计算节点驱动所支持的最低最高cudatoolkit也是确定的,因此实际构建的pytorch镜像数量与所采用cudatoolkit和pytorch版本数量相关;
153.顶层对应的镜像为应用程序镜像,即apps镜像,为最终对用户发布的镜像,apps镜像依赖pytorch镜像。如果apps镜像存在软件缺失或错误,则以此apps镜像为基础构建patch(补丁)镜像进行打补丁修正即可。
154.实施中,本实施例从base镜像开始,依次构建cuda镜像、basic镜像、pytorch镜像、apps镜像,并上传到镜像仓库如harbor仓库,从而对待发布的apps镜像进行功能测试。
155.在一些实施例中,本实施例依次构建与各个层级对应的镜像之后,还包括:
156.将构建的各个层级对应的镜像上传到镜像仓库;
157.当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像,其中所述预设层级包括所述第一软件资源对应的节点所在的层级。
158.实施中,由于第一软件资源与硬件相关,而硬件在较长一段时间内通常不会更改,生命周期较长,且第一软件资源对应的节点所在的层级较低,因此将第一软件资源对应的节点所在的层级对应的镜像作为基础镜像进行复用,本实施例通过软件资源的生命周期,软件版本间依赖关系分多个阶段构建镜像,能够充分复用基础镜像节省harbor仓库和计算节点的存储空间。
159.在一些实施例中,本实施例在依次构建与各个层级对应的镜像时,还用于执行如下步骤:
160.当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。
161.实施中,当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像依赖共同的目标镜像时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。
162.实施中,新镜像发布后,选择新版本镜像的用户被调度到的计算节点,当计算节点上存在的其它镜像与当前选择的新版本镜像依赖共同的目标镜像时,计算节点直接复用目标镜像即可,不需要再去镜像仓库拉取目标镜像,从而有效减少计算节点拉取镜像的时间。
163.本实施例按照软件生命周期和依赖关系分多个层次构建镜像,充分复用多个基础镜像,能够节省harbor仓库和计算节点的存储空间,并降低计算节点拉取新镜像的耗时,并且根据梳理出的软件依赖关系,固化底层软件版本,能够增强镜像的兼容性,使得部分在用
的老版本代码也可以较好的运行。
164.如图3所示,本实施例还提供一种镜像构建的具体实施方法,该方法实施时执行如下步骤:
165.步骤300、根据计算机集群使用的硬件资源,确定第一软件资源,以及根据至少一种应用任务所需的软件资源,确定第二软件资源;
166.步骤301、根据第一软件资源、第二软件资源和各软件资源间的依赖关系,确定软件资源列表;
167.步骤302、响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;
168.步骤303、根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图;
169.其中,所述树状拓扑图包括多个层级,每个层级包括至少一个节点,所述节点表征软件资源,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;生命周期较长的软件资源的层级低于生命周期较短的软件资源的层级。
170.如图4所示,本实施提供的一种基于树状拓扑图的镜像层级结构图,其中从低到高的镜像依次为base镜像,cuda镜像,basic镜像,pytorch镜像,apps镜像,其中:
171.base镜像包括开发常用工具、开发编译工具链、矩阵运算库、解码库等,如ubuntu18.04、ubuntu20.04;
172.cuda镜像包括cudatoolkit、cudnn、mlnx_ofed、gdrcopy、hpcx、nccl、ffmpeg等,如cuda10.2、cuda11.1、cuda11.3;
173.basic镜像包括python3.8、基础包、opencv、libboost等;
174.pytorch镜像包括pytorch、caffe、torchvision、apex、horovod、deepspeed以及onnx相关的工具;如pytorch1.7、pytorch1.8、pytorch1.9、pytorch1.10、pytorch1.11等;
175.apps镜像包括目标检测,跟踪,分类,分割,识别,nlp、ocr等领域相关开源仓库代码依赖软件;具体根据实际项目确定。
176.步骤304、按照所述树状拓扑图中的层级顺序,根据每个层级包含的节点表征的软件资源,依次构建与各个层级对应的镜像;
177.其中,相邻层级中较高层级对应的镜像依赖于较低层级对应的镜像。
178.步骤305、将构建的各个层级对应的镜像上传到镜像仓库;
179.步骤306、当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像;
180.其中所述预设层级包括所述第一软件资源对应的节点所在的层级。
181.步骤307、当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像。
182.本实施例通过梳理整个在用软件技术栈,按照用户关注度(用户指定的硬件资源和应用任务),软件生命周期,软件版本间依赖关系分多个阶段构建镜像,能够充分复用基础镜像节省harbor仓库和计算节点的存储空间;新镜像发布后,选择新版本镜像的用户被调度到的计算节点,当计算节点上存在的其它镜像与当前选择的镜像依赖共同的镜像时能
够明显减少拉取镜像的时间;由于是按照整个在用软件技术栈进行软件版本配套表的选择,固化版本后能够增强镜像的兼容性,防止安装软件包时自动安装的依赖版本不合适问题,使得整个镜像环境对于训练程序的运行具有较好的兼容性。
183.实施例2、基于相同的发明构思,本发明实施例还提供了一种镜像构建的设备,由于该设备即是本发明实施例中的方法中的设备,并且该设备解决问题的原理与该方法相似,因此该设备的实施可以参见方法的实施,重复之处不再赘述。
184.如图5所示,该设备包括处理器500和存储器501,所述存储器501用于存储所述处理器500可执行的程序,所述处理器500用于读取所述存储器501中的程序并执行如下步骤:
185.获取软件资源列表,所述软件资源列表中的软件资源包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;
186.基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;
187.根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。
188.作为一种可选的实施方式,所述处理器500具体被配置为执行:
189.根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图;
190.其中所述树状拓扑图中第i+1个层级包含的节点对应的软件资源中最长的生命周期,小于第i个层级包含的节点对应的软件资源中最短的生命周期。
191.作为一种可选的实施方式,所述处理器500具体被配置为执行:
192.响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;
193.根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图。
194.作为一种可选的实施方式,所述树状拓扑图包括至少3个层级,所述处理器500具体被配置为执行:
195.根据所述第一软件资源中与编译能力相关的软件资源确定第一层级;
196.根据所述第一软件资源中与驱动、通信、加速运算以及编程语言中的至少一种相关的软件资源确定第二层级;
197.根据所述第二软件资源确定第三层级;
198.其中所述层级从低到高依次为第一层级、第二层级、第三层级。
199.作为一种可选的实施方式,所述树状拓扑图还包括最底层级,所述处理器500具体被配置为执行通过如下方式确定所述最底层级:
200.根据与硬件无关的运行库和开发编译工具链,生成所述树状拓扑图中的最底层级;其中所述最底层级低于所述第一软件资源对应的节点所在的层级。
201.作为一种可选的实施方式,所述处理器500具体被配置为执行:
202.根据计算机集群使用的硬件资源,确定第一软件资源;
203.根据至少一种应用任务所需的软件资源,确定第二软件资源;
204.根据所述第一软件资源、所述第二软件资源以及各个软件资源之间的依赖关系,确定软件资源列表。
205.作为一种可选的实施方式,依次构建与各个层级对应的镜像之后,所述处理器500具体还被配置为执行:
206.将构建的各个层级对应的镜像上传到镜像仓库;
207.当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像,其中所述预设层级包括所述第一软件资源对应的节点所在的层级。
208.作为一种可选的实施方式,所述处理器500具体还被配置为执行:
209.当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。
210.作为一种可选的实施方式,所述第i+1个层级对应的镜像基于所述树状拓扑图中第i个层级对应的镜像构建;其中,第1个层级对应的镜像基于公共镜像构建。
211.实施例3、基于相同的发明构思,本发明实施例还提供了一种镜像构建的装置,由于该装置即是本发明实施例中的方法中的装置,并且该装置解决问题的原理与该方法相似,因此该装置的实施可以参见方法的实施,重复之处不再赘述。
212.如图6所示,该装置包括:
213.获取软件单元600,用于获取软件资源列表,所述软件资源列表包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;
214.生成拓扑图单元601,用于基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;
215.构建镜像单元602,用于根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。
216.作为一种可选的实施方式,所述生成拓扑图单元601具体用于:
217.根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图;
218.其中所述树状拓扑图中第i+1个层级包含的节点对应的软件资源中最长的生命周期,小于第i个层级包含的节点对应的软件资源中最短的生命周期。
219.作为一种可选的实施方式,所述生成拓扑图单元601具体用于:
220.响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;
221.根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图。
222.作为一种可选的实施方式,所述树状拓扑图包括至少3个层级,所述生成拓扑图单元601具体用于:
223.根据所述第一软件资源中与编译能力相关的软件资源确定第一层级;
224.根据所述第一软件资源中与驱动、通信、加速运算以及编程语言中的至少一种相关的软件资源确定第二层级;
225.根据所述第二软件资源确定第三层级;
226.其中所述层级从低到高依次为第一层级、第二层级、第三层级。
227.作为一种可选的实施方式,所述树状拓扑图还包括最底层级,所述生成拓扑图单元601具体用于通过如下方式确定所述最底层级:
228.根据与硬件无关的运行库和开发编译工具链,生成所述树状拓扑图中的最底层级;其中所述最底层级低于所述第一软件资源对应的节点所在的层级。
229.作为一种可选的实施方式,所述获取软件单元600具体用于:
230.根据计算机集群使用的硬件资源,确定第一软件资源;
231.根据至少一种应用任务所需的软件资源,确定第二软件资源;
232.根据所述第一软件资源、所述第二软件资源以及各个软件资源之间的依赖关系,确定软件资源列表。
233.作为一种可选的实施方式,依次构建与各个层级对应的镜像之后,还包括复用镜像单元具体用于:
234.将构建的各个层级对应的镜像上传到镜像仓库;
235.当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像,其中所述预设层级包括所述第一软件资源对应的节点所在的层级。
236.作为一种可选的实施方式,所述构建镜像单元602具体还用于:
237.当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。
238.作为一种可选的实施方式,所述第i+1个层级对应的镜像基于所述树状拓扑图中第i个层级对应的镜像构建;其中,第1个层级对应的镜像基于公共镜像构建。
239.基于相同的发明构思,本发明实施例还提供了一种计算机存储介质,其上存储有计算机程序,该程序被处理器执行时实现如下步骤:
240.获取软件资源列表,所述软件资源列表中的软件资源包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;
241.基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;
242.根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。
243.本领域内的技术人员应明白,本发明的实施例可提供为方法、系统、或计算机程序产品。因此,本发明可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本发明可采用在一个或多个其中包含有计算机可用程序代码的计算机
可用存储介质(包括但不限于磁盘存储器和光学存储器等)上实施的计算机程序产品的形式。
244.本发明是参照根据本发明实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的设备。
245.这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令设备的制造品,该指令设备实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
246.这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
247.显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。

技术特征:
1.一种镜像构建的方法,其特征在于,该方法包括:获取软件资源列表,所述软件资源列表中的软件资源包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应,所述第一软件资源对应的节点所在的层级低于所述第二软件资源对应的节点所在的层级;根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建,所述i为大于0的整数。2.根据权利要求1所述的方法,其特征在于,所述基于所述软件资源列表生成树状拓扑图,包括:根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成所述树状拓扑图;其中所述树状拓扑图中第i+1个层级包含的节点对应的软件资源中最长的生命周期,小于第i个层级包含的节点对应的软件资源中最短的生命周期。3.根据权利要求2所述的方法,其特征在于,所述根据所述软件资源列表中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成树状拓扑图,包括:响应于用户指定的硬件资源和应用任务,从所述软件资源列表中筛选出所述指定的硬件资源和应用任务相关的目标软件资源;根据所述目标软件资源中各个软件资源之间的依赖关系和各个软件资源的生命周期,生成所述树状拓扑图。4.根据权利要求1所述的方法,其特征在于,所述树状拓扑图包括至少3个层级,其中:根据所述第一软件资源中与编译能力相关的软件资源确定第一层级;根据所述第一软件资源中与驱动、通信、加速运算以及编程语言中的至少一种相关的软件资源确定第二层级;根据所述第二软件资源确定第三层级;其中所述层级从低到高依次为第一层级、第二层级、第三层级。5.根据权利要求1~4任一所述的方法,其特征在于,所述树状拓扑图还包括最底层级,通过如下方式确定所述最底层级:根据与硬件无关的运行库和开发编译工具链,生成所述树状拓扑图中的最底层级;其中所述最底层级低于所述第一软件资源对应的节点所在的层级。6.根据权利要求1所述的方法,其特征在于,所述获取软件资源列表,包括:根据计算机集群使用的硬件资源,确定第一软件资源;根据至少一种应用任务所需的软件资源,确定第二软件资源;根据所述第一软件资源、所述第二软件资源以及各个软件资源之间的依赖关系,确定所述软件资源列表。7.根据权利要求1所述的方法,其特征在于,依次构建与各个层级对应的镜像之后,还包括:将构建的各个层级对应的镜像上传到镜像仓库;
当存在基于所述第一软件资源构建新的镜像的需求时,通过对所述镜像仓库中预设层级对应的镜像进行复用的方式,构建新的镜像,其中所述预设层级包括所述第一软件资源对应的节点所在的层级。8.根据权利要求1所述的方法,其特征在于,所述依次构建与各个层级对应的镜像,还包括:当计算机集群中的任一计算节点上存在至少一个镜像与所述计算节点当前处理的镜像都基于共同的目标镜像构建时,所述计算节点利用所述目标镜像构建所述至少一个镜像,以减少计算节点拉取目标镜像的时间。9.根据权利要求1所述的方法,其特征在于,所述第i+1个层级对应的镜像基于所述树状拓扑图中第i个层级对应的镜像构建;其中,第1个层级对应的镜像基于公共镜像构建。10.一种镜像构建的设备,其特征在于,该设备包括处理器和存储器,所述存储器用于存储所述处理器可执行的程序,所述处理器用于读取所述存储器中的程序并执行权利要求1~9任一所述方法的步骤。11.一种计算机存储介质,其上存储有计算机程序,其特征在于,该程序被处理器执行时实现如权利要求1~9任一所述方法的步骤。

技术总结
本发明公开了一种镜像构建的方法及设备,能够充分复用基础镜像节省harbor仓库和计算节点的存储空间,固化版本后也能够增强镜像的兼容性。该方法包括:获取软件资源列表,所述软件资源列表中的软件资源包括与硬件资源相关的第一软件资源以及与应用任务相关的第二软件资源;基于所述软件资源列表生成树状拓扑图,其中所述树状拓扑图包括多个层级,每个层级包括至少一个节点,每个节点与一个软件资源对应;根据第i+1个层级包含的节点对应的软件资源,构建与所述第i+1个层级对应的镜像,其中所述第i+1个层级对应的镜像基于所述树状拓扑图中第i+1个层级之前的层级对应的镜像构建。图中第i+1个层级之前的层级对应的镜像构建。图中第i+1个层级之前的层级对应的镜像构建。


技术研发人员:张朋 蔡丹平 吴立 虞响 黄鹏 周祥明
受保护的技术使用者:浙江大华技术股份有限公司
技术研发日:2022.07.11
技术公布日:2022/11/1
转载请注明原文地址: https://tieba.8miu.com/read-6998.html

最新回复(0)