モチベーション
cron的なものをGCPで実現しようとすると、GAE cronかGASのトリガーを利用することが多かったのですが、Cloud SchedulerがBetaとしてリリースされました。
画面からのjob作成では細かい設定ができなさそうだったので、gcloudを利用し、細かいパラメータに関してドキュメントを把握しつつゆるく触ってみます。
作業ログ形式なので、実際に同じようにコマンドを打っていくことでgcloudコマンド経由でschedulerのjobを3つのターゲット(pub/sub, AppEngine, HTTP)を利用して登録することができると思います。(gcloudコマンドになれている人向けで若干省いている点もあるので不親切な部分があるかもしれません)
では進めていきましょう。
事前準備
- gcloudコマンドのインストールが済んでいること
- gcloudコマンドのログイン、GCPプロジェクトの作成が済んでいること
- プロジェクトのbillingが有効になっていること
- プロジェクトのcloud sheduler apiが有効になっていること
- プロジェクトのpub/sub apiが有効になっていること
gcloud beta コマンドのインストール
gcloudコマンドでBeta機能を試すためのbetaコンポーネントをインストールします。
すでにインストールしてある人はこの作業をskipして大丈夫です。
gcloud components install beta --quiet
念の為、コンポーネント一式をアップデートしておきましょう
gcloud components update --quiet
(--quiet オプションは y/n の入力をスキップするためのオプションなので、 y/n をどうしても押したい人は外して実行しましょう)
ターゲットとなるpub/subのtopicを作成する
以下のコマンドでジョブのターゲットとするpub/subを作成します。
pub/subターゲットのscheduleを登録する場合にはpub/subを事前に作成しておく必要があります。
gcloud pubsub topics create cron-topic --project ${PROJECT_ID}
Created topic[projects/{{PROJECT_ID}}/topics/{{TOPIC_NAME}}] のように表示されればOK。
以下のコマンドを実行し、pub/subのサブスクリプションを作成します。
gcloud pubsub subscriptions create cron-sub --topic cron-topic --project ${PROJECT_ID}
1. ジョブを作成する (target: pub/sub)
gcloudコマンドを利用してjobを作成してみます。
gcloudコマンドで作成する場合には、pub/sub, AppEngine http, httpの3つに対してそれぞれ異なるコマンドでの設定を行う必要があるようです。
ひとまず、先程作成したpub/subに向けて定期ジョブを実行できるようにしてみましょう。
pub/subに対するjobを作成する
- スケジュール指定はcrontab互換指定と、従来のAppEngine Cron構文の両方を利用することができるようです(every 3 hours など)、AppEngineからの移行の際には便利ですね。
-
pub/subターゲットの場合には再試行の設定オプションが提供されない
ことに注意する必要があるようです。
実際にコマンドを実行してjobを作成してみます
gcloud --project ${PROJECT_ID} beta scheduler jobs create pubsub pubsub-job --schedule "0 */3 * * *" --topic cron-topic --message-body "OreOre"
pubsub-job という名前で3時間おきにcron-topicに対し OreOre
というメッセージを送ります。
pub/sub側でjobを確認する
Schedulerが実行されるとpub/subにjobが送られますので、その内容を確認してみます。
gcloud pubsub subscriptions pull cron-sub --limit 5 --project ${PROJECT_ID}
おそらくすぐに実行しても Listed 0 items.
という感じでjobが表示されないと思います。
強制的にjobを実行してみる
登録しているジョブを確認してみる
以下のコマンドでjobを確認してみます
gcloud beta scheduler jobs list --project ${PROJECT_ID}
おそらく以下のように表示されるはず
ID LOCATION SCHEDULE (TZ) TARGET_TYPE STATE
pubsub-job asia-northeast1 0 */3 * * * (Etc/UTC) Pub/Sub ENABLED
強制的にjobを実行する
gcloud beta scheduler jobs run pubsub-job --project ${PROJECT_ID}
もう一度pub/subを確認してみる
gcloud pubsub subscriptions pull cron-sub --limit 5 --project ${PROJECT_ID}
今度は1件表示されるはずです。
確認ができたので、pub/subのjobを消しておく
データをpullしつつ、ackを返して消します。
gcloud pubsub subscriptions pull --auto-ack cron-sub --project ${PROJECT_ID}
一旦整理(1)
ここまでで、
- pub/subに定期的にjobを投入する(pub/sub経由での定期実行)ことができた
- 登録したjobをコマンドラインから確認できた
という感じですが、先程のjobを確認した際にTZが(Etc/UTC)となっていたのが気になりますね。
timezoneをAsia/Tokyoとして再度登録してみましょう。
TimeZone指定してjobを投入する
先程登録したジョブを削除する
timezoneを変更したいので登録済みのjobを削除します。
gcloud beta scheduler jobs delete pubsub-job --project ${PROJECT_ID}
TimeZone指定し、再度jobを登録する(AppEngine Cron)
timezoneとして Asia/Tokyo
をパラメータとして渡します。
さらに、毎分実行して見ようと思いますので、 every 1 mins
という感じにAppEngine cron構文で設定してみます。
gcloud --project ${PROJECT_ID} beta scheduler jobs create pubsub pubsub-job --schedule "every 1 mins" --topic cron-topic --message-body "OreOre" --time-zone "Asia/Tokyo"
投入されたjobを確認する
以下のコマンドでtimezoneを指定して登録したjobを確認します。
gcloud beta scheduler jobs list --project ${PROJECT_ID}
以下のような表示になり、今度はtimezoneも正しく設定されていそうです
ID LOCATION SCHEDULE (TZ) TARGET_TYPE STATE
pubsub-job asia-northeast1 every 1 mins (Asia/Tokyo) Pub/Sub ENABLED
pub/subに投入されたjobを確認する
数分時間をおいて以下のコマンドを実行すると複数のjobがpub/sub内に投入されていることが確認できると思います。
gcloud pubsub subscriptions pull cron-sub --limit 5 --project ${PROJECT_ID}
後処理
放って置くとpub/subに大量のjobが投入されてしまうので、jobを停止(削除)します。
(停止はおそらくなさそうです)
gcloud beta scheduler jobs delete pubsub-job --project ${PROJECT_ID}
pub/sub内のjobも削除しておきましょう(場合によっては何度か実行し、jobが空になるまで実行しましょう)
gcloud pubsub subscriptions pull cron-sub --limit 100 --auto-ack --project ${PROJECT_ID}
一旦整理(2)
ここまでで、
- Appengine Cron形式でjobを投入することができた
- TimeZoneを
Asia/Tokyo
として投入することができた
謎) documentには --max-backoff
--max-doublings
などの設定があるが、こちらはpub/subへの投入に失敗した場合のbackoff設定なのかな?
Notice that Pub/Sub target configuration does not provide options for setting retries, because Pub/Sub provides its own retry mechanism and policy.
2. ジョブを作成する (target: AppEngine)
pub/subのjob作成はできたので、AppEngineのjob作成を試してみます。
前提としてすでにAppEngine上に何かしらのアプリケーションをデプロイしている想定で進めます。
AppEngineのエンドポイントはapp.yamlの login:admin
を利用して保護することができるようです。
login:admin
を利用することで外部からのリクエストを防ぎつつ、Schedulerからはアクセスさせるということが実現できます。
AppEngineの場合には、HTTPメソッドを指定できます。デフォルトはPOSTです。
また、サービス、バージョン、インスタンスの指定もできるようです。
送信するデータはPOST,PUTのrequest bodyとして送られます。
殆どの場合にはデフォルトて十分ですが、リトライ方法を指定できます。
では、jobを作成してみます
gcloud beta scheduler jobs create app-engine appengine-job --schedule "every 1 mins" --time-zone "Asia/Tokyo" --relative-url "/" --message-body "Oredayo" --project ${PROJECT_ID}
投入したjobを確認してみる
pub/subと同様で以下のコマンドで確認してみます。
gcloud beta scheduler jobs list --project ${PROJECT_ID}
以下のような表示がされるはずです
ID LOCATION SCHEDULE (TZ) TARGET_TYPE STATE
appengine-job asia-northeast1 every 1 mins (Asia/Tokyo) App Engine ENABLED
HTTPメソッドを変更してみる
先程書いたようにSchedulerからはデフォルトでPOSTが送られます。せっかくなのでGETも試してみましょう
gcloud beta scheduler jobs create app-engine appengine-job --schedule "every 1 mins" --time-zone "Asia/Tokyo" --relative-url "/" --http-method "GET" --project ${PROJECT_ID}
GETの注意点は --message-body
オプションを利用できません。
Targetにservice, version などを指定したい場合には、 --servce
, --version
オプションが利用できます。
もちろん、変更(作成)する前に以下のコマンドで同名のjobを消しておくことをお忘れなく、
gcloud beta scheduler jobs delete appengine-job --project ${PROJECT_ID}
AppEngineへのログを確認した際に、POSTで出力されていたログがGETに変わればOKです。
一旦整理(3)
ここまでで、
- AppEngine TargetへのSchedule jobを登録することができた。
- POST/GET jobを登録することができた
上で試してはいませんが、リトライ系のオプションはパラメータ的にAppEngineのTQ時のリトライと同じようなイメージではないかと。
別の機会で検証してみようと思います。
3. ジョブを作成する (target: HTTP)
HTTPターゲットのjobを作成してみます。
HTTP/HTTPSの任意のターゲットに対して定期実行ができます。もちろんターゲットは外部に公開されている必要があります。
注意事項などに関してはAppEngineなどとほぼ同じです。(URLがFQDNである必要があるぐらい)
では、以下のコマンドでjobを登録してみましょう。
gcloud beta scheduler jobs create http http-job --schedule "every 1 mins" --uri ${TARGET_URL} --http-method GET --time-zone "Asia/Tokyo" --project ${PROJECT_ID}
投入したjobを確認する
gcloud beta scheduler jobs list --project ${PROJECT_ID}
以下のような表示が確認できるはずです
ID LOCATION SCHEDULE (TZ) TARGET_TYPE STATE
http-job asia-northeast1 every 1 mins (Asia/Tokyo) HTTP ENABLED
URI指定したターゲット側のログから定期実行を確認することができると思います。
確認が終わったらjobを消しておきましょう
以下のコマンドで削除が行なえます。
gcloud beta scheduler jobs delete http-job --project ${PROJECT_ID}
まとめ
- 一通りgcloudコマンド経由で触ってみましたが、ドキュメントに注意点なども書かれているのでとても良い
- AppEngine cron記法が使えるので、AppEngine cronからの移行は比較的容易にできそう。
- リトライはある程度デフォルト値が設定されているので、失敗するようなターゲットでも再実行はされる(?)
-
--max-retry-attempts
などがdefault 0なので無制限?
-
- HTTPターゲットの際のURLはエンコード後の長さで2083 characters。
オッと思った点
- pub/sub ターゲットの際のリトライオプションがドキュメントには書いてあるが、
pub/subターゲットの場合には再試行の設定オプションが提供されない
とも書いてあるのでよくわからなかった。 - HTTPターゲットの場合、ターゲットのURLはドメイン認証しなくても普通に登録できた。
- Cloud Schedulerは同時に2つの未処理の実行を許可しない。n+1は実行nが終了するまで開始することはない。(cronと違うので注意)
参考
https://cloud.google.com/scheduler/docs/quickstart?hl=en
https://cloud.google.com/sdk/gcloud/reference/beta/scheduler/jobs/create/pubsub?hl=ja