OSS挂载

对象存储 OSS 提供了与传统文件系统不同的 API,为了支持传统程序的快速迁移,BatchCompute 允许用户将 OSS 目录直接挂载到虚拟机的本地文件系统,应用程序无需针对 OSS 进行特殊编程即可访问 OSS 上的数据。

OSS 挂载分为只读挂载可写挂载两种:

  • 只读挂载用于访问程序的输入数据,通过只读挂载点的数据访问将会被自动转换为 OSS 的访问请求,数据不需要先下载到虚拟机本地。

  • 可写挂载目录下的结果数据将存放在虚拟机的本地,不会上传到OSS上。使用可写挂载时请确保虚拟机为结果数据分配了足够的磁盘空间。

1. 挂载数据目录

提交作业的时候,可以配置挂载,请参考如下示例。

A) 使用 Java SDK

TaskDescription taskDesc = new TaskDescription();
taskDesc.addInputMapping("oss://mybucket/mydir/", "/home/admin/mydir/"); //只读挂载
taskDesc.addOutputMapping("/home/admin/mydir/", "oss://mybucket/mydir/"); //可写挂载

B) 使用 Python SDK

# 只读挂载
job_desc['DAG']['Tasks']['my-task']['InputMapping'] = {
    "oss://mybucket/mydir/": "/home/admin/mydir/"
}

# 可写挂载
job_desc['DAG']['Tasks']['my-task']['OutputMapping'] = {
    "/home/admin/mydir/": "oss://mybucket/mydir/"
}

C) 使用命令行

bcs sub "python main.py" -r oss://mybucket/mydir/:/home/admin/mydir/   # 如果有多个映射,请用逗号隔开

注意

  • 配置 InputMapping,是只读挂载,意思是只能读,不能写,不能删除。

  • 配置 OutputMapping,写到 /home/admin/mydir/目录下的文件或目录,在任务运行完成后会被自动上传到 oss://mybucket/mydir/ 下面。

  • InputMapping 和 OutputMapping 不能指定为同样的映射。

2. 挂载程序目录

假如 main.py 在OSS上的路径为:oss://mybucket/myprograms/main.py,可以挂载 oss://mybucket/myprograms/ 为 /home/admin/myprograms/,然后指定运行命令行python /home/admin/myprograms/main.py 即可。

A) 使用 Java SDK

TaskDescription taskDesc = new TaskDescription();
taskDesc.addInputMapping("oss://mybucket/myprograms/", "/home/admin/myprograms/"); //只读挂载

Command cmd = new Command()
cmd.setCommandLine("python /home/admin/myprograms/main.py")

params.setCommand(cmd);
taskDesc.setParameters(params);

B) 使用 Python SDK

# 只读挂载
job_desc['DAG']['Tasks']['my-task']['InputMapping'] = {
    "oss://mybucket/myprograms/": "/home/admin/myprograms/"
}
job_desc['DAG']['Tasks']['my-task']['Parameters']['Command']['CommandLine']='python /home/admin/myprograms/main.py'

C) 使用命令行

bcs sub "python /home/admin/myprograms/main.py" -r oss://mybucket/myprograms/:/home/admin/myprograms/

3. 挂载文件

说明

需求: 在OSS上有多个不同前缀下的文件,需要挂载到批量计算VM中的同一个目录下,该如何使用;

假设 bucket1 和 bucket2 下有两个文件挂载到 VM 本地的/home/data/下:

  • oss://bucket1/data/file1挂载到/home/data/file1

  • oss://bucket2/data/file2挂载到/home/data/file2

另外,作业结束后有两个 VM 本地的文件分别上传到 bucket1 和 bucket2:

  • /home/output/output1挂载到oss://bucket1/output/file1

  • /home/output/output2挂载到oss://bucket2/output/file2

可以参考如下示例:

A) 使用 Java SDK

TaskDescription taskDesc = new TaskDescription();
taskDesc.addInputMapping("oss://bucket1/data/file1", "/home/data/file1");
taskDesc.addInputMapping("oss://bucket2/data/file2", "/home/data/file2");
taskDesc.addOutputMapping("/home/output/output1", "oss://bucket1/output/file1");
taskDesc.addOutputMapping("/home/output/output2", "oss://bucket2/output/file2");

B) 使用 Python SDK

# 只读挂载
job_desc['DAG']['Tasks']['my-task']['InputMapping'] = {
    "oss://bucket1/data/file1": "/home/data/file1",
    "oss://bucket2/data/file2": "/home/data/file2"
}

# 可写挂载
job_desc['DAG']['Tasks']['my-task']['OutputMapping'] = {
    "/home/output/output1": "oss://bucket1/output/file1",
    "/home/output/output2": "oss://bucket2/output/file2"
}

4. InputMapping 挂载限制说明

A) OSS上存储对象的命名

  • 单个文件名最长为 255 字节,其他字符集编码按照折算成 UTF-8 编码后所实际占用的字节数量计算,通常一个汉字占用 3 个字节。

  • 从根目录开始计算的组合路径+文件名长度最大为 1023 个字节。

  • 合法的文件名仅按照 UTF-8 字符集进行定义,其他字符集需转换为 UTF-8 之后进行合法性检查。

  • 支持 UTF-8 0x80 以上的所有字符。

  • 不支持 0x00-0x1F 和 0x7F,以及\ / : * ? “ < > |字符。

B) InputMapping 挂载文件的访问权限

考虑到多个节点向 OSS 写入文件的一致性问题,InputMapping 挂载服务本身针对 OSS 是只读行为;应用程序通过文件系统接口的操作,在 任何情况 下都不会修改 OSS 上对应文件的内容,也不会删除 OSS 上的对应文件。

  • 所有对挂载目录的修改操作都会缓存在本地(不会同步到 OSS),应用程序可以通过文件系统接口读取到修改后的内容。在应用程序运行结束文件系统Umount并停止挂载服务后,所有本地缓存的改动都会被放弃;接下来如果重新启动挂载服务并 mount,那么本地看到文件同 OSS 上对应 Object 的内容一致,上次的改动不再保留。

  • 在挂载目录中,OSS 上已经存在的文件都会赋予读取以及执行的权限,没有写入权限。应用程序可以执行读操作,但是修改、截断、重命名和删除等操作都会被拒绝。

  • 在挂载目录中,应用程序可以自由地创建文件和文件夹,这些新创建出来的内容都会赋予读取、写入、和执行权限,应用程序可以修改、截断、重命名和删除这些文件。

  • 对于 Windows 操作系统来说,系统认为在只读文件夹下的内容也是无法删除的。因此对于一个 OSS 上已经存在的文件夹,应用程序可以在里面创建文件,也可以进行修改和截断操作,但是删除和重命名操作会被 Windows 系统禁止。比如\127.0.0.1\ossdata\bucket\dir 是 OSS 上已经存在的一个文件夹,应用程序挂载后又在 dir 文件夹里创建了一个文件 file,那么 \127.0.0.1\ossdata\bucket\dir\file 文件是没办法删除和重命名的。但是如果在 \127.0.0.1\ossdata\bucket\dir 下创建文件夹 local, 此时在 \127.0.0.1\ossdata\bucket\dir\local 中再创建其他的文件就都是可以删除和重命名的,如 \127.0.0.1\ossdata\bucket\dir\local\file,Linux 操作系统中不存在这个问题。

C) 挂载语言问题

OSS 上所有的 Object 的名称都是用 UTF-8 编码来保存的,挂载服务本身可以对字符集进行转换,您需要在集群/作业的描述中指定应用程序使用的字符集,这样经过挂载服务的转换,应用程序才可以访问到正确的文件。

注意,应用程序使用的字符集和操作系统默认的字符集可能是不同的。例如工作在一个简体中文操作系统中的繁体程序,需要配置字符集为 BIG5,这样挂载服务会自动将 OSS 上 UTF-8 的路径和文件名转换为 BIG5 编码,虽然从操作系统上观察到挂载盘中的文件名都是乱码,但是应用程序的访问是正确的。

这个字符集转换功能仅仅影响路径的文件名,对于文件的内容并没有作用。

D) 文件锁

基于 NFS 的 DOS Share 和文件锁会影响性能,所以如果有频繁的 IO 操作,建议关闭文件锁(在通过 mount 挂载的时候增加 nolock 选项)。但是有些特定的应用程序如 3DSMAX 必须用的文件锁特性,如果缺失这个特性会导致应用程序执行不正确。

E) 文件挂载

将 OSS 上的单独文件挂载到 VM 本地时,需要保证所有文件到的本地目录不能时另外文件挂载或者目录挂载的父目录。

F) 其他约定

  • 在应用程序运行期间,不应该修改 OSS 应用程序通过挂载正在访问的文件夹,否则可能引起冲突。任何对应用程序正在访问的数据做出的修改(包括但不限于删除、修改文件内容、截断文件、Append 文件内容)都可能引发应用程序运行结果错误。

  • OSS 上的容量近似无限,所以操作系统统计的当前磁盘利用率并没有意义,并不代表当前OSS 上存储空间的使用状况。

  • 同时刻支持挂载同一个账号下多个 bucket 中的内容到虚拟机不同的位置。

  • 同时刻不支持挂载多个账号下的内容到虚拟机。