👌

AIOps入門 AWS Bedrock で障害分析

2024/09/15に公開

こんにちは。
ご機嫌いかがでしょうか。
"No human labor is no human error" が大好きな吉井 亮です。

アプリケーションがエラーを吐いた、システム障害が起きた、などの好ましくない状況が発生した際、その原因を特定するためには、ログやメトリクスを分析することが必要です。
ただ、マイクロサービス化された現代のシステムでは、何から手を付けてよいか悩むことがあります。

そのような時に役立つのが、AIOps です。
今回は AWS SA さんが公開してくれている Failure Analysis Assistant (FA2) を使って、AIOps に入門します。

Failure Analysis Assistant (FA2) とは

AWS サービスを活用した LLM による障害分析ソリューションです。AWS Summit Japan 2024 でデモ展示されていたらしいので、ご覧になった方もいるかもしれません。

image
https://aws.amazon.com/jp/blogs/news/failure-analysis-assistant-aiops/ より引用

https://aws.amazon.com/jp/blogs/news/failure-analysis-assistant-aiops/

リポジトリはこちらです。

https://github.com/aws-samples/failure-analysis-assistant/tree/main

やってみた

導入

まずは Amazon Bedrock 基盤モデルへのアクセスを管理する を参考に、Anthropic Claude 3.5 Sonnet を有効にしておきます。

次に リポジトリ の手順通りに進めれば、簡単に導入できます。感謝。

解析したい事象を検知する CloudWatch Alarm を作成します。

カスタマイズ

そのままでも十分使えますが、システムに合わせてカスタマイズしました。
LLM により正しい回答を出してもらうには、正しい質問をしなければなりません。

107行目付近に ALB アクセスログを検索しているクエリがあります。事象によってはここをより絞り込むことで LLM から正しい回答を引き出す可能性が上がるかもしれません。逆に広げることケースもありそうです。
余談ですが、私はパーティション化されたテーブルにしていたので、パーティションを使うクエリに修正してました。

lambda/functions/fa2-lambda/main.mts
    const albQuery = `SELECT * FROM ${albAccessLogTableName} WHERE time BETWEEN ? AND ? AND elb_status_code > 400`;
    const albQueryParams = [startDate, endDate];

132行目は CloudTrail のクエリです。こちらも絞り込むことで LLM から正しい回答を引き出す可能性が上がるかもしれません。

lambda/functions/fa2-lambda/main.mts
    const trailQuery = `SELECT eventtime, eventsource, eventname, awsregion, sourceipaddress, errorcode, errormessage FROM ${cloudTrailLogTableName} WHERE eventtime BETWEEN ? AND ? AND awsregion = ? AND sourceipaddress LIKE ?`;
    const trailQueryParams = [startDate, endDate, region, "%.amazonaws.com"];

200行目付近には Claude に渡すパラメーターが定義されています。必要に応じて max_tokens を増やします。
Anthropic Claude Messages API

lambda/functions/fa2-lambda/main.mts
    const llmPayload = {
      anthropic_version: "bedrock-2023-05-31",
      max_tokens: 2000,
      messages: [{ role: "user", content: [{ type: "text", text: prompt }] }],
    };

最も肝になりそうなのはプロンプトです。ここをどれだけ正確に記述できるかが、LLM から正しい回答を引き出すための鍵です。
CloudWatch Alarm ごとにプロンプトを用意するのが良さそうに感じました。
また、Athena や CloudWatch Logs を適切に設定している前提であれば、任意のログを LLM に与えることが可能なので、面倒な WAF ログ検査にも使えそうです。RDS のスロークエリログも解析できるかもしれません。

lambda/lib/prompts.ts
  let prompt = `AWS上で稼働するワークロードを監視・運用するエージェントです。必ず日本語で回答してください。
    あなたが担当するワークロードは、CloudFront、ALB、ECS on EC2、DynamoDBで構成されており、ECS on EC2上にSpringアプリケーションがデプロイされています。
    現在、運用管理者から ${errorDescription} という事象が発生したとの連絡がありました。
    あなたは、<logs>タグに与えられたログを確認し、発生した事象の根本原因を推測してください。
    根本原因を記述する際に、参考にしたログの内容についても記載し、運用管理者が実際のログを確認しやすくしてください。
    <logs>
      <ApplicationLogs>${applicationLogs}</ApplicationLogs>
    `;
  prompt += albAccessLogs
    ? `<ALBAccessLogs>${albAccessLogs}</ALBAccessLogs>`
    : "";

  prompt += cloudTrailLogs
    ? `<CloudTrailLogs>${cloudTrailLogs}</CloudTrailLogs>`
    : "";

  prompt += xrayTraces ? `<XrayTraces>${xrayTraces}</XrayTraces>` : "";

  prompt += `
    </logs>
    発生した事象の根本原因 : `;

必要性

個人的に AIOps はとても気になっている領域です。
アプリケーションの全てを知り尽くしたベテランエンジニアがいるプロダクトなら「AIOps は信用ならん」となるかもしれません。優秀なエンジニアがいれば、ログやメトリクスを見て原因を特定することは可能です。
しかし、障害からの早期回復のために属人性を極力排除することは重要です。専門知識を持たない若手エンジニアでも原因の早期発見ができるならば、それは素晴らしいことです。また、障害発生時のストレスも軽減することができるでしょう。

実際に担当しているシステムで発生しているログファイルを解析させてみましたが、一発で正解を出すことはほとんどありません。(それは人間でも一緒ですが。) ただ、無いよりは相当マシで、当たりをつける手助けになりますし、何が起きているのかを Slack チャンネルに共有することが可能です。
用途別に細かくプロンプトと与えるデータを設定しておけば、障害解析の効率化になることは間違いありません。

Discussion