14
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

「Develop fun!」を体現する! Works Human IntelligenceAdvent Calendar 2022

Day 10

【Aurora】【RDS】停止しても7日後に勝手に起動するやつを、最小リソースで解決してみた

Last updated at Posted at 2022-12-09

停止したAuroraが7日後に起動したら、自動的に止める機能をお手軽に作る

TL;DR

前置き

  • 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がこちらです。

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とかで展開していこうと思っています

14
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?