NRIネットコム Blog

NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

【Cfnテンプレートあり!】                      AWS監視をもっと自由に ! CloudWatch Metric Math活用術3選

本記事は  オブザーバビリティウィーク  3日目の記事です。
💻📄  2日目  ▶▶ 本記事 ▶▶  4日目  🔔🏢

はじめに

こんにちは!オブザーバビリティウィーク3日目担当の山本です!
皆さんは、 AWS 環境に構築したシステムに監視を入れる際に Amazon CloudWatch(以後、CloudWatch)アラームの評価値はどのように設定しているでしょうか。 通常 CloudWatch メトリクスを閾値と比較することが多いですが、CloudWatch の Metric Math という機能を使うとメトリクスをもとにした柔軟な評価指標の設定が可能になります。
本稿ではこの機能を使い、実務でも活用できるような評価指標の設定をご紹介します。

Amazon CloudWatch Metric Math とは

CloudWatch Metric Math は CloudWatch のメトリクスを使って数学的な計算を行い、新しい時系列データを生成する機能です。これにより、複数のメトリクスを組み合わせて、 ユーザーのニーズに合わせた監視が可能になります。作成した時系列データは CloudWatch コンソールで可視化し、ダッシュボードに追加できます。 代表的な関数としては SUM(合計)や AVG(平均)、IF(条件分岐)などが挙げられます。

docs.aws.amazon.com

実務で使える評価指標3選

今回は実務でも効果的な評価指標とその指標を使った CloudWatch アラームを作成する CloudFormation テンプレートを3つ紹介します。
※以下で紹介する CloudFormation テンプレート例は CloudWatch アラームのみを作成するものとなっているため、通知が必要な場合は別途追加が必要です。

①移動平均を使った異常検知スコア

メトリクスの現在値が通常の傾向(移動平均)からどれだけ離れているかを定量的に評価します。 移動平均とは対象期間を移動させながら、一定期間のメトリクスの平均値をとったものです。 乖離は単純な絶対値比較の他にパーセンテージでも評価するようなカスタマイズもできます。


ABS(m1 - AVG(m1))

・m1:任意のメトリクス ※ABS(a):aの絶対値、AVG(a):メトリクスaの平均値

・活用例

ユースケース メトリクス例 乖離が示すこと
CPUスパイク検知 CPUUtilization 急な負荷上昇
レスポンスタイム監視 TargetResponseTime UXの悪化兆候
ネットワーク異常 NetworkIn/Out 通信量の急増・急減

・テンプレート例(EC2 の CPU スパイク検知)

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  CPUDeviationAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: CPUDeviationAlarm
      AlarmDescription: "Alarm when CPU deviation exceeds threshold"
      EvaluationPeriods: 5
      Threshold: 20  # 偏差の閾値(任意の値を設定する)
      ComparisonOperator: GreaterThanThreshold
      TreatMissingData: notBreaching
      Metrics:
        - Id: m1
          MetricStat:
            Metric:
              Namespace: AWS/EC2
              MetricName: CPUUtilization
              Dimensions:
                - Name: InstanceId
                  Value: <--ここにインスタンスIDを入れる-->
            Period: 300
            Stat: Average
          ReturnData: false
        - Id: e1
          Expression: AVG(m1)
          Label: MovingAverage
          ReturnData: false
        - Id: e2
          Expression: ABS(m1 - e1)
          Label: Deviation
          ReturnData: true

②ALBのターゲットグループリクエスト集中度スコア

ターゲットグループ間でのリクエスト分散の偏りを検出します。 負荷分散が正しくできていなかったり、DDoS攻撃やボットによるアクセス集中が生じているケースを早期に発見したい場合に有効です。
※ターゲットグループ内の個々のターゲット間の偏りを比較したい場合は、ターゲット側でメトリクスを収集し CloudWatch に送信するといった工夫が必要になります。

  
    MAX([RequestCount_Target1, RequestCount_Target2, ...]) - MIN([RequestCount_Target1, RequestCount_Target2, ...])
  

※MAX(a, b, c):a~bの中で最大の値、MIN(a, b, c):a~bの中で最小の値

・テンプレート例
前提: ALB に2つのターゲットグループが設定されていること。

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  ALBRequestConcentrationAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: ALBRequestConcentrationAlarm
      AlarmDescription: "Alarm when request count concentration between target groups exceeds threshold"
      EvaluationPeriods: 1
      Threshold: 100  # ← リクエスト数の偏差閾値(任意の値に設定する)
      ComparisonOperator: GreaterThanThreshold
      TreatMissingData: notBreaching
      Metrics:
        - Id: m1
          MetricStat:
            Metric:
              Namespace: AWS/ApplicationELB
              MetricName: RequestCount
              Dimensions:
                - Name: TargetGroup
                  Value: <--ここに1つ目のターゲットグループのARNを入れる-->
                - Name: LoadBalancer
                  Value: <--ここにALBのARNを入れる-->
            Period: 60
            Stat: Sum
          ReturnData: false
        - Id: m2
          MetricStat:
            Metric:
              Namespace: AWS/ApplicationELB
              MetricName: RequestCount
              Dimensions:
                - Name: TargetGroup
                  Value: <--ここに2つ目のターゲットグループのARNを入れる-->
                - Name: LoadBalancer
                  Value: <--ここにALBのARNを入れる-->
            Period: 60
            Stat: Sum
          ReturnData: false
        - Id: e1
          Expression: MAX([m1,m2]) - MIN([m1,m2])
          Label: RequestConcentration
          ReturnData: true

③アラーム感度スコア

アラームが発火した回数を一定期間で合計したものを評価します。 これによって閾値が厳しすぎる(頻繁に超える)か、緩すぎる(ほとんど超えない)かを判断して閾値調整の参考に役立てることができます。

  
    SUM(IF(m1 > threshold, 1, 0))
  

・m1:任意のメトリクス
・threshold:評価対象アラームの閾値
※IF(a > b, 1, 0):a > bが正の時1をとり、負の時0をとる

・テンプレート例( EC2 の CPU 使用率を監視するアラームの感度を評価)

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  CPUUtilizationBreachCountAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: CPUUtilizationBreachCountAlarm
      AlarmDescription: "Alarm when CPUUtilization exceeds threshold multiple times in a period"
      ComparisonOperator: GreaterThanThreshold
      EvaluationPeriods: 60
      Threshold: 5  # 閾値例:60分間で5回以上閾値を超えたら通知
      TreatMissingData: notBreaching
      Metrics:
        - Id: m1
          MetricStat:
            Metric:
              Namespace: AWS/EC2
              MetricName: CPUUtilization
              Dimensions:
                - Name: InstanceId
                  Value: <--ここにインスタンスIDを入れる-->
            Period: 60  # 1分ごとのデータ
            Stat: Average
          ReturnData: false
        - Id: e1
          Expression: IF(m1 > <--ここに評価対象のアラームで設定されている閾値を入れる-->, 1, 0) 
          Label: BreachFlag
          ReturnData: false
        - Id: sumBreach
          Expression: SUM([e1])
          Label: BreachCountOverPeriod
          ReturnData: true

おわりに

このように CloudWatch Metric Math を使えばアイデア次第で有用な評価指標を設定することができます。 システム監視には欠かせない CloudWatch アラームですが、ただただ監視する項目を増やすだけでは観測できる範囲は広まるものの運用負荷が増加する一方です。 したがって、運用に適切な評価指標を設定することやアラームの見直しを定期的に行い、より負荷を軽減させられるようなカスタマイズをしていくことが大切です。 日々変化するシステム環境に合わせて、アラームも“育てていく”意識が、持続可能な運用の鍵となるでしょう。

執筆者 : 山本将望
食べることが生きがいのインフラエンジニア
執筆記事一覧 : https://tech.nri-net.com/archive/author/m4-yamamoto