Code Engineのインスタンス数を定期的に増減させる[IBM Cloud汎用操作ツール]

# はじめに
こちらは、下記で公開したツールを利用したユースケースの1例になります。

https://qiita.com/katahiro/items/70502a32492d9320309f

IBM CloudのCode Engineは手軽にコンテナアプリケーションを公開することが可能です。
特に、ゼロスケールに対応しておりデプロイしているアプリケーションが呼び出されるまでコンテナを休眠しておき、課金を抑えることが可能になっています。

:::note
IBM CloudのCode Engineでは動作しているアプリケーションが利用したvCPU、メモリの時間(秒単位)で課金されます。
:::

しかし、コンテナが休眠状態になると起動するまで時間が一定時間かかるため、頻繁に使うにも関わらず都度休眠しているともっさり感にイライラすること間違いないでしょう。
かといってデプロイしているアプリケーションの最小インスタンス数を1にすると、常時起動するため、課金面ではあまり節約できない形になります。

例えば、業務時間中をメインに使われるので、夜間は使わないとわかっているアプリケーションであれば、日中帯はインスタンス数の最小を1に設定して常時稼働にしておき、夜間は最小インスタンス数を0に設定すれば、多少起動に時間がかかることになっても極少数のユーザーにしか影響を与えないのであれば、節約の選択肢になると思います。

では、Code Engineに時間指定でインスタンス数を増減させるサービスはあるのでしょうか？

ありません。。。

なので、先の記事で紹介したツールを利用してそれを実現しましょう。

# Code Engineでの設定
Code Engineの設定をCode Engineで行うという形になりますが、Jobを作成する時に、以下のように設定しましょう。まずは、インスタンス数をゼロにするJobです。

- Job Name : `任意の名称`
- Image Reference : `docker.io/hiroapps/ibmcloud-cli-image:1.1.0`
- Job instances : `1`
- Instance resources 
    - CPU and memory : `0.125 vCPU / 0.25 GB`
    - Ephemeral storage (GB) : `0.04`
- Resiliency settings 
    - Mode : `Task`
    - Number of job retries : 3
- Optional settings
    - Environment Variables (optional)
        - `COMMAND00` : `ibmcloud config --check-version=false`
        - `COMMAND01` : `ibmcloud login -- apikey [権限のあるAPIキー] -r [Code Engineのあるリージョン] -g [Code Engineのリソースグループ]`
        - `COMMAND02` : `ibmcloud ce project select -n [Code Engineのプロジェクト名]`
        - `COMMAND03` : `ibmcloud ce app update -n [Code Engineのアプリ名] -min 0`

:::note
執筆時点で利用するイメージは `docker.io/hiroapps/ibmcloud-cli-image:1.0.0`としていますが、最新のイメージがある場合はそちらを利用ください。
- 2024/1/24 : 最新イメージ `1.1.0` に更新しました
 
また、利用者でツールのイメージを別のコンテナレジストリに格納している場合はそちらを利用ください。
:::

:::note warn
`権限のあるAPIキー`と記載していますが、このCode Engineの操作しか行わないように権限を厳密に指定する場合は、次の項の注意をよくご確認ください。ユーザー権限に紐づくAPIキーを生成している場合は問題ありません。
:::

:::note warn
2024/2/14追記 `COMMAND00` を追加しています。促されるCLIバージョンアップを無視するためのコマンドになります。
:::

最初に指定しているログインコマンドですが、仮にAPIキーが `abcde` 、サービスを作成したリージョンが東京、リソースグループが `Default`の場合は、以下のようになります。
`ibmcloud login --apikey abcde -r jp-tok -g Default`

# 上記操作が可能なAPIキーに必要な権限
IBM CloudではService IDという機能を利用して、アカウント内で特定のサービス権限のみ付与したAPIキーを簡易に作成することが可能です。
多くのIBM Cloudの特定のサービスを操作するためのService IDを作成する場合、そのサービスの権限だけを付与すれば良いのですが、Code Engineのサービスは `どのリソースグループに作成されたか` が重要になります。というのも、Service IDで操作する場合は、そのCode Engineを作成した際に指定されたリソースグループに対する権限が無いとAPIを実行することができません。特にリソースグループの指定をしていない場合は `Default` のリソースグループに作成されています。

従って、Service IDにCode Engineの権限を付与する場合、添付の画像では、特定のCode EngineのProjectの操作権限を与えようとしていますが、それに合わせて赤枠のようにそのCode EngineのProjectが作成されたリソースグループを明示的に指定しなければなりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/8670be08-c910-c058-ed73-9b29b4da24d3.png)

こちらの点に注意してService IDに対する権限設定を行っていただければと思います。

# 実行してみよう
さて、上記の権限設定に問題なければ、先ほど指定した環境変数のコマンドに従ってCode Engineのアプリケーションのインスタンス数の最小値がゼロに更新されます。

Jobを作成して、`Submit Job`でJobを手動実行してみましょう。

以下はJobの実行ログをLogDNAのサービスで確認したものです。
```console
Jan 22 15:19:58 Code Engine cli-test-job-jobrun-zpbr8-0-0 ## COMMAND01 ##
Jan 22 15:19:58 Code Engine cli-test-job-jobrun-zpbr8-0-0 $ ibmcloud login *****
Jan 22 15:19:58 Code Engine cli-test-job-jobrun-zpbr8-0-0 API endpoint: https://cloud.ibm.com
Jan 22 15:19:58 Code Engine cli-test-job-jobrun-zpbr8-0-0 Authenticating...
Jan 22 15:19:58 Code Engine cli-test-job-jobrun-zpbr8-0-0 OK
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Targeted account IBM (アカウントID)
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Targeted resource group Default
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Targeted region jp-osa
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 API endpoint:      https://cloud.ibm.com
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Region:            jp-osa
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 User:              ServiceId-サービスID (サービスID名)
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Account:           IBM (アカウントID)
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Resource group:    Default
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 CF API endpoint:   
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Org:               
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 Space:             
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 ## COMMAND02 ##
Jan 22 15:20:08 Code Engine cli-test-job-jobrun-zpbr8-0-0 $ ibmcloud ce project select -n プロジェクト名
Jan 22 15:20:18 Code Engine cli-test-job-jobrun-zpbr8-0-0 Selecting project 'プロジェクト名'...
Jan 22 15:20:18 Code Engine cli-test-job-jobrun-zpbr8-0-0 OK
Jan 22 15:20:18 Code Engine cli-test-job-jobrun-zpbr8-0-0 ## COMMAND03 ##
Jan 22 15:20:18 Code Engine cli-test-job-jobrun-zpbr8-0-0 $ ibmcloud ce app update -n アプリケーション名 -min 0
Jan 22 15:20:18 Code Engine cli-test-job-jobrun-zpbr8-0-0 Updating application 'アプリケーション名' to latest revision.
Jan 22 15:20:38 Code Engine cli-test-job-jobrun-zpbr8-0-0 Traffic is not yet migrated to the latest revision.
Jan 22 15:20:38 Code Engine cli-test-job-jobrun-zpbr8-0-0 Ingress has not yet been reconciled.
Jan 22 15:20:38 Code Engine cli-test-job-jobrun-zpbr8-0-0 Waiting for load balancer to be ready.
Jan 22 15:20:38 Code Engine cli-test-job-jobrun-zpbr8-0-0 Run 'ibmcloud ce application get -n アプリケーション名' to check the application status.
Jan 22 15:20:38 Code Engine cli-test-job-jobrun-zpbr8-0-0 OK
```
問題なくCode Engineのアプリケーションの最小インスタンス数が0になりました。

これでインスタンス数の最小をゼロにするJobが作成できました。
では、インスタンス数を元に戻すJobを作成しましょう。もう1つJobを新規作成して、下記のように設定してください。

- Job Name : `任意の名称`
- Image Reference : `docker.io/hiroapps/ibmcloud-cli-image:1.1.0`
- Job instances : `1`
- Instance resources 
    - CPU and memory : `0.125 vCPU / 0.25 GB`
    - Ephemeral storage (GB) : `0.04`
- Resiliency settings 
    - Mode : `Task`
    - Number of job retries : 3
- Optional settings
    - Environment Variables (optional)
        - `COMMAND00` : `ibmcloud config --check-version=false`
        - `COMMAND01` : `ibmcloud login -- apikey [権限のあるAPIキー] -r [Code Engineのあるリージョン] -g [Code Engineのリソースグループ]`
        - `COMMAND02` : `ibmcloud ce project select -n [Code Engineのプロジェクト名]`
        - `COMMAND03` : `ibmcloud ce app update -n [Code Engineのアプリ名] -min 1`
:::note info
2024/1/24 : 最新イメージ `1.1.0` に更新しました
:::

:::note warn
2024/2/14追記 `COMMAND00` を追加しています。促されるCLIバージョンアップを無視するためのコマンドになります。
:::

先ほどと何が違うかと言われると `COMMAND03`で指定している最小インスタンス数を `1` に変更しただけです。ここでは1に設定していますが、アプリケーションの目的、状況に合わせて指定ください。

というわけで、インスタンス数をゼロに変更するJobが作成できると、元に戻すJobもすぐに作成することができます。

# Event Subsctiptionへの登録
Event Subscriptionへの登録は次のリンク記事の途中から記載しているので、そちらを参考にしてください。

https://qiita.com/katahiro/items/68dd7609844b98925937#code-engine%E3%81%A7%E7%A8%BC%E5%83%8D%E8%A8%AD%E5%AE%9A

cron形式で起動する時間を指定できるので、夜にインスタンス数を減らすJobを登録して、朝にインスタンス数を戻すJobを登録すれば良いでしょう。

:::note warn
Code EngineのJobは指定された起動時間から、Jobのコンテナイメージをロードして動作するので、指定した時間ピッタリに処理が動く、というわけではありません。少し余裕をみて設定させるようにしましょう。
:::

# さいごに
いかがでしたでしょうか？
IBM Cloud汎用操作ツールで、Code Engineの環境をなるべく費用節約する形で運用する目途がつきました。ぜひ、このユースケースを参考にIBM Cloudで理想的な運用が実現できると幸いです。