遇到的情況是要在 ubuntu 機器上 mount 非 public access 的 gcp storage bucket,然後要給 php web api 做讀寫。
比較正常的解決方式應該是用 google cloud storage api for PHP(https://googleapis.github.io/google-cloud-php/#/docs/cloud-storage/v1.24.1/storage/storageclient 使用說明 & https://github.com/googleapis/google-cloud-php-storage github),但因為要趕著上線並把原本儲存在local disk 改去 gcp cloud storage去,所以趕著做就先用 mount bucket 的方式去做讀寫。
先安裝 gcsfuse
安裝說明可以直接看 https://github.com/GoogleCloudPlatform/gcsfuse/blob/master/docs/installing.md
mount with gcsfuse
可以看 https://github.com/GoogleCloudPlatform/gcsfuse/blob/master/docs/mounting.md,但是要注意的是單純地做 mount 則路徑權限會跟著 mount 的帳號。所以,假設用 root mount,那麼通常 ubuntu 上跑 apache2.4 的 www-data 這跟身分就不能直接存取,就算把 www-data 加入 sudo 身分,也不能使用像是 php 中的 filesize() 這樣的函式。
說明裏頭有提到可以用 credential key file (json format)的方式,另外這篇文章也有提到,不過因為手上這台機器已經有做過 gcloud auth login,所以沒有用這樣的方式。
mount as www-data identity
但很詭異的是照著文件最底下(這邊)所寫的,將 mount 寫在 /etc/fstab 卻一直有問題。所以我改成寫在 crontab 裡頭,但一樣要先確認 www-data 的 id。
$ id --help Usage: id [OPTION]... [USER] Print user and group information for the specified USER, or (when USER omitted) for the current user. -a ignore, for compatibility with other versions -Z, --context print only the security context of the process -g, --group print only the effective group ID -G, --groups print all group IDs -n, --name print a name instead of a number, for -ugG -r, --real print the real ID instead of the effective ID, with -ugG -u, --user print only the effective user ID -z, --zero delimit entries with NUL characters, not whitespace; not permitted in default format --help display this help and exit --version output version information and exit Without any OPTION, print some useful set of identified information. GNU coreutils online help: <http://www.gnu.org/software/coreutils/> Report id translation bugs to <http://translationproject.org/team/> Full documentation at: <http://www.gnu.org/software/coreutils/id> or available locally via: info '(coreutils) id invocation' $ id -g www-data 33 $ id -u www-data 33
然後便是在 crontab 中加入 @reboot 去做 mount
$ crontab -l @reboot gcsfuse --uid 33 --gid 33 --implicit-dirs -o allow_other -file-mode=660 -dir-mode=770 BUCKET-NAME /PATH/TO/MOUNT/
但終究比較好的方式是乖乖用 google cloud storage api, 這樣就只要單純 deploy 程式跟 credential key file 就解決,不用弄這些設定。