👨‍💻

Do It with AIでアプリケーションを構成する:DevSecOpsに組み込む(運用編)

2025/03/09に公開

前回までAmazon Qをベースに開発工程で行える効率化と品質/セキュリティの担保について考えてきました。生成AIが持つ能力を活かしながら、その制約や課題も理解しておく必要があります。今回は開発後に実際にリリース/運用していく過程での活用方法を考えていきたいと思います。

特にこのOpsフェーズでは、生成AIの特性を考慮した慎重な活用が求められます。開発と同様に正解となるもの、ベストプラクティスとなるものもありませんが、Amazon QとBedrockを組み合わせた運用効率化を試行していきます。

Opsフェーズへの適用

開発と同様にAWSのDevSecOps定義に基づき、以下のRelease→Deploy→Operate→Monitorの効率化とセキュア化を考えていきます。

https://aws.amazon.com/jp/builders-flash/202208/create-devsecops-pipeline/

この工程が開発工程と大きく異なるのは、リアルタイム性と正確性が求められることです。

デプロイやリリースのための資材を作成するという点ではAmazon Qの恩恵を引き続き得る事が出来ます。しかし、デプロイし終わったものについてリアルタイムかつ常時対応するためには、Amazon Qをはじめとした指示/依頼型の生成AIサービスでは人手を一度介する必要があるためラグがあります。これを解消するために、Bedrockでの活用もここでは組み合わせて考えていきます。

Amazon Qを主軸とした場合は何かを生成するフェーズでの適用が活用できる場面と前回までお伝えしてきました。ここでの考えは変わらず、Amazon Qでリリース/デプロイに必要な資材を生成する事をメインで考えています。一方、運用/監視(Ops)フェーズでは、CloudWatch、X-RayやGuardDutyなど有用なマネージドサービスが揃っているため、さらなる効率化をBedrockで考えたいと思います。

工程 生成AIを利用すべきか 利用サービス 責任担保の方法
Release 積極的に活用すべき AmazonQ for Developer+CodeDeploy等CDツール ビジネス要件に合わせた展開計画/戦略を考えるため人間側で担保する
Deploy 支援にとどめるべき Amazon Q for Developer+CodeDeploy等CDツール リリースを行うための資材作成を任せつつもアーキテクチャの最適化は人間が実施する
Operate 支援にとどめるべき Bedrock(またはAmazon Q in Quicksight)+マネージドサービス群 マネージドサービスを積極活用し生成AIでない自動化を実現、その補助を行う
Monitor 支援にとどめるべき Bedrock(またはAmazon Q in Quicksight)+マネージドサービス群 マネージドサービスを積極活用し生成AIでない自動化を実現、その補助を行う

各フェーズでの対応

開発フェーズ以上にシステム全体、そして組織体制にも関わるのが運用フェーズです。流れとして開発後に建てつくものではありますが、開発フェーズにも関わってもきます。例えば、CI/CDパイプラインの流れこそが自動化された開発の運用と解釈もできるためです。

Release/Deploy

リリース/デプロイフェーズでは構成したアプリケーションを稼働させユーザに公開する工程です。余談ですが、よりスケールして展開するという意味でReleaseがDeployよりも先になっているのだと推測しております。アプリケーションを公開するためのインフラを設計/構築していく必要があります。Testフェーズでも動作確認をするために開発(ステージング)環境を用意していましたが、このフェーズでは本番環境を構成します。

AmazonQまたはBedrockが自分の設計したAWSを理解できるようにするために一度IaC化するのが有用です。IaC化はアップデート/ロールバック/スケールに柔軟に対応できるため、ベストプラクティスにもなっています。

実装案

AmazonQを使ってCloudFormtaion/Terraform,CDKなどのIaCコードの生成を行いこれを補助できますが、まずはアーキテクチャ設計を行なってから利用する事をここでは考えます。CD(Continuous Deployment)も同じくこの順序で対応を行います。

AWSインフラ設計者だけではなく、開発者/運用者との連携が必要なため、双方に足並みをそろえていくことをここでは考えています。また、開発の時と同様にインフラもデプロイ定義も全てコードとしてGitに保管し、Gitへのマージ/承認が完了したものだけを展開するGitOpsの運用をここでは適用します。

1. AWS設計とデプロイ戦略の策定

DevSecOpsの開発フェーズでデータベース設計や構成するコンピューティングリソース、APIやフロントエンドの公開方法を予め定義し、テストフェーズで動作確認まで行っているのが前提になります。

このRelease/Deployフェーズでは設計/計画フェーズで策定した機能要件と非機能要件を列挙し、インフラを構成するリソースを定義します。本番環境へのアプリケーション展開と運用を見越した構成なので、非機能要件を詰めていく必要があります。

デプロイ戦略でBlue/Green構成とするのか、DRで可用性を重視するのかコストを重視するのかなど、サービス基盤として何を優先するのか次第でインフラ構成が大きく変わるためです。

非機能要件 観点例
性能 スケールアウト/スケールアップの方式策定/想定されるユーザーアクセス数予想/リソース及びアプリの性能監視
信頼性 SLA/SLO/SLIの定義/DR戦略の策定/デプロイ戦略の選択
コスト最適化 ピーク時間、閑散時間の予想/オートスケール定義/コスト監視
セキュリティ IAM最小権限原則の適用/IaaS/PaaSの通信制御/CNAPPによる発見的統制導入
運用 変更/構成管理プロセスの定義/マネージドサービスによる自動化/課題に対応する組織体制策定

2. ベストプラクティスの適用 with Amazon Q

次に、AWS設計とWell Architected Frameworkのベストプラクティスを適用していきます。今までであれば、有識者がリードしたり、ドキュメントやWAツールを用いてベストプラクティスの適用を考えていました。一方、今はAmazonQの恩恵を受ける事が出来ます。まだ日本語未対応なので一度翻訳は必要になるものの、サービス単位で観点を提供してくれます。

AWSマネジメントコンソールでAmazonQアイコンからアクセスしてプロンプトを投げられます。In terms of well architected frameworkのようなプロンプトを添えてあげると各柱の観点で対応方法を提示してくれます。セキュリティ面についてもここで確認できます。

3.WAツールによるダブルチェック

開発フェーズと同様にAmazonQに丸投げするのではなく、観点が足りてないかハルシネーションで誤った事を伝えていなかったかをWAツールを用いながらチェック出来ます。

結局人間がチェックしているので、あまり今までと変わらないようにも見えますが、経験が浅いメンバーでも抽象度の高い柱のチェック項目の具体化とサポートを得る事が出来ます。

ちなみにWAツールでレビューしながらAmazonQにレビュー観点の具体例を訪ねる事も出来ます。英語のみという制約はまだあるものの、”エキスパートに質問する”をある意味シームレスに行えるのは画期的です。

4. IaCコードを入手する

IaCを作成する事はAWSのパラメータ一覧を得る事と等しく、さらに同一構成の横展開や、コスト削減または撤退などの目的でAWS環境を一時的にクローズし再展開の材料にできるなど、設けるだけで多くのメリットが得られます。

必須ではないものの、DevSecOps観点ではベストプラクティスの一つなのでここでは実施します。また、選択するコンピューティングプラットフォーム次第ではIaCではなくK8s,ECSなどプラットフォーム側でインフラの非機能を担保できる場合もあるので線引きもここで出来ると理想です。(*EKSのIngressController,StorageClass等)

ここでは2つのパターンに分けて”4-1”と”4-2”としています。それぞれメリットとデメリットがあるため、状況や規模に合わせて選択します。

4-1. 設計に基づくIaCコードをAmazon Qで生成する

慣れている方や個々のリソースに対して細かい要件が固まっている場合は、AmazonQで最初からIaCコードを生成する”4-1”のパターンを実施します。これにより、実際のリソースを作成せず料金を抑えながら最終的なAWS構成の成果物を得る事が出来ます。一方、コードを細かく作成するには開発フェーズと同じ工程を経る必要があります。作成するリソース量が少ない場合やメンバーの練度が高い場合には有用です。

※サンプルなので少し荒いですが、VPCやELBなど細かく1リソース単位で指定する事でより詳細で有用なコードが生成できます。

4-2. リソースを作成しIaCコードをエクスポートする

CloudFormation/TerraformなどのIaCは細かく定義しようとするとコードが長くなり、書くのも労力がかかるだけでなく、書き方自体も学ぶ必要があり、少しでも間違いがあるとデプロイも出来ません。

慣れていない場合や作成に時間がかかると予想される場合は、予めリソースを作成してからIaC化する従来のやり方も有用です。実際にリソースを作成するので料金はかかってしまいますが、着実なやり方でコードを入手できます。

※AWSネイティブで利用できるCloudFormationのIaCジェネレーターやFormer2のようなOSSを利用してIaCコードをリソースから得られます。

https://former2.com/

リソースを定義する過程でどのようなパラメータを設定する必要があるのか、また、そのパラメータが何なのかを理解しきれない場合はマネジメントコンソールでリソースを作成してしまう方が楽ではあります。

スキャンしたリソースから簡単にIaCコードを得られます。再度コードでAWSリソースを作成すればいいので、節約のためにここでリソースを削除しても問題ありません。

5. Amazon Q/BedrockでIaCレビューを実施する

リソースを作成してTrusted Advisorでレビューを行う事も可能ですが、週次レビューなのとリソースを稼働し続けないといけないというデメリットがあります。無償で有用なので後続のOperateフェーズでは積極活用したいですが、初期のRelease/Deployでは生成AIの力を借りたレビューによってこれらの問題を解消できます。生成またはエクスポートして得られたIaCコードに対してAmazonQで/reviewによるざっくりしたレビューと/devでの細かい指示を加えたレビューが行えます。

※/reviewでは指示を与える事ができないため、ざっくりとしたレビューと指摘に留まりはするもののランタイムの脆弱性を見抜けています。

一方、/devでWell Architected Frameworkの観点をIaCコードだけでなくソースコードも含めてレビューと指摘を実施してくれます。さらにレビュー結果をチャットの回答としてではなく、mdの成果物として提示してくれています。

代案:Bedrock Agentあるいはナレッジベースで精度を上げる

AmazonQはBusiness、Developer、QuickSightなど特定用途向けのサービスです。そのため、WellArchitectedレビューが学習当時の柱や一般論に留まり、コード生成やそのレビュー程の効果が得られない可能性があります。

繰り返し設計/構築を実施するのであればさらなる精度向上と設計の拡充のためにBedrockを使うのも一つの手段です。Bedrock AgentによるWellArchitectedフレームワークの最新ドキュメント確認とWAツールで出力されたレポート、IaCコードを使ったレビュー。ナレッジベースにpdfやテキストに出力したWellArchitectedフレームワークのベストプラクティス集をRAGの材料にした網羅性のあるレビュー。これらを実現できる可能性があります。また、日本語対応もFoundationModelであれば回答が期待できます。

代案:3rdパーティー製品を使う

IaCスキャンという機能をDevSecOpsソリューションとして3rdPartyの有償製品で利用する事も出来ます。これらはCloudFormationだけでなく、TerraformさらにはK8s Manifestにまで及ぶものもあります。

https://docs.gitlab.com/user/application_security/iac_scanning/

https://www.paloaltonetworks.jp/prisma/cloud/infrastructure-as-code-security

https://www.wiz.io/ja-jp/solutions/iac

6. AmazonQでデプロイ定義を生成する

ECS/EKSのようなコンテナアプリケーションのデプロイ定義やNginxのConfのようなサーバ設定ファイルをここでは定義します。ECS/EKSではawscliやkubectl/eksctlを用いて定義ファイルをJSONやYAMLで生成する方法もありますが、コンテナ内や仮想マシン内で動くサーバーの設定ファイルまではカバーできません。

Testフェーズでも実施しているのであまり差はありませんが、本番環境レベルの信頼性と性能、セキュリティを意識した定義がここでは求められます。

また、デプロイ戦略とスケール方針に大きく依存する工程でもあるため要件に応じて定義を依頼していきます。

6.AmazonQでappspec等CDツール定義を生成する

リリース速度を高めつつ、人手を介さずにデプロイできるのがCDツールの魅力です。このCDツールの定義をCIツールと同様にAmazonQに依頼出来ます。また、CDツールはGitOpsと組み合わせる事で真価を発揮できます。Gitで承認されたアプリ成果物(コンテナ/パッケージ等)、IaC、デプロイ定義だけをリリース/デプロイするよう強制化する事も可能です。

+Git付属の生成AIでマージリクエストを説明する

開発同様にGitLabの有償ライセンスでAmazonQを利用し、マージリクエストのサマリを実際のマージリクエストに合わせて作成する事が出来ます。レビュアーが/reviewでコードを追加で確認する事も出来ます。また、GitLab利用の場合、IaCスキャンも行う事が出来ます。

https://aws.amazon.com/jp/blogs/news/introducing-gitlab-duo-with-amazon-q/

Operate/Monitor

運用と監視はそれぞれ補完し合う関係にあると考えているため、ここではあえて一緒にしています。運用観点を定量的に測るために監視が必要で、監視項目を定義するのに運用観点が必要と考えているのが理由です。運用/監視フェーズではアプリケーションに留まらずインフラも含めたシステム全体の運用を行います。アップデート対応、バックアップ/リストア、スケールアウト/イン、セキュリティ対策、コスト最適化などがあります。

オペレーションエクセレンスの柱をベースに各観点に分けて対応案を考えていきます。オペレーションエクセレンスは観点の通り、他の柱を継続的に支えるものとなっています。これらは自動化/効率化をマネージドサービスやAWS外部のサービスを使って実現する事ができます。そのため、無理に生成AIを入れる必要はないとも考えています。運用が建てついてから更なる効率化を試みて実施でも遅くないと思います。

観点 利用サービス
システムログ/メトリクス監視 CloudWatch/X-Rayもしくは3rdパーティーObservability製品
セキュリティ(発見的統制) GuardDuty/CloudTrailもしくは3rdパーティーCNAPP製品
セキュリティ(予防的統制) ControlTower/Organization/SCP
変更管理/リリース管理 CodeBuild,Deploy,Pipelineと外部のGitサービス
パフォーマンス最適化 CloudWatch Application Signalもしくは3rdパーティーAPM製品
インシデント管理 外部のSaaSサービス

さらに、運用/監視はリアルタイムでの対応が求められ、エンドユーザーに直接影響を及ぼす範囲のため安直に生成AIサービスを活用すると危険な側面があります。その危険性を踏まえつつ、運用の補助として活用する案をここでは考えます。

実装案

各観点毎に実装案を考えていくとそれだけで膨大な量になってしまうため、利用アイデアとして今回はセキュリティと性能、コスト、信頼性の全ての分析が行えるログの活用を考えてみました。内容としてはリアルタイムでのログ解説と大量に収集したログの分析になります。

実装案1:リアルタイムでのログ解説( CloudWatch/Lambda+Bedrock)

CloudWatchやCI/CDツールからのログを中心にリアルタイム監視の補助としてBedrockが利用できます。Bedrockの利用イメージとしては以下の通りです。

開発からデプロイまでに繋がるCI/CDのパイプライン、デプロイ後のアプリケーション、これらからアラートやログ発報をCloudWatchに対して行う事が出来ます。CIのビルド失敗やテストの不合格、マージ承認の通知、デプロイ後のアプリケーション側でのエラーなど運用で発生するアラートや注視すべきログがあります。

これらのログを受け取る、内容を確認する、分からなければ調査、さらに困ったら検証するなどの運用が今までの流れでした。ここにBedrockを組み込む事でログの要約や解説を行う事が出来ます。また、日本語での回答も得られるためAmazonQのような制約もありません。

処理の流れとしては以下の通りです。

  1. ログソースよりアラートログまたは実行ログをCloudWatchに送付
  2. アラートまたはロググループより文字列パターン(”[ERROR]”など)を検出
  3. 送付/検出した結果を基にLambdaをトリガーし、ログデータをLambdaに引き渡す
  4. LambdaでBedrock APIに対してシステムプロンプトとログデータを共有し依頼を投げる
  5. ログの要約や解説の依頼を受けBedrockの基盤モデルが回答を生成
  6. 得られた回答を再びLambdaにてメールやチャットツールに連携

最後のメール/チャット通知を運用がたてついたタイミングでインシデント管理ツールに起票するように構成できれば、より運用の自動化/取りこぼしや担当者のいない状態になる事を防げます。

# Amazon Q Developerで生成したLambdaサンプルコード
import json
import os
import boto3
from botocore.exceptions import ClientError

def lambda_handler(event, context):
    """
    Lambda function triggered by CloudWatch alarm that:
    1. Gets CloudWatch alarm details from the event
    2. Uses Amazon Bedrock to summarize the alarm information
    3. Sends the summarized alarm information via email
    
    Args:
        event (dict): The CloudWatch alarm event
        context: Lambda context object
        
    Returns:
        dict: Response containing status and message
    """
    try:
        # Step 1: CloudWatchのEventデータを取得
               print("Received event:", json.dumps(event, indent=2))
        # Parse the CloudWatch alarm event
        alarm_name = event['detail']['alarmName']
        alarm_description = event.get('detail', {}).get('configuration', {}).get('description', 'No description')
        alarm_reason = event.get('detail', {}).get('state', {}).get('reason', 'No reason provided')
        alarm_timestamp = event.get('time', 'Unknown time')
        alarm_region = event.get('region', os.environ.get('AWS_REGION', 'unknown-region'))
        alarm_account = event.get('account', 'Unknown account')
        
        alarm_details = {
            'name': alarm_name,
            'description': alarm_description,
            'reason': alarm_reason,
            'timestamp': alarm_timestamp,
            'region': alarm_region,
            'account': alarm_account
        }
        
        # Step 2: Bedrockからログの要約を取得
        bedrock_summary = get_bedrock_summary(alarm_details)
        
        # Step 3: 要約内容をメールで送付
        send_email(alarm_name, bedrock_summary)
        
        return {
            'statusCode': 200,
            'body': json.dumps({
                'message': 'Successfully processed CloudWatch alarm and sent email',
                'alarm': alarm_name
            })
        }
        
    except Exception as e:
        print(f"Error processing CloudWatch alarm: {str(e)}")
        return {
            'statusCode': 500,
            'body': json.dumps({
                'message': f'Error processing CloudWatch alarm: {str(e)}'
            })
        }

def get_bedrock_summary(alarm_details):
    """
    Use Amazon Bedrock to generate a summary of the CloudWatch alarm
    
    Args:
        alarm_details (dict): Details about the CloudWatch alarm
        
    Returns:
        str: Summarized alarm information
    """
    try:
        # Bedrock client初期化
        bedrock_runtime = boto3.client('bedrock-runtime')
        
        # システムプロンプト
        prompt = f"""
        CloudWatch Alarmの内容を要約してください。観点は以下の通りです。:
        - そのアラームはどういったものなのか
        - なぜアラームが発生したのか
        - 対策として何をすべきか
        
        Alarm情報は以下を参照します:
        - Name: {alarm_details['name']}
        - Description: {alarm_details['description']}
        - Reason for alarm: {alarm_details['reason']}
        - Timestamp: {alarm_details['timestamp']}
        - Region: {alarm_details['region']}
        - Account: {alarm_details['account']}
        
        メールで送付するので運用担当者にとって可読性の高い状態で文章を出力してください。.
        """
        
        # Select the model to use - this example uses Claude
        model_id = "anthropic.claude-v2"  # You can change this to another model as needed
        
        # Create the request
        body = json.dumps({
            "prompt": prompt,
            "max_tokens_to_sample": 500,
            "temperature": 0.5,
            "top_p": 0.9,
        })
        
        # Make the request to Bedrock
        response = bedrock_runtime.invoke_model(
            modelId=model_id,
            body=body
        )
        
        # Parse the response
        response_body = json.loads(response.get('body').read())
        summary = response_body.get('completion', 'Unable to generate summary')
        
        return summary
    
    except Exception as e:
        print(f"Error generating summary with Bedrock: {str(e)}")
        # Return a basic summary if Bedrock fails
        return f"ALERT: CloudWatch Alarm '{alarm_details['name']}' triggered at {alarm_details['timestamp']}. Reason: {alarm_details['reason']}"

def send_email(alarm_name, summary):
    """
    Send an email with the alarm summary
    
    Args:
        alarm_name (str): Name of the CloudWatch alarm
        summary (str): Summarized alarm information from Bedrock
    """
    try:
        # SESクライアント起動
        ses_client = boto3.client('ses')
        
        # Get email configuration from environment variables
        sender = os.environ.get('SENDER_EMAIL', 'alerts@example.com')
        recipient = os.environ.get('RECIPIENT_EMAIL', 'operations@example.com')
        
        subject = f"CloudWatch Alarm Summary: {alarm_name}"
        
        # Emailテンプレート
        body_html = f"""
        <html>
        <head></head>
        <body>
            <h1>CloudWatch Alarm 要約</h1>
            <p>{summary}</p>
            <p>This summary was generated automatically by Bedrock based on the CloudWatch alarm data.</p>
        </body>
        </html>
        """
        
        body_text = f"""
        CloudWatch Alarm Summary
        
        {summary}
        
        This summary was generated automatically by AI based on the CloudWatch alarm data.
        """
        
        # Send the email
        response = ses_client.send_email(
            Source=sender,
            Destination={
                'ToAddresses': [recipient]
            },
            Message={
                'Subject': {
                    'Data': subject
                },
                'Body': {
                    'Text': {
                        'Data': body_text
                    },
                    'Html': {
                        'Data': body_html
                    }
                }
            }
        )
        
        print(f"Email sent! Message ID: {response['MessageId']}")
    
    except ClientError as e:
        print(f"Error sending email: {e.response['Error']['Message']}")

実装案2:シームレスなログの分析と解説( CloudWatch AI Operations)※2025年時点プレビュー

ついにCloudWatchにもAmazonQ Developerの組み込みが始まっています。限られたリージョンでプレビューで利用のため、内容が変更されたり、日本でのサポートに時間がかかる可能性があります。とはいえ、上記のBedrockで行っていたような運用をマネジメントコンソールで完結できるのは魅力的です。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Investigations.html

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Start-Investigation-Alarm.html

下記はサンプルなので実際の挙動は試せていませんが、CloudWatchのログだけではなくメトリクスから傾向分析や異常パターンを検出できます。

AI OperationではCloudTrail、X-RayをAmazonQがエージェントとしてログを確認する事が出来ます。

さらにBedrockで実施していた上記とは異なり外部のチケットシステムに連携したり、チャットツールに連携する事もサービスとしてできます。

分析ソースとしてはログ、メトリクス、アラームの3種がサポートされています。注意すべきなのはリアルタイム分析ではないため、何かインシデントがあってからの事後調査や、現在のAWSリソースの利用状況を確認する補助としての活用がメインになる点です。

サンプルで示されている通り、AmazonQに対してDynamoDBのアラーム内容を基に調査依頼をプロンプトで投げています。

さらに調査依頼は都度行われる一時的なものではなく、調査リソースとして定義する事が出来ます。そのため、追加で調査依頼や参考となる情報を投げることが出来ます。

さらにAmazonQからの回答で納得できるもの、エビデンスチェックが行えたものは承諾として画面左のフィードに追加可能です。

まとめ

今回は前回に続き運用(Ops)でのAmazonQと一部Bedrockの活用ポイントを考えてみました。開発に比べると生成できるものに限りがあるのと、設計や体制に関わる内容のため補助的な使い方がメインになっています。

とはいえ、既存のマネージドサービスを多く活用できるためわざわざ生成AIを入れずとも要件を満たして自動化も十分可能です。

観点 利用サービス
システムログ/メトリクス監視 CloudWatch/X-Rayもしくは3rdパーティーObservability製品
セキュリティ(発見的統制) GuardDuty/CloudTrailもしくは3rdパーティーCNAPP製品
セキュリティ(予防的統制) ControlTower/Organization/SCP
変更管理/リリース管理 CodeBuild,Deploy,Pipelineと外部のGitサービス
パフォーマンス最適化 CloudWatch Application Signalもしくは3rdパーティーAPM製品
インシデント管理 外部のSaaSサービス

それでもIaCやデプロイ定義のyamlファイル、CDツールのファイル生成や、運用/監視時の大量のログ処理効率化など補助として有用な場面は多くあります。今回考えてみたアイデア以上のものが今後考案されるだけでなく、CloudWatch AI OperationのようなサービスへのAmazonQ組み込みに期待しています。

Discussion