こんにちは、yukinasuです。
今回は、Google Compute Engine(以降、GCEと記述)のImageをGoogle Cloud Storage(以降、GCSと記述)にアップロードする方法を紹介します。

この方法を利用すると
* 自分がカスタマイズしたImageを共有する
* 複数のサーバを立ち上げるときのBaseとなるCustomImageを作成する
ことが出来るようになります。

この記事はGCE公式ドキュメントのExport an image to Google Cloud Storageを参考にしています。

1. temporary disk (一時保存用disk)を作成

このdiskはroot persistent disk (アップロード対象のdisk)をtarファイルとして固める際の、ファイル保存領域として使用される一時保存用のdiskとなります。
注意しなくてはいけないことは、このdiskの内容がtarに保存される訳ではないということです。

$ gcloud compute disks create TEMPORARY_DISK_NAME \
    --project PROJECT_NAME \
    --zone ZONE_NAME \

2. Instanceに一時保存用diskを適用

1.で作成したtemporary diskをInstanceに適用します。これには次の2通りの方法が有ります。

2.1 新規にInstanceを作成する場合

root persistent diskのInstanceがまだ作成されていない場合は、gcloud compute instances createコマンドを用いてインスタンスの作成と同時にtemporary diskの適用を行います。

$ gcloud compute instances create INSTANCE_NAME \
    --project PROJECT_NAME \
    --zone ZONE_NAME \
    --image IMAGE_NAME \
    --disk \
      name=TEMPORARY_DISK_NAME \
      device-name=TEMPORARY_DISK_NAME \
    --scopes storage-rw

GCSにアップロードするので、--scopes storage-rwオプションでストレージへの読み込み・書き込みの権限を付加します。

2.2 既存のInstanceに適用する場合

既に稼働しているInstanceに対してdiskを適用する場合は、gcloud compute instances attach-diskコマンドを用いてtemporary diskを適用します。

$ gcloud compute instances attach-disk INSTANCE_NAME \
    --project PROJECT_NAME \
    --zone ZONE_NAME \
    --disk TEMPORARY_DISK_NAME \
    --device-name TEMPORARY_DISK_NAME \

既存のInstanceに適用する場合は、Storageに対する書き込み権限がないとGCSにアップロードできないので、予め権限が存在することを確認しておいてください。

3. 起動したInstanceにSSHで接続

sshで接続するための設定に関してはGCE公式ドキュメントのConnecting to an instance using sshを参考にしてください。

$ gcloud compute ssh INSTANCE_NAME \
    --project PROJECT_NAME \
    --zone ZONE_NAME

4. どこにディスクのデータが存在するかを確認

InstanceにAttachされたdiskは/dev/disk/by-id/配下にgoogle-の接頭語+disk名の形でシンボリックリンクが作成されます。

me@instance:~$ ls -l /dev/disk/by-id/google-*
lrwxrwxrwx 1 root root  9 Jul 29 17:56 /dev/disk/by-id/google-persistent-disk-0 -> ../../sda
lrwxrwxrwx 1 root root 10 Jul 29 17:56 /dev/disk/by-id/google-persistent-disk-0-part1 -> ../../sda1
lrwxrwxrwx 1 root root  9 Aug 25 18:16 /dev/disk/by-id/google-temporary-disk -> ../../sdb

この場合は、google-persistent-disk-0がroot persistent disk、google-temporary-diskがtemporary diskです。

5. temporary diskをフォーマットしマウント

safe_format_and_mountを用いてtemporary diskのフォーマットとマウントを行います。

me@instance:~$ sudo mkdir /mnt/tmp
me@instance:~$ sudo /usr/share/google/safe_format_and_mount -m "mkfs.ext4 -F" /dev/sdb /mnt/tmp

4.で確認時にtemporary diskは/dev/sdbに存在することが確認できていますので、フォーマット対象には/dev/sdbを指定します。

safe_format_and_mountはcompute-image-packagesに含まれているシェルスクリプトでGCEにデフォルトで用意されているImageには予めインストールされています。もし存在しない場合にはwgetなどを用いてcompute-image-packagesのreleasesから最新のtar.gzファイルを取得すれば、利用することが出来ます。

6. カスタマイズしたroot persistent diskをtarファイル化

カスタマイズしたroot persistent diskをimage化しtarファイルに固めます。
この処理を実行するまでにImageに含めたいパッケージのインストールやファイルの配置を終わらせておいてください。

root persistent diskをtarファイルに固めるにはgcimagebundleを用います。
gcimagebundleもsafe_format_and_mountと同じく、compute-image-packagesに含まれるライブラリですので、基本的に予めインストールされています。

me@instance:~$ sudo gcimagebundle -d /dev/sda -o /mnt/tmp/ --log_file=/tmp/abc.log

上記コマンドを実行すると、次の場所にImageのtarファイルが作成されます。

/mnt/tmp/HEX-NUMBER.image.tar.gz

7. GCSへImageをアップロード

Instanceにプリインストールされているgsutilコマンドラインツールを用いてGCSにファイルをアップロードします。

7.1 Bucketを作成

次のコマンドを用いて、Bucketを作成します。
Bucketの命名に関してはBucket and Object Naming Guidelinesを参考にしてください。

me@instance:~$ gsutil mb gs://BUCKET_NAME

7.2 BucketにImageをアップロード

次のコマンドを用いて、7.1で作成したBucketにImageのtarファイルをアップロードします。

me@instance:~$ gsutil cp /mnt/tmp/IMAGE_NAME.image.tar.gz gs://BUCKET_NAME

おわりに

以上で、GCEからGCSにImageをアップロードする一覧の流れは終了です。
これを応用すれば、diskからだけでなく、SnapshotからInstanceを作成し、Image化してGCSにアップロードも可能です。