こんにちは。クイックSREチームのみっちーです。
先日、「AWSからのメンテナンスメールを見落としていて、知らぬ間にEC2が再起動」なんてことがありました。
ログ見ても原因不明。結局メンテナンスというオチで、工数返せよ!って気分になりました。(みなさんもそんな経験ありませんか?)
ということで、反省も踏まえて
「AWSのメンテナンス情報を取得してChatworkへ通知するスクリプトを作った」
のでご紹介します✧(・ㅂ・)و
目次
1. 概要と背景
概要
このスクリプトは、API(AWS コマンドラインインターフェイス) を利用して、「AWS Health」サービスへ情報を取得。
その結果をChatworkへ通知するシェルスクリプトを作成し、cronで1日1回動かすものです。
「AWS Health」とは
「AWS Health」は、ログインアカウント上で利用できる全サービスについて、以下の情報を提供するサービスです。
- 再起動を伴うメンテナンススケジュール
- issues
背景
これまでは、利用しているAWSサービスの全メンテナンス情報をメールで受信する運用にしていました。
しかしこの運用では、以下のような課題がありました。
- issuesを含む全メンテナンス情報が来るので、受信メール数も(当初の想定よりも)多く、内容精査が少々面倒。
- 基本的にはissuesが大多数。そのうちにメール自体を見なくなり、再起動を伴うような肝心なメールの見落とし頻度が増加。
- 結果として、「知らぬ間にEC2が再起動していた」ということも何度か発生。
- 上記に付随し、「予期せぬ再起動」なのか「メンテナンスによるもの」なのかの切り分けにも工数を割かれていた。
そこで、「再起動(ユーザ影響)を伴うメンテナンス情報だけを効率よく拾いたい」と思い調査を開始しました。
2. スクリプトの設計
ほしい情報
AWS管理コンソール上で、
と進むと確認できるメンテナンス情報の中で、
「再起動(ユーザ影響)を伴うメンテナンス情報だけ」がほしい。
具体的には、
以下画像の「Affected resources」に影響があるインスタンス数が表示されており、かつ「StatusがCompleted(またはClose)になっていない」ものが今回取得したい情報です。
設計イメージ
以下を満たすことを前提に行いました。
- 最新のメンテナンス情報を最低でも日に1回は取りたい。
- 将来追加されていくAWSの新サービスについても、取得項目を追加せずとも動的に追従してほしい(ツールのメンテナンスコストを極力減らす)
- 自分達が影響を受けるものだけを抽出するようにしたい。
- できるだけ気づきやすいところに通知するようにしたい。※弊社だとChatworkを日々の業務で使っているので、そこに通知したい。
- Lambda等、他のAWSサービスと連携させて~というのは、(新メンバーなど)後々のメンテナンス性が良くないので、できるだけ避けたい。
3. スクリプトの実装
事前準備
ChatworkAPIの利用申請
- APIを利用できるように事前に申請をしてください。
- なお利用申請方法はここでは省きます✧(・ㅂ・)و
スクリプト実行サーバの構築
- 本記事では、「Amazon Linux AMI release 2017.03」を実行環境として記載しています。
- ※ AWS API コール用のコマンドである「aws」が最初から使えるためです。
- 構築方法はここでは省きます✧(・ㅂ・)و
「~/.aws/credentials」の設置
ソースコード
ご注意ください
- 「ソースコードの品質に関するお問い合わせには応じられません✧(・ㅂ・)و」ので、予めご了承ください。
- 万が一、本ソースコードを利用して損害を被るような事があっても、弊社では一切保証できません。事前によく検証してからご利用下さい。
#!/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です。
実行イメージ
[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上に通知が行きます。
通知内容は、
が含まれていますので、「利用サービスにおいて、再起動を伴うメンテナンスがあるかを気づく」という目的は達成できました。
ただあまり見やすくは無いと思いますので、必要に応じて適宜整形してご利用ください~。
以上で終了です。
少しでも日々の運用のお役に立てば幸いです~ではでは!
\\『明日のはたらくを創る』仲間を募集中です!! // 919.jp