RDSが1週間で自動的に再起動する問題に終止符を打つ

## 概要
RDSのインスタンスを一時停止したい場合、
「DBインスタンスが7日後に自動的に再起動することを確認する」にチェックをつけなければなりません。

普段使いのDBであれば問題ないですが、
半月に1度程度しか使用しないDBの場合、この1週間で再起動する仕様はちょっと厄介です。
※RDSは起動中に課金されるため

そこで、今回はStep Functionsを使用した解決策を投稿します。

## まとめ
Step Functionsにて、下記手順で処理を行うことで自動再起動の時間を考慮する必要がなくなりました。

![スクリーンショット 2024-11-28 14.20.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3811817/38ea0be3-f838-eba0-e111-35c6dfc3e801.png)

起動後に自動アップデート等のメンテナンスが入る場合は、タイムアウト時間を多めに取っておかないとStopDBClusterが実行される前に処理が終了してしまう可能性があります。
現状、こちらでは20分に設定しています。

Wait時間は1分としていますが、各々ご調整ください。

最初はDescribeDBClusterしか実装していませんでしたが、
DBインスタンスの起動前にStopDBClusterが実行されるとエラーになるようです。

## 設計
まず、実装にあたり他のエンジニアの方の記事を拝見しました。

どの記事でも、
インスタンスが自動的に再起動したことをトリガーにするか、
1週間経過したことをトリガーにしていました。

私自身、最初は1週間の経過をトリガーにしようとしていましたが、
起動から一時停止する間に間隔があるため、
停止時間がずれていくことがネックになっていました。

<details><summary>(読まなくても良い)次回再起動時間がズレる原理</summary>

X日の0時0分に一時停止した場合、
次回再起動はX+7日の0時0分頃ですが、
起動開始から一時停止までに十数分はかかります。
そのため、X+14日の再起動時間は0時0分＋再起動時間　となります。
</details>

そこで思いついたのが、
自分でインスタンスを起動してしまえばいいんだ！ということです。

自動的な再起動を待たずこちらで再起動と一時停止を行い一時停止時間を更新してしまえば、
再起動を待つ必要がありません。

また、実行間隔を1週間に設定することで、
必ず自動的な再起動の前にこの処理を実行することができます。

そこで作成したのが下記です。

## 実装
Step FunctionsでDBクラスターを起動させます。※DBインスタンスは自動で起動します。
その後、DescribeにてDBクラスターとDBインスタンスの起動を確認します。
起動が確認できたタイミングで、DBクラスターを停止することで、停止時間を更新できます。

```
{
  "Comment": "A description of my state machine",
  "StartAt": "StartDBCluster",
  "States": {
    "StartDBCluster": {
      "Type": "Task",
      "Parameters": {
        "DbClusterIdentifier": "{DBクラスターID}"
      },
      "Resource": "arn:aws:states:::aws-sdk:rds:startDBCluster",
      "Next": "DescribeDBClusters"
    },
    "DescribeDBClusters": {
      "Type": "Task",
      "Parameters": {
        "DbClusterIdentifier": "{DBクラスターID}"
      },
      "Resource": "arn:aws:states:::aws-sdk:rds:describeDBClusters",
      "Next": "Choice"
    },
    "Choice": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.DbClusters[0].Status",
          "StringEquals": "available",
          "Next": "DescribeDBInstances"
        }
      ],
      "Default": "Wait1Min"
    },
    "Wait1Min": {
      "Type": "Wait",
      "Seconds": 60,
      "Next": "DescribeDBClusters"
    },
    "DescribeDBInstances": {
      "Type": "Task",
      "Parameters": {
        "DbInstanceIdentifier": "{DBインスタンスID}"
      },
      "Resource": "arn:aws:states:::aws-sdk:rds:describeDBInstances",
      "Next": "Choice (1)"
    },
    "Choice (1)": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.DbInstances[0].DbInstanceStatus",
          "StringEquals": "available",
          "Next": "StopDBCluster"
        }
      ],
      "Default": "Wait1Min(1)"
    },
    "Wait1Min(1)": {
      "Type": "Wait",
      "Seconds": 60,
      "Next": "DescribeDBInstances"
    },
    "StopDBCluster": {
      "Type": "Task",
      "Parameters": {
        "DbClusterIdentifier": "{DBクラスターID}"
      },
      "Resource": "arn:aws:states:::aws-sdk:rds:stopDBCluster",
      "End": true
    }
  },
  "TimeoutSeconds": 1200
}
```

最後に、EventBridgeを設定します。
スケジュールとして、1週間おきにStep Functionsが起動するようにすれば実装完了です。

## まとめ
再起動を待たずしてこちらから起動してしまうやり方は、
自分の中では割と画期的な考えだと思っています。
考慮不足や、もっと良いやり方があればじゃんじゃんコメントいただきたいです。

いいねに飢えているので、
少しでも参考になればいいねください！

ありがとうございました。