Назад | Перейти на главную страницу

mount.nfs: не удалось разрешить сервер

У меня проблема с клиентом nfs, который не может разрешить разрешаемое имя DNS.

[root@testserver-2 ~]# host nfs-server-host-name
nfs-server-host-name has address 10.37.4.131

[root@testserver-2 ~]# nslookup nfs-server-host-name
Server:         127.0.0.1
Address:        127.0.0.1#53

Name:   nfs-server-host-name
Address: 10.37.4.126

[root@testserver-2 ~]# showmount -e nfs-server-host-name
clnt_create: RPC: Unknown host

[root@testserver-2 ~]# ss -lnp |grep rpc
LISTEN     0      128                       *:111                      *:*      users:(("rpcbind",7627,8)

[root@testserver-2 ~]# mount -t nfs -o defaults,auto,proto=tcp nfs-server-host-name:/ifs/exports/EXPORT /mnt/export
mount.nfs: Failed to resolve server nfs-server-host-name: Name or service not known

Локальное разрешение настраивается через dnsmasq:

[root@testserver-2 ~]# cat /etc/resolv.conf
options rotate timeout:2 attempts:4
nameserver 127.0.0.1
nameserver 10.1.1.1
nameserver 8.8.8.8

[root@testserver-2 ~]# cat /etc/dnsmasq.conf 
resolv-file=/etc/resolv.conf
server=/nfs-server-host-name/10.37.4.1 #IP address of Isilon smart connect resolver
listen-address=127.0.0.1

Конфигурация nsswitch (по умолчанию Centos 6):

[root@testserver-2 ~]# grep hosts /etc/nsswitch.conf
hosts:      files dns

Обратите внимание, что nfs-server-host-name разрешение обрабатывается резолвером Isilon smart connect, который настроен как резолвер для nfs-server-host-name локально через dnsmasq и работает (как показано в примере выше). Замена nfs-server-host-name с IP-адресом не вариант, поскольку существует несколько узлов NFS, которые сбалансированы преобразователем, поэтому IP-адрес является переменным и не может быть жестко задан. Поэтому нормально, что два приведенных выше результата от hosts и nslookup различаются. Это предполагаемое и ожидаемое поведение.

Также обратите внимание, что nfs-server-host-name - очень точный пример того, как выглядит имя хоста. Фактическое имя хоста выглядит почти идентично, это не полное доменное имя. На самом деле в имени хоста вообще нет точек. Я не контролирую эту функцию.

При монтировании вручную с одним действующим IP-адресом узла экспорт монтируется нормально. Когда адрес одного узла помещается в /etc/hosts, он монтируется. При разрешении с помощью средств DNS он не работает для клиента nfs, но работает для других сетевых инструментов, таких как hosts, dig или ping.

Кажется, это не такая уж редкая проблема, но все советы, которые я нашел до сих пор, говорят «замените имя хоста на IP», что я не могу сделать.

Что я упустил?

Я еще не понял, что за настоящий проблема есть, но решение - удалить rotate вариант от /etc/resolv.conf и поставить точку после nfs-server-host-name в /etc/fstab для предотвращения поиска домена (который происходил, даже когда не было search вариант в /etc/resolv.conf), то есть:

nfs-server-host-name.:/nfs/export/...
                    ^
                    ^---up here

Это может иметь какое-то отношение к параметру сборки ядра CONFIG_NFS_USE_LEGACY_DNS, для которого установлено значение да на моем ядре.

Поведение nfs-client (и только nfs-client) заключалось в том, что он запрашивал только второй сервер имен в /etc/resolv.conf сколько бы их ни было, пока rotate вариант присутствовал. Однако это сработало, когда вообще не было второго сервера имен. Бьет меня ...

В showmount команда имеет вызов RPC, который использует gethostbyname_r чтобы попытаться получить информацию для имени хоста. Он не очень хорошо интерпретирует возвращаемые им ошибки. Не могли бы вы запустить тест, чтобы узнать, в чем на самом деле ошибка? Этот код модифицирован из фактического glibc clnt_gen.c код видел Вот

Пример исходного кода C:

#include <netdb.h>
#include <alloca.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(int argc, char **argv)
{
    struct hostent hostbuf, *h;
    size_t hstbuflen;
    char *hsttmpbuf;
    char *hostname;
    int herr;

    if (argc != 2)
    {
      exit(-1);
    }
    hostname = argv[1];

    hstbuflen = 1024;
    hsttmpbuf = alloca(hstbuflen);
    while (gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen, &h, &herr) != 0 || h == NULL)
    {
        if (herr != NETDB_INTERNAL || errno != ERANGE)
        {
            printf("gethostbyname_r error: %s\n", hstrerror(herr));
            exit(0);
        }
        else
        {
            hstbuflen *= 2;
            hsttmpbuf = alloca (hstbuflen);
        }
    }
}

Сохраните это как ghbntest.c и скомпилируйте с помощью команды gcc -o ghbntest ghbntest.c. Запуск с использованием ./ghbntest nfs-server-host-name. Пример вывода:

$ ./ghbntest 12345.example.com
gethostbyname_r error: Unknown host