GCPインスタンスをNode.js8のCloud Pub/Subでスケジュール起動停止

2019-09-29

GCPでインスタンスをスケジューラーで自動起動・自動停止したいことがある。業務で使用している開発サーバーなどを週7日24h稼働するのはコスト的にも勿体無い。サービスによっては本番公開サーバーであっても稼働する必要がない時間帯があることもあるかもしれない。

GCEで自動起動・自動停止をする場合、Cloud functions(Cloud Pub/Sub)とCloud Schedulerを使用する。
Cloud Scheduler を使用した Compute インスタンスのスケジュール設定

基本的にはここに書かれている通りにすればインスタンスのスケジューリング起動停止ができる。

Nodejs8でのCloud Scheduler & Cloud Pub/Sub

上記URLに書かれている通りにすると正常に動作するのだが「Node6」での話だ。(このリファレンスにもNode6を選択するようにと書かれている)

しかし、Cloud functionsでNode6を選択しようとするとGoogleさんが以下のように注意してきます。

gcp-function

つまり、今時、Node.js6でデプロイするなということですな。なので、私はNode.js8でこのインスタンス起動停止スクリプトをデプロイした。

ところがなんとNode8ではこの起動停止スクリプトが動作しない。ログを見てみたら以下のエラーがキャッチされている。

  1. TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.
  2. at Function.Buffer.from (buffer.js:183:11) at exports.startInstancePubSub (/srv/index.js:20:25) at /worker/worker.js:825:24 at at process._tickDomainCallback (internal/process/next_tick.js:229:7)

GCPの公式リファレンスの通りにしてもNode8だとこのエラーが出てしまうのだ。デバッグしてみたらpubsubMessage.dataがundefindになっていた。

  1. const pubsubMessage = event.data;
  2. const payload = _validatePayload(
  3. // pubsubMessage.data が undefind!
  4. JSON.parse(Buffer.from(pubsubMessage.data, 'base64').toString())
  5. );

なぜこうなるのかわからないが、以下のようにするとeventのmessageを展開でき、正常に動くようだ。

  1. const pubsubMessage = event.data;
  2. const payload = _validatePayload(
  3. JSON.parse(Buffer.from(pubsubMessage, 'base64').toString())
  4. );

だがだがしかし、これ正常に動作しながらも以下のエラーをはいているようだ。

  1. TypeError: callback is not a function at compute.zone.vm.stop.then.then.catch.err
  2. (/srv/index.js:39:9) at at process._tickDomainCallback (internal/process/next_tick.js:229:7)

正常にインスタンスを起動 or 停止した後にfunctionの完了のcallbackでこけているようだ。解決策は「GCPインスタンスをNode.js8のCloud Pub/Subでスケジュール起動停止(2)

というかGoogleさんがこの公式リファレンスのコードを修正して欲しいです。Node8では明らかに動作しない。