NTT東日本の自治体クラウドソリューション

【環境構築編】AWS DevOps AgentはZabbixアラートをどこまで調査できる?zabbix-mcp-server連携で監視情報を深掘り

こんにちは、保坂です。

本コラムは【本編】AWS DevOps AgentはZabbixアラートをどこまで調査できる?zabbix-mcp-server連携で監視情報を深掘りの環境構築編です。

記事本編は上記をご確認ください。

本環境構築編では、以下の流れで検証環境を構築します。

  • CloudFormationでZabbix ServerとApp Serverを構築
  • AWS DevOps AgentのエージェントスペースとWebhookを作成
  • App ServerをZabbixに監視登録
  • ZabbixからAWS DevOps Agentへアラート通知するためのメディアタイプ・アクションを設定
  • zabbix-mcp-serverを設定
  • AWS DevOps AgentにMCPサーバーを登録・紐づけ
  • 動作確認とカスタムスキルを追加

AIエージェントを活用したクラウド環境の監視方法について、NTT東日本のエンジニアがご相談にお応えしますので、お気軽にご連絡ください!

NTT東日本のクラウド事業をご紹介!登録不要・無料公開中、詳細はこちら

1. 検証環境の準備

本手順は検証環境向けです。

セキュリティグループや自己署名証明書、管理者権限、トークンの有効期限・管理など、本番環境で利用する場合には別途セキュリティ要件に応じた対応が必要になる点にご留意ください。

1-1. 検証環境の構成

本コラムで使用するZabbixや監視対象となるEC2インスタンスなどは、CloudFormationテンプレートとして定義しています。

1-2. CloudFormationスタックの展開作業

1-2-1. CloudFormationテンプレート

検証環境を容易に再現できるよう、本コラムではCloudFormationテンプレートを用いて監視環境を一括構築します。テンプレートにはネットワーク環境(VPC・サブネット)に加え、Zabbix Serverと監視対象EC2インスタンス(App Server)が含まれています。

zabbix-sample.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Zabbix 7.0 LTS monitoring infrastructure with application server.

# ==============================================================================
# Parameters
# ==============================================================================
Parameters:
  AllowedCidr:
    Type: String
    Default: 0.0.0.0/0
    Description: CIDR block allowed to access Zabbix Web UI (restrict in production)
    AllowedPattern: ^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$

  DBRootPassword:
    Type: String
    NoEcho: true
    MinLength: 8
    MaxLength: 41
    Description: MySQL root password
    AllowedPattern: ^[a-zA-Z0-9!@#$%^&*()_+=\-]*$

  DBZabbixPassword:
    Type: String
    NoEcho: true
    MinLength: 8
    MaxLength: 41
    Description: MySQL user password for Zabbix
    AllowedPattern: ^[a-zA-Z0-9!@#$%^&*()_+=\-]*$

  MCPAdminPassword:
    Type: String
    NoEcho: true
    MinLength: 10
    MaxLength: 64
    Description: MCP Server admin portal password (min 10 chars, must include uppercase and digit)

  KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: EC2 Key Pair name for SSH access to application server

# ==============================================================================
# Metadata
# ==============================================================================
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Network Settings
        Parameters:
          - AllowedCidr
      - Label:
          default: Database Settings
        Parameters:
          - DBRootPassword
          - DBZabbixPassword
      - Label:
          default: MCP Server Settings
        Parameters:
          - MCPAdminPassword
      - Label:
          default: SSH Settings
        Parameters:
          - KeyPairName

# ==============================================================================
# Resources
# ==============================================================================
Resources:
  # ============================================================================
  # VPC & Networking
  # ============================================================================
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-vpc"

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-igw"

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # --------------------------------------------------------------------------
  # Public Subnet
  # --------------------------------------------------------------------------
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone: !Select [0, !GetAZs ""]
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-public-subnet"

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-public-rt"

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  # ============================================================================
  # Security Groups
  # ============================================================================
  ZabbixSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for Zabbix Server
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref AllowedCidr
          Description: Zabbix Web UI (HTTP)
        - IpProtocol: tcp
          FromPort: 8080
          ToPort: 8080
          CidrIp: 10.0.0.0/16
          Description: Application endpoint (VPC internal)
        - IpProtocol: tcp
          FromPort: 9090
          ToPort: 9090
          CidrIp: !Ref AllowedCidr
          Description: Admin portal
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-zabbix-sg"

  AppServerSG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for application server
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 10050
          ToPort: 10050
          SourceSecurityGroupId: !Ref ZabbixSecurityGroup
          Description: Allow Zabbix Server passive checks
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref AllowedCidr
          Description: SSH access
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-app-sg"

  # ============================================================================
  # IAM Roles
  # ============================================================================
  ZabbixInstanceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-zabbix-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Policies:
        - PolicyName: !Sub "${AWS::StackName}-zabbix-monitoring-policy"
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - cloudwatch:DescribeAlarms
                  - cloudwatch:GetMetricData
                  - cloudwatch:ListMetrics
                  - ec2:DescribeInstances
                  - ec2:DescribeRegions
                  - ec2:DescribeVolumes
                Resource: "*"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-zabbix-role"

  ZabbixInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref ZabbixInstanceRole

  AppServerRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-app-role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-app-role"

  AppServerInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref AppServerRole

  # ============================================================================
  # EC2 - Zabbix Server
  # ============================================================================
  ZabbixInstance:
    Type: AWS::EC2::Instance
    DependsOn: VPCGatewayAttachment
    Properties:
      ImageId: "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}"
      InstanceType: t3.medium
      IamInstanceProfile: !Ref ZabbixInstanceProfile
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          SubnetId: !Ref PublicSubnet
          GroupSet:
            - !Ref ZabbixSecurityGroup
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: 30
            VolumeType: gp3
            Encrypted: true
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-zabbix-server"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          exec > >(tee /var/log/zabbix-install.log) 2>&1

          # Wait for dnf/rpm lock
          while fuser /var/lib/rpm/.rpm.lock /var/cache/dnf/metadata_lock.pid 2>/dev/null; do
            sleep 5
          done

          dnf update -y

          # Install Python 3.14
          dnf install -y python3.14
          ln -sf /usr/bin/python3.14 /usr/local/bin/python3
          ln -sf /usr/bin/pip3.14 /usr/local/bin/pip3

          # Install MySQL 8.4 LTS
          dnf install -y https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm
          dnf install -y mysql-community-server mysql-community-client
          systemctl enable mysqld --now

          TEMP_PASSWORD=$(grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}')

          mysql --connect-expired-password -uroot -p"$TEMP_PASSWORD" <<EOF
          ALTER USER 'root'@'localhost' IDENTIFIED BY '${DBRootPassword}';
          DELETE FROM mysql.user WHERE User='';
          DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
          DROP DATABASE IF EXISTS test;
          DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
          FLUSH PRIVILEGES;
          EOF

          # Install Zabbix 7.0
          rpm -Uvh https://repo.zabbix.com/zabbix/7.0/amazonlinux/2023/x86_64/zabbix-release-latest-7.0.amzn2023.noarch.rpm
          dnf clean all
          dnf install -y zabbix-server-mysql zabbix-web-mysql zabbix-apache-conf zabbix-sql-scripts zabbix-selinux-policy zabbix-agent zabbix-web-japanese

          # Create Zabbix Database
          mysql -uroot -p'${DBRootPassword}' <<EOF
          CREATE DATABASE zabbix CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
          CREATE USER 'zabbix'@'localhost' IDENTIFIED BY '${DBZabbixPassword}';
          GRANT ALL PRIVILEGES ON zabbix.* TO 'zabbix'@'localhost';
          SET GLOBAL log_bin_trust_function_creators = 1;
          FLUSH PRIVILEGES;
          EOF

          # Import Schema
          zcat /usr/share/zabbix-sql-scripts/mysql/server.sql.gz | \
            mysql --default-character-set=utf8mb4 -uzabbix -p'${DBZabbixPassword}' zabbix
          mysql -uroot -p'${DBRootPassword}' -e "SET GLOBAL log_bin_trust_function_creators = 0;"

          # Configure Zabbix Server
          sed -i "s/^# DBPassword=.*/DBPassword=${DBZabbixPassword}/" /etc/zabbix/zabbix_server.conf

          # Configure PHP Frontend
          cat > /etc/zabbix/web/zabbix.conf.php <<'PHPCONF'
          <?php
          $DB['TYPE']             = 'MYSQL';
          $DB['SERVER']           = 'localhost';
          $DB['PORT']             = '0';
          $DB['DATABASE']         = 'zabbix';
          $DB['USER']             = 'zabbix';
          PHPCONF
          echo "\$DB['PASSWORD']         = '${DBZabbixPassword}';" >> /etc/zabbix/web/zabbix.conf.php
          cat >> /etc/zabbix/web/zabbix.conf.php <<'PHPCONF'
          $DB['SCHEMA']           = '';
          $DB['ENCRYPTION']       = false;
          $DB['KEY_FILE']         = '';
          $DB['CERT_FILE']        = '';
          $DB['CA_FILE']          = '';
          $DB['VERIFY_HOST']      = false;
          $DB['CIPHER_LIST']      = '';
          $DB['VAULT_URL']        = '';
          $DB['VAULT_DB_PATH']    = '';
          $DB['VAULT_TOKEN']      = '';
          $DB['DOUBLE_IEEE754']   = true;
          $ZBX_SERVER             = 'localhost';
          $ZBX_SERVER_PORT        = '10051';
          $IMAGE_FORMAT_DEFAULT   = IMAGE_FORMAT_PNG;
          PHPCONF
          echo "\$ZBX_SERVER_NAME        = '${AWS::StackName}';" >> /etc/zabbix/web/zabbix.conf.php
          chown apache:apache /etc/zabbix/web/zabbix.conf.php
          chmod 640 /etc/zabbix/web/zabbix.conf.php

          # Set Japanese locale
          mysql -uzabbix -p'${DBZabbixPassword}' zabbix <<EOF
          UPDATE users SET lang = 'ja_JP' WHERE username = 'Admin';
          UPDATE config SET default_lang = 'ja_JP';
          EOF

          # Install dependencies
          dnf install -y pango gdk-pixbuf2 cairo git

          # Install initMAX MCP Server
          cd /opt
          git clone https://github.com/initMAX/zabbix-mcp-server.git
          cd zabbix-mcp-server
          ./deploy/install.sh

          # Create TLS certificate
          mkdir -p /etc/zabbix-mcp/tls
          LOCAL_IP=$(hostname -I | awk '{print $1}')
          openssl req -x509 -newkey rsa:2048 \
            -keyout /etc/zabbix-mcp/tls/key.pem \
            -out /etc/zabbix-mcp/tls/cert.pem \
            -days 365 -nodes \
            -subj "/CN=zabbix-mcp" \
            -addext "subjectAltName=IP:$LOCAL_IP,DNS:localhost"
          chmod 600 /etc/zabbix-mcp/tls/key.pem
          chmod 644 /etc/zabbix-mcp/tls/cert.pem
          chown -R zabbix-mcp:zabbix-mcp /etc/zabbix-mcp/tls/

          # Configure MCP Server
          LOCAL_IP=$(hostname -I | awk '{print $1}')
          sed -i 's/^host = .*/host = "0.0.0.0"/' /etc/zabbix-mcp/config.toml
          sed -i 's/^public_url = .*/public_url = "https:\/\/'"$LOCAL_IP"'"/' /etc/zabbix-mcp/config.toml
          # TLS: uncomment and set
          sed -i 's|^# *tls_cert_file = .*|tls_cert_file = "/etc/zabbix-mcp/tls/cert.pem"|' /etc/zabbix-mcp/config.toml
          sed -i 's|^# *tls_key_file = .*|tls_key_file = "/etc/zabbix-mcp/tls/key.pem"|' /etc/zabbix-mcp/config.toml

          # Set admin password
          cd /opt/zabbix-mcp-server
          ./deploy/install.sh set-admin-password <<EOF
          ${MCPAdminPassword}
          ${MCPAdminPassword}
          EOF

          # Start MCP Server
          systemctl enable zabbix-mcp-server --now

          # Start Zabbix services
          systemctl enable zabbix-server zabbix-agent httpd php-fpm --now

  # ============================================================================
  # EC2 - Application Server
  # ============================================================================
  AppServer:
    Type: AWS::EC2::Instance
    DependsOn: VPCGatewayAttachment
    Properties:
      ImageId: "{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}"
      InstanceType: t3.small
      IamInstanceProfile: !Ref AppServerInstanceProfile
      KeyName: !Ref KeyPairName
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: "0"
          SubnetId: !Ref PublicSubnet
          GroupSet:
            - !Ref AppServerSG
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-app-server"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          exec > >(tee /var/log/app-setup.log) 2>&1

          while fuser /var/lib/rpm/.rpm.lock /var/cache/dnf/metadata_lock.pid 2>/dev/null; do
            sleep 5
          done

          dnf update -y

          # Install Zabbix Agent 2
          rpm -Uvh https://repo.zabbix.com/zabbix/7.0/amazonlinux/2023/x86_64/zabbix-release-latest-7.0.amzn2023.noarch.rpm
          dnf clean all
          dnf install -y zabbix-agent2

          # Configure Zabbix Agent 2
          ZABBIX_SERVER_IP="${ZabbixInstance.PrivateIp}"

          cat > /etc/zabbix/zabbix_agent2.conf <<EOF
          PidFile=/run/zabbix/zabbix_agent2.pid
          LogFile=/var/log/zabbix/zabbix_agent2.log
          LogFileSize=0
          Server=$ZABBIX_SERVER_IP
          ServerActive=$ZABBIX_SERVER_IP
          Hostname=$(hostname)
          Include=/etc/zabbix/zabbix_agent2.d/*.conf
          EOF

          systemctl enable zabbix-agent2 --now

# ==============================================================================
# Outputs
# ==============================================================================
Outputs:
  ZabbixWebUrl:
    Description: Zabbix Web UI URL
    Value: !Sub "http://${ZabbixInstance.PublicIp}/zabbix"

  ZabbixServerPublicIp:
    Description: Public IP of the Zabbix Server
    Value: !GetAtt ZabbixInstance.PublicIp

  ZabbixServerPrivateIp:
    Description: Private IP of the Zabbix Server
    Value: !GetAtt ZabbixInstance.PrivateIp

  ZabbixServerInstanceId:
    Description: Instance ID of the Zabbix Server
    Value: !Ref ZabbixInstance

  AppServerInstanceId:
    Description: Instance ID of the application server
    Value: !Ref AppServer

  AppServerPrivateIp:
    Description: Private IP of the application server
    Value: !GetAtt AppServer.PrivateIp

  AppServerPublicIp:
    Description: Public IP of the application server (for SSH access)
    Value: !GetAtt AppServer.PublicIp

1-2-2. 事前準備

スタックの展開の前に、キーペアを作成しておきます。

1. マネジメントコンソールの「EC2 > キーペア」より「キーペアを作成」を押下

2. キーペア名を指定して「キーペアを作成」を押下

例では「key-pair」としました

3. キーペアの作成ができると鍵ファイル(.pem)がダウンロードされます

1-2-3. CloudFormationスタックの展開

1. CloudFormationのマネジメントコンソールを開き、「スタックの作成」を押下

2. スタックの作成にて、「テンプレートファイルのアップロード」を選択、「zabbix-sample.yaml」をアップロードし「次へ」を押下

3. スタックの詳細を指定にて、以下入力し「次へ」を押下

項目 入力内容
スタック名 スタック名を入力
パラメータ / AllowedCidr 自身の環境のグローバルIPアドレスを入力
パラメータ / DBRootPassword DBのrootユーザーのパスワードとして設定するものを入力
パラメータ / DBZabbixPassword DBのzabbixユーザーのパスワードとして設定するものを入力
パラメータ / MCPAdminPassword zabbix-mcp-serverの管理者パスワードとして設定するものを入力
パラメータ / KeyPairName 事前準備で作成したキーペアを指定

4. スタックオプションの設定にて、最下部の「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。」のチェックボックスに同意し、「次へ」を押下

5. 確認して作成にて、入力した内容に誤りがない事を確認し「送信」を押下

6. 作成したスタックのステータスが「CREATE_COMPLETE」になれば展開完了

1-2-4. スタックの出力の確認

展開したスタックの「出力タブ」を開き、表示される内容を控えておきます。

1-3. AWS DevOps Agentのエージェントスペースでの作業

1-3-1. エージェントスペースの作成

1. AWS DevOps Agentのマネジメントコンソールを開き、「エージェントスペース」より「エージェントスペースを作成」を押下

2. エージェントスペースを作成画面にて、以下を入力し「作成」を押下

項目 入力内容
エージェントスペース名 agent-space
エージェントの応答言語 Japanese (Japan)

その他の項目はデフォルトのままにしています

3. 以上で完了です

1-3-2. Agent Spaceウェブフックの作成

1. 作成したAgent Spaceの「機能」タブ最下部の「Agent Spaceウェブフック」にて「追加」を押下

2. 「次へ」を押下

3. ウェブフックの認証タイプとして「API キー」を選択し、「次へ」を押下

4. 「URL と認証情報を生成する」を押下

5. 「.csv ファイルをダウンロード」を押下でファイルをダウンロードし、「自分の URL と認証情報を保存して保管しました」にチェックを入れ「追加」を押下

6. 以上で完了です

1-4. App Serverでの作業

1-4-1. App Serverへの接続

スタック展開後に控えたAppServerPublicIpへSSH接続します

例ではTeraTermを使用しています

なお、接続時に必要な情報は以下となります

項目 入力内容
ユーザー名 ec2-user
秘密鍵 キーペア作成時にダウンロードした.pemファイル

1-4-2. MySQLアプリケーションの導入と初期データの流し込み

1. 以下のコマンドでMySQL8.4 LTSをインストールします

sudo dnf install -y https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm
sudo dnf install -y mysql-community-server mysql-community-client
sudo systemctl enable mysqld --now

2. rootパスワードを設定します

初期パスワードを表示します

TEMP_PASSWORD=$(sudo grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}')
echo "Initial password: $TEMP_PASSWORD"

パスワードの再設定及びセキュリティ設定を行います

mysql_secure_installation

以下の内容が対話的に聞かれます

  • 1. Enter password for user root :確認した初期パスワードを入力
  • 2. 新しいパスワードを入力 ※大文字/小文字/数字/記号を含む8文字以上
  • 3. Remove anonymous users? (Press y|Y for Yes, any other key for No) :y
  • 4. Disallow root login remotely? (Press y|Y for Yes, any other key for No):y
  • 5. Remove test database and access to it? (Press y|Y for Yes, any other key for No):y
  • 6. Reload privilege tables now? (Press y|Y for Yes, any other key for No):y

3. 以下のコマンドでデータベースを作成します

mysql -uroot -p <<EOF
CREATE DATABASE appdb;
USE appdb;
CREATE TABLE transactions (
  id INT AUTO_INCREMENT PRIMARY KEY,
  customer_id VARCHAR(64),
  amount DOUBLE,
  status VARCHAR(20) DEFAULT 'pending',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_customer (customer_id),
  INDEX idx_status (status),
  INDEX idx_created (created_at)
);
EOF

4. 以下のコマンドでサンプルデータを入力します

mysql -uroot -p appdb -e "
INSERT INTO transactions (customer_id, amount, status)
SELECT
  CONCAT('cust-', FLOOR(RAND() * 10000)),
  RAND() * 5000,
  ELT(FLOOR(1 + RAND() * 3), 'pending', 'completed', 'failed')
FROM information_schema.columns a
CROSS JOIN information_schema.columns b
LIMIT 100000;
"

5. 以下のコマンドを入力し、「100000」が返れば完了です

mysql -uroot -p appdb -e "SELECT COUNT(*) FROM transactions;"

1-5. Zabbix Webインターフェースでの作業

1-5-1. Zabbix Webインターフェースへのログイン

1. スタック展開後に控えたZabbixWebUrlを開き、Zabbix Webインターフェースにアクセス

スタック展開後にzabbix-serverなどがインストールされるため、アクセスできるようになるまでに時間がかかります

2. ログイン画面にて、以下を入力し「サインイン」を押下

項目 入力内容
ユーザー名 Admin
パスワード zabbix

1-5-2. App Serverの監視登録

1. ログイン後、左ペインより「データ収集 > ホスト」を開き「ホストの作成」を押下

2. 新しいホストの作成画面にて、以下を入力

項目 入力内容
ホスト名 App Server
テンプレート

Linux by Zabbix agent

MySQL by Zabbix agent 2

AWS EC2 by HTTP

ホストグループ Linux servers
インターフェース

タイプ:エージェント

IPアドレス:スタック展開後に控えたAppServerPrivateIpを入力

3. 新しいホストの作成画面の「マクロ」タブにて、以下を入力し「追加」を押下

項目 入力内容
{$AWS.AUTH_TYPE} role_base
{$AWS.EC2.INSTANCE.ID} スタック展開後に控えたAppServerInstanceIdを入力
{$AWS.REGION} CloudFormationスタックを展開したリージョンを入力
{$MYSQL.DSN} tcp://localhost:3306
{$MYSQL.PASSWORD} App ServerへのMySQLセットアップ時に設定したパスワード
{$MYSQL.USER} root

4. 追加できた「App Server」行の「アイテム」を押下

5. アイテムの追加画面にて、「アイテムの作成」を押下

6. 新規アイテムとして、以下を入力し「追加」を押下

項目 入力内容
名前 MySQL process CPU utilization
キー proc.cpu.util[mysqld]
単位
監視間隔 30s

7. 以上で完了です

1-5-3. APIトークンの発行

1. 左ペインより「ユーザー > APIトークン」を開き「APIトークンの作成」を押下

2. 新規APIトークン画面にて、以下を入力し「追加」を押下

項目 入力内容
名前 dev-ops-agent
ユーザー Admin (Zabbix Administrator)
有効期限 任意の有効期限を設定

3. 作成後、「クリップボードにコピー」し「閉じる」を押下

後ほど使用するため無くさないよう控えておきます

4. 以上で完了です

1-5-4. メディアタイプの作成

1. 左ペインより「通知 > メディアタイプ」を開き「メディアタイプの作成」を押下

2. 新規メディアタイプ画面で、以下を入力

項目 入力内容
名前 DevOps Agent Webhook
タイプ Webhook
パラメータ / url 払い出したAgent SpaceウェブフックのURLを入力
パラメータ / token 払い出したAgent Spaceウェブフックのトークンを入力
パラメータ / subject {TRIGGER.NAME}
パラメータ / host {HOST.NAME}
パラメータ / hostip {HOST.IP}
パラメータ / severity {TRIGGER.SEVERITY}
パラメータ / value {ITEM.LASTVALUE}
パラメータ / eventid {EVENT.ID}
パラメータ / eventdate {EVENT.DATE}
パラメータ / eventtime {EVENT.TIME}
パラメータ / instanceid {$AWS.EC2.INSTANCE.ID}
パラメータ / region {$AWS.EC2.REGION}
スクリプト 表下のスクリプトを入力

スクリプトはこちら

var params = JSON.parse(value);

var req = new HttpRequest();
// EVENT.DATE format depends on Zabbix locale (e.g. "2026.08.13")
// Convert to ISO 8601 by replacing dots with dashes
var eventDate = params.eventdate.replace(/\./g, '-');
var timestamp = eventDate + 'T' + params.eventtime + 'Z';

req.addHeader('Content-Type: application/json');
req.addHeader('Authorization: Bearer ' + params.token);
req.addHeader('x-amzn-event-timestamp: ' + timestamp);

var payload = JSON.stringify({
    "eventType": "incident",
    "incidentId": "zabbix-event-" + params.eventid,
    "action": "created",
    "priority": (function(sev) {
        switch(sev) {
            case 'Disaster': return 'CRITICAL';
            case 'High': return 'HIGH';
            case 'Average': return 'MEDIUM';
            case 'Warning': return 'LOW';
            default: return 'MINIMAL';
        }
    })(params.severity),
    "title": params.subject,
    "description": "Host: " + params.host + " (IP: " + params.hostip + ")\n"
        + "Current value: " + params.value,
    "timestamp": timestamp,
    "service": "Zabbix",
    "data": {
        "host": params.host,
        "hostip": params.hostip,
        "trigger": params.subject,
        "severity": params.severity,
        "value": params.value,
        "eventid": params.eventid,
        "instanceId": params.instanceid,
        "region": params.region
    }
});

var response = req.post(params.url, payload);

if (req.getStatus() < 200 || req.getStatus() >= 300) {
    throw 'Request failed with status ' + req.getStatus() + ': ' + response;
}

return 'OK';

3. メッセージテンプレートタブにて、「追加」を押下

4. メッセージテンプレート画面にて、以下を入力し「追加」を押下

項目 入力内容
メッセージタイプ 障害
件名 {EVENT.NAME}
メッセージ {TRIGGER.NAME} on {HOST.NAME}

5. 「追加」を押下

6. 以上で完了です

1-5-5. ユーザーへのメディアタイプの紐づけ

1. 左ペインより「ユーザー > ユーザー」を開き「Admin」ユーザー名を押下

2. メディアタブを開き、「追加」を押下

3. メディア画面にて、以下を入力し「追加」を押下

項目 入力内容
タイプ AWS DevOps Agent Webhook
送信先 dev-ops-agent

4. 「更新」を押下

5. 以上で完了です

1-5-6. トリガーアクションの作成

1. 左ペインより「通知 > アクション > トリガーアクション」を開き、「アクションの作成」を押下

2. 新規アクション画面にて、「名前」に `DevOps Agent - CPU High` を入力し実行条件の「追加」を押下

3. 新規条件画面にて、以下を入力し「追加」を押下

項目 入力内容
タイプ トリガー
トリガー App ServerのLinux: High CPU utilization

4. 実行内容タブにて、実行内容の「追加」を押下

5. 実行内容の詳細画面にて、以下を入力し「追加」を押下

項目 入力内容
ユーザーに送信 Admin
送信メディアタイプ DevOps Agent Webhook

6. 「追加」を押下

7. 以上で完了です

1-6. Zabbix Serverでの作業

Zabbix ServerにSSMで接続し、以下のコマンドを使用して証明書の内容を確認し控えておきます。

sudo cat /etc/zabbix-mcp/tls/cert.pem

実行例:

sh-5.2$ sudo cat /etc/zabbix-mcp/tls/cert.pem
-----BEGIN CERTIFICATE-----
~省略~
-----END CERTIFICATE-----
sh-5.2$

1-7. zabbix-mcp-serverの管理コンソールでの作業

1-7-1. 管理コンソールへのログイン

1. スタック展開後に控えたZabbixServerPublicIpを元に、zabbix-mcp-serverの管理コンソールへアクセスします

管理コンソール:https://<ZabbixServerPublicIp>:9090

証明書関連の警告が出ますが、気にせずアクセスします

2. ログイン画面にて、以下を入力し「サインイン」を押下

項目 入力内容
Username admin
Password スタック展開時に指定したMCPAdminPasswordを入力

1-7-2. Zabbix Serverの設定

1. ログイン後、左ペインより「Zabbix Servers」を開き既存である「production」の「Edit」を押下

2. 以下の項目を更新し、「Save Changes」を押下

項目 入力内容
Zabbix URL http://localhost/zabbix
API Token Zabbix Webインターフェースで作成済みのAPIトークンを入力

3. 更新後、再起動を促されますが一旦無視します

1-7-3. MCPトークンの設定

1. 左ペインより「MCP Tokens」を開き、「Create your first token」を押下

2. Create MCP Token画面にて、以下の内容を入力し「Create Token」を押下

項目 入力内容
Token Name dev-ops-agent
Read-only mode True

3. 画面に表示されたMCPトークンを「Copy」を押下で控え、「Done」を押下

1-7-4. MCPサーバーの再起動

画面上部に表示されてる「Restart now」を押下でzabbix-mcp-serverを再起動します。

1-8. AWS DevOps Agent機能プロバイダーでの作業

1-8-1. プライベート接続の作成

1. AWS DevOps Agentのマネジメントコンソールを開き、「機能プロバイダー」の「プライベート接続」タブより「新しい接続を作成」を押下

2. プライベート接続を設定画面にて、以下を入力し「接続を作成」を押下

項目 入力内容
名前 zabbix-mcp-server-connection
リソースが配置されている VPC CloudFormationスタックで展開したVPCを選択
サブネット CloudFormationスタックで展開したサブネットを選択
TCP ポート範囲 8080
ホストアドレス スタック展開後に控えたZabbixServerPrivateIpを入力
証明書の公開キー 確認した証明書の内容を入力

3. 作成後、ステータスが「完了」になれば作成完了です

1-8-2. MCPサーバーの登録

1. AWS DevOps Agentのマネジメントコンソールの「機能プロバイダー」の「登録」タブの中ほど「MCP Server」より、「Register」を押下

2. MCPサーバーの詳細画面にて、以下を入力し「次へ」を押下

項目 入力内容
名前 zabbix-mcp-server
エンドポイント URL https://<スタック展開後に控えたZabbixServerPrivateIp>:8080/mcp
プライベート接続を使用してエンドポイントに接続 チェック
既存のプライベート接続から選択 先程作成したプライベート接続を指定

<スタック展開後に控えたZabbixServerPrivateIp>の置換を忘れないようにしてください

3. 認証フロー選択画面にて、「API キー」を選択し、「次へ」を押下

4. 認証設定画面にて、以下の内容を入力し「次へ」を押下

項目 入力内容
API キー名 dev-ops-agent
API キーヘッダー Authorization
API キー値 Bearer <zabbix-mcp-serverの管理コンソールで払い出したMCPトークン>

5. 内容に問題なければ「追加」を押下

6. 登録できれば完了です

1-9. AWS DevOps Agentのエージェントスペースでの作業(2回目)

1-9-1. MCPサーバーの紐づけ

1. AWS DevOps Agentのマネジメントコンソールの「エージェントスペース」より作成した「agent-space」を開き、「機能」タブ下部の「MCP サーバー」にて「追加」を押下

2. 機能を追加画面にて、作成した「zabbix-mcp-server」で「追加」を押下

3. MCPサーバーツールを選択画面にて、利用可能なツールをすべて選択し「保存」を押下

4. ウェブフック接続の設定画面に遷移しますが、この情報は使用しないのでそのまま「閉じる」を押下

5. 以上で完了です

1-10. AWS DevOps Agentウェブアプリでの作業

1-10-1. 動作確認

1. 「ウェブアプリ」タブのウェブアプリリンクの「IAM経由で起動する」を押下

2. 新規チャットにて「Zabbixに登録されているホスト一覧を教えて」と聞いてみます

AWS DevOps Agentがzabbix-mcp-serverを利用し、Zabbixの情報を取得してくれれば動作確認完了です

1-10-2. カスタムスキルの追加

1. 左ペインの「ナレッジ」を押下

2. ナレッジ画面の「スキル」タブより、「スキルを追加」を押下

3. 遷移した画面にて「スキルを作成」を押下

4. スキルを作成の画面にて、以下を入力し「スキルを作成」を押下

  • 名前:zabbix-monitoring-investigation
  • 説明:
    Investigation procedures using Zabbix monitoring data via MCP server.
    Use this skill when investigating CPU high utilization, memory pressure,
    disk I/O bottlenecks, or any infrastructure performance alerts that
    originated from Zabbix monitoring. This skill guides the agent to
    retrieve correlated metrics from Zabbix before forming conclusions.
    
  • 指示:
    # Zabbix Monitoring Investigation
    
    When investigating infrastructure issues, ALWAYS retrieve data from the
    Zabbix MCP server before drawing conclusions. Do not rely solely on the
    alert text or AWS CloudWatch metrics.
    
    ## Step 1: Get the full picture of the affected host
    
    Use `host_status_get` to retrieve the overall status of the alerted host.
    This provides a summary of all active problems, recent events, and host health.
    
    ## Step 2: Check all active problems on the same host
    
    Use `problem_active_get` to list all currently active problems.
    Multiple simultaneous alerts often indicate a common root cause.
    
    ## Step 3: Retrieve related metrics history
    
    Based on the alert type, retrieve historical data for correlated metrics:
    
    ### CPU High Utilization
    - `system.cpu.util[,iowait]` - Check if I/O wait is contributing
    - `system.cpu.util[,user]` - Confirm user-space CPU consumption
    - `system.cpu.util[,system]` - Check kernel overhead
    - `system.cpu.load[all,avg5]` - Check load average trend
    - `proc.cpu.util[mysqld]` - Check per-process CPU usage
    - `vfs.dev.read.await` / `vfs.dev.write.await` - Disk latency
    
    Use `history_get` with the relevant item keys over the past 30-60 minutes.
    
    ### Memory Issues
    - `vm.memory.utilization` - Overall memory usage
    - `system.swap.size[,pfree]` - Swap usage (indicates memory pressure)
    - `proc.mem[mysqld,,,,rss]` - MySQL process memory consumption (RSS)
    - `vm.memory.size[available]` - Available memory in bytes
    
    ### Disk Issues
    - `vfs.dev.read.rate` / `vfs.dev.write.rate` - I/O operations
    - `vfs.dev.queue_size` - Disk saturation
    
    ## Step 4: Correlate and identify root cause
    
    Cross-reference the metrics to identify the actual root cause:
    - High CPU + High iowait + High disk latency -> Disk I/O bottleneck
    - High CPU + Low iowait + Single process consuming most CPU -> Process issue
    - High CPU + High memory + Swap usage -> Memory pressure causing thrashing
    - High memory + Single process consuming most memory (proc.mem) -> Process memory leak or misconfiguration
    - High memory + Swap usage + Low available memory -> Immediate OOM risk
    
    ## Step 5: Summarize findings
    
    Provide a summary with:
    1. Root cause identification with supporting metric evidence
    2. Timeline of when the issue started (based on metric trends)
    3. Affected components and their current status
    4. Recommended remediation steps
    
    ## Important Notes
    
    - Always use the `server` parameter set to "production" when calling Zabbix tools
    - Use `item_get` with search to find the correct item IDs before querying history
    - Request data for at least the past 30 minutes to identify trends
    - Check `trigger_get` for trigger dependencies that may reveal cascading failures
    

5. カスタムスキル一覧に表示されれば完了です

AIエージェントを活用したクラウド環境の監視方法について、NTT東日本のエンジニアがご相談にお応えしますので、お気軽にご連絡ください!

2. 検証

以上で環境の構築は完了です。

実際のAWS DevOps Agentの動作に関しては、本編:2-1. 具体的なシチュエーションもあわせてご確認ください。

また、CPU使用率高騰のアラートを発生させる場合は、構築完了後しばらく時間が経過してから試すことをおすすめします。

  • 構築完了後すぐに実施すると、AWS DevOps Agentが「構築に起因した一時的なもの」といった結論を出すことがあります
  • Amazon Web Services(AWS)およびその他のAWS商標は、米国その他の諸国における、Amazon.com, Inc.またはその関連会社の商標です。

ページ上部へ戻る

相談無料!プロが中立的にアドバイスいたします

クラウド・AWS・Azureでお困りの方はお気軽にご相談ください。