HPC 系列文章(14):账务系统(Account)

经过前面的内容,大家应该对于Slurm最基本的功能使用有了认识。不过对于在生产环境中集群多用户使用作业调度系统,其实还没有深入了解。例如集群环境下如何统一作业运行时的用户权限?Slurm的资源限制究竟是如何实现的?如何为不同的用户配置不同的资源限制策略?如何得到集群资源使用情况的数据报表等等。下面我们就介绍这部分内容,先从Slurm的账务系统(accounting)说起。

账务统计

当我们将集群资源开放给多个用户使用时,肯定希望能为不同的用户设定不同的资源使用策略,并且希望知道整个集群的使用率以及作业的各种历史数据等等,也就是说我们希望通过查询历史记录来统计分析这些信息,既然要查询历史记录,那我们就应该有地方做数据存储,这就是Slurm的Accounting系统负责的工作。

状态临时存储

在介绍Accounting之前,我们先回顾一下作业查询并说一下它们的区别。之前介绍过用squeuescontrol show job的方式查询作业,不过你可能会发现这些命令所查询到的作业,并不是历史作业,而是正在运行和刚运行完不久的作业。这似乎也很好理解,毕竟如果通过这样的方式查询到的是所有的历史作业的话,一个包含大量作业的多用户系统光是查询作业就可能把服务拖垮了。不过更为关键的是,这样的查询方式实际上并不是从Accounting系统中所查询出来的,而是保存在slurm的临时文件中的。打开slurm.conf配置文件,其中有一个StateSaveLocation的配置项(默认值是/tmp),它指定了Slurmctld工作时存储状态的临时文件路径。

tmp-files

去到这个目录下,你会看到很多由slurm所创建的文件,这些文件对于Slurm而言至关重要,包括job_state,node_state等等,他们存储了当前的各种状态。Slurmctld会不断更新这些文件,当机器意外重启后,也会根据这些文件来恢复工作。我们通过squeuescontrol show job查询到的作业就是对加载到内存中的这个文件的解析。因为需要被加载到内存中,Slurm通过以下两种方式防止内存被耗尽:

  1. Slurm不允许无限制的提交作业,MaxJobCount限制了系统中允许运行的最大作业量。
  2. Slurm并不会无限期对存储作业状态,而是会定期清理掉已经结束运行的作业(包括错误退出以及正常退出的作业),通过MinJobAge限制作业完成后最大存留时长(默认为5分钟后清理)

了解这些内容有助于你更好的了解Slurm的工作原理,不过这并不是我们所希望的持久化的数据记录。

扩展(如何快速删除大量的作业)

因为上述状态文件记录了各种数据,所以通常情况下是不允许删除和修改的,随意修改和删除可能会导致数据丢失。不过如果你不小心写错了脚本往系统中提交了数以万计的作业,想快速删除掉这些作业,就可以利用删除文件的方式快速清除掉这些作业。

Slurm本身提供了scancel -u $uid的方式批量删除某个用户提交的所有作业,但是这对于超大规模的作业来说并不好使。Slurm的作业取消中有一个比较特殊的逻辑,我们可以看一段儿源码:

source

简单阅读代码可知,为了防止RPC DOS攻击,当系统中大量取消作业时,会自动以斐波那契规律递增一个延迟,直到这个时间变成一秒。简单的说就是如果你删除大量的作业,系统会自动将请求速度降低到1秒钟一个,如果你不小心通过特殊的脚本提交了太多的作业,这个删除效率依然是比较低的。此时更加方便的方式是将slurmctld服务停止,然后删除job_state文件再重启服务。这样就可以快速的删掉所有的作业了。

持久化存储

文件存储

持久化存储才是我们要讨论的主题,Slurm可以将作业信息收集存储到文件或者数据库中。最简单的是存放到文件中,你只需要配置AccountingStorageType=accounting_storage/filetxt或者 JobCompType=jobcomp/filetxt并指定存储路径AccountingStorageLoc或者JobCompLoc,不过这并不是最理想的方式,你需要自行rotate文件,并且它使得Slurm作业无法与账户信息相关联。

数据库存储

利用slurmdbd将数据存储到数据库则是更有吸引力的方案。

数据库部署

首先我们需要安装数据库(Mysql或者Mariadb),这一步很简单就不赘述了。不过你需要适当的做一些优化,尤其是对于作业规模稍大的集群。主要有以下几点:

  • 使用InnoDB引擎
  • 适当增大innodb_buffer_pool_size
  • 建议将innodb_lock_wait_timeout和innodb_log_file_size设置为大于默认值的值

示例配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| innodb_buffer_pool_size | 134217728 |
+-------------------------+-----------+
1 row in set (0.00 sec)

$cat my.cnf
...
[mysqld]
innodb_buffer_pool_size=1024M
innodb_log_file_size=64M
innodb_lock_wait_timeout=900
...
slurmdbd服务部署

slurmdbd是一个独立的服务,你需要单独安装它,它也可以独立部署在一台不包含其他slurm守护进程的服务器上,数据库也可以部署到任意服务器。直接使用rpm安装即可,然后你需要修改一下slurm配置以启用slurmdbd进行统计(为了方便,这里我给出的是比较基本的配置并且给出建议值):

  • AccountingStorageType: 设置为”accounting_storage/slurmdbd”.
  • AccountingStorageEnforce:限制条件,以逗号分隔,可用的值包括:associations,limits,nojobs,nosteps,qos,safe,wckeys等,具体内容我们后面再详细讲解,可以参考一下slurm文档
  • AccountingStorageHost: Slurmdbd服务地址,如果部署在本地可以直接写localhost
  • AccountingStoragePort: Slurmdbd服务端口号,默认6819
  • ClusterName:集群名称,因为支持多集群,所以要为每个集群配置一个名称

然后需要配置一下slurmdbd.conf,这里我给出一个基本配置文件,具体项的意思可以直接查文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#
# Example slurmdbd.conf file.
#
# See the slurmdbd.conf man page for more information.
#
# Archive info
#ArchiveJobs=yes
#ArchiveDir="/tmp"
#ArchiveSteps=yes
#ArchiveScript=
#JobPurge=12
#StepPurge=1
#
# Authentication info
AuthType=auth/munge
#AuthInfo=/var/run/munge/munge.socket.2
#
# slurmDBD info
DbdAddr=localhost
DbdHost=localhost
#DbdPort=7031
SlurmUser=slurm
#MessageTimeout=300
DebugLevel=4
#DefaultQOS=normal,standby
LogFile=/var/log/slurm/slurmdbd.log
PidFile=/var/run/slurmdbd.pid
#PluginDir=/usr/lib/slurm
#PrivateData=accounts,users,usage,jobs
#TrackWCKey=yes
#
# Database info
StorageType=accounting_storage/mysql
StorageHost=localhost
#StoragePort=1234
#StoragePass=some_pass
StoragePass=slurm
StorageUser=slurm
StorageLoc=slurm_acct_db

启动mysql、slurmdbd,并重启slurmctld,各服务正常则说明配置完成了。后面我们再介绍具体的概念和使用方式。

坚持原创技术分享,您的支持将鼓励我继续创作!