GCPでPythonプログラムを定期実行する【GCP/Python】

# やりたいこと
Pythonプログラムを定期実行させる必要がありました。
が、cronだとPCを起動していないといけない。。。ちょっときついので、GCPにやってもらうことにします。
GCPのCloudFunctions、PubSub、CloudSchedulerを使用します。
各種サービスやジョブはコンソールからぽちぽちと作成します、ご了承ください。（terraform勉強中なので、いつかtfファイルで書き直したいです。。）

# 設計 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/f2ff47d1-d296-d6c0-83b0-bbb3a77c39bb.png)

CloudSchedulerで、定期的にPubSubトピックにメッセージをpublishさせる。
そのPubSubトピックにメッセージがpublishされることをトリガーに、CloudFunctionsの関数が実行される。
CloudFunctionsの実行結果はCloudLoggingに出力される。


# 手順
最後にも注意書きしましたが、定期実行は実験が終了したら止めるようにしましょう！課金が進みます

## PubSubトピックを作成する
![2022-06-25_18h30_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/3432ae04-ced8-372c-a8a5-0cf8050c52a3.png)
つくります。



## CloudFunctionsの関数を作成する
![2022-06-25_18h01_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/8ddb369a-d5f7-fd2f-00b4-c957877038d0.png)
トリガーのタイプをPubSubに変更し、先ほど作ったトピックを選択します。
これで、このトピックにmessageがpublishされたら、この関数が動くようになります。
外部からのアクセスを今回は行う必要がないため、ネットワークの設定のうち、上り（内向き）設定を「内部トラフィックのみを許可する」に変更しました。

今回はひとまずこんな関数にしました。
[Cloud Loggingクライアントライブラリ](https://cloud.google.com/logging/docs/reference/libraries?hl=ja)を使って、CloudLoggingにログを出力しています。


```py:main.py
import base64
import datetime
import google.cloud.logging
from logging import getLogger, DEBUG

logging_client = google.cloud.logging.Client()
logging_client.setup_logging()
logger = getLogger(__name__)
logger.setLevel(DEBUG)

def hello_pubsub(event, context):
    pubsub_message = base64.b64decode(event['data']).decode('utf-8')
    now = datetime.datetime.now()

    logger.info("PubSubメッセージ: {}".format(pubsub_message))
    logger.info("now: {}".format(now))
```


CloudLoggingクライアントライブラリのバージョンを`requirements.txt`に記載しておきます。
```py:requirements.txt
google.cloud.logging>=3.0.0
```

## CloudSchedulerのジョブを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/baec0aaf-0847-9fcf-13c3-a5ac430782d9.png)
いったん毎分に設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/b862562e-bbbd-9bf6-b94f-c2c84683d566.png)
ターゲットタイプをPubSubにし、トピックを選択します。
定期的に、PubSubトピックに対してmessageを送るよということですね。
トピックに送信するメッセージを設定します。今回は
```
定期実行のサンプルです。
This is sample of automation.
```
というメッセージをPubSubトピックに送るようにしました。
オプションは特にいじってないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/67800738-171b-483f-612a-4a06ebebb303.png)
CloudSchedulerのジョブが問題なく作成されたら、（今回は毎分の設定なので）次の0分のタイミングで、CloudFunctionsがPubSubにメッセージをパブリッシュします。


## ログを確認する
CloudLoggingを確認してみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/cba160a7-0979-f6ea-0e81-83de04419cb4.png)
問題なくログが出力されていました。
このあとも、１分おきに実行されログが出ていたのが確認できました。

# 注意事項
動作確認が終わったら、CloudSchedulerのジョブを一時停止or削除するのを忘れずに！！
今回は毎分でcronを設定しているので、放置すると順調に課金がすすんでしまいます。
CloudSchedulerのジョブ一覧の画面から該当のジョブを選択し、一時停止/削除を行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320845/b7373c01-3a4b-0e95-57d0-2d2ab325c998.png)



# 参考URL
- [Cloud Logging クライアントライブラリ](https://cloud.google.com/logging/docs/reference/libraries)
- [Cloud Logging LogSeverity](https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity)
- [(Python)Cloud FunctionsからCloud Loggingへのログ連携方法の比較](https://zenn.dev/koshilife/articles/d2c752b3a0d9bb#%E6%96%B9%E6%B3%954.cloud-logging-api%E3%82%92%E7%9B%B4%E6%8E%A5%E4%BD%BF%E3%81%86)
- [Cloud FunctionsでGoogle Cloud Python Loggingライブラリを使ってみる（初心者向け）](https://dev.classmethod.jp/articles/logging-lib-at-cloudfunctions/)