创建任务
该接口用于创建任务,可以指定任务的运行环境,然后创建和执行任务。
POST
接口路径:http://matpool.com:30100/v1/job
示例:
curl --request POST \
--url 'http://matpool.com:30100/v1/job' \
--header 'Authorization: Bearer <YOUR_TOKEN>' \
--header 'content-type: multipart/form-data' \
--form 'spec={"diskGB":10}' \
--form 'envs="FOO=bar;ZZ=qqqqq"' \
--form 'cmd="<YOUR_CMD>"' \
--form 'app_name=ubuntu' \
--form 'app_version=18.04'
准备任务文件
整体流程
任务文件需要先上传到云存储(以下简称'网盘'),再挂载到运行时的容器内。
网盘
- 用户独立的持久化的云存储空间(不同的会员权益限制了大小及用量)
- 每个用户网盘根目录都为
/
,但完全隔离- 具备用户独有控制权,不会因节点回收而导致数据被移除
由整体流程可知,准备任务文件涉及到两个过程,一个是上传,另一个是挂载,矩池云提供了两种上传任务文件的方式,也提供了灵活的挂载规则。
此外,我们有两个目录需要区分,一个是用户的网盘目录(以下简称'网盘目录'),另一个是运行任务容器内的目录(以下简称'容器目录')。
上传文件
需要注意的是,该压缩包本身不会被保存到网盘,而是在之后会被解压,为了便于理解,可以把上传方式 2 视为压缩包等待被解压(即保存)到网盘中,而解压至哪个目录受 volumes
参数影响,解压规则在下文中阐述。
挂载
挂载规则由参数 volumes
决定,该参数支持用户把网盘任意目录挂载至容器任意目录,参数形式和默认值参见本接口挂载映射相关参数。
挂载和解压规则(步骤):
默认
volumes
参数的预处理(若指定了volumes
参数,则跳过这一步)如果用户调用该接口时上传了文件,那么在用户网盘根目录下会新建一个子目录,目录名为随机字符串,如
/A2BF38EE-AB7B-48A3-92E5-FF9AFB26423D/
,此时volumes
参数相当于被指定为[{ "src": "/A2BF38EE-AB7B-48A3-92E5-FF9AFB26423D/", "dest": "/mnt" }]
,进入挂载步骤如果用户调用该接口时没有上传文件,那么
volumes
参数相当于被指定为[{ "src": "/", "dest": "/mnt" }]
,进入挂载步骤
挂载
遍历
volumes
参数(数组),根据每一项的映射规则,将src
字段指定的网盘目录,挂载到dest
字段指定的容器目录,进入下一步解压规则(若未在接口中上传文件,则跳过这一步)
如果有待解压的文件(即在上传阶段使用了上传方式 2),取
volumes
参数(数组)的第一项,把上传的压缩包文件解压到src
指定的网盘目录下的input
目录(input
目录会被自动创建),即对应dest
指定的容器目录下的input
目录
上传方式和挂载规则组合示例
// 方式 1 上传文件,即不指定上传的任务文件
// 不传 volumes 参数,即采用默认的行为
此时 volumes 参数相当于 [{ "src": "/", "dest": "/mnt" }]
挂载结果:网盘根目录 '/' --> 容器内目录 '/mnt'
---------
// 方式 1 上传文件,即不指定上传的任务文件
// 传 volumes 参数,此时跳过'默认 volumes 参数的预处理'步骤
[
{"src": "/jobs", "dest": "/myjobs"},
{"src": "/data", "dest": "/mydata"}
]
挂载结果:
网盘目录 '/jobs' --> 容器内目录 '/myjobs'
网盘目录 '/data' --> 容器内目录 '/mydata'
---------
// 方式 2 上传文件,即指定上传的任务文件,如 task.tar.gz
// 不传 volumes 参数,即采用默认的行为
因为有上传文件,所以会生成随机目录,此时 volumes 参数相当于 [{ "src": "/A2BF38EE-AB7B-48A3-92E5-FF9AFB26423D", "dest": "/mnt" }]
挂载结果:网盘目录 '/A2BF38EE-AB7B-48A3-92E5-FF9AFB26423D' --> 容器内目录 '/mnt'
任务文件 task.tar.gz 被解压到
网盘的 '/A2BF38EE-AB7B-48A3-92E5-FF9AFB26423D/input' 目录,
即对应容器的 '/mnt/input' 目录
---------
// 方式 2 上传文件,即指定上传的任务文件,如 task.tar.gz
// 传 volumes 参数,此时跳过'默认 volumes 参数的预处理'步骤
[
{"src": "/jobs", "dest": "/myjobs"},
{"src": "/data", "dest": "/mydata"}
]
挂载结果:
网盘目录 '/jobs' --> 容器内目录 '/myjobs'
网盘目录 '/data' --> 容器内目录 '/mydata'
任务文件 task.tar.gz 被解压到网盘的 '/jobs/input' 目录,
即对应容器的 '/myjobs/input' 目录
Header
Required | Name | Value | Description |
---|---|---|---|
✔︎ | Authorization | Bearer <token> | 用户鉴权 |
Body(formdata)
该 API 的 Request Body 为 formdata
的形式,可以指定以下的内容。
规格和环境变量
Required | Name | type | Example | Description |
---|---|---|---|---|
✔︎ | spec | string | {"diskGB":10,"gpus":2} | json 字符串,指定任务所需的最小资源要求,当前支持字段:diskGB:使用的磁盘大小,gpus:使用的 GPU 个数。不需要做限制的参数直接不传即可,比如 {"diskGB":10} 表示不需要对使用的 GPU 个数做限制 |
✘ | env | string | FOO=aa;BAR=bb | 注入到容器的环境变量,多个环境变量分号分隔 |
任务文件
任务文件的准备上面已经进行了详细阐述,如果用户需要在创建任务的时候同时上传任务文件,则需要上传以下两个字段的内容
Required | Name | type | Example | Description |
---|---|---|---|---|
✘ | file_name | string | files.tar.gz | 指明要上传的文件名,当前仅支持 *.tar.gz 格式 |
✘ | file | file | - | 对应要上传的压缩包文件 |
挂载映射
该参数支持用户任意网盘目录挂载至容器内任意目录,如需自定义网盘目录挂载至容器目录,则需提供如下字段,该字段为 json 字符串,整体是一个数组形式,每一项是一个对象,指定了网盘目录到容器目录的映射,如果未指定该参数或指定为空数组([]
)则采用默认行为。
默认挂载行为:
- 如果在调用该接口的时候上传了任务文件,用户网盘根目录下会生成一个目录,目录名为随机字符串,如
/A2BF38EE-AB7B-48A3-92E5-FF9AFB26423D
,然后把这个目录挂载到容器的/mnt
目录 - 如果没有在调用接口的时候上传任务文件,那么就把用户网盘根目录
/
挂载到容器目录/mnt
Required | Name | type | Example | Description |
---|---|---|---|---|
✘ | volumes | string | [{"src":"/data","dest":"/home/data","readOnly":false},{"src":"/doc","dest":"/home/doc","readOnly":true}] | 提供自定义挂载映射,若 src 指定的目录在网盘内不存在,则自动创建该目录。readOnly 为 true 表示只读挂载,默认为 false |
端口导出
该参数支持用户访问容器任意端口,如需访问容器端口,则需提供如下字段,该字段为 json 字符串,整体是一个数组形式,每一项是一个对象,指定了要导出的容器端口,访问协议以及拓展信息,如果未指定该参数或指定为空数组([]
)则不导出任何容器端口。
Required | Name | type | Example | Description |
---|---|---|---|---|
✘ | ports | string | [{"port":22,"protocol":1,"extraData":{"pubKey":{"key":"my_public_key"}}},{"port":8888,"protocol":2}] | protocol 字段, 1 表示 ssh , 2 表示 http 。如果是 ssh 协议,则可以通过 extraData 字段传入公钥,对应的公钥会做为容器中环境变量 PUBLIC_KEY 的值。一个任务只支持导出一个 ssh 访问的端口 |
指定镜像
用户必须指定需要运行的容器依赖的 Docker 镜像,根据镜像仓库是否为私有,可以分为以下两种:
私有仓库
假设想使用一个私有仓库的镜像:
<YOUR_PRIVATE_DOCKER_REGISTRY>/<PATH>/<IMAGE>:<TAG>
,那么需要传入登录镜像仓库的用户名和密码,相关的参数对应如下:- app_name:
<PATH>/<IMAGE>
- app_version:
<TAG>
- hostname:
<YOUR_PRIVATE_DOCKER_REGISTRY>
- creds:
{"user": "<YOUR_USERNAME>", "psw": "<YOUR_PASSWD>"}
- app_name:
公共仓库
假设想使用一个公共仓库的镜像:
<PUBLIC_DOCKER_REGISTRY>/<PATH>/<IMAGE>:<TAG>
,那么不需要传入登录镜像仓库的用户名和密码(即creds
字段),也不需要传入hostname
字段,相关的参数对应如下:- app_name:
<PUBLIC_DOCKER_REGISTRY>/<PATH>/<IMAGE>
- app_version:
<TAG>
- app_name:
Required | Name | type | Example | Description |
---|---|---|---|---|
✔︎ | app_name | string | ubuntu | 所用的镜像名,取决于镜像 |
✔︎ | app_version | string | 18.04 | 所用的镜像的版本号 |
✘ | hostname | string | somewhere.registry.com | 私有仓库需要指定的镜像仓库地址 |
✘ | creds | string | {"user": "uu", "psw": "123"} | json 字符串,登录私有仓库的用户名和密码 |
✘ | cmd | string | echo 'hello' | 要在容器中运行的命令,如果没有指定,则运行指定的镜像内默认的命令 |
Response
Normal
job.status
的含义:
- 1:排队中
- 2:已调度
- 3:运行中
- 4:已完成
- 5:已取消
- 6:初始化中
code = 0
示例:
{
"code":0,
"msg":"",
"job":{
"id":525,
"ctx":{
"ownerId":1,
"nodeId":-1
},
"state":{
"status":1, // 当前状态
"log":[ // 状态变更记录,以及发生变更时的时间戳
{
"id":2574,
"status":6,
"ts":{
"seconds":1562317937
},
"sourceId":525
},
{
"id":2575,
"status":1,
"ts":{
"seconds":1562317937
},
"sourceId":525
}
]
},
"status":1, // 当前状态
"app":{ // 调用接口时传入的镜像信息
"name":"ubuntu",
"ver":"18.04",
"envs":"FOO=aa;BAR=bb",
"format":2,
"files":{
"mnt":"/mnt",
"input":"",
"output":"",
"stdout":"",
"stderr":""
},
"cmd":"echo 'hello'",
"hostname":"",
"creds":"",
"ports": [ // 调用接口时传入的端口导出信息
{
"port": 22,
"protocol": 1,
"extraData": {
"pubKey": {
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDmWeBdQxb4YJcus4VPmqPz254lvHeuMEMeJbTDl2ZD6DXdxB+UytLWTJEjt/uiDDI1RusAf3PnURvNW/f3Juu3U3ghFFqLhRCsKat4XZL1xxyp1T2BHj4IPxhqRMAMBye5EAxxGzm2BOqAOGNV986NipppMLPTNaAfgRpDUw7n8sPWtxMoHsHiu+BDAfmEM6153b/HywcpLURuc006ZC346tkARKPXcTeD8/9mQJn5sJwuLl6VW+k/lhYabWztatI1vfOe3ce6HkomUKWUsP7xKxkDstEwT4u0qPYyX0vTJtUWWJ1nLnCISdA4ctvpY0RvMtxYkOTymNkpV/++aYJ1 huangzhiran@huangzhiran"
}
}
},
{
"port": 8888,
"protocol": 2,
"extraData": null
}
],
"urls": { // 导出的端口所对应的URL,访问该URL即可访问到容器对应的端口。key 为端口号加 port_ 前缀拼接成的字符串
"port_22": {
"urls": [
"ssh://matpool.com:34707"
]
},
"port_8888": {
"urls": [
"https://matpool.com:40977?token=4WZwUTNLy4"
]
}
}
},
"res":{ // 镜像运行需要的资源信息
"cpus":0,
"gpus":0,
"diskGB":10
},
"createTime":{ // 创建时间
"seconds":1562317937
},
"vols": [
{
"src": "/",
"dest": "/mnt",
"readOnly": false
}
],
"queueLen": 0
}
}
Exception
code = 1 || 7
参见 全局错误码