Google Cloud(GCP)上で、インスタンスをいっぱい複製しようとしたら、エラーになった話と解決法


# 結論から先に言うと
- マシンイメージを元にインスタンスを作ろうとすると、APIのリミットに引っかかる(10分に1台制限)
- マシンイメージではなく、ディスクイメージを作成してそこからインスタンスを作ると制限対象外になる

# 発生した問題
- いっぱいインスタンスを立てて並列処理がしたかった
- Google CloudのComputer Engineで、マシンイメージを作った
- そのマシンイメージを元にインスタンスを量産しようとした
- 5－6台目位を作ったあたりでエラーになった
- マシンイメージを元にインスタンスを作るとAPIのリミットに引っかかる

↓のようなエラーが出た
```
ERROR: (gcloud.beta.compute.instances.create) Could not fetch resource:
 - Operation rate exceeded for resource '(マシンイメージのリソース名)'. Too frequent operations from the source resource.
```

参考：永続ディスクのスナップショットに関するベスト プラクティス
https://cloud.google.com/compute/docs/disks/snapshot-best-practices#creating_new_zonal_persistent_disks_from_snapshots

参考：Orchestrating many instances from a local - Too frequent operations from the source resource
https://stackoverflow.com/questions/67523920/orchestrating-many-instances-from-a-local-too-frequent-operations-from-the-sou

ちなみにGCPには制限でも申請すれば緩和してもらえるものがあるが、申請しても緩和してくれなさそうな雰囲気があった。
(サポートなどに問い合わせてないので不明)

■ 割り当てと上限
https://cloud.google.com/compute/quotas?hl=ja

# 原因

「スナップショットから新しいゾーン永続ディスクを作成する」と、10分に1回程度しかマシンが作成できない。
マシンイメージからのインスタンス作成も、これに該当するらしい。

参考: スナップショットから新しいゾーン永続ディスクを作成する
https://cloud.google.com/compute/docs/disks/snapshot-best-practices#freq-create-disks


# 回避策

「イメージをソースとして使用して、新しいゾーンまたはリージョン永続ディスクを作成する。」
ことには制限がかかっていない。

違いがよくわからなかったが、やり方によっては回避できそう。

模索してみると、ディスクから作ったカスタムイメージは、この「イメージ」に該当するらしく、制限にならない様子。

# マシンイメージと、ディスクのカスタムイメージの違い

マシンイメージと、ディスクのカスタムイメージってどう違うんや。

マシンイメージは、データのバックアップのされ方が重厚だったり
VM自体の構成(たぶんCPUやメモリなどの設定)まで保存されてるらしい。

ディスクイメージにはそれらは含まれてませんよってことっぽい。

参考：Googleが「マシンイメージ」のβ版を発表、「Compute Engine」の新リソース
https://atmarkit.itmedia.co.jp/ait/articles/2003/13/news059.html

今回は雑に作って、雑に量産したかったし、VMの構成もコマンドで都度指定するのでディスクのカスタムイメージでOK。

# ディスクのカスタムイメージを作る

やり方はいろいろあると思いますが、私が実践した手順は以下の通り

- カスタムイメージの元になるマシンのインスタンスを、Google Compute Engine上に立てる。
- カスタムイメージの元になるマシンにつながれている、ディスクを覚えておく
- GCEコンソール上からインスタンスを停止する
- GCEコンソール上からインスタンスの設定を開き、インスタンス削除時にディスクを削除されないようにする(重要)
- カスタムイメージの元になるマシンのインスタンスを削除する。ディスクは削除しない。(重要)
- インスタンスからディスクが取り外される(ほかにもいい方法あるかも)
- ストレージ＞ディスクのページを開く
- カスタムイメージの元になるマシンにつながれていたディスクの「操作」から「イメージを作成」を選択する
- 必要事項を入力してイメージを作成する
- ディスクのカスタムイメージができる

# gcloudコマンドをインストールする

コマンドからサクッと複数インスタンスを立てたいので、
コマンドでGoogle Cloudが操作できるgcloudコマンドをインストールしてセットアップします。

https://cloud.google.com/sdk/docs/install?hl=ja#deb

# gcloudコマンドでカスタムイメージを元にインスタンスを立ち上げる

まず、CPUやIPなどの制限が、必要な量に対して十分に緩和されているかどうか確認してください。
■ 割り当てと上限

https://cloud.google.com/compute/quotas?hl=ja

gcloud beta compute instances createコマンドから、カスタムイメージを元にインスタンスを作成します。

参考：公式ドキュメント

https://cloud.google.com/sdk/gcloud/reference/beta/compute/instances/create


インスタンスは、こんな感じのコマンドで作りました
```bash
gcloud beta compute instances create (インスタンス名) \
 --project=(自分のGCPのプロジェクトID) \
 --zone=(インスタンスを立てるゾーン) \
 --service-account=(インスタンスを動かすサービスアカウントID) \
 --custom-vm-type=(VMのアーキテクチャ/n2とか) \
 --image-project=(先ほど作成したイメージが保存されているGCPのプロジェクトID) \
 --image=(先ほど作成したカスタムイメージの名前) \
 --boot-disk-type=(ディスクのタイプ、バランスとかSSDとか) \
 --custom-cpu (CPUの数) --custom-memory (メモリサイズ[GB]) \
 --preemptible    
```

「preemptible」は1/3くらいの値段でマシンを使わせてもらう代わりに、
クラウドが混んできたらGoogleさんが勝手に落としてもOKというオプション。
空いてたら安くで使わせたるわ。ってやつ。


使用できるディスクのタイプは
```bash
gcloud compute disk-types list
```
コマンドで確認できます。
```
NAME         ZONE                       VALID_DISK_SIZES
pd-balanced                             10GB-65536GB 
pd-ssd                                  10GB-65536GB 
pd-standard                             200GB-65536GB
pd-balanced                             10GB-65536GB 
pd-ssd                                  10GB-65536GB 
pd-standard                             200GB-65536GB
```

多分、「pd-balanced」が「バランス永続ディスク」とかのはずです。ドキュメントを参照してみてください

# 操作したり削除したりする

■SSH接続したり、SSH経由でコマンドを実行させる

このSSH接続時には、ログイン時のマシン上のアカウントを指定しないと、
新たにユーザが作成されてしまうので注意してください。

https://cloud.google.com/sdk/gcloud/reference/beta/compute/ssh

■インスタンスにファイルを転送

https://cloud.google.com/sdk/gcloud/reference/beta/compute/scp

■インスタンスを削除する

https://cloud.google.com/sdk/gcloud/reference/beta/compute/instances/delete

# 感想
マシンイメージからインスタンス量産してやるぜー！
と意気込んでいたらマシンイメージから作ると結構厳しい制限にひっかかってびっくりした。
がんばっても1時間に6台。マシンを増やしてる間に日が暮れてしまう。

Docker環境立ててそのうえでコンテナたくさん動かすかとか、ディスクから作成したら。とか考えたが微妙だったり、うまくいかなかったりした。

ちなみに、Compute Engineの「コンテナイメージからインスタンスを作る」は、1インスタンスに対して、1コンテナしか動かないらしい。
参考： https://cloud.google.com/compute/docs/containers/deploying-containers

GKEやAWS ECSの活用も考えたが、ちょっと重厚すぎたので何とかしたかった。

ドキュメントをよく読む、、、というか都合よく解釈すると、ディスクのカスタムイメージを元にインスタンスを作れば良さそうなのでやってみた。
都合よく成功してよかった。