Ansibleで学ぶmountモジュール:よくあるエラーと解決策
mount
モジュールの主な機能と特徴
- 主要なパラメータ:
path
(旧name
): マウントポイントのパス(例:/mnt/data
)。必須パラメータです。src
: マウントするデバイスのパス(例:/dev/sdb1
やUUID=...
、NFS共有のパスなど)。state
がpresent
またはmounted
の場合に必須です。fstype
: ファイルシステムの種類(例:ext4
,xfs
,nfs
など)。state
がpresent
またはmounted
の場合に必須です。opts
: マウントオプション(例:defaults
,ro
,noatime
など)。/etc/fstab
のオプションとして設定されます。dump
:fstab
のdump
フィールドを設定します。passno
:fstab
のpassno
フィールドを設定します。fstab
: デフォルトの/etc/fstab
以外のファイルを指定する場合に利用します。通常は使用しません。backup
:fstab
を変更する際にバックアップを作成するかどうかを指定します。
- 状態 (state) パラメータ:
mount
モジュールはstate
パラメータを通じて、マウントポイントの望ましい状態を指定します。主なstate
の値は以下の通りです。mounted
: デバイスをマウントし、必要に応じて/etc/fstab
にもエントリを追加します。マウントポイントのディレクトリが存在しない場合は作成されます。unmounted
: デバイスをアンマウントしますが、/etc/fstab
のエントリは変更しません。present
:/etc/fstab
にエントリがあることを保証しますが、実際にマウントは行いません。absent
:/etc/fstab
からエントリを削除し、マウントされている場合はアンマウントし、マウントポイントのディレクトリも削除します。ephemeral
(Ansible 1.5.0以降のansible.posix.mount
モジュールで追加): デバイスをマウントしますが、/etc/fstab
にはエントリを追加しません。一時的なマウントに便利です。remounted
(Ansible 2.9以降で追加): 既にマウントされているデバイスを再マウントします。主にマウントオプションを変更した場合などに使用します。
- 冪等性 (Idempotency): Ansible の多くのモジュールと同様に、
mount
モジュールも冪等性を持っています。これは、Playbook を複数回実行しても、システムの状態が既に目的の状態であれば、余計な変更は行われないことを意味します。例えば、既にマウントされているものを再度マウントしようとしても、変更は発生しません。 - マウントポイントの制御:
- マウント: デバイスをディレクトリにマウントします。
- アンマウント: マウントされているデバイスをアンマウントします。
/etc/fstab
の管理: システム起動時に自動的にマウントされるように/etc/fstab
にエントリを追加したり、既存のエントリを変更・削除したりできます。
---
- name: マウントポイントを管理する例
hosts: your_target_servers
become: yes # root 権限で実行する必要があるため
tasks:
- name: /dev/sdb1 を /mnt/data に ext4 としてマウントし、fstab にも追加する
ansible.posix.mount: # または mount: (FQCNを使用することが推奨されます)
path: /mnt/data
src: /dev/sdb1
fstype: ext4
opts: defaults
state: mounted
- name: /mnt/backup が fstab に存在することを保証する(マウントはしない)
ansible.posix.mount:
path: /mnt/backup
src: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # UUID を使用することも可能
fstype: xfs
opts: defaults
state: present
- name: /mnt/old_data をアンマウントする(fstab は変更しない)
ansible.posix.mount:
path: /mnt/old_data
state: unmounted
- name: /mnt/obsolete の fstab エントリを削除し、アンマウントし、ディレクトリも削除する
ansible.posix.mount:
path: /mnt/obsolete
state: absent
- name: /mnt/temp_share を一時的にマウントする (fstabには記録しない)
ansible.posix.mount:
path: /mnt/temp_share
src: 192.168.1.100:/share
fstype: nfs
opts: defaults
state: ephemeral
よくあるエラーとその原因
a. path
(マウントポイント) の問題
- 原因:
- 指定された
path
(マウントポイント) が存在しない、または権限がないために作成できない。 - マウントポイントが既に別のファイルシステムによって使用されている、またはプロセスがそのディレクトリを使用しているため、アンマウントできない(
unmounted
やabsent
の場合)。 state: mounted
を使用しているが、マウントポイントのディレクトリが既存のファイルシステムで既に使われている。
- 指定された
- エラーメッセージの例:
"msg": "mount point /mnt/data does not exist"
(Ansibleがマウントポイントのディレクトリを作成できない場合)"msg": "Error mounting /dev/sdb1 on /mnt/data: mount: /mnt/data: mount point is busy."
b. src
(デバイス/ソース) の問題
- 原因:
src
で指定されたデバイス(例:/dev/sdb1
)が存在しない、または名前が間違っている。- デバイスが既に別の場所にマウントされている。
- ファイルシステムタイプ (
fstype
) が間違っている、またはデバイスがそのファイルシステムタイプでフォーマットされていない。 - NFSなどのネットワークファイルシステムの場合、サーバーへの接続性がない、または共有が存在しない。
- エラーメッセージの例:
"msg": "Error mounting /dev/sdb1 on /mnt/data: mount: /dev/sdb1: no such device"
"msg": "Error mounting /dev/sdb1 on /mnt/data: mount: /dev/sdb1 is already mounted on /another/path."
"msg": "Error mounting /dev/sdb1 on /mnt/data: mount: wrong fs type, bad option, bad superblock on /dev/sdb1, missing codepage or helper program, or other error."
c. fstype
(ファイルシステムタイプ) の問題
- 原因:
fstype
パラメータに存在しない、またはサポートされていないファイルシステムタイプを指定した。- 指定されたデバイスが、実際にそのファイルシステムタイプでフォーマットされていない。
- エラーメッセージの例:
"msg": "Error mounting /dev/sdb1 on /mnt/data: mount: unknown filesystem type 'xyzfs'"
d. opts
(マウントオプション) の問題
- 原因:
opts
に無効なマウントオプションを指定した。
- エラーメッセージの例:
"msg": "Error mounting /dev/sdb1 on /mnt/data: mount: /mnt/data: bad option 'bad_option_name'."
e. 権限の問題
- 原因:
- Ansible Playbook が
become: yes
(sudo/root 権限) なしで実行されている、またはリモートホストのユーザーにマウント操作を実行する権限がない。マウント操作は通常、root 権限が必要です。
- Ansible Playbook が
- エラーメッセージの例:
"msg": "mount: permission denied"
f. /etc/fstab
の同期に関する問題
- 原因:
state: mounted
やstate: present
で/etc/fstab
にエントリを追加したはずが、何らかの理由で書き込みに失敗した。fstab
ファイルが破損している、または不正なエントリがある。
- エラーメッセージの例:
- Ansible の出力では直接的なエラーメッセージではなく、マウントは成功したが再起動後にマウントされない、などの挙動で現れることがあります。
a. 詳細なデバッグ出力の確認
- Ansible の実行時に
-vvv
または-vvvv
オプションを追加して、詳細なデバッグ情報を確認します。
これにより、ansible-playbook your_playbook.yml -vvv
mount
コマンドがバックグラウンドでどのように実行され、どのようなエラーメッセージが返されているかを確認できます。
b. リモートホストでの手動実行の試行
- Ansible を実行しているリモートホストに SSH でログインし、Playbook が実行しようとしている
mount
コマンドを手動で試してみます。- 例:
sudo mount /dev/sdb1 /mnt/data
- 例:
sudo umount /mnt/old_data
- 手動で実行することで、Ansible の問題なのか、基盤となるOSレベルの問題なのかを切り分けることができます。エラーメッセージがより明確に出力されることが多いです。
- 例:
c. 前提条件の確認
- マウントポイントディレクトリの確認:
ls -ld /mnt/data
でマウントポイントのディレクトリが存在するか、権限は適切かを確認します。state: mounted
を使用する場合、通常はディレクトリが自動作成されますが、権限の問題などで作成できない場合はエラーになります。file
モジュールで事前に作成することも検討できます。
- ファイルシステムの確認:
sudo blkid /dev/sdb1
でデバイスのUUIDやファイルシステムタイプを確認し、Playbook のsrc
やfstype
と一致しているか確認します。
- デバイスの存在確認:
lsblk
やfdisk -l
、df -h
コマンドを使って、指定したデバイス (src
) が実際に存在し、認識されているかを確認します。- NFS の場合、
ping
やshowmount -e <NFS_SERVER_IP>
でサーバーへの到達性や共有の存在を確認します。
d. マウントポイントの「busy」状態の解消
mount point is busy
エラーの場合、そのマウントポイントを使用しているプロセスを特定して終了させる必要があります。lsof | grep /mnt/data
またはfuser -m /mnt/data
を実行して、どのプロセスがマウントポイントを使用しているかを確認します。- 必要であれば、これらのプロセスを終了させます。
- 強制的にアンマウントする場合は
sudo umount -l /mnt/data
(lazy unmount) やsudo umount -f /mnt/data
(force unmount) を手動で試すこともできますが、データ破損のリスクがあるので注意が必要です。
e. /etc/fstab
の整合性チェック
state: absent
でエントリが削除されない場合、手動で/etc/fstab
を確認し、該当エントリが存在しないか確認します。sudo findmnt --verify
コマンドで/etc/fstab
の構文チェックを行うことができます。/etc/fstab
に手動で誤ったエントリを追加していないか確認します。
f. 冪等性の理解と利用
state: present
とstate: mounted
の違いを理解し、適切に使い分けます。present
:/etc/fstab
にエントリがあることを保証しますが、マウントは強制しません。mounted
: マウントを強制し、必要に応じて/etc/fstab
にもエントリを追加します。
mount
モジュールは冪等性があるため、同じ設定で複数回実行しても問題ありません。エラーが出ている場合は、設定が間違っているか、環境に問題がある可能性が高いです。
g. block
/ rescue
を利用したエラーハンドリング
- Playbook で予期せぬエラーが発生した場合に備え、
block
とrescue
を利用してエラーハンドリングを行うこともできます。- name: マウントを試みる block: - ansible.posix.mount: path: /mnt/data src: /dev/sdb1 fstype: ext4 state: mounted rescue: - name: マート失敗時に通知する debug: msg: "マウント /mnt/data が失敗しました。ログを確認してください。" # 必要であれば、失敗したデバイスのログ収集や、別のリカバリタスクを実行
mount
モジュールを使う際の主要なパラメータは以下の通りです。
state
: マウントポイントの望ましい状態。fstype
: ファイルシステムの種類(例:ext4
,xfs
,nfs
)。src
: マウントするデバイスやソース(例:/dev/sdb1
、UUID=...
、NFSサーバーのパス)。path
: マウントポイントのパス(例:/mnt/data
)。
それぞれの state
に応じたコード例を見ていきましょう。
state: mounted - デバイスをマウントし、必要に応じて /etc/fstab に追加する
この state
は、デバイスが指定されたマウントポイントにマウントされていることを保証し、さらにシステム起動時に自動的にマウントされるよう /etc/fstab
にエントリを追加します。マウントポイントのディレクトリが存在しない場合は、自動的に作成されます。
---
- name: デバイスをマウントし、fstabにも追加する例
hosts: your_target_servers
become: yes # マウント操作にはroot権限が必要
tasks:
- name: /dev/sdb1 を /mnt/data に ext4 としてマウントし、fstab に永続化
ansible.posix.mount:
path: /mnt/data
src: /dev/sdb1
fstype: ext4
opts: defaults,noatime # オプションの指定
state: mounted
解説
state: mounted
: これにより、/dev/sdb1
が/mnt/data
にマウントされ、かつ/etc/fstab
に永続的なエントリが追加されます。opts: defaults,noatime
: マウントオプションとしてdefaults
(デフォルトのオプション) とnoatime
(ファイルのアクセス時刻の更新を無効化) を指定しています。fstype: ext4
: ファイルシステムの種類はext4
です。src: /dev/sdb1
: マウントするデバイスは/dev/sdb1
です。path: /mnt/data
:/mnt/data
がマウントポイントになります。もしこのディレクトリがなければ、Ansibleが自動的に作成します。
state: present - /etc/fstab にエントリがあることを保証する(マウントはしない)
この state
は、指定されたエントリが /etc/fstab
ファイル内に存在することを保証しますが、Playbook 実行時に実際にマウント操作は行いません。システム起動時にマウントされるように設定だけしておきたい場合に便利です。
---
- name: fstabにエントリを追加するが、マウントはしない例
hosts: your_target_servers
become: yes
tasks:
- name: UUID を使用して /mnt/backup の fstab エントリが存在することを確認
ansible.posix.mount:
path: /mnt/backup
src: UUID="a1b2c3d4-e5f6-7890-1234-567890abcdef" # デバイスのUUIDを指定
fstype: xfs
opts: defaults
state: present
解説
state: present
: これにより、/etc/fstab
にエントリが追加または更新されますが、Ansible Playbook の実行中にマウントはされません。マウントは次回のシステム起動時に行われるか、手動でmount /mnt/backup
と実行する必要があります。src: UUID="..."
: デバイスのパスの代わりに UUID (Universally Unique Identifier) を使うと、デバイス名(例:/dev/sdb1
)が変わっても確実に識別できるため、より堅牢な設定が可能です。sudo blkid
コマンドでデバイスの UUID を確認できます。
state: unmounted - マウントされたデバイスをアンマウントする
この state
は、指定されたマウントポイントがアンマウントされていることを保証します。/etc/fstab
のエントリは変更されません。
---
- name: デバイスをアンマウントする例
hosts: your_target_servers
become: yes
tasks:
- name: /mnt/old_data をアンマウントする (fstab は変更しない)
ansible.posix.mount:
path: /mnt/old_data
state: unmounted
解説
state: unmounted
: これにより、/mnt/old_data
がマウントされていればアンマウントされます。もし/etc/fstab
にこのマウントポイントのエントリがあっても、それはそのまま残ります。path: /mnt/old_data
: アンマウントするマウントポイントを指定します。
state: absent - /etc/fstab からエントリを削除し、アンマウントし、ディレクトリも削除する
この state
は、指定されたマウントポイントに関連する /etc/fstab
のエントリを削除し、もしマウントされていればアンマウントし、さらにマウントポイントのディレクトリも削除します。完全にクリーンアップしたい場合に便利です。
---
- name: マウントポイントとfstabエントリを完全に削除する例
hosts: your_target_servers
become: yes
tasks:
- name: /mnt/obsolete を fstab から削除し、アンマウントし、ディレクトリも削除
ansible.posix.mount:
path: /mnt/obsolete
state: absent
解説
state: absent
: この設定により、/mnt/obsolete
に関連する/etc/fstab
のエントリが削除され、もしマウントされていればアンマウントされ、そして/mnt/obsolete
ディレクトリ自体も削除されます。
state: ephemeral - 一時的にマウントする(/etc/fstab に追加しない)
この state
は、デバイスをマウントしますが、/etc/fstab
にエントリを追加しません。一時的なマウントや、Ansible 実行時のみ必要なマウントポイントを設定するのに適しています。Playbook の実行が完了すると、通常はマウントされたままですが、再起動すると消えます。
---
- name: 一時的なマウントの例 (NFS共有)
hosts: your_target_servers
become: yes
tasks:
- name: NFS共有を /mnt/temp_share に一時的にマウント
ansible.posix.mount:
path: /mnt/temp_share
src: 192.168.1.100:/exports/data # NFSサーバーのIPと共有パス
fstype: nfs
opts: defaults
state: ephemeral
state: ephemeral
: これにより、NFS共有が/mnt/temp_share
にマウントされますが、/etc/fstab
には何も書き込まれません。システムを再起動すると、このマウントは失われます。
ansible.builtin.command または ansible.builtin.shell モジュール
最も直接的な代替手段は、command
または shell
モジュールを使って、OS ネイティブのマウント関連コマンドを直接実行することです。これは、mount
モジュールでは対応できない特殊なケースや、非常に細かい制御が必要な場合に利用されます。
利点
- トラブルシューティング時に、Ansible から実行される実際のコマンドを確認しやすい。
mount
モジュールが提供しない特定のオプションや機能を利用できる。- 非常に柔軟性が高く、任意のコマンドを実行できる。
欠点
- 状態のチェックや変更の判断をスクリプト内でロジックとして書く必要がある。
- エラーハンドリングが手動になる。
- 冪等性 (Idempotency) の管理が複雑: ほとんどの
command
やshell
コマンドは冪等性を持たないため、タスクがシステムに不必要な変更を加えないように、自身で条件分岐 (when
) やchanged_when
を使用して冪等性を実装する必要があります。
コード例
a. mount コマンドを直接実行する
- name: commandモジュールでディスクをマウントする (非推奨)
hosts: your_target_servers
become: yes
tasks:
- name: /dev/sdb1 を /mnt/data にマウント(冪等性なし)
ansible.builtin.command: mount /dev/sdb1 /mnt/data
args:
creates: /mnt/data/.mounted_sdb1 # 既にマウントされている場合はスキップする簡単な冪等性対策
# 注意: fstabへの永続化は行われません
b. fstab を編集するために shell と grep/sed を使う (非推奨)
- name: shellモジュールでfstabを編集する (非推奨)
hosts: your_target_servers
become: yes
tasks:
- name: /etc/fstab にエントリを追加(冪等性なし)
ansible.builtin.shell: |
grep -q '/mnt/data' /etc/fstab || echo '/dev/sdb1 /mnt/data ext4 defaults 0 0' >> /etc/fstab
args:
warn: no # このような複雑なコマンドには警告を出さない
# 注意: 既存のエントリの変更や削除はさらに複雑になります
c. 冪等性を考慮した mount コマンドの実行例
- name: mountコマンドと条件分岐で冪等性を確保する
hosts: your_target_servers
become: yes
tasks:
- name: マウントポイントが既にマウントされているか確認
ansible.builtin.shell: mountpoint -q /mnt/data
register: mount_check
failed_when: mount_check.rc not in [0, 1] # 0はマウント済み、1は未マウント
changed_when: false # このタスクは変更を行わない
- name: /dev/sdb1 を /mnt/data にマウント (未マウントの場合のみ)
ansible.builtin.command: mount /dev/sdb1 /mnt/data
when: mount_check.rc == 1 # mountpoint が未マウントを返した場合のみ実行
考察
command
や shell
を使う場合、冪等性の確保が最も重要です。changed_when
、failed_when
、when
などの条件分岐や、creates
/removes
などの args
を駆使して、Playbook が繰り返し実行されても安全であることを確認する必要があります。これは複雑になりがちで、推奨される方法ではありません。
ansible.builtin.lineinfile または ansible.builtin.blockinfile モジュール
これらのモジュールは、/etc/fstab
のようなテキストファイルを管理するのに適しています。ファイル内の特定の行を追加、削除、または変更するために使用できます。
利点
- 設定ファイルのコメントや特定セクションの管理に役立つ。
state: present
/absent
やregexp
(lineinfile
)、block
(blockinfile
) を使って冪等性を実現できる。- テキストファイルの特定の行を確実に管理できる。
欠点
- マウントポイントの存在確認や作成は別途行う必要がある。
- マウントオプションやデバイスのUUIDの自動検出などの高度な機能はない。
- 実際にデバイスをマウント/アンマウントする機能はない。ファイルの内容(
/etc/fstab
)を編集するのみ。
コード例
- name: lineinfileでfstabを管理する例
hosts: your_target_servers
become: yes
tasks:
- name: /etc/fstab に /mnt/data のエントリを追加または更新
ansible.builtin.lineinfile:
path: /etc/fstab
regexp: '^/dev/sdb1\s+/mnt/data' # /dev/sdb1 /mnt/data で始まる行を検索
line: '/dev/sdb1 /mnt/data ext4 defaults,noatime 0 0'
state: present
backup: yes # 変更前に元のファイルをバックアップ
- name: /etc/fstab から /mnt/old_data のエントリを削除
ansible.builtin.lineinfile:
path: /etc/fstab
regexp: '^UUID="a1b2c3d4-e5f6-7890-1234-567890abcdef"\s+/mnt/old_data'
state: absent
考察
lineinfile
は /etc/fstab
のような構造化されていない設定ファイルに特定のエントリを追加・削除するのに便利ですが、マウント操作自体は行いません。したがって、この方法を使う場合は、ファイル編集後に別途 mount -a
コマンドを実行して、設定を反映させる必要があるかもしれません。
ansible.builtin.filesystem モジュール (パーティションのフォーマット)
これは直接マウントを制御するモジュールではありませんが、マウントする前の前提条件として、デバイスをフォーマットするために使用されます。
利点
- 冪等性があるため、既にフォーマットされていれば何も変更しない。
- 特定のデバイスを目的のファイルシステムで確実にフォーマットできる。
欠点
- ディスクの初期化やパーティション作成のステップは別途必要。
- マウント操作自体は行わない。
コード例 (mount モジュールと組み合わせて使う)
- name: 新しいディスクのフォーマットとマウントの例
hosts: your_target_servers
become: yes
tasks:
- name: マウントポイントディレクトリを作成
ansible.builtin.file:
path: /mnt/new_data
state: directory
mode: '0755'
- name: /dev/sdc を ext4 でフォーマット(すでにフォーマット済みならスキップ)
ansible.posix.filesystem: # filesystemモジュールは ansible.posix コレクションに属します
fstype: ext4
dev: /dev/sdc
force: yes # 必要であれば強制的にフォーマット
- name: /dev/sdc を /mnt/new_data にマウントし、fstab に追加
ansible.posix.mount:
path: /mnt/new_data
src: /dev/sdc
fstype: ext4
opts: defaults
state: mounted
より複雑なロジックや、Ansible が提供するモジュールでは対応が難しい特定のベンダー固有のストレージ管理ツールなどを利用する必要がある場合は、カスタムのシェルスクリプトや Python スクリプトを書き、それを ansible.builtin.script
または ansible.builtin.command
/ansible.builtin.shell
モジュールで実行する方法もあります。
利点
- 特定のツールや API と連携できる。
- 任意の複雑なロジックを実装できる。
欠点
- デバッグやメンテナンスが難しくなる可能性がある。
- Ansible の抽象化の恩恵を受けられない。
- 冪等性の管理が完全に自己責任: スクリプト内で冪等性を考慮したロジックを実装する必要がある。
Ansible でマウントポイントを制御する際には、**公式の mount
モジュールを使用することが最も推奨されます。**これは、冪等性が組み込まれており、エラーハンドリングが適切に処理され、コードの可読性と保守性が高いためです。