BFT名古屋 TECH BLOG

日々の業務で得た知識を所属するエンジニアたちがアウトプットしていきます。

【GCP】GCPインスタンスの自動起動・自動停止を実装する方法

こんにちは!
BFT名古屋支店の佐野です。

早速ですが、今回はGCPのお話。
これまではAWSの諸々についてお話する機会が多かったですが、GCPを利用するケースも挙がってきたこともあり、そちらについても今後触れていこうと思います。
その第1回目として、Compute Engineインスタンスを決まった時刻に自動的に起動させたり停止させたりする仕組みづくりのお話をしていきます。

考え方としては以前にお話している「【AWS】EC2の自動起動・自動停止を実装する方法」と同じです。

bftnagoya.hateblo.jp

AWSのEC2、GCPのCompute Engineインスタンスはどちらも環境上で作成できる仮想マシンです。
そしてどちらも「起動しているだけ料金がかかる」従量課金制です。
使った分だけ料金を支払うクラウドサービスではよくある形態であり、しっかりと使っている時間だけ起動していれば効率的にサービスを利用できます。
逆に使っていないのに起動したままにしておくと、その時間だけ無駄なコストが発生してしまいます。
多くの場合は「使わない時は停止しておく」運用がされていますが、うっかり停止し忘れてしまうミスも見られます。
そのチープミス防止のためにも、起動や停止は自動化しておくのがよいです。

ではCompute Engineインスタンスの起動や停止を自動化するにはどういった方法があるのでしょうか。


はじめに:Compute Engineインスタンスを自動で起動・停止させるために使うサービス

AWS仮想マシン、EC2インスタンス自動起動と自動停止を実装する記事ではEvent Bridgeによるイベント管理、およびSystems Managerの機能を使用していました。
GCPでも同じようなことが可能ですが、今回のCompute Engineインスタンス自動起動・停止にはCloud Functionsを使用します。

Cloud FunctionsはAWSにおけるLambdaに相当するサーバーレスコンピューティングサービスで、関数単位でインスタンスなしにコードを実行できるものです。
もちろんGCP内のリソースを操作するコードを書いて実行もできるため、インスタンスの起動と停止を行なう関数を作成します。

Cloud Functionsで実装したインスタンスの起動と停止を行なう処理を自動かつ定期的に実行させるためにはCloud Schedulerを使用します。
Cloud SchedulerはAWSで言えばAWS EventBridgeであり、様々な処理をCron式によってタイミングを指定して実行させられるものです。

なお、実はCloud FunctionsとCloud Schedulerを使ったインスタンスの定期的な自動起動および自動停止の実装方法はGoogleCloud公式のドキュメントに詳しいアナウンスがあります。

cloud.google.com

本記事ではこの公式のドキュメントをベースに、少し分かりにくい箇所や解説されていない箇所について話していきます。

本記事で解説する構成

今回使用するサービスおよび作成するリソースの関係と構成は以下の通りです。

今回の構成図

なお今回の構成では、VPC内に起動・停止対象のインスタンスを置いており、また外部からCloud Functionsを直接トリガーできるジョブ管理サーバも置いています。
これはCloud Schedulerによる定期的な起動と停止だけでなく、ジョブ管理サーバによる起動と停止の制御を想定しているためです。

Compute Engineインスタンスの設定

Cloud Functionsでインスタンスを起動・停止させる関数を作る前に、そのCloud Functionsで起動と停止を行なう対象を区別できるようにしておきましょう。
その方法が公式ドキュメントでも触れられているリソースラベルの設定です。
リソースラベルはkey-value(キーと値)のペアとなっており、例えば任意のラベルをインスタンスに設定すると同一のラベルを持つインスタンスを設定したラベルに属するグループのように扱えます。
今回の自動起動と自動停止を行なう対象のインスタンスは、ラベルのキーが「env」、値が「dev」となっているものとしたいため、このラベルを自動起動・停止したいインスタンスに設定します。

ラベルの設定

※Compute Engineインスタンス自体の作成方法は割愛します。

Cloud Functionsの設定

構成図で示した通り、起動の処理を行なう関数と停止の処理を行なう関数をそれぞれひとつずつ作成します。
手順および実装するコードは先に掲示した公式ドキュメントが詳しいものの、ここでは詳しく画像付きにて解説します。
また今回はVPC内にあるプライベートなインスタンスに処理を行なうため、それに必要な手順も示します。

まずは「関数を作成」を選択して関数の選択画面に入ります。
そして以下のパラメータを示す通りに設定していきます。
※表記していないパラメータはデフォルトのままにします。

なお作成する関数を実行するためのトリガーはこの時点では無いため、ここで作成を行ないます。
「Cloud Pub/Subトピックを選択してください」のプルダウンを展開した後「トピックを作成する」を選択すると「トピックの作成」ダイアログボックスが表示されるため、任意のトピックIDを入力して「トピックを作成」を選択します。

パラメータ 入力値
関数名 任意の関数名
リージョン 起動・停止対象のインスタンスと同じものを設定
トリガーのタイプ Cloud Pub/Sub
トピック ID 任意のトピックID
※「トピックを作為性する」を選択して入力、作成する

関数名、リージョン

トリガータイプの選択、トピックの選択

トピックの作成画面へ

トピックの作成

そして先述の通り今回VPC内のインスタンスに対して処理を行なうため、VPCの入り口となるVPCコネクタとの紐づけを行なう必要があります。
以下のようにVPCコネクタを設定します。

  1. 「ランタイム、ビルド、接続、セキュリティの設定」から「接続」を選択する。
  2. 「ネットワーク」プルダウンから操作対象のインスタンスがあるVPCVPCコネクタを選択する。

接続の設定

VPCコネクタの選択

VPCコネクタが無い場合は以下の手順にて作成しましょう。

  1. 「サーバーレスVPCコネクタを作成」を選択する
  2. 「サーバーレスVPCアクセス」コンソールに遷移するので「コネクタを作成」を選択する
  3. 「名前」は任意のVPCコネクタの名前、「リージョン」は操作対象のインスタンスがあるVPCのリージョンと同じリージョン、「ネットワーク」は操作対象のインスタンスがあるVPC、「サブネット」は操作対象のインスタンスがあるサブネットをそれぞれ入力・選択します。
  4. 「スケーリング設定」を展開し、「最大インスタンス数」を3にします。※CPU利用上限に引っかからないようにするためです。
  5. インスタンスのタイプ」はe2-microのままにしておき、「作成」を選択します。

サーバーレスVPCアクセスコンソール

VPCコネクタの作成画面

VPCコネクタの作成ができたら、新しく作成したVPCコネクタを「ネットワーク」プルダウンから選択できるようになります。

新たに作成したVPCコネクタを選択する

関数の設定を終えたら「次へ」を選択し、コードの設定画面に移ります。
コードおよびエントリポイントは先に上げた公式ドキュメントを参照してください。ただしランタイムについては「Node.js 10」以上を設定すれば問題ありません。

ランタイム、エントリポイント、コードの設定

ランタイム、エントリポイント、コードを設定し終えたら「デプロイ」を選択すれば関数を作成できます。

起動と停止をテストする

関数を作成したら、きちんと動作するかのテストを行ないます。
テストを行なうには関数を選択し、「関数の詳細」画面に入って「テスト中」タブを選択します。
なおPub/Subトリガーで作成した関数をテストする場合、イベントのメッセージデータはBase64エンコードされている必要があります。
例えばアベイラビリティゾーンとラベルを指定し、それに当てはまるインスタンスに対して処理を行なうという場合は以下のメッセージデータが必要となります。

{"zone":"asia-northeast1-b","label":"env=dev"}

これをBase64エンコードして、テストイベントに当てはめた場合は以下のようになります。

{"data":"eyJ6b25lIjoiYXNpYS1ub3J0aGVhc3QxLWIiLCJsYWJlbCI6ImVudj1kZXYifQ=="}

このテストイベントを「トリガーとなるイベントを構成する」に入力し、「関数をテストする」を実行するとテストが行えます。
その後、「出力」の下に結果が表示されます。停止する関数の場合「Successfully stopped instance」と表示が出れば成功です。

関数のテスト

関数テスト結果

外部からCloud Functions関数を実行する

関数を直接実行する場合、このテスト実行を行なうか、gcloud CLIのコマンドを使用します。
関数を実行するためのコマンドは以下の通りです。

gcloud functions call (関数名) --data '{"name":"(メッセージデータ)"}'

コマンドの実行をジョブ管理サーバにジョブとして登録しておけば、ジョブ管理サーバから直接関数を実行できます。

Cloud Schedulerの設定

Cloud Functions関数で起動と停止の処理を実装したら、あとはCloud Schedulerでそれぞれの関数を定時実行するジョブを設定するだけです。
Cloud Schedulerのページに移動し、「ジョブを作成」を選択するとジョブの作成画面に入ります。

そして以下のパラメータを示す通りに設定していきます。

パラメータ 入力値
名前 任意のスケジュール名
リージョン 起動・停止対象のインスタンスと同じものを設定
頻度 0 9 * * 1-5 ※起動の場合
0 18 * * 1-5 ※停止の場合
(平日の9時に起動、18時に停止する)
タイムゾーン 日本標準時JST
※選択時、「日本」で検索可能
ターゲットタイプ Pub/Sub
Cloud Pub/Subトピックを選択してください 起動用・停止用のCloud Functionsで作成したトピックを選択
メッセージ本文 {"zone":"asia-northeast1-b","label":"env=dev"}

なおここでのメッセージはBase64へのエンコードは不要です。

名前、リージョン、頻度、タイムゾーンの設定

ターゲットタイプ、トピック選択、メッセージ本文を選択・入力

スケジュールを作成する

あとは指定した時間になったと同時にジョブが実行されることを確認すれば、定時実行のジョブ設定も完了となります。

さいごに:Cloud Functionsを使わない方法もあります

今回はCloud Functionsを使用するパターンでインスタンス自動起動・自動停止する仕組みを実装しましたが、Cloud Functionsを使わずGCEの機能のみを使っても実装は可能です。
以下の公式ドキュメントにて解説されている通り、インスタンススケジュールによってシンプルに起動と停止のスケジュールが設定できます。

cloud.google.com

こちらの方法がより新しい方法であり、AWSでいうEventBridgeで実装するEC2の自動起動・自動停止に近いです。
しかしインスタンススケジュールで実装した場合、行なえるのはスケジュールによる起動停止のみです。
他のジョブ管理サーバから起動や停止を行ないたい場合はやはり今回紹介したようなCloud Functionsによる実装が必要となります。
任意の起動停止を行ないたいだけであるなら直接GCPコンソールからインスタンスを停止してしまえばいいため、どこから起動および停止を制御するかでどちらの方式が適するかが分かれてきます。
用途やケースに応じて、どちらの方法を使うかを検討していきましょう。