【AWS】俺の中でSSM Change Calendarがアツい【カレンダー感覚でEvent発火】

# TL;TD

* SSM Change CalendarとはAWS内で作れるカレンダーである
* iCalendar形式で作成ができる
* 最近のアップデートによってEventBridgeとの連携が可能になった。
    * https://aws.amazon.com/about-aws/whats-new/2020/11/aws-systems-manager-change-calendar-integrates-with-amazon-eventbright/
* 実質的にカレンダーベースでのAWS操作の実行予約が可能に。
    * Cronでは表現できない複雑なスケジュール実行管理などにどうぞ
* 環境ごとの起動停止スケジュールをいい感じに管理したかった私にとって、待ち望んでいた機能追加でした
* ~~応用が利くサービスの割にAWS側のドキュメント薄いし、特に記事も少ないので私が書く~~


# SSM Change Calendarとは

* AWS内で作れるカレンダーです。
* SSMのほかの機能と組み合わせて指定時刻で環境操作が可能か判別するのに使えます
* こちらの記事で概要はわかります
    * https://dev.classmethod.jp/articles/systems-manager-change-calendar-release/

* カレンダーはこんな感じ。本当に普通のカレンダーですね(笑)
    * [use-env]って書かれているのがeventと呼ばれます。event内では開始時刻と終了時刻を定義します
    * カレンダーにはStatusが「OPEN」と「CLOSED」があってeventでStatusが変化します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372042/e6040d5b-2586-93e9-9758-69e115ab34ff.png)

* カレンダーの中身はiCalendarになっています
    * APIでドキュメントを見てみるとこんな感じ

```
aws ssm get-document --name start-stop-sreepur-develop --document-format TEXT --profile hue-utility
{
    "Name": "start-stop-sreepur-develop",
    "DocumentVersion": "11",
    "Status": "Active",
    "Content": "BEGIN:VCALENDAR\r\nPRODID:-//AWS//Change Calendar 1.0//EN\r\nVERSION:2.0\r\nX-CALENDAR-TYPE:DEFAULT_CLOSED\r\nX-WR-CALDESC:\r\nBEGIN:VEVENT\r\nDTSTAMP:20201214T075527Z\r\nUID:279e94f8-b8b3-435e-9dad-63817907bc5c\r\nSEQUENCE:0\r\nSUMMARY:stop-time\r\nDTSTART;TZID=Etc/UTC:20201214T220000\r\nDTEND;TZID=Etc/UTC:20201214T223000\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nDTSTAMP:20201214T075527Z\r\nUID:793903c8-da95-4c28-8956-8f74d5d23944\r\nSEQUENCE:0\r\nSUMMARY:use-env\r\nDTSTART;TZID=Asia/Tokyo:20201214T170000\r\nDTEND;TZID=Asia/Tokyo:20201214T200000\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nDTSTAMP:20201214T075527Z\r\nUID:24fe2dcf-b683-4c53-9e99-2e334767f18c\r\nSEQUENCE:0\r\nSUMMARY:use-env\r\nDTSTART;TZID=Asia/Tokyo:20201216T100000\r\nDTEND;TZID=Asia/Tokyo:20201216T210000\r\nRRULE:FREQ=DAILY;UNTIL=20201231T000000Z;INTERVAL=1\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n",
    "DocumentType": "ChangeCalendar",
    "DocumentFormat": "TEXT"
}

```

* 成型してみるとこんな感じ

```txt
BEGIN:VCALENDAR
PRODID:-//AWS//Change Calendar 1.0//EN
VERSION:2.0
X-CALENDAR-TYPE:DEFAULT_CLOSED
X-WR-CALDESC:
BEGIN:VEVENT
DTSTAMP:20201214T075527Z
UID:279e94f8-b8b3-435e-9dad-63817907bc5c
SEQUENCE:0
SUMMARY:stop-time
DTSTART;TZID=Etc/UTC:20201214T220000
DTEND;TZID=Etc/UTC:20201214T223000
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20201214T075527Z
UID:793903c8-da95-4c28-8956-8f74d5d23944
SEQUENCE:0
SUMMARY:use-env
DTSTART;TZID=Asia/Tokyo:20201214T170000
DTEND;TZID=Asia/Tokyo:20201214T200000
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20201214T075527Z
UID:24fe2dcf-b683-4c53-9e99-2e334767f18c
SEQUENCE:0
SUMMARY:use-env
DTSTART;TZID=Asia/Tokyo:20201216T100000
DTEND;TZID=Asia/Tokyo:20201216T210000
RRULE:FREQ=DAILY;UNTIL=20201231T000000Z;INTERVAL=1
END:VEVENT
END:VCALENDAR
```


# EventBridgeとの連携が可能に

* https://aws.amazon.com/about-aws/whats-new/2020/11/aws-systems-manager-change-calendar-integrates-with-amazon-eventbright/
* こんな感じのEventが発行されます

```json
{
  "version": "0",
  "id": "33ac1ac8-315a-4994-55a0-c980b543f766",
  "detail-type": "Calendar State Change",
  "source": "aws.ssm",
  "account": "123456789012",
  "time": "2020-09-17T18:10:00Z",
  "region": "us-east-1",
  "resources": ["arn:aws:ssm:us-east-1:123456789012:document/CWEDemo"],
  "detail": {
    "state": "OPEN",
    "atTime": "2020-09-17T18:10:00Z",
    "event": "CWEDemo"
  }
}
```

* これによって、カレンダーベースのEvent発火が可能になります

# 活用例

## 起動停止スケジュールを管理したい

* 私が運用管理しているアプリケーションはお客様ごとに環境を構築しています
    * 数は100環境以上あります

* 多くはec2でホストしているので、使わない夜間などは停止したい
* 今は専用の社内ツールを使って起動時間を環境ごとに管理しています
* これをAWSで完結できるようにしたい

### 今までの起動停止管理ってどんな感じ？？

* AWSが提供している AWS Solutionだとこんなものがあります
    * https://aws.amazon.com/jp/solutions/implementations/instance-scheduler/
    * DynamoDBでスケジュールデータ管理
    * CloudWatchEventでLambdaを定期発火。Dynamoへのスケジュール問い合わせと起動停止API実行
    * ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372042/7cc55c46-4943-5ee4-9b5d-cdce6fb9d515.png)

* これだと以下のような問題が
    * DynamoDBのコスト・保守費用がかかる
        * 意外と運用コストがかかります
    * 定期的なLambdaの実行
        * ほんとはEvent発火でやりたいが、Dynamoへ問い合わせないとスケジュールが分からない

### Change Calendar +EventBridgeだと・・？

* 環境起動と環境停止のeventを設定する
* 後はEventBridgeで好きなサービスと連携する
    * 僕の場合はCodebuildと連携して元々ある起動停止用スクリプトを実行しています
* EventBridgeでのRuleはこんな感じです
    * Eventの開始と終了でそれぞれ発火させて、Statusの「OPEN」か「CLOSED」かによって、codebuild内の処理を分岐させてます
* こんなカレンダーを環境ごとに用意。必要に応じてEventを変更すればそれで起動停止時刻が変更可能

```json
{
  "source": [
    "aws.ssm"
  ],
  "detail-type": [
    "Calendar State Change"
  ],
  "detail": {
    "event": [
      "use-env"
    ]
  }
}
```

* これが***タダ***でできます
* ***DynamoDBのコストもLambdaのコストもかかりません***

## そのほかにも

* event名で指定したインスタンスを起動or停止するスケジュール
    * EventBridgeでSSM Automationを実行
    * event名をインプットトランスフォーマーで渡してあげる
* ビルドスケジュールの管理
    * 今まではRuleでCronで設定したのを置き換える
    * 複雑なスケジュールや、急遽実施したいビルドにも対応

可能性は無限かと思います

# まとめ

* Change Calendar目立っていないけど、応用度高い
* Cronではハンドルできないスケジュール管理に使える
* 地味だけど魅力的な機能追加をさらりとするAWS、やっぱええっすね。