🦔
TiDB Cloudを夜間停止する
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}"
}'
参考情報
Discussion