Amazon-Bedrock

CloudWatchのCPUグラフをBedrockに分析させてみた

はじめに

こんにちは、ディーネットの山田です。

案件という訳ではないですが、興味本位でサクッと試してみました。

その内容は、「CloudWatchで取得されているEC2のCPUグラフをBedrock(特にClaude)で分析させるとどういった結果が返ってくるのか?」というものです。

※分析結果とかの文章をAIに頼りきるのではなく、人(エンジニア)が分析する際の手助けに利用できないか?と観点で検証を行っております。

早速試してみた

とあるEC2の4月のCPU使用率のグラフ

yesコマンドを長期間実行することで、1ヶ月間かけてCPU使用率に反映させました。

分析結果

人(エンジニア)で分析するとこうなるでしょう。

4/7~4/10、4/16頃にそれぞれCPU使用率が100%に張り付いている。
4/18頃にCPU使用率が50%になっている時間帯がある。

では、AIに分析させてみます。

(※プロンプトや、プロンプトに与えている情報を書いたソースコードは、後ほど)

## EC2インスタンス稼働分析

### 概要
グラフから、EC2インスタンスのCPU使用率は通常時は低負荷(5%未満)で推移していますが、4/7-4/9と4/16に100%近い急激な負荷上昇が発生しています。また、4/18には約50%のスパイクも観測されています。

### 注意点
4/7-4/9の期間は長時間(約2日間)にわたり100%近いCPU使用率が継続しており、システム過負荷またはバッチ処理の可能性があります。4/16の急激なスパイクは短時間ですが、リソース競合が発生した可能性があります。

### 推奨アクション
- 高負荷期間の原因調査(バッチ処理、異常プロセス、DoS攻撃など)
- Auto Scalingの設定検討
- 定期的な高負荷が予測される場合はスケジュールベースのスケーリング実装
- CloudWatchアラームの設定(CPU使用率70%超過で通知)

人(エンジニア)による分析とAIによる分析でほとんど大差ないことが見てわかると思います。

検証に利用したソースコード

AIに分析してもらうので、追加情報を与えています。

1時間置きのCPU使用率の値を文章レベルでもプロンプトに与えるように改良しています。

import boto3
import json
import base64
from datetime import datetime, timezone, timedelta

def get_cloudwatch_metrics(instance_ids, start_time, end_time, region_name='ap-northeast-1'):
    cloudwatch = boto3.client('cloudwatch', region_name=region_name)

    metrics_data = []
    for instance_id in instance_ids:
        response = cloudwatch.get_metric_statistics(
            Namespace='AWS/EC2',
            MetricName='CPUUtilization',
            Dimensions=[{'Name': 'InstanceId', 'Value': instance_id}],
            StartTime=start_time,
            EndTime=end_time,
            Period=3600,
            Statistics=['Average']
        )

        datapoints = response['Datapoints']
        datapoints.sort(key=lambda x: x['Timestamp'])

        metrics_data.append({
            'InstanceId': instance_id,
            'CPUData': datapoints
        })

    return metrics_data

def get_cloudwatch_graph(image_config, region_name='ap-northeast-1'):
    cloudwatch = boto3.client('cloudwatch', region_name=region_name)

    response = cloudwatch.get_metric_widget_image(
        MetricWidget=json.dumps(image_config),
        OutputFormat='png'
    )

    return response['MetricWidgetImage']

def encode_image(image_bytes):
    return base64.b64encode(image_bytes).decode('utf-8')

def analyze_with_claude(metrics_data, image_base64, region_name='us-east-1', inference_profile_arn=None):
    bedrock = boto3.client('bedrock-runtime', region_name=region_name)

    metrics_text = ""
    for instance in metrics_data:
        metrics_text += f"インスタンス {instance['InstanceId']} のCPU使用率:\n"
        for point in instance['CPUData']:
            # UTCから日本時間(JST)に変換(+9時間)
            jst_time = point['Timestamp'].replace(tzinfo=timezone.utc).astimezone(timezone(timedelta(hours=9)))
            timestamp = jst_time.strftime('%Y-%m-%d %H:%M:%S')
            metrics_text += f"  {timestamp}: {point['Average']:.2f}%\n"
        metrics_text += "\n"

    prompt = f"""
    以下のAWS EC2インスタンスのCPU使用率データを分析し、考察してください。

    {metrics_text}

    また、添付された画像はこれらのインスタンスのCPU使用率グラフです。

    分析してほしいポイント:
    1. 各インスタンスのCPU使用率の傾向と状況
    2. 異常値や注意すべき日時

    技術的な観点から分析してください。
    分析結果は、EC2インスタンスの月次稼働報告として提出します。

    Markdown形式で以下のように出力してください(全体で200文字程度に収めてください):

    ## EC2インスタンス稼働分析

    ### 概要
    [ここに概要を記載 - 全体の傾向]

    ### 注意点
    [ここに異常値や注意すべき点を記載]

    ### 推奨アクション
    [ここに推奨されるアクションを記載]
    """

    request_body = {
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": 2048,
        "temperature": 0.2,
        "top_p": 0.999,
        "messages": [
            {
                "role": "user",
                "content": [
                    {
                        "type": "text",
                        "text": prompt
                    },
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": "image/png",
                            "data": image_base64
                        }
                    }
                ]
            }
        ]
    }

    try:
        response = bedrock.invoke_model(
            modelId=inference_profile_arn,
            body=json.dumps(request_body)
        )
    except Exception as e:
        print(f"インファレンスプロファイル使用中にエラー: {e}")
        response = bedrock.invoke_model(
            modelId="anthropic.claude-3-sonnet-20240229-v1:0",
            body=json.dumps(request_body)
        )

    response_body = json.loads(response['body'].read())
    return response_body['content'][0]['text']

def main():
    cloudwatch_region = 'ap-northeast-1'
    bedrock_region = 'us-east-1'

    inference_profile_arn = "arn:aws:bedrock:us-east-1:YYYYYYYYYYYY:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0"

    instance_ids = ["i-XXXXXXXXXXXXXXXXX"]

    # 日本時間で入力するか、明示的にUTCを指定してください
    start_time = datetime.strptime("2025-03-31T15:00:00.000Z", "%Y-%m-%dT%H:%M:%S.%fZ")
    end_time = datetime.strptime("2025-04-28T06:39:00.000Z", "%Y-%m-%dT%H:%M:%S.%fZ")

    image_config = {
        "view": "timeSeries",
        "stacked": False,
        "metrics": [
            ["AWS/EC2", "CPUUtilization", "InstanceId", "i-XXXXXXXXXXXXXXXXX"]
        ],
        "width": 1200,
        "height": 600,
        "start": start_time.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
        "end": end_time.strftime("%Y-%m-%dT%H:%M:%S.000Z"),
        "timezone": "+0900"
    }

    print("CloudWatchからデータを取得中...")
    metrics_data = get_cloudwatch_metrics(instance_ids, start_time, end_time, region_name=cloudwatch_region)

    print("CloudWatchグラフを取得中...")
    graph_image = get_cloudwatch_graph(image_config, region_name=cloudwatch_region)

    image_base64 = encode_image(graph_image)

    with open("ec2_cpu_graph.png", "wb") as f:
        f.write(graph_image)

    print("Claude 3.7で分析中...")
    analysis = analyze_with_claude(
        metrics_data, 
        image_base64, 
        region_name=bedrock_region,
        inference_profile_arn=inference_profile_arn
    )

    print("\n=== 分析結果 ===\n")
    print(analysis)

    with open("cpu_analysis.md", "w", encoding="utf-8") as f:
        f.write(analysis)
    print("\n分析結果をcpu_analysis.mdに保存しました")

if __name__ == "__main__":
    main()

分析結果

## EC2インスタンス稼働分析

### 概要
インスタンス i-XXXXXXXXXXXXXXXXX は通常時1〜2%の低負荷で稼働していますが、4月7日〜10日と4月16日〜17日に100%の高負荷状態が発生しました。特に4月7日17時から4月10日13時までは約3日間連続で100%のCPU使用率が続いています。

### 注意点
- 4月7日〜10日:約3日間CPU使用率100%が継続(異常な負荷または意図的な高負荷処理)
- 4月16日:16時から18時にかけて急激なCPU使用率上昇(96.79%→100%→48.42%)
- 4月18日:9時〜11時に一時的な負荷上昇(10.45%〜11.78%)

### 推奨アクション
1. 長時間の100%CPU使用の原因調査(プロセス監視、ログ分析)
2. 自動スケーリングポリシーの検討(負荷ピーク時の対応)
3. リソースモニタリングの強化と閾値アラートの設定
4. 定期的な高負荷が予測される場合はインスタンスタイプのアップグレードを検討

少し詳細に結果を分析してくれるようになりましたね。

備考

運用負荷を下げつつ、付加価値向上のために活用できたら最高ですね。。。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA