Terraform loop処理の応用編(5) - Metric Alarm

大晦日も淡々と自宅PoCをし、淡々と記事を書く。Terraform loop処理シリーズ、今回はEC2インスタンスに対するCloudWatch Alarmの作成をやってみる。 ...

December 31, 2021

CloudWatchアラーム + SNSからのメール本文をカスタマイズする(3)

表題のテーマ、過去にもCloudWatchアラーム通知メールのカスタマイズについて書いたが、表示時刻がUTCなのでJSTに変換しようと考えた。 過去記事 CloudWatchアラーム + SNSからのメール本文をカスタマイズする(2) CloudWatchアラーム + SNSからのメール件名をカスタマイズする CloudWatchアラームから渡されるeventの、元データの時刻表示は例えば'2021-10-24T09:35:10Z’となっている。これをJSTにするのに手っ取り早いのはpytzを使う方法だが、諸事情により標準ライブラリの範囲でやる必要がある。 で、試行錯誤。当初datetime型にしてからJSTに変換しようとしたがいいやり方が見つからなかったため「unixタイムスタンプに変換後、JSTに変換」とすることにした。 from datetime import datetime, timezone, timedelta from dateutil import parser JST = timezone(timedelta(hours=+9), 'JST') utcstr = '2021-10-24T09:35:10Z' utcstr_parsed = parser.parse(utcstr) #UNIXタイムスタンプに変換 ux_time = utcstr_parsed.timestamp() #int型にする epoch = int(ux_time) #JSTに変換 dt = datetime.fromtimestamp(epoch).replace(tzinfo=timezone.utc).astimezone(tz=JST) print(dt) 2021-10-25 03:35:10+09:00 当初JSTに変換した後の時間が変だ+18時間になってる何故だ、と悩んだが、拠点にした時間から+18時間になるのはおそらく実行環境がJSTだから。UTCの環境でやれば+9時間になるんだろう。くそ、こんなことで数時間週末を無駄にした。俺の休息時間はいつなんだ? ともあれ、修正したのが以下。コメントの「時刻変換」と、「件名に投入するアラーム名を抽出」を追加した。前回はメール件名規則を「任意の文字列 + 発生契機 + 対象リソース(dimention)」としていたが、発生契機はいらないから代わりにアラーム名にした。 lambda_function.py (時刻表示JSTバージョン) import boto3 import json import os import re from botocore.exceptions import ClientError from datetime import datetime, timezone, timedelta from dateutil import parser print('Loading function') sns_arn = os....

November 20, 2021

CloudWatchアラーム + SNSからのメール本文をカスタマイズする(2)

表題の件、過去記事ではメール件名カスタマイズが主題だったが、メール本文を人間が判読可能なフォーマットにすべく、Lambdaコードを改良してみた。これがSNSに渡り、整形された本文がメール送信される想定である。前回はメール件名を環境変数にしたが今回はコード内から値を取り出している。 類似の過去記事 CloudWatchアラーム + SNSからのメール件名をカスタマイズする lambda_function.py import boto3 import json import os import re from botocore.exceptions import ClientError print('Loading function') sns_arn = os.environ['SNS_TOPIC_ARN'] def lambda_handler(event, context): data = event s = json.dumps(data) e = json.loads(s) print(e) # eventから項目を抽出 t = e['time'] trig = e['detail-type'] alarm = e['resources'] #これはリスト。文字列にするにはalarm[0] # 「理由」となる詳細抽出 reason = e['detail']['state']['reason'] # リソース(ここではインスタンスID)を抽出し、文字列整形 resource = e['detail']['configuration']['metrics'][0]['metricStat']['metric']['dimensions'] res_str = json.dumps(resource) res = re.sub(r"[{}\"]", "", res_str) # 件名整形 subject_str = "本番環境 - アラーム " + trig + " - " + res # メッセージ本文整形 fix_msg = "以下のアラームが発生しました" + "\n" trig_msg = "発生契機:" + "\n" + trig time_msg = "発生時刻:" + "\n" + t alm_msg = "アラーム:" + "\n" + alarm[0] res_msg ="対象リソース:" "\n" + res dtl_msg ="理由:" "\n" + reason msg = fix_msg + "\n\n" + trig_msg + "\n\n" + time_msg + "\n\n" + alm_msg + "\n\n" + res_msg + "\n\n" + dtl_msg try: sns = boto3....

November 14, 2021

AWS監視の方式を整理したい

AWSで過去普通にやってた監視実装も、2,3年経つと(或いはそれより短い周期で)陳腐化する。以前は限られたサービスのリソース範囲でやれることをやっていればよかったが、今はSSM(Systems Manager)、Lambda、EventBridgeなどの「登場人物」が増えて、カスタマイズが可能になったからだ。やれることが増えた分、実装が複雑になる。その分チャレンジングな分野になって楽しめると言えないこともないが…、時間が足りないんだ。頭痛ぇな、まったく。絡み合った糸をほぐすためにまとめてみる。 監視の種別としては大枠としてノード監視、閾値監視、ログ監視、プロセス監視、イベント監視と想定する。それぞれの実装方式が若干異なってくるため整理したい。 監視方式大枠 ノード監視 CloudWatchアラーム(ステータスチェック) ー> (EventBridgeルール) ー> Lambda ー> SNSトピック ー> メール送信 ※ハード障害等でインスタンスが落ちた時に発動される想定。手動で落とした時は発動しないので通知は来ない。 閾値監視 CloudWatchアラーム(閾値チェック) ー> (EventBridgeルール) ー> Lambda ー> SNSトピック ー> メール送信 ※EC2インスタンスのCPU使用率、ディスク使用率を想定。メモリ監視は別途カスタムメトリクスの実装がいる。 ログ監視 CloudWatchLogsでログ出力(サブスクリプションフィルタキーワード検知)ー> Lambda ー> SNSトピック ー> メール送信 ※これだけEventBridgeを使用しない。 プロセス監視 EC2インスタンス上のプロセス数監視に相当する。検索すると「プロセス落ちていたらインスタンス再起動」アクションの事例が多いが、今回やりたいのはメール通知だけ。一応メモっておくけど。 CWエージェント + SSM + インスタンス停止、Lamabdaなし EC2上のプロセスを監視し自動復旧する CWエージェント + SSM + 自動再起動、Lamabdaなし AWSでプロセス監視を実装したい CWエージェント + Lamabda + SSM + 自動再起動 EC2のプロセス監視と自動再起動 procstat事例 以下はSSMを使用せず、procstatプラグインを使用してプロセス監視する例。記事には監視設定以降の通知イベント事例はなし。 CloudWatch Agent でProcstatプラグインの利用が可能になりました SSMを使わずCloudwatchでEC2上のプロセス監視をしてみる 以下は途中まで参照したところ(後半は有料サービスの案内)、アラームを作成するところまでわかりやすかった。であれば、閾値監視と同様にEBルールを挟んでLambdaをターゲットに指定 ー> SNSトピックに渡されてメール送信、でいけるはず。 CloudWatchでプロセス監視する手順をLinuxとWindowsともに詳しく紹介 イベント監視 イベント発生 ー> (EventBridgeルール) ー> Lambda ー> SNSトピック ー> メール送信 ※1....

November 7, 2021

CloudWatchアラーム + SNSからのメール件名をカスタマイズする

CloudWatchアラーム + SNSトピックでメール飛ばす時の件名を変更したい。ということで、過去記事 AWS EventBridge + SNSからのメール件名をカスタマイズする でイベントからのメール通知でやったことを、アラームに変えてやってみた。アラームのトリガーはEC2インスタンスCPU使用率閾値超えとする。 ベースの参照は以下クラメソさんネタ。ただしこちらは本文のカスタマイズであり、件名は変えていない。またLambdaも使用していない。これに先の過去記事パターンを合体させてやってみた。 CloudWatch アラームの通知メールを少しでも読みやすくしたい 処理概要 CloudWatchアラームのステータスがALARMに変わる。 Lambda関数起動 SNSに連携される メール通知 作業概要 SNSトピック作成〜サブスクライブ CloudWatchアラーム作成 Lambda関数作成(Lambda用IAMロールは既存流用) EventBridgeルール作成 EventBridgeルールのターゲットに3.のLambda関数を設定する 対象EC2インスタンスのCPU負荷を上げてアラームステータスにする メール通知確認 検証に使用したアイテム アイテム 名称 SNSトピック alarm-notification-topic CloudWatchアラーム CPU_Utilization_Test Lambda関数 cw-alarm-sns-function EventBridgeルール cw-alarm-rule やったこと SNSトピック作成、Lambda関数作成は冒頭のリンク過去記事でもやったので省略。Lambda関数の環境変数でSNSトピック、メール件名を指定している。一応後半にスクショあり。 CLIよりCloudWatchアラーム作成。少ない負荷でもアラームステータスになるように閾値は10%にしてある。 $ aws cloudwatch put-metric-alarm --alarm-name "CPU_Utilization_Test" \ --metric-name "CPUUtilization" \ --namespace "AWS/EC2" \ --statistic "Maximum" \ --period 60 \ --evaluation-periods 1 \ --datapoints-to-alarm 1 \ --threshold 10 \ --comparison-operator "GreaterThanThreshold" \ --dimensions "Name=InstanceId,Value=i-0xxxxxxxxxxx9" EventBridgeルールの作成。以下の場合、“CPU_Utilization_“を含むアラームと関連付けられる...

November 3, 2021

CloudWatchアラーム作成時のメモ(過去事例)

AWSで、CloudWatchアラームのメッセージをSNSトピックかましてメール送信。昔からよくあるオーソドックスなパターンだが、しばらく縁がなかったので記憶がかすんでいる。過去に構築した時の記録を掘り返してみる。 数年前、CloudFormation(CFn)で環境構築したのだが(主担当は別のメンバー)、CWアラーム作成はCFnで作るのに不向きということでAWS CLIで作成していた。何故CFnが不向きなのか、理由は何だったか思い出せない。以下の記事を見ると普通にCFnでアラーム作成しているから問題なさそうではあるのだが… CloudFormationでCloudWatchAlermを作成する ここで、書いていてうっすら思い出した。過去事例ではオートスケールのアラームだったが、その場合は他のアラームと異なるのかもしれない。(つまりオートスケールのアラームはポリシーを別出しにする)確かASG(オートスケーリンググループ)自体もCFnで作るのは不向きということでCLIで作成してた。CFnだと勝手に変な名前付けられるから、って理由だったかな。しかしハッキリとは思い出せない。 もやもや感が払拭しきれないが、とりあえず過去のメモ書きをのせておく。 ここから。 オートスケーリンググループのCloudWatchアラーム作成時のポイントは、先にSNSトピック、ポリシーを作成する。ポリシー作成のCLIを実行するとARNが出力されるので、その値を定義してアラームを作成する。SNSトピック自体はCFnで作成していた。サブスクリプション作成はコンソールからやったような。グダグダな記憶だが、メールアドレスをサブスクライブする時に手動での承認が発生するのは確か。(設定したメールアドレスに届いたメール内のリンクを押下すると承認が完了する) サブスクリプション承認は手動になるが、アラーム作成時に指定するのはトピックARN。承認しないと後続作業ができないわけではない、と思われる。(ただし承認対応は3日以内に実施すること) 以下、ec2オートスケーリングのスケールアウト/インポリシー作成CLIの例。ec2のオートスケールってパターンもすでにオールドファッション化しているけど…、数年前の事例なので。 スケールアウトポリシー $ aws autoscaling put-scaling-policy \ --auto-scaling-group-name test-web-asg \ --policy-name test-web-scaleout-policy \ --scaling-adjustment 2 \ --adjustment-type ChangeInCapacity \ --cooldown 300 \ --region ap-northeast-1 スケールインポリシー $ aws autoscaling put-scaling-policy \ --auto-scaling-group-name test-web-asg \ --policy-name test-web-scalein-policy \ --scaling-adjustment -2 \ --adjustment-type ChangeInCapacity \ --cooldown 600 \ --region ap-northeast-1 この後、以下のCLIを実行。スケールアウトアラーム作成CLI例。--alarm-actions オプションで 先に作成しておいた$snstopic, $scaleoutpolicy の値を指定している。 snstopic="arn:aws:sns:ap-northeast-1:[AWSアカウントID]:test-alert-mail" scaleoutpolicy="arn:aws:autoscaling:ap-northeast-1:[AWSアカウントID]:scalingPolicy:[ランダム値]:autoScalingGroupName/test-web-asg:policyName/test-web-scaleout-policy" $ aws cloudwatch put-metric-alarm \ --alarm-name "test-web-scaleout-alarm" \ --alarm-description "Alarm when CPU exceeds 70%" \ --metric-name CPUUtilization \ --namespace AWS/EC2 \ --statistic Average \ --period 60 \ --threshold 70 \ --comparison-operator GreaterThanThreshold \ --dimensions Name=AutoScalingGroupName,Value="test-web-asg" \ --evaluation-periods 4 \ --alarm-actions $scaleoutpolicy $snstopic \ --unit Percent \ --region ap-northeast-1 スケールイン時のアラームも同様に作成する。...

October 10, 2021