Блог "Дети ОИТа"
/поиск

Диагностика NFSv4

> [!INFO] Применимость > **ALT Linux 10.4–11.x** · только NFSv4.0/4.1/4.2 · сервер и клиент Linux · CLI/TTY · доступ `root` > > Цель: определить, находится ли проблема в DNS, TCP/2049, конфигурации ex

[!INFO] Применимость
ALT Linux 10.4–11.x · только NFSv4.0/4.1/4.2 · сервер и клиент Linux · CLI/TTY · доступ root

Цель: определить, находится ли проблема в DNS, TCP/2049, конфигурации export, правах, state recovery, клиентском mount или серверном хранилище.

Для NFSv4 не использовать showmount как основной диагностический инструмент. Он относится к старому протоколу MOUNT и может не показывать рабочие NFSv4 exports.

Оглавление

  • [[#Быстрый алгоритм|Быстрый алгоритм]]
  • [[#Сбор исходных данных|Сбор исходных данных]]
  • [[#Уровень 1. DNS и сеть|Уровень 1. DNS и сеть]]
  • [[#Уровень 2. Версия NFSv4|Уровень 2. Версия NFSv4]]
  • [[#Уровень 3. Сервер и exports|Уровень 3. Сервер и exports]]
  • [[#Уровень 4. Клиентский mount|Уровень 4. Клиентский mount]]
  • [[#Уровень 5. Права и ID mapping|Уровень 5. Права и ID mapping]]
  • [[#Уровень 6. Состояние NFSv4 и locks|Уровень 6. Состояние NFSv4 и locks]]
  • [[#Уровень 7. Backend storage сервера|Уровень 7. Backend storage сервера]]
  • [[#NFS server not responding|NFS server not responding]]
  • [[#Stale file handle|Stale file handle]]
  • [[#Процессы в состоянии D|Процессы в состоянии D]]
  • [[#Долгая загрузка или выключение|Долгая загрузка или выключение]]
  • [[#Kerberos-ошибки|Kerberos-ошибки]]
  • [[#Таблица ошибок|Таблица ошибок]]
  • [[#Сбор диагностического пакета|Сбор диагностического пакета]]
  • [[#Расширенная отладка|Расширенная отладка]]
  • [[#Что не делать|Что не делать]]
  • [[#Источники|Источники]]

Быстрый алгоритм

На клиенте:

su -
getent hosts <SERVER_FQDN>
timeout 3 bash -c '</dev/tcp/<SERVER_FQDN>/2049'
echo $?
mount -t nfs \
  -o nfsvers=4.2,proto=tcp,hard \
  <SERVER_FQDN>:/<EXPORT_PATH> \
  <MOUNTPOINT>

После ошибки:

journalctl -k -b -n 100 --no-pager

Если mount уже существует:

nfsstat -m
mountstats /<MOUNTPOINT>

На сервере:

systemctl status nfs --no-pager
cat /proc/fs/nfsd/versions
exportfs -v
ss -lntp | grep ':2049'
journalctl -b -u nfs --no-pager

Локализация:

Где сломалось Вероятный уровень
DNS NSS/DNS
TCP/2049 Маршрут, firewall, сервер
4.2 не монтируется, 4.1 работает Сервер не поддерживает 4.2
access denied by server /etc/exports, IP клиента, sec=
Mount есть, запись запрещена Unix-права, ACL, UID/GID
Mount зависает Сеть, сервер, backend storage
Stale file handle Export/FS был заменён или inode исчез
nobody ID mapping или отсутствующий пользователь
Kerberos ticket есть, доступа нет Principal mapping, sec=, ACL
После перезапуска сервера locks не возвращаются State recovery/grace/client identity

Сбор исходных данных

Зафиксировать:

ALT Linux client:
ALT Linux server:
Client kernel:
Server kernel:
nfs-utils:
Server FQDN:
Server IP:
Client IP:
Export:
Mountpoint:
Requested version:
Negotiated version:
Security flavor:
Когда началась проблема:
Что изменялось:
Есть ли другие работающие клиенты:

Команды клиента:

cat /etc/os-release
uname -a
mount.nfs -V
nfsstat -m
findmnt -rn -t nfs,nfs4 -o TARGET,SOURCE,FSTYPE,OPTIONS

Команды сервера:

cat /etc/os-release
uname -a
rpc.nfsd --version
exportfs -v
cat /proc/fs/nfsd/versions

Уровень 1. DNS и сеть

DNS

getent ahosts <SERVER_FQDN>
host <SERVER_FQDN>

Сравнить IP с ожидаемым.

Маршрут

ip route get <SERVER_IP>

Проверить:

интерфейс
source IP
gateway

TCP/2049

timeout 3 bash -c '</dev/tcp/<SERVER_FQDN>/2049'
echo $?

При наличии nc:

nc -vz -w 3 <SERVER_FQDN> 2049

Firewall клиента

nft list ruleset

Если используется iptables:

iptables -S
iptables -L -n -v

Не очищать firewall ради теста.

Firewall сервера

Проверить входящий TCP/2049:

nft list ruleset

Интерфейсные ошибки

ip -s link show <INTERFACE>
ethtool -S <INTERFACE> | grep -Ei \
'error|drop|crc|timeout|reset|miss'

MTU

ip link show <INTERFACE>

Для IPv4 MTU 1500:

ping -M do -s 1472 <SERVER_IP>

Мелкие операции могут работать, а крупные чтения зависать из-за MTU/VPN-проблем.

Уровень 2. Версия NFSv4

На клиенте проверить активный mount:

nfsstat -m

Ожидается:

vers=4.2

или:

vers=4.1

На сервере:

cat /proc/fs/nfsd/versions

Пример:

-3 +4 +4.0 +4.1 +4.2

Если 4.2 недоступна:

-4.2

проверить 4.1:

mount -t nfs \
  -o nfsvers=4.1,proto=tcp,hard \
  <SERVER_FQDN>:/<EXPORT_PATH> \
  <MOUNTPOINT>

Не проверять NFSv3 как fallback.

Проверка конфигурации сервера

grep -nA20 '^\[nfsd\]' /etc/nfs.conf

При наличии:

nfsconf --get nfsd vers3
nfsconf --get nfsd vers4
nfsconf --get nfsd vers4.1
nfsconf --get nfsd vers4.2

После изменения:

systemctl restart nfs

В рабочей среде перезапуск согласовать.

Уровень 3. Сервер и exports

Служба

systemctl status nfs --no-pager

Порт

ss -lntp | grep ':2049'

Активные exports

exportfs -v

Конфигурация

grep -vE '^[[:space:]]*(#|$)' /etc/exports

Перечитать exports

exportfs -rav

Проверить псевдокорень

Должен существовать один export:

fsid=0

Пример:

/srv/nfs4 10.20.30.0/24(ro,fsid=0,sync,no_subtree_check,root_squash,sec=sys)

Рабочая ветка:

/srv/nfs4/projects 10.20.30.0/24(rw,sync,no_subtree_check,root_squash,sec=sys)

Клиент монтирует:

server:/projects

а не:

server:/srv/nfs4/projects

если /srv/nfs4 определён как fsid=0.

Bind mount

Проверить:

findmnt /srv/nfs4/projects

Если export указывает на пустой каталог, а реальные данные должны быть bind-mounted, клиент увидит пустоту. Протокол исправен, человек забыл один уровень пирога.

Журнал

journalctl -b -u nfs --no-pager
journalctl -k -b --no-pager | grep -Ei 'nfsd|nfs'

Уровень 4. Клиентский mount

Точка

ls -ld <MOUNTPOINT>
findmnt --target <MOUNTPOINT>

Ручной mount

mount -v -t nfs \
  -o nfsvers=4.2,proto=tcp,hard \
  <SERVER_FQDN>:/<EXPORT_PATH> \
  <MOUNTPOINT>

После ошибки

journalctl -k -b -n 100 --no-pager

Параметры

nfsstat -m

Статистика mount

mountstats <MOUNTPOINT>
nfsiostat 1 5 <MOUNTPOINT>

Проверить fstab

grep -nE '[[:space:]]nfs[[:space:]]' /etc/fstab

Проверить systemd unit

systemctl list-units --type=automount --type=mount | grep -F '<UNIT_PREFIX>'
journalctl -b -u <UNIT.mount> -u <UNIT.automount> --no-pager

Уровень 5. Права и ID mapping

Клиент:

id <USER>

Сервер:

id <USER>

Сравнить UID/GID.

Проверить серверный путь:

namei -l <SERVER_PATH>
getfacl -p <SERVER_PATH>

Проверить export:

exportfs -v

Проверить idmap domain:

nfsidmap -d

на клиенте и сервере.

Проверить пользователя:

getent passwd <UID>
getent group <GID>

Очистить кеш после исправления:

nfsidmap -c

Симптомы:

Permission denied
nobody
nogroup
root не пишет

могут быть штатным результатом прав и root_squash, а не неисправностью NFS.

Уровень 6. Состояние NFSv4 и locks

NFSv4 является stateful-протоколом. Сервер хранит сведения о клиентах, open state и locks.

Активные клиенты сервера

Проверить:

command -v nfsdclnts

Если доступно:

nfsdclnts

Альтернативно:

cat /proc/fs/nfsd/clients/*/info 2>/dev/null

Client identifier

На клиенте:

cat /sys/module/nfs/parameters/nfs4_unique_id 2>/dev/null

Проверить hostname:

hostnamectl

Клонированные машины с одинаковой NFSv4 identity могут конфликтовать при state recovery.

Grace period

После рестарта сервера NFSv4 входит в grace period, во время которого клиенты восстанавливают state/locks.

Проверить журнал:

journalctl -b -u nfs --no-pager | grep -Ei \
'grace|reclaim|client|state'

Не перезапускать сервер повторно во время recovery без необходимости.

Locks

Проверить процессы:

lslocks

Проверить приложение на обоих клиентах. В NFSv4 locking встроен в протокол; параметры nolock и отдельный NLM к NFSv4 не относятся.

Уровень 7. Backend storage сервера

Проверить заполнение:

df -hT <SERVER_PATH>

Проверить inode:

df -ih <SERVER_PATH>

Проверить read-only:

findmnt -no OPTIONS <SERVER_PATH>

Проверить дисковую нагрузку:

iostat -xz 1

Проверить ошибки:

journalctl -k -b --no-pager | grep -Ei \
'I/O error|Buffer I/O|read-only|EXT4-fs error|XFS.*error|BTRFS.*error|reset|timeout'

Проверить RAID/LVM/Multipath по архитектуре сервера.

NFS-клиент может сообщать:

server not responding
I/O error

когда сеть исправна, но серверная ФС или СХД зависла.

NFS server not responding

На клиенте

journalctl -k -b --no-pager | grep -Ei \
'NFS: server|not responding|timed out'

Проверить TCP:

timeout 3 bash -c '</dev/tcp/<SERVER>/2049'

Проверить route:

ip route get <SERVER_IP>

Проверить retransmissions:

ss -tin dst <SERVER_IP>:2049
nstat -az | grep -E 'TcpRetransSegs|TcpExtTCPLostRetransmit'

На сервере

systemctl status nfs --no-pager
ss -lntp | grep ':2049'
top
iostat -xz 1
journalctl -k -b -n 200 --no-pager

Не менять hard на soft

soft может заставить приложение получить ошибку вместо ожидания и не лечит причину недоступности сервера.

Stale file handle

Причины:

  • файл или каталог удалён и создан заново;
  • export перенесён;
  • серверная ФС пересоздана;
  • изменился filesystem identity;
  • bind mount заменён;
  • клиент сохранил старый file handle;
  • failover выдал другой backend без согласованной identity.

Проверка

Клиент:

journalctl -k -b --no-pager | grep -i 'stale'
findmnt <MOUNTPOINT>

Сервер:

findmnt <SERVER_PATH>
stat <SERVER_PATH>

Исправление

Остановить приложение:

fuser -vm <MOUNTPOINT>

Отключить:

umount <MOUNTPOINT>

Подключить заново:

mount <MOUNTPOINT>

Если ошибка возвращается, проверять backend identity и export path.

Не удалять рабочий серверный каталог и не создавать его заново ради сброса stale handle.

Процессы в состоянии D

Показать:

ps -eo pid,ppid,state,wchan:32,cmd | \
grep -E '^[[:space:]]*[0-9]+[[:space:]]+[0-9]+[[:space:]]+D'

Проверить конкретный PID:

cat /proc/<PID>/stack
ls -l /proc/<PID>/fd

Если процесс ждёт NFS I/O, kill -9 не гарантирует немедленное завершение. Он завершится только после возврата из непрерываемого ожидания.

Действия:

  1. восстановить доступность сервера;
  2. проверить backend storage;
  3. остановить приложение штатно;
  4. отключить mount после освобождения;
  5. аварийно использовать umount -l, если ресурс больше не будет возвращён.

Долгая загрузка или выключение

Проверить fstab:

grep -nE '[[:space:]]nfs[[:space:]]' /etc/fstab

Рекомендуемые параметры:

_netdev
nofail
x-systemd.automount
x-systemd.mount-timeout=30s
x-systemd.idle-timeout=300

Показать critical chain:

systemd-analyze critical-chain

Проверить units:

systemctl list-units --type=automount --type=mount | grep -i nfs

Журнал:

journalctl -b -u <UNIT.mount> -u <UNIT.automount> --no-pager

Не использовать soft как средство ускорения загрузки. Для этого существует automount и timeout первоначального подключения.

Kerberos-ошибки

Проверить mount:

nfsstat -m

Проверить ticket:

klist -ef

Проверить время:

timedatectl

Проверить DNS:

getent hosts <SERVER_FQDN>

Проверить gssd:

systemctl list-units --all | grep -E 'gssd|nfs'
journalctl -b --no-pager | grep -Ei \
'gssd|gss|kerberos|nfs'

Проверить keytab сервера:

klist -k /etc/krb5.keytab

Ожидается principal:

nfs/<SERVER_FQDN>@<REALM>

Проверить export:

exportfs -v

sec=krb5p на клиенте должен быть разрешён сервером.

Таблица ошибок

Сообщение Основные причины
Protocol not supported Клиент/сервер не поддерживает запрошенную minor version
Connection refused nfs не запущен, TCP/2049 закрыт
Connection timed out Сеть/firewall/server hang
access denied by server IP клиента, sec=, export path
No such file or directory Неверный путь относительно fsid=0
Permission denied Mode/ACL/UID/GID/root_squash/Kerberos
Stale file handle Backend/export identity изменён
NFS server not responding Сеть, nfsd, CPU, storage
NFS server OK Связь восстановилась после timeout
nobody/nogroup ID mapping/NSS
Required key not available Kerberos ticket/gssd/keytab
Operation not permitted ACL, root_squash, unsupported operation
Resource busy Открытые файлы или cwd
Mount работает, showmount пуст Для NFSv4 это возможно и нормально

Сбор диагностического пакета

Клиент

mkdir -p /root/nfsv4-diag-client
cat /etc/os-release \
  > /root/nfsv4-diag-client/os-release.txt
uname -a \
  > /root/nfsv4-diag-client/uname.txt
mount.nfs -V \
  > /root/nfsv4-diag-client/mount-nfs-version.txt 2>&1
nfsstat -m \
  > /root/nfsv4-diag-client/nfsstat-m.txt
mountstats \
  > /root/nfsv4-diag-client/mountstats.txt
findmnt -rn -t nfs,nfs4 -o TARGET,SOURCE,OPTIONS \
  > /root/nfsv4-diag-client/findmnt.txt
journalctl -k -b --no-pager \
  > /root/nfsv4-diag-client/kernel.txt
ip addr > /root/nfsv4-diag-client/ip-addr.txt
ip route > /root/nfsv4-diag-client/ip-route.txt
ss -tin > /root/nfsv4-diag-client/ss-tcp.txt

Сервер

mkdir -p /root/nfsv4-diag-server
exportfs -v \
  > /root/nfsv4-diag-server/exportfs.txt
cat /proc/fs/nfsd/versions \
  > /root/nfsv4-diag-server/versions.txt
journalctl -b -u nfs --no-pager \
  > /root/nfsv4-diag-server/nfs-service.txt
journalctl -k -b --no-pager \
  > /root/nfsv4-diag-server/kernel.txt
df -hT > /root/nfsv4-diag-server/df-hT.txt
df -ih > /root/nfsv4-diag-server/df-ih.txt

Архив:

tar -C /root -czf \
  /root/nfsv4-diag-client.tar.gz \
  nfsv4-diag-client

Не включать keytab и Kerberos credentials в диагностический архив.

Расширенная отладка

Использовать только на время воспроизведения.

Client RPC/NFS debug

Проверить:

command -v rpcdebug

Включить минимально необходимое:

rpcdebug -m nfs -s all

Воспроизвести одну ошибку.

Выключить:

rpcdebug -m nfs -c all

Для RPC:

rpcdebug -m rpc -s all

После теста:

rpcdebug -m rpc -c all

Проверить журнал:

journalctl -k -b -n 500 --no-pager

Отладка создаёт много сообщений. Не оставлять включённой.

Packet capture

tcpdump -i <INTERFACE> \
  -s 0 \
  -w /root/nfsv4-2049.pcap \
  host <SERVER_IP> and tcp port 2049

PCAP может раскрывать имена, операции и при sec=sys содержимое NFS-трафика. Передавать только доверенным специалистам.

Что не делать

  • Не проверять NFSv4 только через showmount.
  • Не включать NFSv3 ради диагностики.
  • Не менять hard на soft для сокрытия зависаний.
  • Не перезапускать сервер до сбора state и журналов.
  • Не очищать firewall целиком.
  • Не удалять и не создавать заново export path при stale handle.
  • Не применять kill -9 как лечение процессов D.
  • Не включать весь rpcdebug навсегда.
  • Не копировать keytab в диагностический архив.
  • Не считать доступный TCP/2049 доказательством исправного backend storage.

Источники