CloudWatchでSSM Agentプロセスを監視してみた

2023.04.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

CloudWatchでプロセス監視の設定を行う機会があったのでブログに残します。

やること

  1. Systems Manager パラメータストアにCloudWatch Agentの設定を登録
  2. EC2へCloudWatch Agentのインストール
  3. CloudWatchメトリクスに値が登録されていることを確認する

設定

1. Systems Manager パラメータストアにCloudWatch Agentの設定を登録

まずはSSM Agentプロセスを監視するためのCloudWatch Agentの設定を作成します。
プロセスの監視はこちらのドキュメントに記載されているprocstat プラグインを使用します。
プロセスを指定する方法は以下の3つの方法があります。

指定方法 説明
pid_file 作成するプロセス識別番号 (PID) ファイルの名前でプロセスを選択します。
/var/run に配置されているような.pidファイルを指定することができます。
exe 正規表現の照合ルールを使用して、指定した文字列と一致するプロセス名のプロセスを選択します。
一致は「含む」一致です。つまり、一致する用語として agent を指定した場合、cloudwatchagent のような名前を持つプロセスは、その用語に一致します。
grep Name /proc/プロセスID/status でプロセスの名前を確認することが可能です。
pattern プロセスの起動に使用するコマンドラインでプロセスを選択します。
正規表現の照合ルールを使用して指定した文字列と一致するコマンドラインを持つすべてのプロセスが選択されます。
コマンドで使用されるパラメータやオプションを含むコマンドライン全体が確認されます。
ps aux で出力されたCOMMAND列が該当するものになります。

また取得できるメトリクスはcpu_usageやpid_countなどが取得できます。
詳しくは公式ドキュメントをご確認ください。

今回はpid_count (プロセス数)を取得してみました。
CloudWatch Agentの設定は以下になります。

{
  "metrics": {
    "metrics_collected": {
      "procstat": [
        {
          "exe": "amazon-ssm-agent",
          "measurement": [
            "pid_count"
          ]
        }
      ]
    },
    "append_dimensions": {
      "InstanceId": "${aws:InstanceId}"
    }
  }
}

上記の設定ではexeでプロセス名を指定しています。
また、append_dimensionsでディメンションにインスタンスIDを設定しました。

この設定内容でSystems Manager パラメータストアに登録していきます。
上記の設定をjsonファイルに保存してください。
パラメータストアへの登録は以下のコマンドで行います。
パラメータ名は「AmazonCloudWatch-」から始まる名前にしてください。
今回EC2が使用するIAMポリシー「CloudWatchAgentAdminPolicy」は「AmazonCloudWatch-」から始まるパラメータ名でないと使用できなくなっています。
独自の名前にしたい場合はカスタムポリシーを作成してください。

aws ssm put-parameter --name AmazonCloudWatch-process-monitoring --type String --value file://jsonファイル名

登録に成功すると以下のようにバージョンが返ってきます。

{
    "Version": 1,
    "Tier": "Standard"
}

2. EC2へCloudWatch Agentのインストール

パラメータストアにパラメータの登録が完了したらEC2へCloudWatch Agentのインストールを行っていきます。
監視対象のEC2は以下のCloudFormationテンプレートで作成しました。

CloudFormationテンプレート (ここをクリックしてください)
AWSTemplateFormatVersion: "2010-09-09"

Description: Session Test Stack

Metadata:
# ------------------------------------------------------------#
# Metadata
# ------------------------------------------------------------# 
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label: 
          default: Parameters for VPC
        Parameters:
          - VPCCIDR
      - Label: 
          default: Parameters for Subnet
        Parameters:
          - PublicSubnet01CIDR
      - Label: 
          default: Parameters for EC2
        Parameters:
          - EC2VolumeSize
          - EC2VolumeIOPS
          - EC2AMI
          - EC2InstanceType

Parameters:
# ------------------------------------------------------------#
# Parameters
# ------------------------------------------------------------# 
  VPCCIDR:
    Default: 172.30.0.0/16
    Type: String

  PublicSubnet01CIDR:
    Default: 172.30.0.0/24
    Type: String

  EC2VolumeSize:
    Default: 30
    Type: Number

  EC2VolumeIOPS:
    Default: 3000
    Type: Number

  EC2AMI:
    Default: ami-079a2a9ac6ed876fc
    Type: AWS::EC2::Image::Id

  EC2InstanceType:
    Default: t3.micro
    Type: String

Resources:
# ------------------------------------------------------------#
# VPC
# ------------------------------------------------------------# 
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VPCCIDR
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags: 
        - Key: Name
          Value: test-vpc

# ------------------------------------------------------------#
# InternetGateway
# ------------------------------------------------------------# 
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags: 
        - Key: Name
          Value: test-igw

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

# ------------------------------------------------------------#
# Subnet
# ------------------------------------------------------------# 
  PublicSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: ap-northeast-1c
      CidrBlock: !Ref PublicSubnet01CIDR
      MapPublicIpOnLaunch: true
      Tags: 
        - Key: Name
          Value: test-pub-01
      VpcId: !Ref VPC

# ------------------------------------------------------------#
# RouteTable
# ------------------------------------------------------------# 
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: test-pub-rtb

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

  PublicRtAssociation1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref PublicRouteTable
      SubnetId: !Ref PublicSubnet01

# ------------------------------------------------------------#
# Security Group
# ------------------------------------------------------------# 
  EC2SG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: for ec2
      GroupName: test-sg-ec2
      SecurityGroupEgress: 
        - CidrIp: 0.0.0.0/0
          FromPort: -1
          IpProtocol: -1
          ToPort: -1
      Tags: 
        - Key: Name
          Value: test-sg-ec2
      VpcId: !Ref VPC

# ------------------------------------------------------------#
# IAM
# ------------------------------------------------------------# 
  EC2IAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - ec2.amazonaws.com
            Action: 
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/CloudWatchAgentAdminPolicy
      RoleName: test-iam-role-ec2
      Tags:
        - Key: Name
          Value: test-iam-role-ec2

  EC2IAMInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: test-iam-instanceprofile-ec2
      Roles: 
        - !Ref EC2IAMRole

# ------------------------------------------------------------#
# KeyPair
# ------------------------------------------------------------# 
  KeyPair:
    Type: AWS::EC2::KeyPair
    Properties: 
      KeyName: test-ec2-key
      KeyType: rsa
      Tags: 
        - Key: Name
          Value: test-ec2-key

# ------------------------------------------------------------#
# EC2
# ------------------------------------------------------------# 
  EC2:
    Type: AWS::EC2::Instance
    Properties:
      BlockDeviceMappings: 
        - DeviceName: /dev/xvda
          Ebs:
            DeleteOnTermination: true
            Encrypted: true
            Iops: !Ref EC2VolumeIOPS
            VolumeSize: !Ref EC2VolumeSize
            VolumeType: gp3
      DisableApiTermination: false
      EbsOptimized: true
      IamInstanceProfile: !Ref EC2IAMInstanceProfile
      ImageId: !Ref EC2AMI
      InstanceType: !Ref EC2InstanceType
      KeyName: !Ref KeyPair
      NetworkInterfaces: 
        - AssociatePublicIpAddress: true
          DeleteOnTermination: true
          DeviceIndex: 0
          GroupSet: 
            - !Ref EC2SG
          SubnetId: !Ref PublicSubnet01
      Tags:
        - Key: Name
          Value: test-ec2

上記のCloudFormationテンプレートではパブリックサブネットに1台EC2が起動します。
デプロイは以下のコマンドで行います。

aws cloudformation create-stack --stack-name CloudFormationスタック名 --template-body file://CloudFormationテンプレートファイル名 --capabilities CAPABILITY_NAMED_IAM

EC2の作成が完了したら以下のコマンドでCloudWatch Agentのインストールを行います。

aws ssm send-command --instance-ids インスタンスID --document-name "AWS-ConfigureAWSPackage" --parameters '{"action":["Install"],"name":["AmazonCloudWatchAgent"]}'
aws ssm send-command --instance-ids i-0a031789d94c080f6 --document-name "AmazonCloudWatch-ManageAgent" --parameters '{"action":["configure"],"optionalConfigurationLocation":["AmazonCloudWatch-process-monitoring"]}'

上記2つのコマンドはSystems Manager Run Commandを実行しています。
1つ目のコマンドでCloudWatch Agentのインストールを行っています。
2つ目のコマンドでCloudWatch Agentの設定をパラメータストアから読み込ませています。

3. CloudWatchメトリクスに値が登録されていることを確認する

ここからはマネジメントコンソールで確認していきます。
マネジメントコンソールからCloudWatchダッシュボードへ移動します。
画面遷移後、左の項目から「すべてのメトリクス」をクリックします。

「カスタム名前空間」の「CWAgent」をクリックします。

画面遷移後、「InstanceId,exe,pid_finder」をクリックするとインスタンス名が「test-ec2」でInstanceIdが該当のものが作成されています。

グラフを見ると値が1で登録されていることが確認できます。

さいごに

設定自体はとても簡単でした。
上手く設定できていない可能性があるのでブログには記載していませんが、カーネルモードのプロセス (psコマンドで[]がついてるもの、[kthreadd]や[rcu_gp]など)はexeやpatternで指定してもメトリクス値が0のままでした。
原因は不明ですがこちらについてはもう少し検証を行ってみたいと思います。