新西兰.net和java
新西兰的经济取决于农业,农业对气候变化高度敏感。 这使得开发分析功能以评估其影响并调查可能的缓解和适应方案至关重要。 可以使用诸如农业系统模型之类的工具进行分析。 简而言之,它涉及创建一个模型来量化特定作物在特定条件下的行为,然后模拟更改一些变量以查看行为的变化。 一些可用于执行此操作的软件包括华盛顿州立大学的CropSyst和澳大利亚联邦科学与工业研究组织(CSIRO)的农业生产系统模拟器( APSIM )。
从历史上看,这些模型主要用于众所周知的所有变量的小面积(基于点)仿真。 对于大面积研究(景观尺度,例如整个区域或国家水平),土壤和气候数据需要按比例放大或缩小以达到感兴趣的分辨率,这意味着不确定性增加。 造成这种情况的主要原因有两个:1)很难创建和/或获取对高分辨率,地理参考的网格化数据集的访问权限; 和2)最常见的作物建模软件安装是在最终用户的台式机或工作站上,该台式机或工作站通常运行Microsoft Windows的一种受支持版本(系统建模人员倾向于使用工具的GUI功能来准备和运行仿真,这是然后受限于所用硬件的计算能力)。
新西兰有几家皇冠研究所,它们在对国民经济具有重要意义的许多不同领域提供科学研究,包括土地保护研究,国家水与大气研究所(NIWA)以及新西兰植物与食品研究所。 在一个联合项目中,这些组织提供了与该国的土壤,地形,气候和作物模型有关的数据集。 我们希望创建一个分析框架,使用APSIM进行足够的模拟,以覆盖大约25 km 2的整个新西兰范围内有关气候变化问题(> 100年的气候变化数据价值)的相关时间尺度。 我们正在谈论数百万个仿真,每个仿真至少需要10分钟才能在单个CPU内核上完成。 如果我们要使用标准台式机,那么在外面等一下看看会发生什么可能会更快。
输入HPC
高性能计算(HPC)是使用并行处理来高效,可靠和快速地运行程序。 通常,这意味着利用跨多个主机的批处理,每个单独的进程仅处理少量数据,并使用作业调度程序对其进行编排。
幸运的是,作物建模是一个令人尴尬的并行问题:不管有多少数据或有多少变量,每个变化的变量都意味着需要运行一个完整的模拟。 而且由于仿真彼此独立,因此可以运行与CPU数量一样多的仿真。
解决依赖地狱
APSIM是一个复杂的软件。 它的代码库由用多种不同的编程语言编写的模块组成,并且在过去的三十年中紧密集成。 该应用程序通过利用Mono Project框架实现了Windows与GNU / Linux操作系统之间的可移植性,但是在Linux环境中运行该应用程序所需的外部依赖项和变通办法的数量使实现变得不平凡。
构建和安装文档很少,并且确实存在的说明针对的是Ubuntu Desktop版本。 几个必需的依赖项没有记录,并且构建过程有时依赖binfmt_misc内核模块来允许直接执行链接到Mono库的.exe文件(而不是调用mono file.exe ),但是这样做不一致(此后已经固定在上游)。 更令人困惑的是,某些.exe文件是Mono程序集,而某些是本机(libc)二进制文件(这样做是为了避免操作系统平台之间的可执行文件名有所不同)。 最后,Linux构建是由开发人员按需“内部”创建的,但是由于缺乏外部用户的兴趣,因此没有公开可访问的自动化构建。
所有这些都可能在单个组织中进行,但是这使APSIM在其他环境中采用时面临挑战。 HPC集群倾向于在一种Linux发行版(例如Red Hat Enterprise Linux,CentOS,Ubuntu等)和作业调度程序(例如PBS,HTCondor,Torque,SGE,Platform LSF,SLURM等)上实现标准化。存储和网络体系结构,网络配置,用户身份验证和授权策略等。因此,什么软件可用,什么版本以及如何集成是高度特定于环境的。 像OpenHPC这样的项目旨在为这种情况提供一些理智,但现实情况是,大多数HPC集群本质上都是根据组织的需求量身定制的。
解决这些问题的一种简单方法是引入容器化技术。 这不足为奇(毕竟这是本文的标题)。 容器允许创建一个独立的,自给自足的工件 ,该工件可以运行而无需在支持运行它们的任何环境中进行更改。 但是,从“可重现的研究”角度来看,容器还具有其他优势:可以以可重现的方式创建软件容器,一旦创建容器,生成的容器图像既可移植 又不可更改 。
可重现性:按照最佳做法(例如,确保已明确定义安装的软件版本)编写容器定义文件后,可以以确定性方式创建相同的结果容器映像。
可移植性:管理员创建容器映像时,他们可以编译,安装和配置所需的所有软件,并包括运行它们所需的任何外部依赖项或库,一直到堆栈到Linux发行版本身。 在此过程中,除了硬件之外,没有必要将执行环境作为目标。 创建容器映像后,可以将其作为独立工件分发。 这将特定软件的构建和安装阶段与执行该软件时的运行时阶段完全分开。
不变性:构建后,容器映像是不变的。 即,不创建新图像就无法更改其内容并保留它们。
这些属性使您能够捕获处理过程中使用的软件堆栈的确切状态,并将其与原始数据一起分发,以在不同环境中复制分析,即使该环境中使用的Linux发行版与容器映像内部使用的发行版不匹配时也是如此。 。
码头工人
尽管操作系统级虚拟化不是一项新技术,但主要是因为Docker才变得越来越流行。 Docker提供了一种以简单方式开发,部署和运行软件容器的方法。
APSIM容器映像的第一次迭代是在Docker中实现的,复制了开发人员部分记录的构建环境。 这样做是作为有关对应用程序进行容器化和运行的可行性的概念证明。 第二次迭代引入了多阶段构建:一种创建容器映像的方法,该方法允许将构建阶段与安装阶段分开。 这种分离很重要,因为它减小了生成的容器映像的最终大小,该大小将不包括仅在构建期间所需的任何依赖项。 Docker容器并非特别适合多租户HPC环境。 需要考虑三个主要方面:
1.数据所有权
容器映像通常不存储与企业身份验证目录(例如Active Directory,LDAP等)集成所需的配置,因为这会降低可移植性。 取而代之的是,用户信息通常直接在图像中直接进行硬编码(如果没有,默认情况下使用root )。 当容器启动时,所包含的进程将以此硬编码身份运行(请记住,默认情况下使用root )。 结果是由容器化过程创建的输出数据归用户所有,而该用户可能仅存在于容器映像中。 不是由启动容器的用户(也有,我提到默认情况下使用root吗?)。
解决此问题的可能方法是在容器启动时覆盖运行时用户(使用docker run -u…标志)。 但这给用户带来了更多的复杂性,他们现在必须了解用户身份(UID),POSIX所有权和权限, docker run命令的正确语法以及找到其UID,组标识符(GID)的正确值。 ,以及他们可能需要的任何其他组。 所有这些对于只想完成一些科学工作的人而言。
还值得注意的是,这种方法并非每次都有效。 并非所有应用程序都乐于以任意用户或系统数据库中不存在的用户身份运行(例如/ etc / passwd文件)。 这些是极端情况,但它们存在。
2.访问持久性存储
容器映像仅包含应用程序运行所需的文件。 它们通常不包括应用程序要处理的输入或原始数据。 默认情况下,当实例化容器映像时(即,启动容器时),呈现给容器化应用程序的文件系统将仅显示容器映像中存在的那些文件和目录。 要访问输入或原始数据,最终用户必须将所需的安装点从主机服务器显式映射到容器中文件系统内的路径(通常使用绑定 安装 )。 使用Docker,无法在全局范围内预先配置这些“卷挂载”,并且在启动容器时必须在每个容器的基础上进行映射。 这不仅增加了运行应用程序所需命令的复杂性,而且还带来了另一个不良后果……
3.计算主机安全性
以任意用户身份启动进程的能力以及将任意文件或目录从主机服务器映射到正在运行的容器的文件系统的能力是Docker提供给操作员的几项强大功能中的两项。 但这是可行的,因为在Docker采用的安全模型中 ,运行容器的守护程序必须在具有root特权的主机上启动。 结果,有权访问Docker守护程序的最终用户最终具有对主机的根访问权限。 由于它违反了“最小特权原则”,因此引入了安全问题。 恶意行为者可以执行超出其初始授权范围的操作,但是即使没有恶意,最终用户也可能无意中破坏或破坏了数据。
解决此问题的可能方法是实现用户名称空间 。 但是在实践中,这些维护很麻烦,尤其是在用户身份集中在企业目录中的公司环境中。
奇点
为了解决这些问题,使用奇点实现了APSIM容器的第三次迭代。 Singularity社区于2016年发布,是一个专门针对科学和HPC环境设计的开源容器平台。 “ Singularity容器内的用户与容器外的用户相同 ”是Singularity的定义特征之一。 它允许最终用户以他或她自己的身份在容器映像内部运行命令。 相反,它不允许在启动容器时模拟其他用户。
奇点方法的另一个优点是容器映像在磁盘上的存储方式。 使用Docker,容器映像存储在多个单独的“层”中,Docker守护进程需要在容器运行时对其进行覆盖和展平。 当多个容器映像重用同一层时,仅需要该层的一个副本即可重新创建运行时容器的文件系统。 这样可以更有效地利用存储,但是在分发和检查容器映像时确实增加了一些复杂性,因此Docker提供了特殊的命令来执行此操作。 使用奇点功能,整个执行环境都包含在单个可执行文件中。 当多个图像具有相似的内容时,这会引入重复,但是由于现在可以使用传统的文件传输方法,协议和工具来完成这些图像的分配,因此它变得微不足道。
Docker容器配方文件(即Dockerfile和相关资产)可用于重新创建为项目构建的容器映像。 奇异性允许本地导入和运行Docker容器,因此相同的文件可用于两个引擎。
生活中的一天
为了用一个实际的例子来说明上面的内容,让我们来看看计算科学家。 因此,不要特别挑剔任何人,请想象您想使用ToolA,它可以处理输入文件并创建带有有关它们的统计信息的输出。 在要求系统管理员帮助之前,您决定在本地桌面上测试该工具以查看是否有效。
ToolA具有简单的语法。 它是一个二进制文件,它使用一个或多个文件名作为命令行参数,并接受-o {json | yaml}标志来更改结果的格式。 输出存储在与输入文件相同的路径中。 例如:
$ ./ToolA file1 file2
$ ls
file1 file1.out file2 file2.out ToolA
您有数千个文件要处理,但是即使ToolA使用多线程独立地处理文件,该计算机上也没有一千个CPU内核。 您必须使用群集的作业计划程序。 大规模执行此操作的最简单方法是,启动每个作业所需的文件数量,每个作业使用一个CPU线程。 您测试新方法:
$ export PATH=$(pwd):${PATH}
$ cd ~/input/files/to/process/samples
$ ls -l | wc -l
38
$ # we will set this to the actual qsub command when we run in the cluster
$ qsub=""
$ for myfiles in *; do $qsub ToolA $myfiles; done
...
$ ls -l | wc -l
75
优秀的。 是时候对sysadmin进行调试并在集群中安装ToolA了。
事实证明,ToolA很容易在Ubuntu Bionic中安装,因为它已经在存储库中,但是在我们的HPC集群使用的CentOS 7中进行编译是一场噩梦。 因此,系统管理员决定创建一个Docker容器映像并将其推送到公司的注册表。 在恳求您不要行为不端后,他还将您添加到docker组中。
您查找Docker命令的语法,并决定在提交可能潜在失败的数千个作业之前进行几次测试运行。
$ cd ~/input/files/to/process/samples
$ rm -f *.out
$ ls -l | wc -l
38
$ docker run -d registry.example.com/ToolA:latest file1
e61d12292d69556eabe2a44c16cbd27486b2527e2ce4f95438e504afb7b02810
$ ls -l | wc -l
38
$ ls *out
$
啊,当然,您忘记了挂载文件。 让我们再试一次。
$ docker run -d -v $(pwd):/mnt registry.example.com/ToolA:latest /mnt/file1
653e785339099e374b57ae3dac5996a98e5e4f393ee0e4adbb795a3935060acb
$ ls -l | wc -l
38
$ ls *out
$
$ docker logs 653e785339
ToolA: /mnt/file1: Permission denied
您向系统管理员寻求帮助,他告诉您SELinux正在阻止进程访问文件,并且您在docker run中缺少标志。 您不知道SELinux是什么,但是您记得它在文档中的某个地方提到过,因此您可以查找并重试:
$ docker run -d -v $(pwd):/mnt:z registry.example.com/ToolA:latest /mnt/file1
8ebfcbcb31bea0696e0a7c38881ae7ea95fa501519c9623e1846d8185972dc3b
$ ls *out
$
$ docker logs 8ebfcbcb31
ToolA: /mnt/file1: Permission denied
您回到sysadmin,他告诉您默认情况下容器使用myuser的UID 1000,但是您的文件只能由您读取,并且您的UID是不同的。 因此,您执行了您所知道的不好的做法,但是您受够了:在再次尝试之前运行chmod 777 file1 。 您也已经厌倦了必须复制和粘贴哈希值,因此在docker run中添加了另一个标志:
$ docker run -d --name=test -v $(pwd):/mnt:z registry.example.com/ToolA:latest /mnt/file1
0b61185ef4a78dce988bb30d87e86fafd1a7bbfb2d5aea2b6a583d7ffbceca16
$ ls *out
$
$ docker logs test
ToolA: cannot create regular file '/mnt/file1.out': Permission denied
las,至少这次您会遇到其他错误。 进展! 友好的系统管理员会告诉您,由于身份不匹配,容器中的进程将对目录没有写权限,并且您在命令行上需要更多标志。
$ docker run -d -u $(id -u):$(id -g) --name=test -v $(pwd):/mnt:z registry.example.com/ToolA:latest /mnt/file1
docker: Error response from daemon: Conflict. The container name "/test" is already in use by container "0b61185ef4a78dce988bb30d87e86fafd1a7bbfb2d5aea2b6a583d7ffbceca16". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.
$ docker rm test
$ docker run -d -u $(id -u):$(id -g) --name=test -v $(pwd):/mnt:z registry.example.com/ToolA:latest /mnt/file1
06d5b3d52e1167cde50c2e704d3190ba4b03f6854672cd3ca91043ad23c1fe09
$ ls *out
file1.out
$
成功! 现在,我们只需要将作业调度程序使用的命令包装起来,然后再用for循环包装所有命令即可。
$ cd ~/input/files/to/process
$ ls -l | wc -l
934752984
$ for myfiles in *; do qsub -q short_jobs -N "toola_${myfiles}" docker run -d -u $(id -u):$(id -g) --name="toola_${myfiles}" -v $(pwd):/mnt:z registry.example.com/ToolA:latest /mnt/${myfiles}; done
现在有点笨拙,不是吗? 让我们看一下如何使用奇点简化它。
$ cd ~
$ singularity pull --name ToolA.simg docker://registry.example.com/ToolA:latest
$ ls
input ToolA.simg
$ ./ToolA.simg
Usage: ToolA [-o {json|yaml}] <file1> [file2...fileN]
$ cd ~/input/files/to/process
$ for myfiles in *; do qsub -q short_jobs -N "toola_${myfiles}" ~/ToolA.simg ${myfiles}; done
需要我多说?
之所以可以这样做,是因为默认情况下,奇点容器以启动它们的用户身份运行。 没有后台守护程序,因此不允许特权升级。 默认情况下,奇点还绑定绑定了一些目录( $ PWD , $ HOME , / tmp , / proc , / sys和/ dev )。 管理员可以配置其他默认情况下也在全局(即主机)基础上安装的其他程序,最终用户也可以(可选)在运行时绑定任意程序。 当然,标准的Unix权限适用,因此仍然不允许无限制地访问主机文件。
但是气候变化呢?
哦! 当然。 回到正题。 我们决定分解每个项目需要运行的大量仿真。 然后,每个项目都可以专注于特定的作物,特定的地理区域或不同的作物管理技术。 完成特定项目的所有模拟后,将它们整理到MariaDB数据库中,并使用RStudio Shiny Web应用程序进行可视化。
![原型闪亮应用截图 Prototype Shiny app screenshot](https://i-blog.csdnimg.cn/blog_migrate/23b123f7b442bc1c0b1e4ee1ab9e57b9.png)
原型“闪亮”应用程序的屏幕快照显示了气候变化在全国范围内对玉米青贮饲料的影响,并比较了当前和本世纪末的情景。
该应用程序允许我们比较用户可以通过从与气候相关的变量(包括当前气候和本世纪中叶及末期的气候变化预测)组合中进行选择来构建的两种不同场景(参考与替代)世纪),土壤和特定的管理技术(例如灌溉或肥料使用)。 结果显示为栅格值或差异(平均值或每个像素的结果变化系数)及其在整个关注区域中的分布。
上面的屏幕截图显示了在“耕地”上在全国范围内运行的原型的示例,在该示例中,我们比较了最极端排放情景下的青贮玉米生物量的基准值(1985-2005)与未来的气候变化(2085-2100)。 在此示例中,我们不考虑管理技术的任何变化,例如调整播种日期。 我们看到,对南半球产量的最大负面影响发生在北部地区,而最南端则显示出积极的React。 当然,我们会建议(并且您会期望)农民从一年开始就开始适应温暖的温度,并做出相应的React(例如,较早播种,这将减少负面影响并增强正面影响)。
下一步
有了框架,剩下的就是繁重的工作。 运行所有模拟! 当然,这说起来容易做起来难。 我们的内部集群是共享资源,我们必须在其中与其他几个项目和团队竞争能力。
计划进行其他工作以进一步概括我们如何在计算资源之间分配作业,以便我们可以在任何可获得的地方利用容量(如果项目获得足够的额外资金,则包括公共云)。 这将意味着与作业调度程序无关,并解决数据严重性问题。
还在进一步完善Web应用程序的UI和UX方面的工作,直到我们感到可以将其发布给决策者和其他有关方面为止。
如果您从科学的角度对我们的工作感兴趣,请与我联系 ,我将与您联系项目负责人。 对于所有其他查询,您也可以与我联系,我将尽力为您提供帮助。
EricBurgueño将于1月21日至25日在新西兰基督城的linux.conf.au 上展示“ 使用容器分析气候变化和土壤对新西兰农作物的影响” 。
翻译自: https://opensource.com/article/19/1/using-containers-analyze-climate-change
新西兰.net和java