停止したAuroraが7日後に起動したら、自動的に止める機能をお手軽に作る
TL;DR
- RDSの管理操作にはEVENT IDとというものがある
- これはEventBridgeで拾えるので、そこからRDSの停止処理をするリソースにつなげる
- 停止処理はそれぞれよしなに。自分はAutomationを使いました。
- よくわからん。。とりあえず実現だけしたい!という方はこちらへ
前置き
- 50や100を超えるAuroraを管理する手法を検討しています
- 1,2個しかない場合はほかの解決方法の方が楽かもしれません。
RDSの停止は7日で起動してしまう
AWS側でのメンテナンスの実施など様々な理由がありますが、停止したつもりがいつの間にか起動し、請求が。。。
みたいなことはRDSで開発した人はみな経験があるのではないでしょうか。
AWSの記事
AWSもわかっているので、いくつか回答を用意しています。
- Lambdaの作成がが必要
-
スケジュールでの停止しかできない
- 環境によって停止時間が違うので一律スケジュールはできない
こちらは2021の記事。
- 作成するリソースが多い
- イベントサブスクリプション/SNS/Stepfunction/Lambda * 3
- AWSアカウントは複数アカウントで存在しており、すべてのアカウントでこのリソース作成と管理をしたくはない
- ここまでしてやりたいことでもない。
でもこの記事を見ると、RDSから自動起動に対してイベントが発行されていることがわかります
EventBridgeの活用
イベントといえば、、そうEventBridgeです
イベントが出ているならEventBridgeで拾えるやろ!ということで、やってみたらできました。
このページからClusterの自動起動に関しては↓のように書かれてます
通知
RDS-EVENT-0153
停止中の最大許容時間を超えたため、DB クラスターがスタートされています。
そして実際のEventを見てみるとこんな感じ
{
"version": "0",
"id": "XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX",
"detail-type": "RDS DB Cluster Event",
"source": "aws.rds",
"account": "XXXXXXXXXXX",
"time": "2022-12-06T13:00:16Z",
"region": "ap-northeast-1",
"resources": [
"arn:aws:rds:ap-northeast-1:XXXXXXX:cluster:XXXXXXXX"
],
"detail": {
"EventCategories": [
"notification"
],
"SourceType": "CLUSTER",
"SourceArn": "arn:aws:rds:ap-northeast-1:XXXXXXXX:cluster:XXXXXXXXXX",
"Date": "2022-12-06T13:00:16.580Z",
"Message": "DB cluster is being started due to it exceeding the maximum allowed time being stopped.",
"SourceIdentifier": "XXXXXX",
"EventID": "RDS-EVENT-0153"
}
}
なのでEventBridgeのルールとしては以下になります。
{
"source": ["aws.rds"],
"detail-type": ["RDS DB Cluster Event"],
"detail": {
"EventID": ["RDS-EVENT-0153"]
}
}
Auroraを停止させるためのAPIに必要な引数はこのドキュメントを見ると
どうやらDBClusterIdentifierがあればできそうです。
お、、DBClusterIdentifierはイベント内のSourceIdentifierなので、イベントの情報だけで停止できそうですね
停止方法について
Lambda使うのが一般的かもと思いますが、コードの管理が面倒なので、他の方法を考えました。
EventBridgeから呼び出せる+コードを書かずにAWSのAPIを実行できるサービスは以下になります
- SSM Automation
- StepFunctions
どちらを選んでもOKですが、複雑な分岐や別サービスとのオーケストレーションなどは必要ないのでシンプルに実装ができそうなSSM Automationでやってみました。
注意点としては、ドキュメントでは↓のように書かれていますが、イベントが発火した時点では、Clusterが起動し始めただけなので、停止前にまずはAuroraが起動完了するのを待つ必要があります。
この関係でAWSが用意しているAutomation RunbookであるAWS-StartStopAuroraClusterはうまく動かないので不採用となりました。
結果としてできたRunbookがこちらです。
- ※実行にはIAM Roleの作成が必要なので、あらかじめ作成をしておいてください
- これはEC2周りの記事ですが、参考になると思います。
https://qiita.com/m-oka-system/items/6ca3becfac1206b2d59a
- これはEC2周りの記事ですが、参考になると思います。
description: Stop RDS instance
schemaVersion: '0.3'
assumeRole: '{{ AutomationAssumeRole }}'
parameters:
ClusterName:
type: String
description: (Required) RDS Cluster Id to stop
AutomationAssumeRole:
type: String
description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
default: ''
mainSteps:
- name: AssertNotStopping
action: 'aws:assertAwsResourceProperty'
isCritical: false
onFailure: 'step:WaitClusterAvailable'
nextStep: CheckStop
inputs:
Service: rds
Api: DescribeDBClusters
DBClusterIdentifier: '{{ClusterName}}'
PropertySelector: '$.DBClusters[0].Status'
DesiredValues:
- stopping
- name: WaitClusterAvailable
action: 'aws:waitForAwsResourceProperty'
inputs:
Service: rds
Api: DescribeDBClusters
DBClusterIdentifier: '{{ClusterName}}'
PropertySelector: '$.DBClusters[0].Status'
DesiredValues:
- available
- name: WaitInstanceAvailable
action: 'aws:waitForAwsResourceProperty'
inputs:
Service: rds
Api: DescribeDBInstances
Filters:
- Name: db-cluster-id
Values:
- '{{ClusterName}}'
PropertySelector: $.DBInstances..DBInstanceStatus
DesiredValues:
- available
- name: StopCluster
action: 'aws:executeAwsApi'
inputs:
Service: rds
Api: StopDBCluster
DBClusterIdentifier: '{{ClusterName}}'
- name: CheckStop
action: 'aws:waitForAwsResourceProperty'
onFailure: Abort
maxAttempts: 10
timeoutSeconds: 600
inputs:
Service: rds
Api: DescribeDBClusters
DBClusterIdentifier: '{{ClusterName}}'
PropertySelector: '$.DBClusters[0].Status'
DesiredValues:
- stopped
EventBridgeとAutomationを紐づける
Runbookもできたので、EventBridgeから実行できるようにしましょう
ポイントはInputTransfomerを活用して、イベントのSourceIdentifierをRunbookのパラメータである、ClusterNameに渡してあげることです。
また、AutomationAssumeRoleにはAutomation作成時に用意したIAM RoleのARNをわたしてあげましょう
入力パス
{
"ClusterName": "$.detail.SourceIdentifier"
}
入力テンプレート
{
"ClusterName": ["<ClusterName>"],
"AutomationAssumeRole": ["SSM実行に使用できるIAM RoleのARN"]
}
これによって、どのAuroraClusterであっても、自動起動した際に停止することができるようになりました。
RDS版について
RDSの場合はEVENT-IDがRDS-EVENT-0154
になります
通知
RDS-EVENT-0154
停止中の最大許容時間を超えたため、DB インスタンスが起動されています。
また、停止のAPIも変わります
なので、それに合わせて対応してください
注意点
停止中は自動バックアップなども取られません。いつの間にかバックアップがなくなったなどにならないように、あらかじめSnapshotを取得しておくなどしましょう
Aurora はまた、クラスターが停止している間に基礎となるデータを変更できないため、自動バックアップを実行できません。Aurora は、クラスターの停止中にそのバックアップ保持期間を延長しません。
結論
EventBridge / SSM / IAMだけで実現することができました。
AWS記事のイベントサブスクリプション/SNS/Stepfunction/Lambda * 3に比べたら、かなりコンパクトに実装できています。
もちろん信頼性などはあちらの実装の方が高いなどはあると思います。
気軽に実装したい場合などにぜひ利用してみてください
よくわからん。。とりあえず実現だけしたい!という方へ
Cloudformationのテンプレート作ったので、これでStack作れば1発です
このテンプレートはWHIのAWSアカウントにもStackSetとかで展開していこうと思っています