【问题标题】:Running MPI programs with sudo permission on cluster在集群上运行具有 sudo 权限的 MPI 程序
【发布时间】:2019-11-18 11:21:30
【问题描述】:

我正在开发小型 Raspberry PI 集群,我的主机程序创建 IP 数据包片段并将它们发送到多个中继程序。中继接收这些数据包片段并使用原始套接字将它们转发到目的地。由于原始套接字,我的中继程序必须在 sudo 权限下运行。我的设置涉及 RPi 3 B v2 和 RPi 2 B v1。 SSH 已经设置好了,节点可以在没有密码的情况下通过 SSH 登录,尽管我必须在每个节点上运行 ssh-agent 和 ssh-add 我的密钥。我已经设法运行从一个节点向另一个节点发送等级的程序(2 个不同的 RPis)。我以 MPMD 方式运行 MPI 程序,因为我只有 2 个 RPis 我在节点 #1 上运行主机和中继,并在节点 #2 上中继。主机程序将文件路径作为命令行参数发送。

如果我跑:

mpirun --oversubscribe -n 1 --host localhost /home/pi/Desktop/host /some.jpeg : -n 2 --host localhost,rpi2 /home/pi/Desktop/relay

它运行了,但显然程序失败了,因为没有 sudo 权限,中继无法打开原始套接字。

如果我跑:

mpirun --oversubscribe -n 1 --host localhost /home/pi/Desktop/host /some.jpeg : -n 2 --host localhost,rpi2 sudo /home/pi/Desktop/relay

relays 报告世界大小:1 并且主机程序挂起。

如果我跑:

mpirun --oversubscribe -n 1 --host localhost sudo /home/pi/Desktop/host /some.jpeg : -n 2 --host localhost,rpi2 sudo /home/pi/Desktop/relay

所有中继和主机报告世界大小为 1。

我在这里发现了类似的问题:OpenMPI / mpirun or mpiexec with sudo permission

按照我运行的简短回答:

mpirun --oversubscribe -n 1 --host localhost /home/pi/Desktop/host /some.jpeg : -n 2 --host localhost,rpi2  sudo -E /home/pi/Desktop/relay

导致:

[raspberrypi:00979] OPAL ERROR: Unreachable in file ext2x_client.c at line 109
[raspberrypi:00980] OPAL ERROR: Unreachable in file ext2x_client.c at line 109
*** An error occurred in MPI_Init
*** An error occurred in MPI_Init
*** on a NULL communicator
*** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
***    and potentially your MPI job)
[raspberrypi:00979] Local abort before MPI_INIT completed completed successfully, but am not able to aggregate error messages, and not able to guarantee that all other processes were killed!
*** on a NULL communicator
*** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
***    and potentially your MPI job)
[raspberrypi:00980] Local abort before MPI_INIT completed completed successfully, but am not able to aggregate error messages, and not able to guarantee that all other processes were killed!
--------------------------------------------------------------------------
Primary job  terminated normally, but 1 process returned
a non-zero exit code. Per user-direction, the job has been aborted.
--------------------------------------------------------------------------
--------------------------------------------------------------------------
mpirun detected that one or more processes exited with non-zero status, thus causing
the job to be terminated. The first process to do so was:

  Process name: [[32582,1],1]
  Exit code:    1
--------------------------------------------------------------------------

我已经运行了 sudo visudo 并且我在两个节点上的文件看起来像这样:

# User privilege specification
root    ALL=(ALL:ALL) ALL
pi      ALL = NOPASSWD:SETENV:  /etc/alternatives/mpirun
pi      ALL=NOPASSWD:SETENV:    /usr/bin/orterun
pi      ALL=NOPASSWD:SETENV:    /usr/bin/mpirun

当我在一个节点上运行所有东西时,它就可以工作:

sudo mpirun --alow-run-as-root --oversubscribe -n 1 --host localhost /home/pi/Desktop/host /some.jpeg : -n 2 --host localhost,localhost /home/pi/Desktop/relay //主机

int main(int argc, char *argv[]) {
    MPI_Init(&argc, &argv);

    int world_size = []() {
        int size;
        MPI_Comm_size(MPI_COMM_WORLD, &size);
        return size;
    }();

    int id = []() {
        int id;
        MPI_Comm_rank(MPI_COMM_WORLD, &id);
        return id;
    }();

    if (argc != 2) {
        std::cerr << "Filepath not passed\n";
        MPI_Finalize();
        return 0;
    }

    const std::filesystem::path filepath(argv[1]);
    if (not std::filesystem::exists(filepath)) {
        std::cerr << "File doesn't exist\n";
        MPI_Finalize();
        return 0;
    }

    std::cout << "World size: " << world_size << '\n';

    MPI_Finalize();
    return 0;
}

//relay
int main(int argc, char *argv[]) {
    MPI_Init(&argc, &argv);

    int world_size = []() {
        int size;
        MPI_Comm_size(MPI_COMM_WORLD, &size);
        return size;
    }();

    int id = []() {
        int id;
        MPI_Comm_rank(MPI_COMM_WORLD, &id);
        return id;
    }();

    std::cout << "World size: " << world_size << '\n';

    MPI_Finalize();
    return 0;
}

如何配置节点以允许它们使用 sudo 运行 MPI 程序?

【问题讨论】:

  • 如果您sudo mpirun --alow-run-as-root 有多个主机怎么办?请注意,您必须能够以 root 身份进行无密码 ssh(例如 sudo ssh remotehost hostname 应该可以正常工作)。您也可以考虑将suid 位设置为您的二进制文件并在没有sudo 的情况下运行它(注意安全隐患),或者甚至使用为您创建原始套接字的助手。
  • 如果我运行sudo mpirun --alow-run-as-root,一切都会挂起。我尝试设置中继程序的 suid,sudo -ichmod u+s relay_program 并在一个节点上运行它们,但它仍然无法打开。我不知道如何配置对 root 的无密码 ssh 访问。助手是什么意思?
  • 从您的用户帐户运行所有内容,在MPI_Init() 之前您可以fork&amp;exec sudo helper。 helper 的目的是创建原始套接字,然后通过 fd 传递将它们传递给 MPI 程序。另一种选择是让您的 MPI 应用程序 setuid 由 root 拥有,在 MPI_Init() 之前为用户创建原始套接字和 setuid,然后从您的用户帐户中运行 mpirun。
  • 我做了一个小程序,它创建原始套接字然后初始化 MPI pastebin.com/RRTX9kzr。然后sudo -i 并用mpic++ 编译程序,用chmod u+s a.out 更改suid,使其成为root 拥有并在执行-rwsr-xr-x 1 root root 36316 lip 9 23:28 a.out 时具有sudo 权限。当我像普通程序./a.out 一样简单地运行它时,它可以工作,但是当我使用mpirun -n 1 /home/pi/Desktop/a.out 运行它时,它会因错误pastebin.com/x2Q8iGvH 而崩溃。如果我使用--allow-run-as-root 运行它,它会挂起,我错过了什么?
  • 好吧,我错过了将uid设置回用户的事情,基本上我所做的是用mpic++编译程序,sudo -i,然后用chown 0:0 a.out将所有者更改为root,并将suid设置为root chmod u+s a.out。在两个节点上重复它并以mpirun -n 2 --host localhost, rpi1 /home/pi/Desktop/a.out 的用户身份运行 MPI 程序,一切正常。在代码中,我使用 setreuid(geteuid(), getuid()); 在 MPI_Init 之前更改了 uid。这是一个很好的解决方案,我很高兴我可以进一步开发和测试我的应用程序!虽然我必须在它准备好用于商业用途之前正确解决问题。

标签: linux sockets raspberry-pi mpi openmpi


【解决方案1】:

解决这个问题最简单的方法是设置文件的能力,它仍然存在安全问题,但没有将程序的suid设置为root那么严重。设置程序允许打开原始套接字的功能:setcap program cap_net_raw,cap_net_admin+eip.

【讨论】:

    猜你喜欢
    • 2018-09-28
    • 2017-01-09
    • 2015-10-09
    • 2020-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2015-09-24
    相关资源
    最近更新 更多