GCP VMインスタンスとCloudストレージでサーバー作成

2019.12.19 (木)

VMインスタンスにCloud StorageをHDDやSSDのようにディスクとしてマウントできます。単にデータ置き場として利用する場合は、VMインスタンスに付属のストレージを使うより安上がりになりますが、内部のプログラム言語の実行や通常ディレクトリ上でできる様々な作業に制限があります。実際は、画像や動画、圧縮したデータの置き場などに使うのが一般的です。プログラムリソースもJavascriptやCSSなどのスタティックなものに限りおいて置いておくことは可能です。私は個人的に外付けHDDっみたいなものとして使ってます。

VMインスタンスの作成

普通にVMインスタンスを作成します。SSHでログインできるようにしておけば取り敢えずOKです。
GCEのアクセス権設定を設定します。Cloud APIアクセススコープの項目で、ストレージの項目で「読み取り/書き込み」の権限か、フルアクセスの権限を与えておくのと、サービス管理の項目で、「読み取り / 書き込み」権限を与えます。(後から追加できますが、サーバー停止しないと駄目なので要注意)


Cloud strageの作成

こちらも普通に作成しておきます。リージョンはVMインスタンスと同じにしておくとやりやすいかもです。権限設定をしてそとから見れないことを確認します。パケットの詳細から概要タブをクリックし、リンク先URLでアクセスしてみます。
Cloud Strageのアクセス制限

Cloud storageをマウントする

gcsfuseが使えるようにする

Cloud Storage FUSE とその依存関係のインストール手順を行います。まずは、gcsfuseが使えるようにリポジトリの追加をします。

sudo tee /etc/yum.repos.d/gcsfuse.repo > /dev/null <<EOF
[gcsfuse]
name=gcsfuse (packages.cloud.google.com)
baseurl=https://packages.cloud.google.com/yum/repos/gcsfuse-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
       https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

yumを更新します。

# yum -y update

インストールします。

# yum -y install gcsfuse

確認

# which gcsfuse
/bin/gcsfuse
且つ
# gcsfuse -v
gcsfuse version 0.28.1 (Go version go1.9.7)

これでOK

認証する

認証方法にはいくつかありますが、チュートリアルには3つのっています。

  • Compute Engine の組み込みサービス アカウントを使用。(storage-full が構成されているスコープで Google Compute Engine インスタンスを実行している場合)
  • gcloud auth application-default login を実行した場合、Cloud Storage FUSE でこれらの認証情報を使用できます。
  • 環境変数 GOOGLE_APPLICATION_CREDENTIALS をサービス アカウントの JSON キーファイルのパスに設定している場合、Cloud Storage FUSE はこの認証情報を使用できます。

楽で応用が効きそうなのが3つ目の「サービスアカウントのJSONキーファイル」を利用する、がよいと思います。問題なければその他の認証方法でも大丈夫ですがここでは割愛。通常同じプロジェクト内で同じリージョンにあれば認証作業は不要で(自動的に内部で認証作業を行い)そのままマウントできます。

マウントする

ディレクトリを作成します。ちょっと注意したいのが、OSのユーザーでマウントすることです。rootでマウントすると、root以外のユーザーからはストレージ自体が見えなくなります。またOSの中でのchownやchmodもマウントしたストレージには使えません。つまりOSユーザーがgcsfuseの認証を行っているということになります。hogeユーザーで行い場合は、

$ su - hoge
$ mkdir /foo/bar
$ gcsfuse storage-bucket-name /foo/bar

Cloud storageにすでにたくさんのファイルが格納してある場合は、マウントに結構な時間がかかります。お茶を入れて待ちましょう。
更にマウントが完了したように見えても格納されているファイルが数十GBぐらいあると、ファイルが出現するまでに更に時間がかかります。

確認

$ df -h
Filesystem           Size  Used Avail Use% Mounted on
devtmpfs             841M     0  841M   0% /dev
...中略...
tmpfs                170M     0  170M   0% /run/user/0
storage-bucket-name  1.0P     0  1.0P   0% /foo/bar

/foo/barにアクセスして中身を確認します。マウントされるのにややしばらく時間がかかりますが、数分(数十分?)待つとCloud Storageに上がっているファイルがVMインスタンスから見れるようになります。
以下のコマンドでCloud strageにファイルが上がっているかどうかの一覧が確認できます。

$ gsutil ls gs://storage-bucket-name

アンマウント

$ fusermount -u /foo/bar

fusermount: old style mounting not supportedというのが出るときは-uオプションがないとき。またストレージが有効できちんとマウントしているときじゃないとアンマウントできないので注意。(サービスアカウントを無効にしているときとか)
アンマウントできないときはプロセスごとkillするとかいろいろ情報ありますね。

インスタンス起動時に自動でマウント(自動起動)

/etc/fuse.confに権限を追加します。

#user_allow_other
↓
user_allow_other

systemdの設定をします。

$ sudo vi /etc/systemd/system/gcsfuse-mount.service

以下のように設定します。

[Unit]
Description=A user-space file system for interacting with Google Cloud Storage
After=systemd-networkd.service

[Service]
Type=simple
Environment=PATH=$PATH:/opt/bin:/bin
ExecStart=/bin/gcsfuse -o allow_other -file-mode=777 -dir-mode=777 --foreground {bucket-name} /path/to/mount
ExecStop=/bin/fusermount -u /path/to/mount/
User={username}

[Install]
WantedBy=multi-user.target

自動起動設定

# systemctl enable gcsfuse-mount.service

確認

# systemctl list-unit-files  -t service | grep gcsfuse-mount.service
gcsfuse-mount.service                         enabled

自動起動の解除

systemctl disable gcsfuse-mount.service

いろいろな注意点

  • どういうわけか、外部IPを与えてあげないとマウントは成功しても中に入ってファイルにアクセスできないという事態になりました。NATまたは、エフェメラルでもなんでもいいのですが、グローバルIPを付与してあげたVMインスタンスにはCloud Storageはちゃんとマウントできるのですが、そうじゃない場合はVMインスタンスがCloud Storageを見に行くさいに経路を失っているような印象。外部IPをもたないVPC上のVMインスタンスをインターネットにつなげるにあるようにインターネットに出てゆく何らかの経路を与えてやらないとストレージのマウント後にうまく動かないということになります。
  • VMインスタンスとCloud Storageのリージョンは同じにしないとダメかもしれない。(もしかしたら、そうじゃなくてもマウントできる方法があるのかもしれないけど)今のところ同じにしないとダメだった。ひょっとしたらCloud storageをマルチリージョンにすればうまくいくのかもしれない。
  • マウントした後でも、Cloud storage内のファイルやディレクトリのパーミッションは変更できない。(基本644になってました。)
  • VMインスタンスを起動した後、Cloud Storageの容量自体が大きい場合、ちょっと待たないとマウントされないようです。マウントして読み込むのにかなり時間がかかる。SSHでログインしても数分待たないとマウント先のディレクトリは空のままになっています。私が試したのは100GB程度で1,2分待たないとマウントされませんでした。

PCのストレージなどにマウントする

上記やり方でPCや外部の普通のサーバーにマウントすると以下のようなエラーが出ます。

$ gcsfuse STORAGE_NAME /foo/bar
Using mount point: /foo/bar
Opening GCS connection...
daemonize.Run: readFromProcess: sub-process: mountWithArgs: getConn: DefaultTokenSource: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.

サーバー間での本番環境アプリケーションの認証の設定
となるのでトークンを発行して認証しないといけません。