Русский
Русский
English
Статистика
Реклама

Ossh параллельное выполнение команд на многих серверах

Иногда бывает нужно запустить патч Бармина какую-то команду на многих серверах и желательно не ждать слишком долго результатов выполнения. Для этого я написал ossh (One SSH to rule them all). Вот пример его работы:

$ wc -l /tmp/ossh.ips21418 /tmp/ossh.ips$ time ossh -n -h /tmp/ossh.ips -c uptime -p 1000 >/tmp/ossh.outreal    3m10.310suser    0m30.970ssys     0m19.282s$ grep 'load average' /tmp/ossh.out | sort -n -k5 | tail -n110.23.91.97   [1]  13:37:55 up 828 days,  2:34,  0 users,  load average: 8.29, 4.45, 3.90$

В данном примере в файле /tmp/ossh.ips находится 21418 ip адресов машин. -n означает, что не нужно делать реверс запросы, чтобы определить имя по адресу. -c uptime задает команду, которую я хочу выполнить. -p 1000 позволяет использовать до 1000 соединений одновременно. Как видно из вывода отработала команда достаточно быстро.

Что еще умеет ossh?

$ ossh -?Usage: ossh [-?AinPv] [-c COMMAND] [-C COMMAND_FILE] [-H HOST_STRING] [-h HOST_FILE] [-I FILTER] [-k PRIVATE_KEY] [-l USER] [-o PORT] [-p PARALLELISM] [-T TIMEOUT] [-t TIMEOUT] [parameters ...] -?, --help        Show help -A, --askpass     Prompt for a password for ssh connects -c, --command=COMMAND                   Command to run -C, --command-file=COMMAND_FILE                   file with commands to run -H, --host=HOST_STRING                   Add the given HOST_STRING to the list of hosts -h, --hosts=HOST_FILE                   Read hosts from file -i, --ignore-failures                   Ignore connection failures in the preconnect mode -I, --inventory=FILTER                   Use FILTER expression to select hosts from inventory -k, --key=PRIVATE_KEY                   Use this private key -l, --user=USER   Username for connections [$LOGNAME] -n, --showip      In the output show ips instead of names -o, --port=PORT   Port to connect to [22] -p, --par=PARALLELISM                   How many hosts to run simultaneously [512] -P, --preconnect  Connect to all hosts before running command -T, --connect-timeout=TIMEOUT                   Connect timeout in seconds [60] -t, --timeout=TIMEOUT                   Run timeout in seconds -v, --verbose     Verbose output$

Список хостов можно задать либо прямо в командной строке через опцию -H (в случае нескольких хостов их надо перечислить через пробел, а весь список взять в кавычки как в примерах ниже) либо загрузить из файла при помощи опции -h. Строки в файле, начинающиеся с #, игнорируются. Адрес может содержать порт: my.host:2222. Можно использовать brace expansion: host{1,3..5}.com превратится в host1.com host3.com host4.com host5.com. И -H и -h можно использовать многократно.

Для авторизации будут использованы
  • пароль, который ossh запросит при использовании опции -A
  • ssh ключ, заданный опцией -k
  • ssh-agent (в этом случае у вас должна быть определена переменная окружения SSH_AUTH_SOCK)

Именно в таком порядке.

Иногда бывает нужно убедиться, что вы можете залогиниться на все машины прежде чем выполнить команду. Для этого есть опция -P. По умолчанию если хоть одна машина будет недоступна ossh завершится с ошибкой. Если вы хотите игнорировать неудачные соединения используйте опцию -i.

Ossh может использовать вашу систему инвентаризации. Для этого в путях должна находится команда ossh-inventory, которой будут переданы параметры опции -I. Эта опция может быть использована многократно. Команда ossh-inventory должна выдавать на стандартный вывод строки в формате:
имя_машины адрес_машины

Где адрес_машины может быть как днс именем, так и ip адресом.

Команды для выполнения задаются опциями -C (читать из файла) или -c (брать из командной строки). Эти опции могут использоваться многократно. При наличии и -C и -c сперва выполнятся команды из файлов, потом из командной строки.

Помимо просто выполнения команд при помощи ossh можно стримить логи в реальном времени:

$ ossh -H "web05 web06" -c "tail -f -c 0 /var/log/nginx/access.log|grep --line-buffered Wget"web05 192.168.1.23 - - [22/Jun/2016:12:24:02 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"web05 192.168.1.49 - - [22/Jun/2016:12:24:07 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"web06 192.168.1.117 - - [22/Jun/2016:12:24:23 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"web05 192.168.1.29 - - [22/Jun/2016:12:24:30 -0700] "GET / HTTP/1.1" 200 1532 "-" "Wget/1.15 (linux-gnu)"...


Вот симуляция rolling deployment:

$ ossh -p 1 -H "test0{1..3}" -c "sleep 10 && date"test01 Wed Jun 22 12:38:24 PDT 2016test02 Wed Jun 22 12:38:34 PDT 2016test03 Wed Jun 22 12:38:44 PDT 2016$


Видно, что команды выполняются на машинах последовательно. В каждый момент времени задействована только одна машина. Для настоящего деплоймента sleep 10 && date надо заменить на, к примеру, apt-get install -y your_package.

Именно для деплоймента была написана самая первая версия ossh. Кто-то спросит почему я не использовал какую-то общепринятую систему управления конфигурациями? Дело в том, что это было в далеком 2013-м году и мы использовали chef. Было ясно, что chef нас не устраивает в частности неопределенностью когда именно будут применены изменения (chef-client отрабатывал раз в 30 минут). Для того, чтобы согласованно выкатывать изменения на многих машинах некоторые разработчики применяли грязный хак: chef-client не работал постоянно, а однократно запускался (через ssh) только в тот момент, когда было нужно сделать деплоймент. Уже в тот момент шла работа по замене chef на salt, но переход был не простым и завершение его требовало дополнительного времени. Мы же разрабатывали новый сервис, который требовал частых деплойментов и раскатывался единственным дебиановским пакетом. Сперва мы использовали утилиту knife из состава chef. Эта утилита позволяла соединяться по ssh с нужными серверами и выполнять на них команды. В какой-то моент я понял, что chef в данном случае является лишним звеном и написал ossh.

Важно отметить, что ossh является инструментом для разрешения масштабных и нестандартных проблем. Если необходимость использовать ossh возникает часто это повод задуматься все ли у вас хорошо с инфраструктурой и управлением серверами. Вот некоторые ситуации, в которых ossh помог лично мне:
  • Однажды я наводил порядок в /root/.ssh/authorized_keys на большом количестве серверов (на тот момент их было около 7000). Разработчики прописали туда свои ключи, в частности для процессов обновления своих сервисов. Нужно было получить список всех ключей, использованных на всех машинах, и убедиться, что удаление этих ключей не приведет к катастрофическим последствиям.
  • Для безболезненного прохождения leap second
  • Когда мы боролись с TCP SACK PANIC правила для iptables выкатывались системой управления конфигураций. Чтобы убедиться, что все хорошо, я проверил наличие нужных правил при помощи ossh. И это было совсем не зря, обнаружились машины, на которых правила не применились.
  • Иногда мне приходится создавать тестовые среды состоящие из сотен (а иногда из тысяч) машин. Часто эти машины изолированы от production сети и не доступны для штатной системы управления конфигурациями. В подобных ситуациях конфигурирование машин можно проводить при помощи ossh.

Предвижу вопрос почему я не использовал готовое решение. Как я упомянул выше необходимость в прогонах команд на тысячах машин первый раз возникла у меня в 2013-м году. На тот момент мне удалось найти только parallel ssh, который не устроил меня следующим:
  • Мне не удалось поднять параллелизм выше 150, начали возникать ошибки при соединении с удаленными серверами
  • parallel ssh накапливал весь вывод и выдавал его по завершении команды. Стримить логи, к примеру, с его помощью было невозможно
  • Вывод parallel ssh был (лично для меня) неудобен для парсинга

Исходно ossh был написан на ruby, для увеличения производительности я задействовал event machine, а потом и fiber-ы. Относительно недавно я переписал ossh на go. Буду признателен если go-эксперты (я таковым на данный момент не являюсь) посмотрят на мой код и укажут на возможные способы улучшить его.
Источник: habr.com
К списку статей
Опубликовано: 15.03.2021 04:23:51
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Системное администрирование

Ssh

Linux

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru