🌩️

TiDB Cloudの定期開始・停止をTypeScript×GitHub Actionsで実装

2024/05/08に公開

TL;DR

  • TiDB Cloudの定期開始・停止をTypeScript×GitHub Actionsで実現
  • TiDB Cloudの操作はTiDB Cloud API(REST API)を利用
  • 定期開始・停止の流れ
    • プロジェクトの一覧を取得
    • プロジェクトに紐づくクラスターの一覧を取得
    • 条件に該当するクラスターを開始 or 停止を実行

事前に

AWS上でもEventBridgeとLambdaを使えば可能ですが、今回はあえてより楽にできる方法ということでTypeScript×GitHub Actionsを採用しています。
https://zenn.dev/micoworks/articles/a6030ec6227c67

また、TiDB Cloud API(REST API)にはCurlでの利用方法は記載されているので、Curlで十分という方は公式のドキュメントを参照してください。

TypeScriptでTiDB Cloudを操作

0. 事前準備

TypeScriptの環境を用意

※ ここは割愛させていただきます
※ 最近はサクッとScript用意するならBunを利用することが多いです

TiDB CloudでAPI Keyを発行

※ こちらも割愛させていただきます
※ 以下の記事(APIキーの取得部分)が参考になります
https://qiita.com/bohnen/items/48bd6fbc5ada6c21a8ed

1. APIにアクセスするClientを用意

TiDB Cloud APIへのリクエストはHTTPダイジェスト認証を通じて行います。
今回はfetchを利用してアクセスしますが、HTTPダイジェスト認証をデフォルトでサポートしていないため、digest-fetchを利用します。

api-client.ts
const client = new DigestClient(
  process.env.TIDB_PUB_KEY, // 発行したAPI Keyを利用
  process.env.TIDB_PRIV_KEY, // 発行したAPI Keyを利用
);

2. プロジェクトの一覧を取得

上記で作成したClientを元にList all accessible projectsのAPIをCallします。

ListProjects.ts
type ListProjectsResult = {
	items: {
		id: string;
		org_id: string;
		name: string;
		cluster_count: number;
		user_count: number;
		create_timestamp: string;
		aws_cmek_enabled: boolean;
	}[];
	total: number;
};

const result = await client.fetch(
	"https://api.tidbcloud.com/api/v1beta/projects",
);

const listProjectsResult = await result.json() as ListProjectsResult

3. プロジェクトに紐づくクラスターの一覧を取得

上記で取得したプロジェクトの一覧から該当のプロジェクトに対してList all clusters in a projectのAPIをCallします。
※ プロジェクト1件ごとにしか取得できません
※ 今回は検証環境に対してのみ実行しているため、プロジェクト一覧取得後に絞り込みをしています

ListClustersOfProject.ts
type ListClustersOfProject = {
	items: {
		id: string;
		project_id: string;
		name: string;
		cluster_type: "DEVELOPER" | "DEDICATED";
		cloud_provider: "AWS" | "GCP";
		region: string;
		create_timestamp: string;
		config: any; // 割愛
		status: {
			tidb_version: string;
			cluster_status:
				| "AVAILABLE"
				| "CREATING"
				| "MODIFYING"
				| "PAUSED"
				| "RESUMING"
				| "UNAVAILABLE"
				| "IMPORTING"
				| "MAINTAINING"
				| "PAUSING";
			node_map: any; // 割愛
			connection_strings: any; // 割愛
		};
	}[];
	total: number;
};

const result = await client.fetch(
	`https://api.tidbcloud.com/api/v1beta/projects/${project.id}/clusters`,
);

const listClustersOfProject = await result.json() as ListClustersOfProject

4. 条件に該当するクラスターを開始 or 停止を行う

上記で取得したクラスターの一覧から該当のクラスターに対してModify a TiDB Dedicated clusterのAPIをCallします。

ここで注意が必要なのが、開始 or 停止できるのはDedicated(Not Serverless)のクラスターのみであり、クラスターのステータス次第で開始 or 停止できるか決まります。
Modify a TiDB Dedicated clusterのAPIにも記載されています)

if (cluster.cluster_type === "DEDICATED" && cluster.status.cluster_status === "AVAILABLE") {
	// 停止できる
}
if (cluster.cluster_type === "DEDICATED" && cluster.status.cluster_status === "PAUSED") {
	// 開始できる
}

上記を条件を満たした上で、以下のようにCallします。

UpdateCluster.ts
const isPaused = "停止したい" ? true : false
await client.fetch(
	`https://api.tidbcloud.com/api/v1beta/projects/${project.id}/clusters/${cluster.id}`,
	{
		method: "PATCH",
		body: JSON.stringify({
			config: {
				paused: isPaused,
			},
		}),
	},
);

以上でTypeScriptでTiDB Cloudを操作する部分は完了です。

GitHub Actionsで定期開始・停止を作成

1. TiDB CloudのAPI KeyをSecretsに登録

GitHub Actions でのシークレットの使用を参考に設定します。


TiDB CloudのAPI KeyをSecretsに登録する例

2. 定期停止(開始)するワークフローを作成

以下が実際に作成したワークフローになります。
定期開始したい場合はTIDB_CLUSTER_IS_PAUSEDfalseにすることで設定できるようにしています。

cron-stop-cluster.yaml
name: 'Stop Cluster'

on:
  schedule:
    - cron: '59 14 * * 1-5' # UTC 14:59 Mon-Fri(日本時間 23:59 Mon-Fri)

env:
  TIDB_PROJECT_NAME: {{対象のプロジェクト名}}
  TIDB_CLUSTER_IS_PAUSED: true # 停止or開始を設定するための環境変数

jobs:
  stop-cluster:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20.x
      - name: Install
        run: yarn install
      - name: Run
        run: yarn dev # 実行コマンドはよしなに設定してください。
        env: 
          TIDB_PUB_KEY: ${{ secrets.TIDB_PUB_KEY }}
          TIDB_PRIV_KEY: ${{ secrets.TIDB_PRIV_KEY }}
          TIDB_PROJECT_NAME: ${{ env.TIDB_PROJECT_NAME }}
          TIDB_CLUSTER_IS_PAUSED: ${{ env.TIDB_CLUSTER_IS_PAUSED }}

以上でTiDB Cloudの定期開始・停止の設定は完了です。

おわりに

TerraformにもTiDB Cloudを操作するためのProvider(tidbcloud Provider)は用意されています。
ですが、まだまだ操作できる範囲が少ないので上記のような定期開始・停止はまだ難しそうです。
(TiDB Cloud上にクラスターを構築するぐらいならできます)

TiDB Cloud API(REST API)も機能がどんどん追加されているみたいなんで、Terraformの対応にも今後期待してます。

レバテック開発部

Discussion