如何确保 nfs-server 在能够解析主机名之前不会启动?(16.10)

如何确保 nfs-server 在能够解析主机名之前不会启动?(16.10)

概括:有没有办法确保 NFS 服务器在能够正确解析指定的客户端机器名称之前不会由 systemd 启动/etc/exports

问题描述:我发现服务器(运行 16.10)重新启动后,NFS 共享无法正常使用。客户端收到“服务器拒绝访问”错误,直到在服务器上手动运行exportfs -raservice nfs-server restart。此后,一切都按预期运行。

服务器/etc/exports仅包含:

/mnt/raidarray clientmachine(rw)

其中clientmachine是本地网络上 NFS 客户端计算机的主机名。

问题识别:(以下)的输出systemctl status nfs-server清楚地表明了问题:在 NFS 服务器启动时无法解析客户端的名称。

● nfs-server.service - NFS server and services
Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled
Active: active (exited) since Tue 2017-01-17 16:47:38 CST; 26min ago
Main PID: 1520 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 4915)
CGroup: /system.slice/nfs-server.service
Jan 17 16:47:38 servermachine exportfs[1511]: exportfs: Failed to resolve clientmachine
Jan 17 16:47:38 servermachine systemd[1]: Started NFS server and services.

NetworkManager-wait-online.service已启用,我已经明白用于确保network.target(取决于哪个)在满足nfs-server之前不会满足。network-online.target

没有帮助的事情

  1. 以防我误解了什么NetworkManager-wait-online.service,我尝试在 中添加显式的After=network-online.targetand Wants=network-online.targetnfs-server.service这并没有解决任何问题。我看到 中出现了新的依赖项systemctl list-dependencies,但名称解析在启动时仍然失败。因此,这似乎network-online.target不能保证主机名解析可以发生。

  2. 一些谷歌搜索表明,要求nss-lookup.target可以确保网络分辨率可用,但将其添加为Wants和/或After依赖项nfs-server.service也不能解决问题!

  3. 添加 Wantsand/orAfter依赖systemd-resolved.service而不是nss-lookup.target也不能解决问题。

添加所有这些依赖项后,nfs-server在启动过程的很晚的时候启动(就在桌面登录之前),但仍然无法解析主机。根据systemd-analyze plot,似乎nmbd此时卡住了,但我不知道这是否相关。

配置信息:这是 kubuntu 16.10 的桌面版本,基本上是全新安装。

NetworkManager.service已启用并且systemd-networkd.service已禁用 - 我没有更改默认设置。

以下是NetworkManager-wait-online服务定义:

[Unit]
Description=Network Manager Wait Online
Documentation=man:nm-online(1)
Requisite=NetworkManager.service
After=NetworkManager.service
Before=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/nm-online -s -q --timeout=30
RemainAfterExit=yes
[Install]
WantedBy=network-online.target

作为一种解决方法,我可以将 IP 地址而不是主机名硬编码到/etc/exports或中/etc/hosts,但这似乎有些脆弱。 有更好的答案吗?

编辑-更新:按照下面@muru的建议,我尝试编写一个脚本来等待解析主机名——只是为了看看需要多长时间。我的脚本在systemd-resolved启动后必须等待数十秒才能真正解析主机。这非常奇怪。我想知道这是否实际上是本地网络问题?听起来也许需要硬编码(并且可能是自动更新,正如@mark-stosberg 所建议的那样)/etc/exports/etc/hosts文件。

答案1

根据@muru 的评论,我编写了一个 python 脚本来等待 DNS 解析:

import socket
import time
import itertools

TIMEOUT = 30
HOSTS = ['stanford.edu', 'google.com', 'example.com']

def main():
    hosts = itertools.cycle(HOSTS)
    t0 = time.time()
    for host in hosts:
        t = time.time()
        elapsed = t - t0
        if elapsed > TIMEOUT:
            break
        try:
            socket.getaddrinfo(host, None, proto=socket.IPPROTO_TCP)
            print('Resolved {} at t = {}'.format(host, elapsed))
            break
        except socket.gaierror:
            print('Could not resolve {} at t = {}'.format(host, elapsed))
        time.sleep(0.25)
        t = time.time()

if __name__ == '__main__':
    main()

我将该脚本保存为/etc/systemd/system/nfs-server.service.d/wait_for_dns.py(必须先创建父目录),然后运行sudo systemctl edit --full nfs-server,并在其他 ExecStartPre 行之前添加以下内容:

ExecStartPre=/usr/bin/python3 /etc/systemd/system/nfs-server.service.d/wait_for_dns.py

效果不错,尽管感觉有点黑客化,而且可以在很多方面改进。(在这种情况下,我最终放弃了 NFS;它带来的痛苦比它的价值更大。)

答案2

就您要用 做什么而言systemd,您已经尝试做最好的事情,即将您的服务设置为在 之后启动network-online。我读了很多systemd问题,其他人也报告了这样做时网络无法完全在线的问题。

/etc/exports我建议按照您的建议输入 IP 地址/etc/hosts。这可以简化启动过程中重要的磁盘安装任务。

为了使系统更加强大,您可以使用 cron 作业或 systemd 计时器定期检查相关主机的 DNS 是否已更改。如果已更改,则自动/etc/hosts使用新值进行更新。

答案3

我在 ubuntu 16.04.03 LTS 安装中遇到了同样的问题。
重启后,exportfs 无法正常运行,因此 nfs-kernel-server 无法正常启动。
我尝试在 /etc/init.d/nfs-kernel-server 中的启动案例中添加 sleep ,但这没有帮助。
我还尝试了一些提示https://discourse.osmc.tv/t/nfs-kernel-server-wont-start-on-boot/5936/7
我最终通过在 /etc/rc.local 中添加以下行解决了该问题

systemctl restart nfs-kernel-server

答案4

今天遇到了同样的问题(我使用的是 AlmaLinux 8.6),并使用 systemctl edit nfs-server 进行了修复:

[Unit]  
Requires=network.target network-online.target  
After=network.target network-online.target  

相关内容