概要:/etc/exports
で指定されたクライアントマシン名を適切に解決できるまで、NFSサーバーがsystemdによって起動されないようにする方法はありますか?
問題の説明:サーバー(16.10を実行)が再起動した後、NFS共有が適切に使用可能にならないことがわかりました。 exportfs -ra
またはservice 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
が依存する)が満たされないことを確認するのに役立ちます。
助けにならなかったもの:
NetworkManager-wait-online.service
の機能を誤解した場合、明示的にAfter=network-online.target
とWants=network-online.target
をnfs-server.service
に追加してみました。これは何も修正しません。 systemctl list-dependencies
に新しい依存関係が表示されますが、ブート時に名前解決が失敗します。したがって、network-online.target
はホスト名の解決が保証されるわけではないようです。
一部のグーグルは、nss-lookup.target
を要求することでネットワーク解像度が利用できることを保証することを示唆しましたが、それをWants
および/またはAfter
依存関係としてnfs-server.service
に追加しても問題は解決しません!
systemd-resolved.service
の代わりにnss-lookup.target
にWants
および/またはAfter
依存関係を追加しても、問題は修正されません。
これらの依存関係をすべて追加した後、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
にハードコーディングできましたが、これはやや脆いようです。より良い答えはありますか?
EDIT-更新:以下の@muruのアドバイスに従って、ホスト名の解決を待つスクリプトを作成してみました(所要時間を確認するためだけです)。私のスクリプトは、systemd-resolved
が開始してから実際にホストを解決できるようになるまで数十秒待つ必要があります。これは非常に奇妙です。実際にローカルネットワーキングの問題なのだろうか?おそらくハードコードされた(そしておそらく@ mark-stosbergが示唆する自動更新)/etc/exports
または/etc/hosts
ファイルのように聞こえます。
@muruのコメントに基づいて、DNS解決まで待機するpythonスクリプトを作成しました。
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 __== '__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をあきらめました。それは価値があるというよりも苦痛でした。)
Ubuntu 16.04.03 LTSのインストールでも同じ問題が発生しました。
exportfsは再起動後に適切に実行されなかったため、nfs-kernel-serverは適切に起動しませんでした。
/etc/init.d/nfs-kernel-serverの開始ケースにスリープを追加しようとしましたが、助けにはなりませんでした。
また、いくつかのヒントを試しました https://discourse.osmc.tv/t/nfs-kernel-server-wont-start-on-boot/5936/7
/etc/rc.localに次の行を追加することで問題を解決しました
systemctl restart nfs-kernel-server
systemd
で実行しようとしていることに関しては、network-online
の後にサービスを開始するように設定することで、すでに最善を尽くしています。私はsystemd
の質問をたくさん読みましたが、これを行うとネットワークが完全にオンラインにならないという問題を報告しました。
IPアドレスを/etc/exports
または/etc/hosts
に入れることをお勧めします。これにより、起動時の重要なディスクマウントタスクが簡素化されます。
システムをより堅牢にするために、対象ホストのDNSが変更されたかどうかを定期的にチェックするcronジョブまたはsystemdタイマーを使用できます。その場合、/etc/hosts
を新しい値で自動的に更新します。