OCIでAnsible実行時、mountモジュールで /etc/fstab パースエラーに四苦八苦した話


OCI(Oracle Cloud Infrastructure)を利用することがあり、その中でAnsibleのmountタスクがエラーになるケースがあったので紹介します。
といっても仕事の中でのことだったのと、あれこれ細かな課題対応が続発するなかでのこと。エラー発生時のキャプチャや具体的なエラーメッセージの内容を示せませんがご容赦ください。

発生条件

  • OCIのDB System(VM/BM)やComputeを利用している。
  • mountモジュールで state=mounted を指定してマウントを行おうとしている。

他にも条件があるはずです。Googleで検索をしても類似事象を見つけられなかたことからそう推測しています。
ひとまず分かったのはここまでです。

Playbookではmountモジュールに state=mounted を指定しています。
このためモジュールは、「指定されたデバイスが指定されたマウントポイントにマウントされていることを確認、されていなければマウント、加えて /etc/fstab ファイルにそのマウントの定義情報を書き込んで再起動後もマウントが約束されるようにする」ところまで行ってくれます。

発生事象

mountモジュールの処理がエラーとなりPlaybookの実行が中断されます。
エラーメッセージとしては /etc/fstab のパースに失敗した云々の内容が出力されます。

fatal: [(hostname)]: FALED! => {"changed": false, "msg": "Error mounting (mount point): mount: /etc/fstab: parse error: ignore entry at line (line number). \nmount: can't find (mount point) in /etc/fstab\n"}

/etc/fstab の内容を確認すると、本来「既存エントリーの次の行に、つまり改行を挟んで、新規エントリーを追加」しなくてはならないところが「既存エントリーの末尾にそのまま、つまり改行なしに、新規エントリーを追加」してしまっている状態。

期待される書式:

<device><TAB><mount point><TAB>...<TAB><file system check order><LF>
<device><TAB><mount point><TAB>...<TAB><file system check order><LF>
<device><TAB><mount point><TAB>...<TAB><file system check order><LF>
...

実際の書き込まれた書式:

<device><TAB><mount point><TAB>...<TAB><file system check order><LF>
<device><TAB><mount point><TAB>...<TAB><file system check order><device><TAB><mount point><TAB>...<TAB><file system check order><LF>
...

なるほどこれではパースに失敗するだろうな、仮にこの状態で /etc/fstab に基づきマウントが実行されたら既存エントリーで定義されたマウントも一蓮托生でエラーになるだろうな、という状態です。

ちなみにこの不正な「新規エントリー」部分をvi等で削除したり、「既存エントリー」と「新規エントリー」の間に改行を挿入してやったりしてからPlaybookを再実行すると今度は正常に処理ができます。後者の改行挿入はともかく前者の「一旦消せば次は成功」という動作はちょっと不可思議です。

回避策

mountモジュールのまえにlineinfileモジュールで「先頭に改行文字を持つfstabエントリーを挿入」してしまいました。とても雑な対応ですがこれで後続のmountモジュールは動作するようになりました。

原因

不明。

なんとなくの推測としては、Ansibleのmountモジュールは /etc/fstab ファイルの末尾、既存の最後のエントリーの行末に、改行文字がもともと入っていることを前提にしているのではないか、ところが私が作業していた環境では(何らかの理由で)そうなっておらず、「既存エントリーの直後に、改行なしに、新規エントリーを挿入」ということになったのではないか、──と想像しています。