Запуск программ MPI с разрешением sudo в кластере

Я работаю над небольшим кластером Raspberry PI, моя хост-программа создает фрагменты IP-пакетов и отправляет их нескольким программам-ретрансляторам. Ретрансляторы получают эти фрагменты пакетов и пересылают их к месту назначения, используя необработанные сокеты. Из-за необработанных сокетов мои программы-ретрансляторы должны запускаться с разрешением sudo. Моя установка включает RPi 3 B v2 и RPi 2 B v1. SSH уже настроен, узлы могут подключаться по SSH без пароля, хотя я должен запустить ssh-agent и ssh-add свои ключи на каждом узле. Мне удалось запустить программу, отправляющую ранг с одного узла на другой (2 разных RPis). Я запускаю программы MPI в формате MPMD, поскольку у меня есть только 2 RP, я запускаю хост и ретрансляцию на узле №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

ретрансляторы сообщают о размере мира: 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 или mpiexec с разрешением sudo

После короткого ответа я бегу:

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;
}

Как настроить узлы, чтобы они могли запускать программы MPI с помощью sudo?

что, если вы sudo mpirun --alow-run-as-root с несколькими хостами? обратите внимание, что вы должны иметь возможность использовать ssh без пароля от имени пользователя root (например, sudo ssh remotehost hostname должен работать). вы также можете подумать о том, чтобы установить бит suid в свой двоичный файл и запустить его без sudo (помните о последствиях для безопасности) или даже использовать помощника, который создает необработанные сокеты для вас.

Gilles Gouaillardet 09.07.2019 02:30

Если запустить sudo mpirun --alow-run-as-root все зависает. Я пытался установить suids релейных программ, sudo -i, chmod u+s relay_program и запустить их на одном узле, но он все равно не открывается. Я не могу разобраться с настройкой беспарольного доступа ssh к root. Что вы имеете в виду под помощником?

Hana0xAF 09.07.2019 23:28

Запускайте все из своей учетной записи пользователя, и до MPI_Init() вы можете fork&exec sudo helper. Целью помощника является создание необработанных сокетов, а затем передача их в программу MPI через передачу fd. Другой вариант — сделать ваше приложение MPI setuid а также владельцем root, создать необработанные сокеты и setuid для пользователя перед MPI_Init(), а затем запустить mpi из вашей учетной записи пользователя.

Gilles Gouaillardet 10.07.2019 16:47

Я сделал небольшую программу, которая создает необработанный сокет, а затем инициализирует MPI pastebin.com/RRTX9kzr. Затем sudo -i и скомпилировал программу с помощью mpic++, изменил suid на chmod u+s a.out, что сделало ее корневой и с разрешением sudo при выполнении -rwsr-xr-x 1 root root 36316 lip 9 23:28 a.out. Когда я просто запускаю ее как обычную программу ./a.out, она работает, но потом, когда я запускаю ее с помощью mpirun -n 1 /home/pi/Desktop/a.out, она вылетает с ошибкой pastebin.com/x2Q8iGvH. Если я запускаю его с --allow-run-as-root, он зависает, где я что-то пропустил?

Hana0xAF 10.07.2019 20:53

Хорошо, я пропустил момент, когда uid возвращался пользователю, в основном я скомпилировал программу с помощью mpic++, sudo -i, затем сменил владельца на root с помощью chown 0:0 a.out и установил suid на root с помощью chmod u+s a.out. Повторил это на обоих узлах и запустил программу MPI от имени пользователя с mpirun -n 2 --host localhost, rpi1 /home/pi/Desktop/a.out и все работает. В коде я изменил uid непосредственно перед MPI_Init, используя setreuid(geteuid(), getuid());. Это хорошее решение, и я рад, что могу дальше разрабатывать и тестировать свое приложение! Хотя мне придется решить проблему должным образом, прежде чем он будет готов к коммерческому использованию.

Hana0xAF 10.07.2019 22:24

обратите внимание, что вы можете использовать возможности вместо бита setuid (ping раньше был suid root, но теперь использует возможности, которые более безопасны: $ getcap /usr/bin/ping /usr/bin/ping = cap_net_admin,cap_net_raw+p

Gilles Gouaillardet 11.07.2019 04:04

Я проверил решение с помощью возможностей, в основном я устанавливаю возможности с помощью setcap program cap_net_raw,cap_net_admin+eip. Все работает просто отлично, и мне не нужно устанавливать suid для пользователя перед MPI_Init. Я думаю, что это действительно элегантное решение, спасибо.

Hana0xAF 11.07.2019 23:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
805
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Самый простой способ решить проблему - установить возможности файла, это все еще создает проблему безопасности, но это не так серьезно, как установка suid программы для root. Чтобы установить возможности программы, позволяющие открывать необработанный сокет: setcap program cap_net_raw,cap_net_admin+eip.

Другие вопросы по теме