在 Ubuntu 上安装 SLURM 集群资源管理器

SLURM 是一个类似 Sun Grid Engine (SGE) 的开源分布式资源管理软件,用于超级计算机和大型计算节点集群,可高度伸缩和容错。SUN 被卖给 Oracle 后,好用的 SGE 变成 Oracle Grid Engine 并且从 6.2u6 版本开始成为商业软件了(可以免费使用90天),所以我们不得不另寻其他的开源替代方案,SLURM 是上次在德班高性能会议的时候一位陌生人介绍的,听上去不错。

SLURM 通过一对冗余集群控制节点(冗余是可选的)来管理集群计算节点,是由一个名为 slurmctld 的管理守护程序实现的,slurmctld 提供了对计算资源的监视、分配和管理,并将进入的作业序列映射和分发到各个计算节点上。每个计算节点也有一个守护程序 slurmd,slurmd 管理在其上运行的节点,监视节点上运行的任务、接受来自控制节点的请求和工作、将工作映射到节点内部等等。图示如下:

slurm architecture

官方网站提供的 Super Quick Start 安装文档一点都不 quick,看了头大。以下步骤使用两台服务器演示:主机名为 slurm00 的服务器用作控制节点;主机名为 slurm01 的服务器用作计算节点。

在控制节点和计算结点分别安装 slurm 包,这个包里面既含有控制节点需要的 slurmctld 也含有计算结点需要的 slurmd:

# apt-get install slurm-llnl

控制节点和计算结点之间需要通信,通信就需要认证,slurm 支持两种认证方式:Brent Chun’s 的 authd 和 LLNL 的 MUNGE,MUNGE 是专为高性能集群计算打造的,这里我们选用 MUNGE,生成 key 后启动 munge 认证服务:

# /usr/sbin/create-munge-key
Generating a pseudo-random key using /dev/urandom completed.

# /etc/init.d/munge start

使用 SLURM Version 2.3 Configuration Tool 在线配置工具生成配置文件,然后把配置文件拷贝控制节点以及各个计算结点的 /etc/slurm-llnl/slurm.conf(是的,控制节点和计算结点使用同一个配置文件)。

有了配置文件和启动了 munge 服务后就可以在控制节点启动 slurmctld 服务了:

# /etc/init.d/slurm-llnl start
 * Starting slurm central management daemon slurmctld                             [ OK ]

把控制节点生成的 munge.key 拷贝到各个计算结点:

# scp /etc/munge/munge.key ubuntu@slurm01:/etc/munge/

登陆计算节点后启动 munge 服务(注意需要改变 munge.key 的 owner 和 group 为 munge,否则会启动失败)和 slurmd 服务:

# ssh ubuntu@slurm01

# chown munge:munge munge.key 
# /etc/init.d/munge start
 * Starting MUNGE munged                                                           [ OK ]

# slurmd

在控制节点上(slurm00)测试一下是否顺利连接到计算结点(slurm01),并且简单运行一个程序 /bin/hostname 看看效果吧:

# sinfo 
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
debug*       up   infinite      1   idle slurm01

# srun -N1 /bin/hostname 
slurm01

SGE 运行在 OpenStack 上的 HOST_NOT_RESOLVABLE 问题

4月份在介绍《安装 Sun Grid Engine》的时候曾经提过我们希望能在云计算平台上快速创建多个高配置虚拟机并自动接入到我们的 SGE (Sun Grid Engine) 集群,这样能迅速满足整个实验室计算高峰需求。

我们现在已经把 OpenStack 整合到了高性能集群生产环境,每台物理服务器上配置成一个 OpenStack Compute 计算节点(nova-compute),每个 Compute 节点上运行一个虚拟机,每个虚拟机配置成一个 SGE 运算节点(sge_execd)。为啥不直接在物理服务器上配置成 SGE 运算节点?因为运行在虚拟机上更方便、更灵活,可以随时迅速关闭、重装、更换、启动系统。这也是云计算、虚拟机的巨大优势,不用去机房捣腾硬件、不用刻盘重装系统,省时省力。

在 OpenStack 的一个实例上(Ubuntu)安装完 SGE 执行结点(hostname 是 grid62),手动启动守护进程(sge_execd)的时候报错:

$ ssh root@grid62

# /etc/init.d/gridengine-exec restart
 * Restarting Sun Grid Engine Execution Daemon sge_execd
error: communication error for "grid62.novalocal/execd/1" running on port 6445: "can't bind socket"
error: commlib error: can't bind socket (no additional information available)

到主控节点(hostname 是 grid00)上查看日志发现原因 grid62.novalocal 这个域名不能解析:

$ ssh root@grid00

# cat /var/spool/gridengine/qmaster/messages | grep grid62
...
08/26/2012 12:14:15|listen|grid00|E|commlib error: can't resolve host name (can't resolve rdata hostname "grid62.novalocal")
08/26/2012 12:14:16|listen|grid00|E|commlib error: local host name error (remote rdata host name "grid62.novalocal" is not equal to local resolved host name "(HOST_NOT_RESOLVABLE)")

进一步调查发现 grid62.novalocal 这个名字我们的 Puppet 服务器在 OpenStack 启动虚拟机实例后注射到虚拟机 /etc/hosts 里面的(我们的 SGE 节点由 Puppet 管理),Puppet 得到这个 grid62.novalocal 名字而不是 grid62.vpsee.com 这样真实的域名和 OpenStack 自己的 DNS 管理有关,这个问题从 Puppet 或 OpenStack dnsmasq 方面入手都可以解决,不过最简单的方法是从虚拟机实例入手。

解决办法是在 grid62 这个虚拟机实例的 /etc/hosts 文件里加上 grid62 一行,然后 kill 掉现有的 sge_execd 进程并重新启动 gridengine-exec (sge_execd):

# vi /etc/hosts
127.0.0.1	localhost.localdomain	localhost
192.168.2.62	grid62.vpsee.com	grid62

# killall sge_execd

# /etc/init.d/gridengine-exec start

在 Ubuntu 11.10 上安装 Sun Grid Engine

Sun Grid Engine(现在叫做 Oracle Gird Engine)是一套开源的分布式资源管理软件,用来统一管理和利用所有(愿意被管理的)电脑上的资源,使得这些电脑(集群)使用起来就像一台电脑一样,好处是可以随意扩展总的计算资源(买更多的电脑加入集群),并且管理上就像使用一台电脑一样方便。使用者只需要把需要计算的工作准备好,提交到 Sun Grid Engine (SGE),SGE 就会根据已经订好的管理策略以及使用者的需求在集群里找到合适的电脑来完成计算工作。SGE 主要用在高性能计算、网格计算等领域。

我们云计算项目里面有个想法就是能在我们的云计算平台上快速创建多个高配置虚拟机并自动接入到 SGE 集群,能迅速满足整个实验室高峰时期的计算需求。目前我们的 SGE 集群包含 2 台 IBM 超级计算机,n 台 PC 服务器和多个刀片服务器,以后为了临时满足高峰时期的计算要求会从云里申请多个虚拟机并自动配置到 SGE 集群里。

安装 Sun Grid Engine 需要 Java 的支持(最好是 SUN 的 Java 版本),所以所有结点都需要安装 Java 包。Ubuntu 从 11.10 版本不在提供 SUN 的官方 Java 版本,需要另外的源:

$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:ferramroberto/java
$ sudo apt-get update
$ sudo apt-get install sun-java6-jre

首先在所有结点上修改 /etc/hosts,grid00 是主控结点,grid01 和 grid02 是执行结点(我们一般把主控结点叫做 master 或者 head,执行结点叫做 client):

$sudo vi /etc/hosts
127.0.0.1	localhost.localdomain	localhost
192.168.2.10	grid00.vpsee.com	grid00
192.168.2.11	grid01.vpsee.com	grid01
192.168.2.12	grid02.vpsee.com	grid02

在主控结点(grid00)上安装 gridengine-master 以及一些管理工具 qhost/qconf/qstat 等(包含在 gridengine-client 中):

$ sudo apt-get install gridengine-client gridengine-common gridengine-master

如果不习惯命令行界面,可以在主控结点上装个 qmon 图形管理工具,界面如下:

$ sudo apt-get install xserver-xorg gridengine-qmon

sun grid engine qmon guy

在所有执行结点(grid01 和 grid02)上安装 gridengine-exec:

$ sudo apt-get install gridengine-exec

在主控结点上执行以下操作把所有的执行结点加到集群里:

$ sudo -i

# qconf -ah grid01
# qconf -ah grid02

在所有执行结点执行以下操作,通过 act_qmaster 这个文件识别主控结点,然后启动服务:

$ sudo echo "grid00.vpsee.com" > /var/lib/gridengine/default/common/act_qmaster

$ sudo /etc/init.d/gridengine-exec start

最后在主控结点上查看一下是否成功:

# qhost
HOSTNAME                ARCH         NCPU  LOAD  MEMTOT  MEMUSE  SWAPTO  SWAPUS
-------------------------------------------------------------------------------
global                  -               -     -       -       -       -       -
grid00.vpsee.com        -               -     -       -       -       -       -
grid01.vpsee.com        lx26-amd64     24 24.00   63.0G    1.7G    3.7G     0.0
grid02.vpsee.com        lx26-amd64      8  0.01   55.2G  642.2M    1.0G     0.0

测试

如何知道这个集群是否能正常工作呢?提交一个任务(job)测试一下。在主控结点上写一个简单脚本打印当前 Linux 内核版本:

# vi uname.sge 
#!/bin/bash
uname -a

然后用 qsub 提交这个脚本到 SGE 集群:

# vi uname.sge 
#!/bin/bash
uname -a

# qsub uname.sge
qsub uname.sge 
Your job 3557 ("uname.sge") has been submitted

如果运行成功就会在某个执行结点的自己目录下面(我这里用的是 root 帐号,所以是 /root 目录)得到2个文件,执行结果就在 uname.sge.o3557 这个文件里:

# ls
uname.sge.e3557  uname.sge.o3557

# cat uname.sge.o3557 
Linux grid02 3.0.0-16-server #29-Ubuntu SMP Tue Feb 14 13:08:12 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux