1
/
5

特定の障害対応を自動化してみた

こんにちは、那須です。

2ヶ月ほど前にAWSからIncident Managerというサービスが登場しましたね。詳細は↓こちらのブログをご参照ください。運用担当の方にとっては最高のサービスが出てきたと思ってます。

AWS Systems Manager の新機能である Incident Manager で IT インシデントを迅速に解決 | Amazon Web Services
IT エンジニアは、アプリケーションやインフラストラクチャを構築する自らの能力と配慮に誇りを持っています。しか [...]
https://aws.amazon.com/jp/blogs/news/resolve-it-incidents-faster-with-incident-manager-a-new-capability-of-aws-systems-manager/

記事にもあるように、障害は突然やってきます。だいたい今から飲みにいくぞー!って時に障害コールが来たりするんですよね。そんな時に限って簡単に解決できない内容だったりします。

私が所属するdotDではonedogというサービスを提供しています。AWSのサービスを活用して運用していて、障害発生時はインフラ担当である私がメインで動くことが多いです。そして先日までは障害対応を全て手作業で対応していました。普段の運用タスクもある中で障害対応で時間を取られるとかなりツライですよね。そこでIncident Managerに目をつけて実際にやってみた内容をご紹介します。

▼目次

  • これまでの障害対応の問題点
  • 描いていた障害対応自動化
  • 実装概要
  • 実際の実装内容
  • インシデント発生テスト
  • 実装後の運用上のメリット
  • 別の実装案
  • さいごに

これまでの障害対応の問題点

以下のような問題を抱えていました。

復旧まで1時間弱かかったり、復旧手順を知っている人しか対応しづらかったり、手作業なのでオペミスしてさらに別の問題が発生してしまう、などの問題は大なり小なりどこの運用業務でもあるんじゃないでしょうか?(最近はもしかしたら少ないのかもしれませんね)

これらの問題を解決すべく、真剣にどうすればいいか考えてみました。

描いていた障害対応自動化

障害対応の自動化と言っても様々です。何を、どういうタイミングで、どうやって自動化するのか、運用担当への連絡はどうするのか、連絡が必要なら手段はどうするか等々、考えることはたくさんありますね。今回はRDSインスタンスのCPU使用率が100%にはりついてしまった場合にスケールアップする内容を例にやったことをご紹介します。

では自動化の内容を考えてみましょう。RDSインスタンスのスケールアップをする場合、対象のRDSインスタンス名、今のインスタンスタイプ、スケールアップ後のインスタンスタイプが情報として必要です。タイミングはCloudWatchアラームで検知したタイミングでOKです。Incident ManagerはアクションとしてSystems Manager Automation(以降 SSM Automation)が使えるので、SSM Automationドキュメントにスケールアップ実行の流れを書いて対応しましょう。

実装概要

図にするとこういう構成です。RDSのCPU使用率が100%近くになったら検知するCloudWatchアラームを設定して、アクションにIncident Managerのレスポンスプランを指定します。レスポンスプランは、チャットチャネルやエンゲージメントで通知するSlackチャンネルや電話番号を設定しておきましょう。あとはランブックで実行するSSM Automationドキュメントと実行に必要なIAMロールを指定すればOKです。たったこれだけで障害復旧作業を自動化できます。


実際の実装内容

SSM Automationドキュメント

まずはSSM Automationドキュメントから作成しましょう。コンテンツは以下のYAMLの通りです。Step1でaws:executeScriptアクションを指定してPythonスクリプトを実行する形にして、RDSインスタンス名やインスタンスタイプのリストを直書きして定義しておきます。SSM Automationでinputできるようにしていたとしても、レスポンスプランからinput情報を渡すことは現時点ではできません。

やってみてちゃんと動いてはいるものの、もうちょっといいやり方があるような気がしています。誰かこうすればいいよ!ってのがあれば教えてください。

description: null
schemaVersion: '0.3'
assumeRole: 'arn:aws:iam::111111111111:role/IAMロール名'
outputs:
- DefineRDSInstanceType.CurrentType
- DefineRDSInstanceType.TargetType
mainSteps:
- name: DefineRDSInstanceType
action: 'aws:executeScript'
inputs:
Runtime: python3.7
Handler: script_handler
Script: |-
def script_handler(events, context):
import boto3
client = boto3.client('rds')

current = client.describe_db_instances(
DBInstanceIdentifier='RDSインスタンス名'
)['DBInstances'][0]['DBInstanceClass']

type_list = ('db.m5.large', 'db.m5.xlarge', 'db.m5.2xlarge', 'db.m5.4xlarge', 'db.m5.8xlarge', 'db.m5.12xlarge', 'db.m5.16xlarge', 'db.m5.24xlarge')

for list in type_list:
if list == current:
target = type_list[type_list.index(list)+1]
break

return {'current': current, 'target': target}
isEnd: false
outputs:
- Selector: $.Payload.target
Type: String
Name: TargetType
- Selector: $.Payload.current
Type: String
Name: CurrentType
- name: ScaleupRDS
action: 'aws:executeAwsApi'
inputs:
Service: rds
Api: ModifyDBInstance
DBInstanceIdentifier: RDSインスタンス名
ApplyImmediately: true
DBInstanceClass: '{{ DefineRDSInstanceType.TargetType }}'
isEnd: falsedescription: null
schemaVersion: '0.3'
assumeRole: 'arn:aws:iam::111111111111:role/IAMロール名'
outputs:
- DefineRDSInstanceType.CurrentType
- DefineRDSInstanceType.TargetType
mainSteps:
- name: DefineRDSInstanceType
action: 'aws:executeScript'
inputs:
Runtime: python3.7
Handler: script_handler
Script: |-
def script_handler(events, context):
import boto3
client = boto3.client('rds')

current = client.describe_db_instances(
DBInstanceIdentifier='RDSインスタンス名'
)['DBInstances'][0]['DBInstanceClass']

type_list = ('db.m5.large', 'db.m5.xlarge', 'db.m5.2xlarge', 'db.m5.4xlarge', 'db.m5.8xlarge', 'db.m5.12xlarge', 'db.m5.16xlarge', 'db.m5.24xlarge')

for list in type_list:
if list == current:
target = type_list[type_list.index(list)+1]
break

return {'current': current, 'target': target}
isEnd: false
outputs:
- Selector: $.Payload.target
Type: String
Name: TargetType
- Selector: $.Payload.current
Type: String
Name: CurrentType
- name: ScaleupRDS
action: 'aws:executeAwsApi'
inputs:
Service: rds
Api: ModifyDBInstance
DBInstanceIdentifier: RDSインスタンス名
ApplyImmediately: true
DBInstanceClass: '{{ DefineRDSInstanceType.TargetType }}'
isEnd: false

SSM Automationドキュメント実行用IAMロール

上記のSSM Automationドキュメントを実行するためのロールを作成します。信頼されたエンティティはssm.amazonaws.comとしましょう。ポリシーは以下の通りです。

{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"rds:ModifyDBInstance",
"rds:DescribeDBInstances"
],
"Resource": "arn:aws:rds:ap-northeast-1:111111111111:db:RDSインスタンス名",
"Effect": "Allow"
}
]
}{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"rds:ModifyDBInstance",
"rds:DescribeDBInstances"
],
"Resource": "arn:aws:rds:ap-northeast-1:111111111111:db:RDSインスタンス名",
"Effect": "Allow"
}
]
}

Incident ManagerレスポンスプランからSSM Automationドキュメントを実行するためのIAMロール

SSM AutomationドキュメントはIncident Managerから実行されます。信頼されたエンティティはssm-incidents.amazonaws.comとして、ポリシーは以下でIAMロールを作成しましょう。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": "arn:aws:ssm:*:111111111111:automation-definition/SSM Automationドキュメント名:*",
"Action": "ssm:StartAutomationExecution"
},
{
"Effect": "Allow",
"Resource": "arn:aws:iam::111111111111:role/実行用IAMロール名",
"Action": "sts:AssumeRole"
}
]
}{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": "arn:aws:ssm:*:111111111111:automation-definition/SSM Automationドキュメント名:*",
"Action": "ssm:StartAutomationExecution"
},
{
"Effect": "Allow",
"Resource": "arn:aws:iam::111111111111:role/実行用IAMロール名",
"Action": "sts:AssumeRole"
}
]
}

Incident Managetレスポンスプラン

以下のAWSドキュメントに従ってAWS Chatbotや連絡先を設定しましょう。ランブックのところで、上記で作成したSSM Automationドキュメントとそれを実行するためのIAMロールを指定すれば設定完了です。設定は大して難しくないのとあまりいい絵ではないので、画面キャプチャは省略します。

Preparing for incidents in Incident Manager
Learn about AWS Systems Manager Incident Manager incident response plans.
https://docs.aws.amazon.com/incident-manager/latest/userguide/incident-response.html


CloudWatchアラーム

最後にCloudWatchアラームからIncident Managerを呼び出す設定をしましょう。ステップ2のアクションの設定画面の一番下にSystems Managerアクションという設定箇所があります。そこで インシデントを作成 を選択して、先ほど作成したレスポンスプラン名を選択するだけです。これでALARM状態になったらIncident Managerで設定したレスポンスプランが呼び出されるようになりました。

以上で設定は完了です。ではテストしてみましょう。

インシデント発生テスト

IAMロールのポリシーを本当に必要なもののみに絞って設定したので、AWSマネジメントコンソールから先ほど作成したSSM Automationドキュメントを直接実行してテストすることができません。ですので実際の障害発生を想定してテストしてみましょう。以下のAWS CLIコマンドで指定したアラームをALARM状態にすることができますので、実行して擬似的に障害検知させてみます。

 aws cloudwatch set-alarm-state --alarm-name アラーム名 --state-value ALARM --state-reason "test"

CloudWatchアラームで障害検知直後にSlackに通知が以下の画像のように来ました。インシデントが開始されたこと、OpsItemが作成されたこと、1分後にランブックが実行完了したことが通知されていますね。また、インシデント発生と同時に自動音声で電話がかかってきました。インシデント名をそのまま読み上げたりしてくれるので、レスポンスプランの名前は自動音声が読みやすい名前にしておくと電話でもある程度何が起こっているのかを知ることができます。

Incident Managerの画面では、タイムラインとランブックの状態を確認できます。タイムラインにはカスタムイベントとして自由に時系列で対応内容を追記することができますので、インシデントに関する情報はインシデントのタイムラインにまとめておくのもいいかもしれませんね。

SSM Automationのステータスも確認しました。出力にスケールアップの前後のインスタンスタイプが表示されているので、このタイミングで何から何に変更したのかがわかるようになっています。

実際に対象のRDSインスタンスを確認すると、インスタンスタイプがdb.m5.8xlargeになっていました。RDSコンソールで最近のイベントをお見せして同じ日時に変更がかかっているのを紹介したかったんですが、画像を撮り忘れました…

実装後の運用上のメリット

実際に実装してみて、かなり障害対応の負荷が時間的にも体力的にも精神的にも下がったように思います。手順が決まっている復旧作業はこのような形で自動化しておくと、サービスを利用されているユーザの皆様にもご迷惑をおかけしてしまう時間をかなり短縮できますね。

別の実装案

上記の実装内容でこのように書きました。

これは、複数のリソースをSSM Automationの対象としても、リソースごとにSSM Automationドキュメントを作成しないといけない、ということになります。大規模なシステムを運用されている場合だと、この制約はかなりつらいのではないでしょうか?

でも大丈夫です! 複数リソースに対応して、かつIncident Managerを使って(手作業にはなりますが)タイムラインを残したり自動電話連絡をかけたりすることはできます。

図で示すとこのような構成にして複数リソースに対応できます。やってることは単純で、EventBridgeでCloudWatchアラームのALARM状態をトリガーにして、動的にinputを定義できるSSM Automationドキュメントを実行するだけです。一方でIncident Managerから実行するSSM Automationは説明や確認手順を記載しただけのものを定義して自動電話連絡するようにしておけば、どのリソースで障害発生していて何を確認すればいいのかがわかります。他にもやり方はあると思いますが、このようなシンプルな形で始めるのもいいと思います。


さいごに

今回は障害対応の自動化について実際に実装した内容をご紹介しました。これでElasticsearchのEBSサイズ拡張とRDSスケールアップとAPIのデプロイ作業が自動化された環境になりました。他にもやりたいことはたくさんありますが、少しずつ自動化タスクも進めていきたいと思います。

今回は障害対応の自動化を例に書きましたが、他にも運用タスクで自動化したり開発がスムーズになるような仕組みを整えたりしています。このような自動化の仕組みを作ったり運用したりしていくメンバーがまだまだ必要です。規模に関係なく何かしらの自動化に興味がある方がいれば是非一緒にやっていきましょう!


SREエンジニア
SREとして新規事業のプラットフォームを支えるエンジニア募集!!
【世の中に新しい価値を生み出し続ける事業創造ファーム】 私たちは自社事業と共創事業の2つを軸に、技術・知識・経験を相互に作用させることで、新しい事業を生み出し、常にアップデートし続けることで、ひとりひとりの「当たり前」に変化をもたらす価値を創造し続けます。 ①共創事業 大企業様の新規事業戦略立案から開発まで、先方の持っている課題感や構想をヒヤリングすることから始め、事業を成功に導くためのお手伝いをしています。大企業の社会的影響力や利用可能な資源の量、dotDの強みである発想力や敏捷性・柔軟性と、その両方を掛け合わせることでひとりひとりの「当たり前」に変化をもたらす価値を創造し続けます。 ▼直近の案件例 “クルマのデジタルキー”から“スマートシティを支えるサービス”へ「TOKAI RIKA Digitalkey」 https://digitalkey.jp/ TOKAI RIKA Digitalkeyは、クルマ以外のモビリティ、オフィスなどの建物、駐車場などもデジタルキー化を促進させ、物理的な「鍵」のない安全で便利な社会の実現を目指します。様々な場所をデジタルキー化することで、それぞれが繋がり、お客様へのシームレスなサービス提供と課金、事業者様における人員削減などに貢献します。 ②自社事業 dotDには、社会や身近に課題意識を持ったメンバーがおり、課題が深く難易度が高い領域への事業化に可能性やビジョンをもってチャレンジしながらサービス開発をしています。 現在はPetTech(ペット x テクノロジー)、EdTech(エデュケーション x テクノロジー)での新サービス開発を中心に取り組んでいますが、今後もどんどんチャレンジする領域を広げていきます。 愛犬とオーナーに幸せを届けるプラットフォーム「onedog」 https://onedog.io/ja/app/index.html 子どもの本当の好きに出会える課外活動マッチングサービス「meepa」 https://meepa.io/ フィジタル空間を実現し、新たなオンライン体験を模索するプロジェクト「iDovatar」 https://project.idovatar.com/
株式会社dotD


採用情報 | 株式会社dotD
株式会社dotDの採用情報ページです。世の中に必要とされるサービスを生み出し続け、社会インフラとなる企業を目指す私たちと一緒に働く仲間を募集しています。
https://dotd-inc.com/ja/careers/


株式会社dotDでは一緒に働く仲間を募集しています
同じタグの記事
今週のランキング
株式会社dotDからお誘い
この話題に共感したら、メンバーと話してみませんか?