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

zac*_*han 5 server nfs networking systemd 16.10

摘要: 有没有办法确保 NFS 服务器不会由 systemd 启动,直到它可以正确解析 中指定的客户端计算机名称/etc/exports

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

服务器/etc/exports仅包含:

/mnt/raidarray clientmachine(rw)
Run Code Online (Sandbox Code Playgroud)

哪里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.
Run Code Online (Sandbox Code Playgroud)

NetworkManager-wait-online.service已启用,我已经理解这有助于确保network.targetnfs-server取决于)在满足之前network-online.target不满足。

没有帮助的事情

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

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

  3. 添加 Wants和/或After依赖于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
Run Code Online (Sandbox Code Playgroud)

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

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

zac*_*han 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()
Run Code Online (Sandbox Code Playgroud)

我将该脚本保存为/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
Run Code Online (Sandbox Code Playgroud)

这工作得很好,尽管它确实感觉有点黑客,并且可以在很多方面进行改进。(在这种情况下,我最终放弃了 NFS;它带来的痛苦超过了它的价值。)