概要
タイトルの通り、GCSFuseを使ってLinuxにGCSをマウントする話です。
nofailオプションを普通に指定してマウントした場合のエラーと、その解決法についての記事になります。
前提
まず前提となる実行環境と、GCSFuseの概要について軽く触れておきます。
操作元の環境
手元の環境はM1 Macです。
ところどころterraformやansibleの内容を載せているので、以下は参考までに。
> terraform --version
Terraform v1.8.1
on darwin_arm64
+ provider registry.terraform.io/hashicorp/google v5.26.0
> ansible --version
ansible [core 2.17.5]
実行VM環境
実験したのはGCEのdebian-11環境です。
resource "google_compute_instance" "main" {
name = "test-gcsfuse"
# 略
boot_disk {
initialize_params {
image = "debian-cloud/debian-11"
size = 10
type = "pd-balanced"
}
}
# 略
}
GCSFuseを使ったマウント方法の概要
基本的には公式ドキュメントを参照いただければと思います。
ざっくり抜粋すると
- GoogleCloudのリポジトリを登録したaptでgcsfuseをインストールする
- マウントを実行する
という流れになります。
マウントの実行にはいくつか方法があります。
- 一時的なマウント
- gcsfuseコマンド
- mountコマンド
- 持続的なマウント
- /etc/fstabに記述してmountまたはreboot
今回は持続的なマウントに焦点を当てています。
nofailオプションは/etc/fstabに記述する際のオプションです。
エラーについて
本題となる実際に遭遇したエラーについて触れていきます。
エラー内容
GCSのマウントをfstabに記述する際には、公式ドキュメントにも言及がある通りオプションに _netdev
や implicit_dirs
を指定するなど、一工夫必要なケースが多いと思います。
以下は /etc/fstab
の記述内容の一例になります。
bucket-name /path/to/mount/point gcsfuse rw,_netdev,implicit_dirs,uid=0,gid=0,allow_other,nofail 0 2
これを記述した状態でインスタンスごと sudo reboot
を実行すれば、正常にマウント成功します。
しかし sudo mount /path/to/mount/point
を実行するとエラーになってしまいます。
同じ記述内容であれば普通はどちらも成功するはずでは、と思っていました。ここで原因がわからず結構詰まった。
また、類似のパターンとしてAnsibleから以下のようにして普通にマウントしようとするとエラーになります。
- name: Mount GCS
ansible.posix.mount:
path: /path/to/mount/point
src: "bucket-name"
fstype: gcsfuse
opts: rw,_netdev,implicit_dirs,uid=0,gid=0,allow_other,nofail
passno: 2
state: mounted
エラーメッセージ全体をコピペ掲載することは避けますが、エラーは以下のような内容です。
Error: daemonize.Run: readFromProcess: sub-process: Error while mounting gcsfuse: mountWithArgs: mountWithStorageHandle: mount: mount: invalid argument
...
running gcsfuse: exit status 1
mountに不正な引数を指定したことによるエラーとなっています。
この不正な引数というのが nofail
になります。試しに nofail
オプションを外して実行すると成功します。
ならオプションを外せば良いかというと、そうもいきません。
GCSのマウントはネットワークの状況などにも左右されやすく、失敗するリスクを考慮しておきたいため nofail
オプションはなるべく指定しておきたいところです。
エラー原因
私も詳細に語れるほどの知識はないのですが、同じ設定で違う結果が得られることから、少なくとも実行内容が異なることはお分かりいただけると思います。
reboot時はsystemdがmountを管理しているのに対して、手動で実行する場合は直接mountを実行しています。この違いによって今回のようにreboot時にはエラーが発生せず、手動mount時にはエラーが発生する、といったことが起きます。
GCSFuseは名前の通りFuseをベースとしています。
Fuseのオプションにはnofailが存在しないため、直接mountを実行した場合はnofailオプションがそのままGCSFuseに渡されて invalid argument
エラーを出すことになります。
一方で、systemdが管理してmountを実行した場合はsystemd側でnofailオプションを除外した状態でmountを実行しているものと思われます。
エラー回避方法
つまり、回避するにはmountを直接は実行せずに、systemdに管理させればOKです。
sudo systemctl start path-to-mount-point.mount
Ansible記述例
参考までに、本エラーを回避してGCSをマウントするAnsible記述例です。
- name: Create fstab
ansible.posix.mount:
path: /path/to/mount/point
src: "bucket-name"
fstype: gcsfuse
opts: rw,_netdev,implicit_dirs,uid=0,gid=0,allow_other,nofail
passno: 2
state: present
register: fstab_result
- name: Reload systemd
ansible.builtin.systemd_service:
daemon_reload: true
when: fstab_result.changed
- name: Mount with systemctl using fstab
service:
name: path-to-mount-point.mount
state: started
when: not ansible_check_mode
おわりに
意外と検索してもこのエラーについての記事が見当たらなかったので、備忘も兼ねて久しぶりに記事を書きました。
なかなかエラー発生原因が掴めず苦労したので、どなたかの助けになれば幸いです。