# NFS - сетевая файловая система _Протоколы · LinuxLab Knowledge Base_ **TL;DR:** NFS - сетевая ФС от Sun. v3 - stateless, v4.1+ - stateful с делегациями и pNFS. /etc/exports на сервере, mount -t nfs на клиенте. root_squash, sync/async, lock manager - три главные опции. ## Зачем NFS Network File System, стандартный способ "примонтировать чужой диск по сети" в Unix. Прозрачно: open/read/write/close работают как с локальной ФС, всё кэшируется страничным кэшем. Используется для: - Shared home directories в корпоративных сетях - Storage для VM-images (KVM, Proxmox) - ML-датасеты, расшаренные между GPU-нодами - Backup-таргеты - Kubernetes Persistent Volumes (NFS-CSI driver) Альтернативы: SMB/CIFS (Windows-родной), [[cmd-rsync|rsync]] (для периодической синхронизации, не live-mount), CephFS/GlusterFS (распределённое), object-storage (S3, для не-POSIX). ## NFSv3 vs NFSv4 | Признак | v3 (1995) | v4.0 (2003) / v4.1 (2010) | |---------|-----------|---------------------------| | State | stateless | stateful | | Транспорт | UDP или TCP | TCP only | | Порты | 111 (rpcbind) + динамические | 2049 single port | | Lock manager | rpc.lockd (отдельный) | встроенный | | Auth | sys (uid/gid из RPC) | + Kerberos (krb5/krb5i/krb5p) | | Делегации | нет | да (read/write delegation) | | pNFS | нет | да в v4.1 (parallel NFS) | | ACL | POSIX через protocol-extension | NFSv4 ACL (Windows-style) | | Через NAT/firewall | сложно (динамические порты) | просто (one port) | **NFSv3 ещё жив** в legacy и embedded; для нового кода **NFSv4.1+**. ## Сервер: /etc/exports ```bash # Установка apt install nfs-kernel-server # Debian/Ubuntu dnf install nfs-utils # RHEL # Создать share mkdir -p /srv/nfs/data chown nobody:nogroup /srv/nfs/data ``` `/etc/exports`: ``` /srv/nfs/data 10.0.0.0/24(rw,sync,no_subtree_check,root_squash) /srv/nfs/backup 10.0.0.5(ro,sync,no_subtree_check) 10.0.0.6(rw,sync,no_subtree_check) /srv/nfs/krb5 *(rw,sync,sec=krb5p,no_subtree_check) ``` Применить: ```bash exportfs -ra # переэкспорт всех exportfs -v # покажет активные exports systemctl enable --now nfs-server ``` ## Главные опции exports | Опция | Что | |-------|-----| | `rw` / `ro` | права для подсети | | `sync` (default) | ответ клиенту только после fsync | | `async` | ответ сразу, fsync позже, **быстрее, но при крахе сервера данные теряются** | | `root_squash` (default) | root клиента маппится на nobody, защита | | `no_root_squash` | root клиента остаётся root'ом, **очень опасно** | | `all_squash` | все юзеры → nobody (для public-share) | | `anonuid=`, `anongid=` | в кого мапить squashed | | `subtree_check` / `no_subtree_check` | проверка что путь внутри export'а; `no_subtree_check` быстрее, default с modern | | `sec=sys|krb5|krb5i|krb5p` | sys = uid/gid доверенный; krb5 = аутентификация Kerberos; krb5i = + integrity; krb5p = + privacy | | `nohide` | для nested mount'ов на сервере | | `crossmnt` | пересекать mount-points при обходе | ## Клиент: mount ```bash apt install nfs-common # Debian mount -t nfs server:/srv/nfs/data /mnt/data mount -t nfs4 server:/srv/nfs/data /mnt/data ``` В [[mount-and-fstab|fstab]]: ```fstab server:/srv/nfs/data /mnt/data nfs4 rw,_netdev,vers=4.2,hard,timeo=600,retrans=3,nofail 0 0 ``` Главные mount-опции: | Опция | Что | |-------|-----| | `vers=4.2` | принудительная версия (default, auto-negotiate) | | `hard` (default) | при потере связи блокировать I/O пока не вернётся | | `soft` | возвращать I/O error после `timeo*retrans` мс, **опасно**, может портить данные | | `timeo=N` | timeout в децисекундах (`600` = 60 сек) | | `retrans=N` | сколько повторов до признания "сервер мёртв" | | `_netdev` | сначала поднять сеть (для systemd) | | `nolock` | без NLM (для read-only mount'ов) | | `nfsvers=3,proto=tcp,port=2049` | для жесткого pinning v3 | | `noatime` | как везде, выкл atime | | `nconnect=N` | (5.3+) N TCP-соединений к серверу, boost throughput | **`hard` vs `soft`**: всегда `hard`. `soft` теоретически даёт failover, на практике портит файлы при коротких сетевых разрывах. ## Кэширование и согласованность NFS не гарантирует строгого "записал на одной ноде → видно на другой немедленно". Модель, **close-to-open consistency**: при `close()` клиент flush'ит; при `open()` другой клиент проверяет mtime через GETATTR и инвалидирует кэш. Это значит: для shared-БД NFS не подходит (разные клиенты не увидят правки). Для shared home / build-output / ML-датасета, норм. ## Kerberos: sec=krb5p Без Kerberos NFS-клиент **сам говорит свой UID** через RPC AUTH_SYS доверие на уровне "у нас одни UID на всех машинах". В мульти-юзер enterprise-окружениях это слабо. С `sec=krb5p`, каждая операция аутентифицирована Kerberos-тикетом пользователя, payload зашифрован. Требует: - KDC ([kerberos](/kb/kerberos.md)) - Service principal `nfs/server.example.com@REALM` в keytab сервера - `idmapd.conf` для маппинга `user@REALM` → UID на клиентах Сложно, но единственный production-grade вариант для shared homes. ## NFSv3 vs NFSv4 firewall v3: - 111 (portmap/rpcbind) TCP/UDP - 2049 (nfs) TCP/UDP - mountd, statd, lockd, rquotad, динамические порты! - Решение: `/etc/nfs.conf` зафиксировать порты v4: - **2049 TCP only**, всё через один порт, в т.ч. lock manager - Через NAT работает без боли Это одна из главных причин миграции на v4. ## Когда что-то пошло не так - **`mount.nfs: Connection refused`**, nfs-server не запущен или не слушает 2049 (`ss -tlnp | grep 2049`). - **Зависает `ls /mnt/data` навсегда**, `hard`-mount, сервер недоступен. `umount -f -l /mnt/data` (lazy umount). - **`Stale file handle`**, файл удалён на сервере, клиент держит fd. `umount && mount` чинит. На v4.1+ менее частая проблема. - **Чужие файлы видны как `nobody:nogroup`**, нет idmapd-маппинга. На NFSv4 убедись что `nfs-idmapd` запущен и `Domain =` совпадает в `/etc/idmapd.conf` на обоих. - **Performance медленный на больших файлах**, `wsize=1048576,rsize=1048576`, `nconnect=4` (5.3+), и проверь jumbo frames на проводе. - **`Permission denied` несмотря на mode 777**, `root_squash` мапит root'а в nobody. Создавай файлы от обычного юзера, либо `no_root_squash` (только в trusted-сети!). - **Lockd не работает между host'ами**, на v3 нужны `rpc.statd` + portmap; на v4 встроено. Проверь firewall не режет статд-порт на v3. ## Альтернативы - **SMB/CIFS** (Samba), Windows-стандарт, работает и в Linux - **CephFS**, distributed, replicated, для масштаба - **GlusterFS**, то же, deprecated с поглощением Red Hat'а IBM - **sshfs** (FUSE), туннель через SSH, для разовых случаев - **S3/MinIO**, для не-POSIX object-storage ## Команды ```bash exportfs -v ``` Все активные NFS exports - что на самом деле отдаётся ```bash exportfs -ra ``` Перечитать /etc/exports без рестарта nfs-server ```bash showmount -e nfs.example.com ``` Со стороны клиента: какие share отдаёт удалённый сервер (только v3) ```bash mount -t nfs4 -o vers=4.2,hard,nconnect=4 server:/data /mnt/data ``` Mount с v4.2 + 4 параллельных TCP - boost throughput ```bash nfsstat -c ``` Статистика клиентских RPC-операций - сколько read/write/getattr ```bash rpcinfo -p server ``` Какие NFS-сервисы и порты слушает удалённый сервер - debug v3 firewall ```bash cat /proc/fs/nfsd/clients/*/info 2>/dev/null ``` Какие клиенты держат connection к NFSv4-серверу прямо сейчас ## См. также - [mount и /etc/fstab - подключение ФС](/kb/mount-and-fstab.md) - [rsync - инкрементальная синхронизация файлов](/kb/cmd-rsync.md) - [TCP three-way handshake](/kb/tcp-handshake.md) - [UDP - User Datagram Protocol](/kb/udp-basics.md) - [File permissions: rwx и chmod](/kb/file-permissions.md) - [Kubernetes storage - PV, PVC, StorageClass, CSI](/kb/kubernetes-storage.md)