クイック エンジニアリングブログ

株式会社クイック Web事業企画開発本部のエンジニアリングチームが運営する技術ブログです。

【AWS Health】AWSのメンテナンス情報を取得してChatworkへ通知するスクリプトを作った

こんにちは。クイックSREチームのみっちーです。

先日、「AWSからのメンテナンスメールを見落としていて、知らぬ間にEC2が再起動」なんてことがありました。
ログ見ても原因不明。結局メンテナンスというオチで、工数返せよ!って気分になりました。(みなさんもそんな経験ありませんか?)

ということで、反省も踏まえて
AWSのメンテナンス情報を取得してChatworkへ通知するスクリプトを作った」
のでご紹介します✧(・ㅂ・)و

目次

1. 概要と背景

2. スクリプトの設計

3. スクリプトの実装

1. 概要と背景

概要

このスクリプトは、APIAWS コマンドラインインターフェイス) を利用して、「AWS Health」サービスへ情報を取得。
その結果をChatworkへ通知するシェルスクリプトを作成し、cronで1日1回動かすものです。

AWS Health」とは

AWS Health」は、ログインアカウント上で利用できる全サービスについて、以下の情報を提供するサービスです。

  • 再起動を伴うメンテナンススケジュール
  • issues

背景

これまでは、利用しているAWSサービスの全メンテナンス情報をメールで受信する運用にしていました。
しかしこの運用では、以下のような課題がありました。

  • issuesを含む全メンテナンス情報が来るので、受信メール数も(当初の想定よりも)多く、内容精査が少々面倒。
  • 基本的にはissuesが大多数。そのうちにメール自体を見なくなり、再起動を伴うような肝心なメールの見落とし頻度が増加。
  • 結果として、「知らぬ間にEC2が再起動していた」ということも何度か発生。
  • 上記に付随し、「予期せぬ再起動」なのか「メンテナンスによるもの」なのかの切り分けにも工数を割かれていた。

そこで、「再起動(ユーザ影響)を伴うメンテナンス情報だけを効率よく拾いたい」と思い調査を開始しました。

2. スクリプトの設計

ほしい情報

AWS管理コンソール上で、

と進むと確認できるメンテナンス情報の中で、
「再起動(ユーザ影響)を伴うメンテナンス情報だけ」がほしい。

具体的には、
以下画像の「Affected resources」に影響があるインスタンス数が表示されており、かつ「StatusがCompleted(またはClose)になっていない」ものが今回取得したい情報です。 f:id:aimstogeek:20190313161220p:plain

設計イメージ

以下を満たすことを前提に行いました。

  • 最新のメンテナンス情報を最低でも日に1回は取りたい。
  • 将来追加されていくAWSの新サービスについても、取得項目を追加せずとも動的に追従してほしい(ツールのメンテナンスコストを極力減らす)
  • 自分達が影響を受けるものだけを抽出するようにしたい。
  • できるだけ気づきやすいところに通知するようにしたい。※弊社だとChatworkを日々の業務で使っているので、そこに通知したい。
  • Lambda等、他のAWSサービスと連携させて~というのは、(新メンバーなど)後々のメンテナンス性が良くないので、できるだけ避けたい。

3. スクリプトの実装

事前準備

ChatworkAPIの利用申請

  • APIを利用できるように事前に申請をしてください。
  • なお利用申請方法はここでは省きます✧(・ㅂ・)و

スクリプト実行サーバの構築

  • 本記事では、「Amazon Linux AMI release 2017.03」を実行環境として記載しています。
  • AWS API コール用のコマンドである「aws」が最初から使えるためです。
  • 構築方法はここでは省きます✧(・ㅂ・)و

「~/.aws/credentials」の設置

  • AWSAPIを利用するためのキーペアを設置します。
  • 作成と設置の方法はここでは省きます✧(・ㅂ・)و

ソースコード

ご注意ください

  • ソースコードの品質に関するお問い合わせには応じられません✧(・ㅂ・)و」ので、予めご了承ください。
  • 万が一、本ソースコードを利用して損害を被るような事があっても、弊社では一切保証できません。事前によく検証してからご利用下さい。
#!/bin/bash

# define local command, & dir path.
BASEDIR=$(cd $(dirname "$0") && pwd)
LOGDIR="${BASEDIR}/logs/"

# define argument.
TARGET_ACCOUNT_AWS_PROFILE=$1

# Chatwork token.
CHATWORK_TOKEN='APIトークン情報を入れてね'
CHATWORK_ROOM_ID='通知先のルームIDを入れてね'

# exec.
## check argument.
if [ $# != "1" ];then
  echo "usage: $0 <target account for ~/.aws/credentials>"
  exit 1
fi

cd ${BASEDIR}
if [ ! -d "${LOGDIR}" ];then
  mkdir -p ${LOGDIR}
fi
ARN_NAME="${LOGDIR}/${TARGET_ACCOUNT_AWS_PROFILE}.arn"
LOG_NAME="${LOGDIR}/${TARGET_ACCOUNT_AWS_PROFILE}.log"

## initialize.
echo "" > ${LOG_NAME}

aws health --profile=${TARGET_ACCOUNT_AWS_PROFILE} describe-events --region us-east-1 \
--query 'events[?eventTypeCategory == `scheduledChange` && statusCode != `closed`].arn' | grep arn | tr -d '\,' > ${ARN_NAME} 2>&1

if [ -s "${ARN_NAME}" ];then
  for EVENT_ARN in `cat ${ARN_NAME}`
  do
    aws health --profile=${TARGET_ACCOUNT_AWS_PROFILE} describe-affected-entities --region us-east-1 --filter eventArns="${EVENT_ARN}" --query 'entities[].[entityValue,eventArn]' >> ${LOG_NAME}
  done

  SEND_MESSAGES=`echo "[info][title]警告:AWSの「再起動を伴うメンテナンス情報」が更新されました@${TARGET_ACCOUNT_AWS_PROFILE}[/title]" && cat ${LOG_NAME} && echo "[/info]"`
  ## for Chatwork report. 
  curl -X POST -H "X-ChatWorkToken:${CHATWORK_TOKEN}" -d "body=${SEND_MESSAGES}" \
  "https://api.chatwork.com/v2/rooms/${CHATWORK_ROOM_ID}/messages"  1>&2
fi

exit 0

ソースコードの説明

aws health describe-events

  • ここで指定したアカウントが利用可能なサービスの、「メンテナンス情報一覧」を取得できます。

aws healthで指定する「--region」は「us-east-1」 で固定。

  • リージョンはGlobal になるので、us-east-1(Global)で固定です。これ以外を入れるとエラーが返ってきます。

https://api.chatwork.com/v2/~

  • チャットワークにメッセージをPOSTするときに指定するAPIのURLです。
  • ${CHATWORK_ROOM_ID} は、通知したいチャットワークのルームIDです。

実行イメージ

  • ここでは実行環境として、「Amazon Linux AMI release 2017.03」を使用しています。
[ec2_user@test-ec2-instance] $ cat ~/.aws/credentials
[default]
aws_access_key_id = アクセスID
aws_secret_access_key = 秘密鍵

[ec2_user@test-ec2-instance] $ ./get_aws_health.sh default

スクリプトの引数として「~/.aws/credentials」のユーザ名(ここではdefault)を指定して実行します。
すると、こんな感じにChatwork上に通知が行きます。 f:id:aimstogeek:20190313162309p:plain

通知内容は、

  • タイトルに「影響を受けるAWSアカウント名」

  • 本文に、「影響を受けるインスタンスID」「影響を受けるサービス名」、および「メンテナンススケジュールのID」

が含まれていますので、「利用サービスにおいて、再起動を伴うメンテナンスがあるかを気づく」という目的は達成できました。
ただあまり見やすくは無いと思いますので、必要に応じて適宜整形してご利用ください~。

以上で終了です。
少しでも日々の運用のお役に立てば幸いです~ではでは!



\\『明日のはたらくを創る』仲間を募集中です!! // 919.jp