Red Hatの森若です。
systemdの前後関係で問題が発生することが原因で、NFS mountに失敗することがあります。
実際の問題で困っている人は以下のナレッジ記事をどうぞ :)
今回はこの背景を簡単に紹介します。
systemdによる前後関係の矛盾検出
systemdはどのunitをいつ起動するかを、After= および対応する Before= で管理しています。
この定義はシステム起動やシャットダウン時のような、複数のunitのstart/stopが関連する操作の時に利用され、systemdはこの前後関係が満たされる範囲で並列にstart/stopをおこないます。
以下では「unit Aを開始する」を A/start と記述します。
systemdは、実際に起動の操作をおこなう前の計画段階で矛盾を検出します。ここで言う「矛盾」は、前後関係にループが作成されることです。
たとえば 以下のようになっているとループが発生します。
- A/start のあとに B/start
- B/start のあとに C/start
- C/start のあとに A/start
systemd-fstab-generator による fstabから mount unitの作成
systemdは、/etc/fstab を直接扱えませんが、fstabで定義されたmountをどのような順番で実行するかを決めるのはsystemdです。
systemdの起動直後、rootファイルシステム変更、systemctl daemon-reload 実行時等のタイミングでsystemd-fstab-generator というプログラムが /etc/fstabを読み込み、systemd用の unit fileを /run/systemd/generator/ 以下に生成します。そのため、fstabを編集したあとにはsystemctl daemon-reload を実行して unit fileを再生成して読み込み直す必要があります。
mount unit の名前では、mount pointを一定の規則で置き換えた、以下のような名前が利用されます。
/は-.mount/varは var.mount/boot/efiはboot-efi.mount
シンプルな例
/etc/fstab
UUID=xxxx / xfs defaults 0 0 10.0.0.100:/exp /mnt nfs defaults 0 0
いろいろ省略していますが、関連する前後関係はこのようになります。

この場合、 -.mount/start、NetworkManager.service/start、mnt.mount/startの順に実行して特に問題になりません。
問題のある例
/mnt/opt/foo を /opt/foo にbind mountすることにします。
/etc/fstab
UUID=xxxx / xfs defaults 0 0 10.0.0.100:/exp /mnt nfs defaults 0 0 /mnt/opt/foo /opt/foo none bind 0 0

この場合、opt-foo.mount/start が local-fs.target(ローカルファイルシステムのmountが完了したことを示すtarget unit) より先にある必要があるため、矛盾が発生しています。このように実行順が決まらない場合、systemdはサイクル内に登場するランダムなjobを間引いて解決します。
どのunitの起動が間引かれるかは起動毎にかわるので、サイクルをそのままにすると、mnt.mount/startに失敗したり、opt-foo.mount/startに失敗したり、NetworkManager.service/start に失敗するような、部分的な問題が発生します。
問題修正した例
この例の場合、問題の解決は簡単で、 bind mountの行に _netdev オプションを追加するだけです。
/etc/fstab
UUID=xxxx / xfs defaults 0 0 10.0.0.100:/exp /mnt nfs defaults 0 0 /mnt/opt/foo /opt/foo bind,_netdev 0 0

なぜ直るのか?
_netdev の有無であっさり動作がかわりました。
これは systemd-fstab-generator の動作によるもので、/etc/fstab 内でファイルシステムが nfs や cifs 等である場合や _netdev がある場合にはBefore=remote-fs.target を、そうでない場合には Before=local-fs.target を指定します。 興味がある方はソースを辿ってみると詳細がわかります。