Как автоматически перемонтировать SSHFS через systemd
День прошёл, число сменилось, нихуя не изменилось. Привет, коллеги!
читать первым в телеграм читать первым в макс
Как-то года 3 назад мы настолько устали каждую неделю ремонтировать маунтшары через glusterfs, что было принято решение выкинуть его нахуй и пойти в сторону упрощения. Много что попробовали, но остановились на sshfs.
По вводным: у нас есть baremetal-сервер с огромными HDD-дисками на овер 500 терабайт. На диске хранится статика, которую отдаём через nginx. Задача: подключать этот диск в облачную инфраструктуру к различным нодам. Условия: чтобы работало и не воняло.
Тут всё достаточно просто. Даём команду на нужной нам ноде, и шара монтируется в папку /mnt/storage:
sshfs -o compression=no,allow_other,reconnect storage@bashdayz.ru:/storage /mnt/storage
compression— не использовать компрессию;allow_other— разрешить доступ к шаре;reconnect— нативный реконнект, если шара отвалилась.
Из плюсов: на baremetal-сервере не надо устанавливать никакой дополнительный софт, всё работает по протоколу SSH.
Но есть нюансы. Допустим, если ноду перезагрузить, то всё отвалится. Либо придут сетевые ножницы, и оно тоже отвалится.
Запихать в fstab не вариант. Так как на этапе маунта ещё нет сети, загрузка сервера просто остановится в попытках примонтировать шару. А ключик reconnect работает как ему захочется, даже если выставить таймауты проверок.
Решение простое, создаём три юнита в systemd.
Первый юнит — монтирование SSHFS
[Unit]
Description=Mount remote filesystem over sshfs with fuse
After=network.target
[Install]
WantedBy=multi-user.target
[Mount]
What=storage@bashdayz.ru:/storage
Where=/mnt/storage
Type=fuse.sshfs
Options=kernel_cache,compression=no,allow_other,reconnect
After=network.target— запускать маунт только после того, как на хосте поднимется сеть;What=storage@bashdayz.ru:/storage— что монтируем;Where=/mnt/storage— куда монтируем.
Важно! Файл юнита должен называться в соответствии с путём, куда монтируем. Узнать имя можно командой:
systemd-escape -p /mnt/storage
Первый юнит сохраняем сюда: /etc/systemd/system/mnt-storage.mount.
Второй юнит — таймер проверки
Теперь нужно сделать юнит проверки на случай, если шара отвалилась. Для начала создаём юнит с таймером:
[Unit]
Description=Run ssh mount /mnt/storage check
After=mnt-storage.mount
[Timer]
Unit=mnt-storage.service
OnCalendar=*-*-* *:*:00
[Install]
WantedBy=timers.target
After=mnt-storage.mount— обеспечит запуск таймера после загрузки сервера, но только после того, как mount-юнит будет запущен, то есть после того, как удалённая ФС смонтируется;Unit=mnt-storage.service— какой юнит будем запускать при срабатывании таймера. О нём чуть ниже;OnCalendar=*-*-* *:*:00— это означает каждую минуту.
Юнит-файл таймера можно называть как угодно. Но чтобы было понятнее, будем называть так же, как и mount-юнит. Итак, сохраняем в /etc/systemd/system/mnt-storage.timer.
Третий юнит — проверка маунта
Теперь нужно создать юнит, который будет заниматься проверкой маунта и его перезапуском при необходимости:
[Unit]
Description=SSH mount /mnt/storage check
[Service]
Type=oneshot
ExecStart=/bin/bash -c "if [[ ! -f /mnt/storage/mount.yes ]]; then systemctl restart mnt-storage.mount; fi"
TimeoutSec=300
[Install]
WantedBy=multi-user.target
Здесь всё просто. Bash-строка в ExecStart — это bash-однострочник, проверяющий наличие маркерного файла mount.yes, при отсутствии которого будет перезапущен mount-юнит. В более новой версии systemd можно было бы это всё сделать иначе, но зато такой вариант более универсален.
Сохраняем в /etc/systemd/system/mnt-storage.service.
Активируем юниты
systemctl daemon-reload
systemctl enable mnt-storage.mount
systemctl enable mnt-storage.timer
Третий юнит mnt-storage.service при загрузке сервера активировать не нужно, поскольку этот юнит вызывается таймером mnt-storage.timer. Он будет всегда Active: inactive (dead), это нормально.
Ну и в финале запускаем таймер:
systemctl start mnt-storage.timer
Вот и всё! Наша шара успешно взята под контроль, подключена. А в случае отвала по любым причинам она сама перемонтируется без лишних вопросов. Ну и после перезагрузки ноды тоже всё поднимется из коробки.
