Debian 13: SSHFS проти NFS — обирайте те, що не зависатиме випадково (і налаштуйте правильно)

Було корисно?

Ви не «втратили» сервер. Ви втратили час — стоїте перед терміналом, який не повертає управління, тому що якийсь процес застряг у незупинному ввід/виводі,
і тепер ls виконує роль переговорника. Пейджер не переконаний, що шар «зазвичай працює».

У Debian 13 питання SSHFS проти NFS — не філософське. Воно операційне: що відмовляє передбачувано, що відновлюється чисто,
і як налаштувати монтування так, щоб рутинні відмови не перетворювалися на параліч хоста.

Принципове рішення: використовуйте NFS для продакшну, SSHFS — для крайніх випадків

Якщо ваша ціль — «не зависати випадково», обирайте NFS із systemd automount для будь-чого, що нагадує продакшн розподілене сховище.
SSHFS чудовий, коли потрібне шифрування без інфраструктури, коли ви тягнете дані з машини, яку не контролюєте,
або коли вам потрібне швидке тимчасове монтування для одноразового завдання. Але якщо ви монтуєте SSHFS як критичну залежність і очікуєте,
що воно поводитиметься як LAN-файловий сервер, ви незабаром зустрінете семантику FUSE, мережеві глюки TCP і буферизацію в просторі користувача
у найнезручніший спосіб.

NFS — не магія. Воно також може зависати — особливо з монтуваннями hard (за замовчуванням), бо «не повертати пошкоджені дані» — поважний принцип.
Але різниця в тому, що NFS дає кращі інструменти, кращу інтеграцію в ядро та явніший контроль поведінки при відмовах.
Більшість «випадкових зависань» не випадкові; це ви обрали блокуючу семантику без виходу.

Практичне правило:

  • Використовуйте NFSv4.2 для спільних домашніх директорій, артефактів збірки, зон приземлення бекапів і «кілька клієнтів потребують одні і ті ж дані».
  • Використовуйте SSHFS для разового доступу, перетину недружніх мереж або коли потрібна автентифікація на рівні користувача без підняття NFS.
  • Ніколи не монтуйте ні те, ні інше так, щоб це блокувало завантаження або зупиняло критичні демони. Automount або явне впорядкування залежностей — завжди.

Одна цитата, щоб тримати себе в руках. Вернер Фогельс (CTO Amazon) має широко відому ідею — парафраз: «Все відмовляє постійно».
Якщо ви це приймаєте, перестаєте сприймати зависання як містерію і починаєте проєктувати прийнятний режим відмови.

Факти та історія, що справді важливі у 2025 році

Кілька контекстних тез, які можна використати на нарадах, коли хтось каже «це всього лиш монтування, що тут складного?»

  1. NFS має вік, щоб мати шрами. Воно з’явилося в середині 1980-х у Sun Microsystems, і його дизайн відображає реальний корпоративний біль: спільні UNIX-файли в масштабі.
  2. NFSv4 був фактично переписом. Він консолідував протоколи, покращив безпеку і станність, і пішов до «одного порт-френдлі» підходу.
  3. Раніше NFS любив UDP. У ранніх деплойментах часто використовували UDP; сучасна найкраща практика — TCP для надійності і контролю заторів.
  4. SSHFS — це FUSE. Це означає файлову розводку в просторі користувача; гнучко, але не ідеально для «завжди в ядрі» сховища.
  5. Семантика FUSE може здивувати. Перевірки прав, кешування і пропагування помилок поводяться інакше, ніж файлові системи в ядрі — особливо при відмовах.
  6. Клієнт NFS має багато політик. «hard» проти «soft», таймаути, повторні передачі та кешування атрибутів визначають, наскільки «зависання» відчувається.
  7. Systemd змінив правила гри. Automount-юнити і залежності монтування дозволяють зберігати завантаження та сервіси живими навіть при нестабільному сховищі.
  8. Блокування історично хитке. Блокування в NFS колись працювало через окремі менеджери блокувань; NFSv4 інтегрував блокування, але спадкові припущення все ще дають про себе знати.
  9. Відображення ідентичностей — прихована міна. NFSv4 використовує відображення ідентичностей за іменами, якщо ви явно не налаштуєте інакше; невідповідності виглядають як «раптом зламалися права».

Що насправді означає «випадкове зависання» (і хто винен)

Коли інженери кажуть «SSHFS зависло» або «NFS зависло», вони зазвичай мають на увазі одне з чотирьох:

1) Процес застряг у стані D (uninterruptible sleep)

Класика: ps показує D, kill -9 не допомагає, і єдиний «вихід» — відновити віддалений сервер або перезавантажитись.
Це найчастіше трапляється з NFS hard-монтуваннями під час відмови сервера або мережевої роздільності.

2) Виклик монтування блокується назавжди

Зависання під час завантаження або старту сервісу, бо щось намагалося змонтувати віддалену файлову систему і чекало. Це конфігураційна помилка:
немає automount, немає таймауту, і ланцюг залежностей дозволяє віддаленому шару захопити хост в заручники.

3) Переліки директорій зависають, але деякі читання працюють

Операції з метаданими (lookup, getattr, readdir) чутливі до кешування і мережевого джиттера.
SSHFS може відчуватися гірше тут, бо кожна операція метаданих — це черговий раунд через SSH-канал плюс накладні витрати SFTP.
NFS також може так поводитись, якщо кешування атрибутів не відрегульовано або сервер перевантажений.

4) «Повільно» виглядає як «зависло»

30-секундна пауза у find або du часто — це просто посилення латентності:
тисячі дрібних метаоперацій, помножені на кілька мілісекунд кожна, дають відчуття «термінал помер».

Жарт №1: віддалена файлова система — як колега у відпустці: офіційно ще працює, але відповіді до обіду ви не дочекаєтесь.

Хто частіше «випадково зависає»?

SSHFS частіше роз’єднується або стає непередбачувано повільним у ненадійних мережах, особливо якщо не налаштовані keepalive.
Але коли SSHFS відмовляє, воно зазвичай відмовляє «м’якше» (ви отримуєте помилки I/O, монтування пропадає, повторне підключення може спрацювати),
ніж застрягання ядра в нескінченних повторних спробах.

NFS частіше блокує назавжди за дизайном з типовими hard-монтуваннями. Це не випадково; це політика.
Якщо ви хочете, щоб «хост не зависав», потрібно спроєктувати режим відмови: automount, таймаути там, де доречно,
і чітке рішення про hard vs soft для конкретного робочого навантаження.

Швидкий план діагностики (перший/другий/третій)

Це «у мене п’ять хвилин, поки це не перетвориться на воєнну кімнату» потік. Мета — визначити, чи ми маємо справу з
(a) досяжністю мережі, (b) навантаженням або відмовою демонів на сервері, (c) семантикою монтування на клієнті, або (d) DNS/відображенням ідентичностей.

Перший крок: підтвердіть базову досяжність

  • Чи можете ви пропінгувати IP сервера (або хоча б розв’язати ім’я)?
  • Чи доступний TCP порт 2049 для NFSv4? Чи доступний TCP 22 для SSHFS?
  • Чи є втрата пакетів або висока латентність, що перетворює метадані на мед?

Другий крок: перевірте, чи клієнт заблоковано в I/O ядра

  • Чи є процеси, що застрягли в стані D?
  • Чи зависає cat /proc/mounts або mount?
  • Чи працює доступ до інших файлових систем нормально?

Третій крок: допитати конкретний протокольний шлях

  • Для NFS: nfsstat, rpcinfo (якщо v3), журнали ядра, статус експорту сервера і чи відповідає сервер.
  • Для SSHFS: keepalive SSH, стан підсистеми SFTP і чи застряг SSH-звʼязок через мертву TCP-сесію.

Точки прийняття рішень

  • Якщо сервер недосяжний: automount запобігає повній зупинці хоста; виправте мережу або проведіть перемикання.
  • Якщо сервер досяжний, але повільний: ви обмежені по потужності — CPU, диски або надто багато клієнтів; налаштуйте і масштабуюйте.
  • Якщо один клієнт зависає, а інші ні: підозрівайте DNS клієнта, відображення ідентичностей або зависле стан монтування.

Практичні завдання: команди, виводи та що робити далі

Це дії при онколі, які розділяють «думаю, це NFS» від «клієнт у жорстких повторних спробах, бо сервер перестав відповідати на COMPOUND операції».
Кожне завдання включає: команду, що означає вивід, і що робити далі.

Завдання 1: Побачити, що змонтовано і чи ви маєте справу з NFS або FUSE

cr0x@server:~$ findmnt -t nfs,nfs4,fuse.sshfs
TARGET        SOURCE                 FSTYPE     OPTIONS
/mnt/shared   nas01:/export/shared   nfs4       rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,sec=sys,clientaddr=10.0.0.21
/mnt/adhoc    devbox:/home/builds    fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000

Значення: у вас обидва. NFS — в ядрі; SSHFS — через FUSE. Рішення: застосуйте відповідні інструменти для налагодження — nfsstat для NFS, журнали SSH для SSHFS.

Завдання 2: Перевірити, чи процеси застрягли у незупинному I/O (стан D)

cr0x@server:~$ ps -eo state,pid,comm,wchan:30 | awk '$1=="D"{print}'
D  18472 rsync  nfs_wait_bit_killable
D  21205 du     rpc_wait_bit_killable

Значення: ці процеси заблоковані в очікуванні ядра, типово при NFS hard-повторюваннях. Рішення: припиніть сподіватися, що kill -9 допоможе; відновіть сервер/мережу або обережно зробіть відʼєднання монтування.

Завдання 3: Швидко підтвердити мережевий шлях (латентність і втрати)

cr0x@server:~$ ping -c 5 nas01
PING nas01 (10.0.0.50) 56(84) bytes of data.
64 bytes from 10.0.0.50: icmp_seq=1 ttl=63 time=0.453 ms
64 bytes from 10.0.0.50: icmp_seq=2 ttl=63 time=0.482 ms
64 bytes from 10.0.0.50: icmp_seq=3 ttl=63 time=12.103 ms
64 bytes from 10.0.0.50: icmp_seq=4 ttl=63 time=0.469 ms
64 bytes from 10.0.0.50: icmp_seq=5 ttl=63 time=0.476 ms

--- nas01 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4093ms
rtt min/avg/max/mdev = 0.453/2.797/12.103/4.650 ms

Значення: один спайк. Це може бути достатньо, щоб метаданти-важкі навантаження відчувалися «завислими». Рішення: якщо спайки корелюють із зависаннями, шукайте затори, bufferbloat або проблеми NIC.

Завдання 4: Для NFSv4 перевірте доступність порту (2049)

cr0x@server:~$ nc -vz -w2 nas01 2049
Connection to nas01 (10.0.0.50) 2049 port [tcp/nfs] succeeded!

Значення: базова підключуваність в порядку. Рішення: перестаньте звинувачувати фаєрвол; дивіться на навантаження сервера, стан демонів NFS або семантику монтування на клієнті.

Завдання 5: Для SSHFS підтвердьте стан транспорту SSH і швидкість автентифікації

cr0x@server:~$ ssh -o BatchMode=yes -o ConnectTimeout=5 build@devbox 'echo ok'
ok

Значення: SSH відповідає. Рішення: якщо SSH працює, але SSHFS зависає, зосередьтесь на підсистемі SFTP, keepalive і поведінці FUSE під навантаженням.

Завдання 6: Перегляньте журнали ядра для таймаутів NFS і повідомлень про «server not responding»

cr0x@server:~$ sudo journalctl -k -n 20
Aug 12 14:03:19 app01 kernel: nfs: server nas01 not responding, still trying
Aug 12 14:03:50 app01 kernel: nfs: server nas01 not responding, still trying
Aug 12 14:04:23 app01 kernel: nfs: server nas01 OK

Значення: «зависання» — це клієнт робить те, що ви йому наказали: продовжувати спроби. Рішення: якщо це блокує продакшн, додайте automount і подумайте про soft лише для некритичних читань.

Завдання 7: Подивіться статистику по кожному монтуванню NFS (retrans — це дим)

cr0x@server:~$ nfsstat -m
/mnt/shared from nas01:/export/shared
 Flags:	rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.0.21
 Stats:	age: 00:43:11  ops/s: 127
	xprt:	tcp  90632  211  0  0  0
	per-op statistics
	READ: 42.1%  WRITE: 11.7%  GETATTR: 20.4%  LOOKUP: 14.2%  ACCESS: 7.6%

Значення: рядок транспорту показує retransmits (друге число після викликів). Якщо retrans зростає, ви втрачаєте відповіді. Рішення: дослідіть мережеві втрати, насичення сервера або надто агресивні таймаути.

Завдання 8: Визначте, чи DNS спричиняє затримки (реверсні пошуки можуть заважати)

cr0x@server:~$ getent hosts nas01
10.0.0.50       nas01

Значення: імʼя розв’язується швидко. Рішення: якщо це зависає або повертає несподівані адреси, виправте DNS перед тим, як чіпати монтування.

Завдання 9: Перевірте експорти на сервері (на сервері)

cr0x@nas01:~$ sudo exportfs -v
/export/shared  10.0.0.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,root_squash,no_all_squash)

Значення: експорт існує; root squashed; sync ввімкнено. Рішення: якщо клієнтам потрібні права root, не «вирішуйте» це all_squash-хаками — використайте правильне відображення UID/GID або сервісний акаунт.

Завдання 10: Підтвердіть, що служби NFS на сервері запущені

cr0x@nas01:~$ systemctl status nfs-server --no-pager
● nfs-server.service - NFS server and services
     Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
     Active: active (exited) since Tue 2025-08-12 13:01:21 UTC; 3h 2min ago
       Docs: man:nfsd(8)

Значення: служба «active (exited)» — це нормально для деяких NFS-юнитів після підняття потоків у ядрі. Рішення: якщо вона впала, не налагоджуйте клієнтів — виправляйте сервер спочатку.

Завдання 11: Виявити монтування, що зависне вашу оболонку (спробуйте timed stat)

cr0x@server:~$ timeout 3 stat /mnt/shared || echo "stat timed out"
stat timed out

Значення: виклик метаданих заблокований більше ніж на 3 секунди. Рішення: ваш додаток також буде блокуватись; обійдіть шлях, зробіть unmount або зафенсуйте залежність.

Завдання 12: Безпечно спробувати lazy unmount (коли віддалений зник)

cr0x@server:~$ sudo umount -l /mnt/shared

Значення: відсутність виводу зазвичай означає успіх. Lazy unmount відʼєднує точку монтування зараз і прибирає її, коли посилання зникнуть. Рішення: використовуйте, коли потрібно повернутися до роботи; потім усуньте причину відмови.

Завдання 13: Примусово оновити монтування через systemd (на клієнті)

cr0x@server:~$ sudo systemctl restart mnt-shared.mount

Значення: systemd переоцінює юніт монтування. Рішення: якщо restart блокується, переключіться на automount, щоб монтування відбувалося на вимогу і могло таймаутитись без блокування завантаження/старта сервісів.

Завдання 14: Для SSHFS перевірте мертві TCP-сесії та поведінку keepalive

cr0x@server:~$ ss -tpn '( sport = :ssh or dport = :ssh )'
ESTAB 0 0 10.0.0.21:52418 10.0.0.60:22 users:(("ssh",pid=29102,fd=3))

Значення: SSH-зʼєднання існує. Рішення: якщо воно в ESTAB, але I/O застряг, швидше за все у вас напівмертвий шлях (станоформний middlebox, NAT, Wi‑Fi із сном). Додайте keepalive і ServerAliveInterval для SSHFS.

NFS, яке не буде вам соромом: конфігурації сервера та клієнта для Debian 13

Репутація NFS дивна: або «скеля», або «зачароване». У продакшні це в основному визначається тим, чи ставитесь до нього як до системного компонента
(з ідентичностями, експортами та automount), чи як до швидкого рядка монтування з вікі 2009 року.

Сервер: встановіть і експортуйте розумно

На сервері NFS (Debian 13) вам потрібен простий експорт, TCP та передбачувані права. Якщо вам потрібна сильна безпека через недовірені мережі,
використовуйте Kerberos; для довірених LAN зазвичай достатньо sec=sys, якщо мережа дійсно довірена.

cr0x@nas01:~$ sudo apt update
Hit:1 ... InRelease
Reading package lists... Done
cr0x@nas01:~$ sudo apt install -y nfs-kernel-server
Reading package lists... Done
...
Setting up nfs-kernel-server ...

Створіть експорт. Прапори мають значення:
sync поступається частиною продуктивності заради цілісності; для багатьох бізнес-вантажів це правильний вибір.
no_subtree_check уникає болісних перевірок за шляхом (і сюрпризів під час перейменувань).
Тримайте доступ обмеженим: підмережа або набір хостів.

cr0x@nas01:~$ sudo mkdir -p /export/shared
cr0x@nas01:~$ sudo chown -R root:root /export
cr0x@nas01:~$ sudo chmod 755 /export /export/shared
cr0x@nas01:~$ sudo tee /etc/exports >/dev/null <<'EOF'
/export/shared 10.0.0.0/24(rw,sync,no_subtree_check,root_squash)
EOF
cr0x@nas01:~$ sudo exportfs -ra
cr0x@nas01:~$ sudo exportfs -v
/export/shared  10.0.0.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,root_squash,no_all_squash)

Клієнт: монтуйте з NFSv4.2 і обирайте семантику відмов

Ключовий вибір — hard проти soft:

  • hard: повторює нескінченно. Безпечніше для коректності даних. Також класичне джерело «хост здається завислим».
  • soft: повертає помилку після повторних спроб. Краще для інтерактивних клієнтів і некритичних читань. Небезпечно для додатків, які не вміють обробляти часткові відмови.

У продакшні я за замовчуванням обираю hard + automount. Таким чином ви не корумпуєте робочі процеси і не чіпляєте завантаження.
Для некритичних інструментів (наприклад, робоча станція розробника, що читає медіа-шару) soft може бути прийнятним.

cr0x@server:~$ sudo apt install -y nfs-common
Reading package lists... Done
...
Setting up nfs-common ...

Протестуйте ручне монтування для валідації базових речей.

cr0x@server:~$ sudo mkdir -p /mnt/shared
cr0x@server:~$ sudo mount -t nfs4 -o vers=4.2,proto=tcp,hard,timeo=600,retrans=2 nas01:/export/shared /mnt/shared
cr0x@server:~$ mount | grep /mnt/shared
nas01:/export/shared on /mnt/shared type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.0.0.21)

Що ці опції означають на практиці:

  • proto=tcp: бажано TCP, якщо ви не любите дебагати втрати пакетів «у мене працює».
  • timeo=600: для TCP це в десятих частках секунди. 600 → 60s на спробу RPC. Це консервативно.
  • retrans=2: кількість повторів перед ескалацією логіки таймаутів. Це не «загальна кількість повторів» для hard-монтувань; hard-монтування можуть продовжувати спроби.
  • rsize/wsize: великі розміри допомагають пропускній здатності, але не виправлять латентність метаданих. Вони не лікують «find повільний».

Права та ідентичність: зробіть це нудним

NFS — не система прав; воно переадресовує ідентичність. Якщо UID/GID не збігаються між машинами, ви отримаєте «випадкове» access denied.
Виправляйте це в джерелі: узгоджені UID/GID для сервісних акаунтів і спільних користувачів.

SSHFS, що поводиться: keepalive, systemd і розумне кешування

SSHFS привабливий тим, що це просто SSH. Ніяких експортів, ніякої ностальгії за rpcbind, ніяких спеціальних фаєрвол-зустрічей.
Але SSHFS живе в просторі користувача, говорить SFTP і залежить від стабільної SSH-сесії. Це дуже ввічлива файлова система: вона просить дозвіл на все,
по одному питанню за раз, через зашифрований тунель. Така ввічливість дорога.

Встановлення і базове монтування

cr0x@server:~$ sudo apt install -y sshfs
Reading package lists... Done
...
Setting up sshfs ...
cr0x@server:~$ mkdir -p /mnt/adhoc
cr0x@server:~$ sshfs build@devbox:/home/builds /mnt/adhoc -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,Compression=no
cr0x@server:~$ findmnt /mnt/adhoc
TARGET     SOURCE              FSTYPE     OPTIONS
/mnt/adhoc build@devbox:/home/builds fuse.sshfs rw,nosuid,nodev,relatime,user_id=1000,group_id=1000

Опції keepalive — обов’язкові, якщо між вами і сервером є NAT, Wi‑Fi або «апарат безпеки»:
ServerAliveInterval надсилає SSH-рівневі пінги; reconnect намагається відновити сесію.

Жарт №2: SSHFS — як проводити шафу через аеропорт — усе перевіряється, і ви платите за привілей.

Типові шаблони зависання SSHFS

  • Напіввідкриті TCP-сесії: ноутбук заснув, NAT вичерпав таймаут, зʼєднання виглядає ESTAB, але пакети не йдуть. Keepalive скорочує час виявлення.
  • Проблеми підсистеми SFTP: віддалений sftp-server повільний, виснажений ресурсами або обмежений forced commands.
  • Конкуренція потоків FUSE: важкі паралельні виклики файлової системи можуть заблокувати демон у просторі користувача; сплески CPU на клієнті виглядають як «монтування зависло».

Опції монтування SSHFS, що зменшують біль

  • reconnect: намагається перепідключитись, якщо зʼєднання впало.
  • ServerAliveInterval=15 та ServerAliveCountMax=3: швидко виявляють мертві сесії.
  • workaround=rename (іноді): допомагає з додатками, що роблять атомарні перейменування і потрапляють у крайові випадки.
  • cache=yes або kernel_cache: можуть покращити пропускну здатність, але зашкодити узгодженості. Використовуйте обережно, якщо є кілька записувачів.
  • Compression=no у швидкому LAN: економить CPU і часто покращує латентність.

Якщо кілька клієнтів одночасно записують ті самі файли і вам важлива узгодженість, кешування SSHFS — пастка.
NFS має власну історію кешування/узгодженості, але вона розроблена для багатоклієнтського доступу. SSHFS призначений для доступу, а не для координації.

Припиніть зависати на завантаженні: шаблони automount у systemd

Найбільш запобіжне «випадкове зависання» — те, що відбувається під час завантаження, бо /etc/fstab наказав хосту чекати, поки віддалена машина відповість.
Не робіть так. Використовуйте systemd automount, щоб монтування відбувалося при першому доступі, і щоб таймаути не перетворювали хост у цеглину.

NFS з /etc/fstab і systemd automount

Додайте це в /etc/fstab на клієнті. Воно монтується на вимогу, а не під час завантаження:

cr0x@server:~$ sudo tee -a /etc/fstab >/dev/null <<'EOF'
nas01:/export/shared /mnt/shared nfs4 nofail,x-systemd.automount,x-systemd.device-timeout=10s,x-systemd.mount-timeout=10s,_netdev,vers=4.2,proto=tcp,hard,timeo=600,retrans=2 0 0
EOF
cr0x@server:~$ sudo systemctl daemon-reload
cr0x@server:~$ sudo systemctl restart remote-fs.target
cr0x@server:~$ systemctl status mnt-shared.automount --no-pager
● mnt-shared.automount - /mnt/shared
     Loaded: loaded (/etc/fstab; generated)
     Active: active (waiting) since Tue 2025-08-12 14:10:12 UTC; 2s ago

Значення: automount озброєно і чекає. Рішення: цей хост завантажується навіть якщо nas01 не відповідає; перший доступ тригерить спробу монтування з таймаутами.

SSHFS з systemd (переважно краще, ніж fstab для користувацьких монтувань)

SSHFS часто працює краще як користувацька служба або з явними systemd-юнитами, бо це процес у просторі користувача і вам потрібне чисте керування життєвим циклом.
Ось приклад системного юніта, якщо ви хочете змонтувати для сервісного акаунта (підлаштуйте user/шляхи за потреби).

cr0x@server:~$ sudo tee /etc/systemd/system/mnt-adhoc.mount >/dev/null <<'EOF'
[Unit]
Description=SSHFS mount for /mnt/adhoc
After=network-online.target
Wants=network-online.target

[Mount]
What=build@devbox:/home/builds
Where=/mnt/adhoc
Type=fuse.sshfs
Options=_netdev,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,Compression=no,IdentityFile=/home/build/.ssh/id_ed25519

[Install]
WantedBy=multi-user.target
EOF
cr0x@server:~$ sudo systemctl daemon-reload
cr0x@server:~$ sudo systemctl enable --now mnt-adhoc.mount
Created symlink /etc/systemd/system/multi-user.target.wants/mnt-adhoc.mount → /etc/systemd/system/mnt-adhoc.mount.

Рішення: якщо ви бачите, що це монтування іноді клинилося, додайте супутній .automount юніт і монтуйте на вимогу — той самий принцип, що й для NFS.

Три корпоративні міні-історії з країни «це мало працювати»

Інцидент через неправильне припущення: «Hard mounts нам не шкодять»

Середня компанія мала Debian апсервери, які підтягують статичні ресурси та кілька конфіг-фрагментів з NFS-шару.
Припущення було простим: hard-монтування запобігають пошкодженим читанням, отже вони «безпечні». Хтось навіть сказав, що краще зависання, ніж погані дані,
що в абстракті вірно і в реальному інциденті — ні.

Під час вікна обслуговування команда зберігання перезавантажила NFS-сервер. Перезавантаження зайняло більше часу, ніж очікували, бо на машині виконувався fsck.
Тим часом апсервери працювали далі, поки деплой не тригерив скрипт, що зробив рекурсивний find по змонтованому шляху.
Раптом усі агенти деплою застрягли. Потім моніторинговий агент спробував прочитати файл під тим шляхом. Потім hook logrotate зробив те саме.

«Неправильне припущення» було в тому, що hard-монтування завжди локалізоване. Воно не було. Точка монтування була частиною надто багатьох кодових шляхів.
Наслідок — не одна заблокована задача, а весь флот із накопиченням застряглих процесів і навантаженням від повторних спроб.
Деякі вузли деградували настільки, що оркестратор почав флапати сервіси.

Виправлення не було «використовувати soft всюди». Це було automount плюс редизайн: перестати робити критичні runtime-залежності від віддаленої файлової системи,
якщо додаток явно не толерує повільність або недоступність цієї залежності. Hard-монтування лишилися для даних, які цього справді потребують,
але доступ став ініційованим за потребою і обмеженим за часом на рівні systemd.

Оптимізація, яка відплатилася: «Піднімаємо кеш і rsize/wsize до максимуму»

Інша компанія мала фарм збірок, що читав великі артефакти зі спільного сховища. Хтось зробив розумно: підвищив rsize/wsize до 1 MiB,
включив агресивне кешування на клієнті і оголосив перемогу після бенчмарку, який копіював кілька баггігабайтних файлів швидше.
Дашборд покращився. Люди плескали. Зміна розгорнулась.

Потім почалися дивні випадки. Збірки час від часу падали з «file not found» на кроках, які очікували, що файл зʼявиться відразу після того, як інша задача його завантажить.
Іноді файл був, але мав старіший timestamp. Іноді перелік директорії не включав його кілька секунд.
Схоже на eventual consistency, що не найкраща асоціація для POSIX-подібної файлової системи.

Відплата прийшла від змішування робочих навантажень: той самий шар обслуговував великі послідовні читання і метаданто-чутливу координацію.
Кешування, налаштоване для пропускної здатності, зробило видимість метаданих запізнілою. Система не «зависла»; вона на мить прибрехала.
Це гірше за зависання, бо породжує фантомні баги.

Вони відновились, розділивши навантаження: один експорт NFS для великих артефактів, інший шлях для координації зі строгішою семантикою кешу,
і перехід до явного версіонування артефактів, щоб читачі ніколи не залежали від «latest file у директорії», що має зʼявитись миттєво.
Урок: тонке налаштування продуктивності не універсальне; воно залежить від робочого навантаження, а змішані навантаження карають оптимізм.

Нудна, але правильна практика, що врятувала день: automount + відфенсовані залежності

Фінансова організація (та, що має вікна змін і папірці на папірцях) мала набір Debian батч-серверів,
що періодично підтягують файли зі спільного шару. Шар був важливий, але сервери мали й інші обовʼязки.
Раніше один обережний інженер наполіг на двох речах: systemd automount для всіх мережевих файлових систем і явні таймаути на спроби монтування.
Ніхто цього особливо не любив. Це не було «покращення продуктивності». Це не зʼявилось у демках.

Однієї ночі бекенд зберігання мав часткову відмову — половина NFS-нод була досяжна, але перевантажена,
повертала відповіді настільки повільно, щоб клієнти почали повторні спроби. Клієнти без automount заблокувалися б під час завантаження після перезавантаження,
а рестарт будь-якого сервісу став би лотереєю.

Натомість батч-сервери залишились живими. Завдання, що потребували шару, падали швидко з чіткими помилками і повторювалися пізніше.
Моніторинг працював. SSH доступ залишався чутливим. Інцидент залишився у межах «конвеєр затримується», а не «не можемо зайти в систему».

Постмортем був нудним. І це була перемога. Нудні практики не потрапляють на слайди,
але вони не дозволяють вашій інфраструктурі стати учасником відмови когось іншого.

Поширені помилки: симптом → корінна причина → виправлення

1) Симптом: завантаження зависає або триває хвилини, коли NAS недоступний

Корінна причина: блокуючі монтування в /etc/fstab без nofail, automount або таймаутів.

Виправлення: додайте x-systemd.automount, nofail і таймаути; або перетворіть на явні systemd-юнити.

2) Симптом: ls у точці монтування ніколи не повертається; процеси у стані D

Корінна причина: NFS hard монтування + сервер не відповідає; ядро повторює нескінченно.

Виправлення: відновіть сервер/мережу; якщо потрібно повернути хост негайно, використайте umount -l і перепроєктуйте з automount, щоб уникнути глобального блокування.

3) Симптом: «Permission denied» на NFS, але той самий шлях працює на іншому клієнті

Корінна причина: невідповідність UID/GID між хостами (або невідповідності відображення ідентичностей NFSv4).

Виправлення: уніфікуйте ідентичності; забезпечте консистентні user IDs; не «виправляйте» unsafe export-опціями.

4) Симптом: SSHFS монтування зависає після сну ноутбука або роумінгу Wi‑Fi

Корінна причина: напіввідкрита SSH-сесія; NAT/становий пристрій вичерпав потік.

Виправлення: додайте ServerAliveInterval/ServerAliveCountMax і reconnect; розгляньте automount для монтувань на вимогу.

5) Симптом: SSHFS «добре» для великих файлів, але жахливо для find або дрібних файлів

Корінна причина: накладні витрати SFTP на кожну операцію; латентність метаданих посилюється.

Виправлення: не використовуйте SSHFS для метаданто-важких спільних навантажень; використайте NFS або локальний синк (rsync, fetch артефактів) залежно від випадку.

6) Симптом: NFS здається завислим тільки в пікові години

Корінна причина: перевантаження сервера (CPU, латентність диска, контенція блокувань) або мережеве заторення, що викликає retransmits.

Виправлення: підтвердіть через nfsstat і метрики сервера; масштабуйтесь, перемістіть «гарячі» дані або розділіть експорти; не «налаштовуйте» таймаути замість реального масштабування.

7) Симптом: монтування працюють по IP, але не по імені хоста

Корінна причина: проблеми DNS, затримки з реверсними запитами або неконсистентні записи.

Виправлення: виправте DNS; зафіксуйте стабільні імена; не вшивайте IP у конфіги флоту, якщо не хочете брати на себе операційний борг.

8) Симптом: unmount зависає

Корінна причина: зайняте монтування з застряглими процесами, що тримають дескриптори; NFS hard-повторювання; демон FUSE застряг.

Виправлення: ідентифікуйте власників (lsof/fuser, якщо вони відповідають), використайте umount -l; для FUSE зупиніть процес sshfs і потім зробіть lazy unmount.

Чеклісти / покроковий план

Покроково: оберіть протокол (реалії продакшну)

  1. Якщо кілька клієнтів потребують ті самі записувані дані: обирайте NFSv4.2.
  2. Якщо це разовий доступ через напівнедружні мережі: обирайте SSHFS.
  3. Якщо вам потрібне «спільне сховище», але додаток не терпить семантику файлової системи: не використовуйте ні те, ні інше — використайте обʼєктне сховище, HTTP-отримання артефактів або локальне реплікування.
  4. Визначте режим відмов:
    • Віддавайте перевагу hard + automount для коректності без зависань при завантаженні.
    • Використовуйте soft лише коли додаток коректно обробляє помилки I/O.

Покроково: правильно імплементуйте NFS на Debian 13

  1. Сервер: встановіть nfs-kernel-server.
  2. Сервер: створіть відокремлений шлях експорту; встановіть власність свідомо.
  3. Сервер: налаштуйте /etc/exports з sync і no_subtree_check; обмежте клієнтів.
  4. Клієнт: встановіть nfs-common.
  5. Клієнт: протестуйте ручне монтування з vers=4.2,proto=tcp.
  6. Клієнт: переключіться на /etc/fstab з x-systemd.automount, nofail і таймаутами.
  7. Валідація: симулюйте відмову сервера і переконайтесь, що хост залишається придатним до роботи і нормально завантажується.

Покроково: імплементуйте SSHFS без самосаботажу

  1. Встановіть sshfs.
  2. Підтвердіть, що безінтерактивний SSH працює швидко (BatchMode).
  3. Монтуйте з reconnect і SSH keepalive.
  4. Якщо це не тимчасово: керуйте монтуванням через systemd-юнити; додайте automount при потребі.
  5. Будьте обережні з кешуванням, якщо є кілька записувачів.

Операційний чекліст: «цей шар ніколи не повинен вивести хост із ладу»

  • Automount включено для всіх мережевих монтувань.
  • Встановлені таймаути монтування (device timeout і mount timeout).
  • Критичні сервіси не мають жорсткої залежності від віддаленого монтування, якщо це не передбачено дизайном.
  • Консистентність UID/GID забезпечена між клієнтами.
  • Є задокументована процедура «як відʼєднати зависле монтування».
  • Регулярно тестуєте відмови: перезавантаження сервера, обрив мережі, помилки DNS.

Питання й відповіді

1) Що ймовірніше не зависне: SSHFS чи NFS?

SSHFS менш ймовірно зачепить ядро нескінченними повторними спробами так, як це робить hard NFS, але воно частіше буде ставати повільним або розʼєднуватися у нестабільних мережах.
Для «не виводити хост із ладу» переможець — NFS з systemd automount і таймаутами.

2) Чи варто використовувати NFS hard чи soft монтування?

За замовчуванням обирайте hard для коректності, але поєднуйте з automount, щоб відмови не заморожували завантаження чи старт сервісів.
Використовуйте soft тільки коли додаток толерує помилки I/O і ви віддаєте перевагу відмові, а не очікуванню.

3) Чому kill -9 не вбиває завислий процес на NFS?

Бо він застряг у незупинному сні в ядерному виклику в очікуванні завершення I/O. Сигнал фіксується, але доставиться тільки після повернення виклику.
Виправлення — відновити сервер/мережу або відʼєднати монтування (lazy unmount), щоб процес зміг розвернутись.

4) Чому SSHFS такий повільний у директоріях з великою кількістю дрібних файлів?

Операції з метаданими вимагають багато раунтріпів, а SSHFS додає простір користувача та накладні SFTP на кожну.
Для дрібнофайлових навантажень і спільних директорій зазвичай краще підходить NFS.

5) Чи вимагає NFSv4 rpcbind?

NFSv4 спроєктовано простіше і зазвичай використовує порт 2049 без старого portmapper, від якого залежало NFSv3.
Насправді в вашому середовищі можуть працювати суміжні RPC-сервіси, але у NFSv4 історія з фаєрволом простіша.

6) Які опції монтування найважливіші, щоб уникнути «випадкових зависань»?

Для обох: найважливіші — systemd automount і таймаути.
Для SSHFS специфічно: ServerAliveInterval, ServerAliveCountMax і reconnect.
Для NFS: явне vers=4.2, proto=tcp і усвідомлений вибір між hard та soft.

7) Як звільнити хост, де все, що торкається монтування, зависло?

Спочатку перестаньте торкатись його. Потім відновіть сервер/мережу, якщо можливо. Якщо треба повернути хост негайно, використайте umount -l на точці монтування.
Якщо присутній SSHFS, зупиніть процес sshfs (systemd-юнит) і потім зробіть lazy unmount.

8) Чи «достатньо безпечний» SSHFS у порівнянні з NFS?

SSHFS базується на SSH, тож за замовчуванням шифроване і аутентифіковане. NFS також може бути безпечним, але його потрібно налаштовувати — часто з Kerberos для сильної автентифікації.
Для недовірених мереж SSHFS простіший в експлуатації. Для довіреного LAN продакшну NFS зазвичай стабільніший інструмент.

9) Використовувати /etc/fstab чи systemd-юнити?

Для NFS /etc/fstab з x-systemd.automount підходить і простий в управлінні в масштабі.
Для SSHFS systemd-юнити часто чистіші, бо це демон у просторі користувача з потребою в життєвому циклі.

10) А що з блокуванням файлів і коректністю для збірних систем?

Якщо ваша збірна система залежить від семантики блокувань і кількох записувачів, NFSv4 зазвичай дає кращі шанси на коректність ніж SSHFS.
Але реальна відповідь архітектурна: уникайте використання розподіленої файлової системи як бази координації, якщо можете.

Наступні кроки, які ви можете зробити сьогодні

Якщо зробите лише три речі, зробіть ці:

  1. Переведіть мережеві монтування на systemd automount з явними таймаутами. Це саме по собі запобігає найпрининішим зависанням.
  2. Обирайте семантику відмов свідомо: NFS hard для коректності, soft лише там, де помилки прийнятні. Припиніть успадковувати значення за замовчуванням як політику.
  3. Прогоніть діагностику у спокійні години: зафіксуйте базовий nfsstat -m, підтвердіть DNS, портову досяжність і симулюйте відключення сервера.

Потім будьте трохи безжальні: якщо додаток не може терпіти дивну поведінку віддаленої файлової системи, не давайте йому таку залежність.
Замініть «спільну директорію як інтеграційний шар» на публікацію артефактів, локальний кеш або повноцінний сервіс. Ваш майбутній on-call ви помітить.

← Попередня
Debian 13: Ротація SSH-ключів — відкликайте доступ чисто та уникайте розростання ключів (випадок №13)
Наступна →
Збої TLS-рукопотискання в SMTP: як правильно виправити сертифікати, шифри й ланцюги

Залишити коментар