Как автоматически перемонтировать 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

Вот и всё! Наша шара успешно взята под контроль, подключена. А в случае отвала по любым причинам она сама перемонтируется без лишних вопросов. Ну и после перезагрузки ноды тоже всё поднимется из коробки.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Способ рабочий, полёт стабильный более трёх лет. Можешь приспособить к своим каким-то изобретениям и использовать уже юниты, а не закроненные bash-скрипты. А шары монтировать через sshfs, а не через вонючий, разваливающийся gluster. Фак еее!