AWS
elasticache

AWSからの大量のメンテナンス予告メールを捌く技術

2018年もそろそろ終わりになりますが、今年の出来事で印象的だったのはElastiCacheの大量メンテナンスがあったことです。
弊社ではElastiCacheノードをテスト環境や本番環境、インスタンスサイズ大小様々なものを合わせると約600ノード運用しております。
最終的には運用中のノード全体の3分の2である約400ノードがメンテナンス対象となりました。
このメンテナンス通知はメールが主体であったため、これらをどうやって捌いたかを説明したいと思います。

AWSはAPIでメンテナンス情報を取得できるのでは?

基本的にAWSはAPI経由でほぼ全ての情報を取得できるのですが、大規模なメンテナンス時では時折メンテナンス情報がAPI経由で取得できず、
メールがメインの情報源になる場合があります。記憶の限りでは2014年のXenの脆弱性対応による大規模なEC2メンテナンスでも同様となりました。

メールをコピペするのは辛い

弊社はメールとしてG Suite(Gmail)を利用しているのですが、メンテナンス予告メールは大量に来るため手でコピペして処理するのは無理があります。
スクリーンショット 2018-12-06 22.49.42.png
なんとか必要なメールだけファイルに書き出す方法は無いものかと探したところ、良い方法が見つかりました。

  1. 対象のメールにラベルを付ける。(上のスクリーンショットではECと付けています)
  2. https://takeout.google.com/settings/takeoutにアクセスする
  3. 「自分のデータをダウンロード」ページでメールのみにチェックを入れ、「ラベルを選択」で1で付与したラベルを選択する。 スクリーンショット 2018-12-06 22.56.08.png

この操作で対象のメールのみ固められた、mbox形式のメールがファイルとしてダウンロードすることができます。
このmbox形式は平文テキストなのですが、少々扱いにくいです。多くのプログラミング言語でmbox形式ファイルを読み書きできるライブラリが存在するので、
それらを使用しメール1通ごとに分割し、扱いやすい形に加工しましょう。
ざっくりですが、私がpythonで書いた簡単なスクリプトを出しておきます。

import mailbox
import quopri
import re
from collections import defaultdict

mbox = mailbox.mbox('/path/to/maintenance.mbox')
bodies = defaultdict(list)
for message in mbox:
    quoted = str(message.get_payload(0))
    body = quopri.decodestring(quoted).decode('utf-8')
    num = re.findall('Account: (\\d+)', message['Subject'])
    bodies[num[0]].append(body)

アカウント番号をキー、値をリストとしたdefaultdictを用意し、メール本文を詰めていきます。
あるアカウントのElastiCacheノードが、メンテナンス対象になったという通知のメールが1通にまとめて送られるとは限らず別々のタイミングで送られることもあるため、アカウントごとにまとめる処理を行っています。
このような前処理をしておくと、その後の活用が楽になります。この情報を元に下記のような作業を行いました。

  • 予告されたElastiCacheノードが既に存在しない場合もあるため、AWS APIを利用した突き合わせ
  • メンテナンス対象リストをGoogleスプレッドシートにして、作業進捗状況の確認
  • 本番環境用のElastiCacheクラスタは自動フェイルオーバーが有効になっているが、それをメンテナンス中に行いたい場合の手動対応

今時通知系の情報がメールで来ることはあまり考えられませんが、たまにこういう場合がありますので
mbox形式のファイルにしてから処理というのは便利、ということをお伝えしたいです。
ニッチなケースですがお役に立てば幸いです。