🦔

TiDB Cloudを夜間停止する

2023/07/07に公開

TiDB Cloudを夜間停止する

コスト削減の定番、夜間停止ネタです。

TiDB Cloudを採用しているサービスがあり、検証環境にもTiDB Cloud上でクラスターを構築しています。検証環境なので本当はServerless Tierを使えれば良いのですが、Dedicated Tierとバージョンを揃えることができないのでDedicated Tierを採用しています。夜間は基本的に使用しないのでAWS LambdaからAPIを叩いて自動で止まるようにします。

事前準備

TiDB Cloudに管理者アカウントでログインしAPIキーを発行します。
またプロジェクトIDとクラスターIDが必要なのでメモしておきます。

構成イメージ

構築

コードを作成します。 TiDB CloudのAPIが {"paused": true} が入力されると停止、 {"paused": false} が入力されると起動するため、eventで受け取って制御するようにしています。

lambda_function.py
import os
import json
import requests
from requests.auth import HTTPDigestAuth

def lambda_handler(event, context):
    try:
        # 環境変数から設定情報を取得
        public_key = os.environ['TIDB_CLOUD_PUBLIC_KEY']
        private_key = os.environ['TIDB_CLOUD_PRIVATE_KEY']
        project_id = os.environ['TIDB_CLOUD_PROJECT_ID']
        cluster_id = os.environ['TIDB_CLOUD_CLUSTER_ID']

        # APIエンドポイントのURLを構築
        url = f"https://api.tidbcloud.com/api/v1beta/projects/{project_id}/clusters/{cluster_id}"

        # リクエストヘッダーとデータを設定
        headers = {'content-type': 'application/json'}
        data = {"config": {"paused": event['paused']}}

        # PATCHリクエストを送信
        response = requests.patch(url, auth=HTTPDigestAuth(public_key, private_key), headers=headers, data=json.dumps(data))

        # レスポンスを処理
        if response.status_code == 200:
            print(f"API call succeeded. Response: {response.text}")
        else:
            print(f"API call failed. Status code: {response.status_code}, Error: {response.text}")

        return {
            'statusCode': response.status_code,
            'body': response.text
        }

    except Exception as e:
        print(f"An error occurred: {e}")
        return {
            'statusCode': 500,
            'body': f"An error occurred: {e}"
        }
requirements.txt
requests

以下のように配置します。

.
└── function
    ├── lambda_function.py
    └── requirements.txt

デプロイ用パッケージを作成します

cd function
pip3 install -t . -r requirements.txt
zip -r ../deployment-package.zip .

LambdaとEventBridge SchedulerのIAM Roleを作成します。

# TiDB_Cloud_Pause Role
aws iam create-role \
--role-name TiDB_Cloud_Pause \
--assume-role-policy-document \
'{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}'

aws iam attach-role-policy \
  --role-name TiDB_Cloud_Pause \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

# TiDB_Cloud_Pause_Scheduler Role
aws iam create-role \
--role-name TiDB_Cloud_Pause_Scheduler \
--assume-role-policy-document \
'{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "scheduler.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}'

aws iam attach-role-policy \
  --role-name TiDB_Cloud_Pause_Scheduler \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaRole

関数をデプロイします。

cd ..
aws lambda create-function \
--function-name TiDB_Cloud_Pause \
--runtime python3.10 \
--role arn:aws:iam::xxx:role/TiDB_Cloud_Pause \
--handler lambda_function.lambda_handler \
--timeout 30 \
--memory-size 128 \
--environment \
'{
  "Variables": {
    "TIDB_CLOUD_CLUSTER_ID": "xxx",
    "TIDB_CLOUD_PRIVATE_KEY": "xxx",
    "TIDB_CLOUD_PROJECT_ID": "xxx",
    "TIDB_CLOUD_PUBLIC_KEY": "xxx"
  }
}' \
--architectures arm64 \
--zip-file fileb://deployment-package.zip

スケジュールを設定します

# pause schedule
aws scheduler create-schedule \
--name TiDB_Cloud_Pause \
--flexible-time-window '{"Mode": "OFF"}' \
--schedule-expression 'cron(0 18 * * ? *)' \
--schedule-expression-timezone 'Asia/Tokyo' \
--target \
'{
  "Arn": "arn:aws:lambda:ap-northeast-1:xxx:function:TiDB_Cloud_Pause",
  "RoleArn": "arn:aws:iam::xxx:role/TiDB_Cloud_Pause_Scheduler",
  "Input": "{\"paused\": true}"
}'

# resume schedule
aws scheduler create-schedule \
--name TiDB_Cloud_Resume \
--flexible-time-window '{"Mode": "OFF"}' \
--schedule-expression 'cron(0 9 ? * MON-FRI *)' \
--schedule-expression-timezone 'Asia/Tokyo' \
--target \
'{
  "Arn": "arn:aws:lambda:ap-northeast-1:xxx:function:TiDB_Cloud_Pause",
  "RoleArn": "arn:aws:iam::xxx:role/TiDB_Cloud_Pause_Scheduler",
  "Input": "{\"paused\": false}"
}'

参考情報

https://docs.pingcap.com/tidbcloud/api/v1beta

Micoworks株式会社

Discussion