LinuxにCloudWatch Agentをインストールしてデータ収集

LinuxインスタンスにCloudWatch Agentをインストールして、ログとメトリクスを収集する構成

CloudWatch Agentを使用することによって、ログやメトリクスを収集することができます。

オペレーティングシステム全体で Amazon EC2 インスタンスから内部システムレベルのメトリクスを収集します。(中略)

Linux または Windows Server を実行している Amazon EC2 インスタンスおよびオンプレミスサーバーから、ログを収集します。

CloudWatch エージェントを使用した Amazon EC2 Instances インスタンスとオンプレミスサーバーからのメトリクスとログの収集

今回はLinuxインスタンス(Amazon Linux 2)を対象とします。
なおWindowsインスタンスにCloudWatch Agentをインストールする手順については、以下のページをご確認ください。

あわせて読みたい
WindowsにCloudWatch Agentをインストールしてデータ収集 【WindowsインスタンスにCloudWatch Agentをインストールして、ログとメトリクスを収集する構成】 CloudWatch Agentを使用することによって、ログやメトリクスを収集す...

構築する環境

Diagram of install CloudWatch Agent and collect data.

今回の構成では、プライベートサブネット内のインスタンスにCloudWatchエージェントをインストールし、データを収集します。そのためには、VPCエンドポイントを経由し、3種類のサービス(S3, System Manager, CloudWatch)にアクセスします。

環境構築用のCloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置します。

https://github.com/awstut-an-r/awstut-fa/tree/main/015

テンプレートファイルのポイント解説

CloudWatchエージェントをインストール・使用するための権限

EC2インスタンスに付与する権限を確認します。

Resources:
  InstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - ec2.amazonaws.com
      Policies:
        - PolicyName: AllowAccessToYumRepositoryInS3AndUseCloudWatchAgentPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObject
                Resource:
                  - !Sub "arn:aws:s3:::amazonlinux.${AWS::Region}.amazonaws.com/*"
                  - !Sub "arn:aws:s3:::amazonlinux-2-repos-${AWS::Region}/*"
              - Effect: Allow
                Action:
                  - cloudwatch:PutMetricData
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "*"
        - PolicyName: DeliverLogPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:PutObject
                  - s3:PutObjectAcl
                  - s3:ListBucket
                Resource:
                  - !Sub "arn:aws:s3:::${SSMLogBucket}"
                  - !Sub "arn:aws:s3:::${SSMLogBucket}/*"
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicyCode language: YAML (yaml)

SSMを使用してCloudWatch Agentをインストールするために必要な権限に関して、AWS公式では以下のように言及されています。

ポリシーのリストで、[CloudWatchAgentServerPolicy] の横にあるチェックボックスを選択します。(中略)

Systems Manager を使用して CloudWatch エージェントをインストールまたは設定するには、[AmazonSSMManagedInstanceCore] の横にあるボックスを選択します。

Amazon EC2 インスタンスの CloudWatch エージェントで使用する IAM ロールを作成する

上記に従い、ManagedPolicyArnsプロパティにて、2つのAWS管理ポリシーを指定します。

今回の構成で作成するインスタンスはAmazon Linux 2ですので、S3バケットで構築されたリポジトリに対して、yumを実行することが可能です。S3バケットに対してyumを実行するためには、インスタンスにそのバケットにアクセスする権限を付与する必要があります。詳細は以下のページをご確認ください。

あわせて読みたい
プライベートサブネットのインスタンスでyum/dnfを実行する 【プライベートサブネット内のインスタンスでyum/dnfを実行する構成】 プライベートサブネット内のインスタンスで、yum/dnfを実行する方法を確認します。 今回は以下の2...

CloudWatchエージェントを介して、CloudWatchにメトリックやログを配信するため、インスタンスに3つの権限(cloudwatch:PutMetricData, logs:CreateLogStream, logs:PutLogEvents)を付与します。

後述するSSMドキュメントの実行ですが、実行時のログをS3バケットに出力することができます。今回はこれを使用するため、対象バケットへのアクセスを許可します。

CloudWatchエージェントのコンフィグをSSM Parameter Storeに登録する

CloudWatch Agentを起動するために必要なコンフィグをSSM Parameter Storeで定義します。

Resources:
  CloudWatchConfigParemeter:
    Type: AWS::SSM::Parameter
    Properties:
      Name: AmazonCloudWatch-linux
      Type: String
      Value: !Sub |
        {
          "agent": {
            "metrics_collection_interval": 60,
            "run_as_user": "root"
          },
          "logs": {
            "logs_collected": {
              "files": {
                "collect_list": [
                  {
                    "file_path": "/var/log/messages",
                    "log_group_name": "${Prefix}",
                    "log_stream_name": "${Instance}"
                  }
                ]
              }
            }
          },
          "metrics": {
            "append_dimensions": {
              "ImageId": "${!aws:ImageId}",
              "InstanceId": "${!aws:InstanceId}",
              "InstanceType": "${!aws:InstanceType}"
            },
            "metrics_collected": {
              "cpu": {
                "measurement": [
                  "cpu_usage_idle",
                  "cpu_usage_iowait",
                  "cpu_usage_user",
                  "cpu_usage_system"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                  "*"
                ],
                "totalcpu": false
              },
              "disk": {
                "measurement": [
                  "used_percent",
                  "inodes_free"
                ],
                "metrics_collection_interval": 60,
                "resources": [
                  "*"
                ]
              },
              "mem": {
                "measurement": [
                  "mem_used_percent"
                ],
                "metrics_collection_interval": 60
              }
            }
          }
        }
Code language: YAML (yaml)

CloudWatch Agentを起動するためのコンフィグは、Agentをインストールするインスタンスのローカルに設置することも可能ですが、SSM Parameter Storeに登録することもできます。

SSM Agent を使用して CloudWatch エージェントをサーバーにインストールする場合は、CloudWatch エージェント設定ファイルを手動で編集した後、Systems Manager Parameter Store にアップロードできます。

CloudWatch エージェント設定ファイルの Systems Manager Parameter Store へのアップロード

コンフィグの内容に関しては、CloudWatch エージェント設定ファイルを手動で作成または編集するに詳しいですが、logsおよびmetricsセクションを定義し、インスタンスのログとメトリクスを取得するように設定します。具体的には、ログとして/var/log/messagesの内容を、メトリクスとしてCPU・ディスク・メモリの複数の項目を収集するように設定します。

取得するメトリクスにインスタンスID等を追加します。append_dimentionsオプション内で、「${aws:InstanceId}」のような記法で記述します。注意点はこの記法がCloudFormationの組み込み関数Fn::Subの変数の記法と同様であるという点です。今回は同関数を使用して、ログの配信先であるロググループ名とストリーム名を指定します。ただ同関数の実行時に、先述のappend_dimentionsオプション内のディメンション値も対象と評価され、エラーが発生します。これを回避するために、「!」を追加してエスケープします。

ドル記号と中括弧 (${}) をそのまま書き込むには、最初の中括弧の後に感嘆符 (!) を追加します (${!Literal} など)。AWS CloudFormation では、このテキストは ${Literal} のようになります。

Fn::Sub

SSMドキュメントでCloudWatchエージェントをインストール・起動する

2種類のSSMドキュメントを実行して、CloudWatchエージェントのセットアップを行います。

AWS-ConfigureAWSPackage

まずCloudWatchエージェントをインストールするためのSSMドキュメントを確認します。

Resources:
  AWSConfigureAWSPackageAssociation:
    Type: AWS::SSM::Association
    Properties:
      AssociationName: !Sub "${Prefix}-aws-configure-aws-package-association"
      Name: AWS-ConfigureAWSPackage
      OutputLocation:
        S3Location:
          OutputS3BucketName: !Ref SSMLogBucket
          OutputS3KeyPrefix: !Sub "${Prefix}/aws-configure-aws-package-association"
      Parameters:
        action:
          - Install
        installationType:
          - Uninstall and reinstall
        name:
          - AmazonCloudWatchAgent
        version:
          - latest
      Targets:
        - Key: InstanceIds
          Values:
            - !Ref Instance
      WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

SSMドキュメントの実行は、AWS::SSM::Associationリソースを定義することで実現できます。
Nameプロパティで実行するSSMドキュメントを指定します。今回実行するべきドキュメントは以下のように定められています。

[Command document] リストで、[AWS-ConfigureAWSPackage] を選択します。

CloudWatch エージェントをダウンロードして設定する

S3Locationプロパティで、ドキュメントを実行した際のログを設置先を指定します。
今回は先述のバケットを指定します。Targetsプロパティでドキュメントを実行する対象インスタンスを指定します。今回はインスタンスIDを指定します。
Parametersプロパティでドキュメントを実行するためのパラメータを指定します。渡すべきパラメータはドキュメントを参照することで確認できます。以下にAWS-ConfigureAWSPackageのパラメータに関する記述を引用します。

{
  "parameters": {
    "action": {
      "description": "(Required) Specify whether or not to install or uninstall the package.",
      "type": "String",
      "allowedValues": [
        "Install",
        "Uninstall"
      ]
    },
    "installationType": {
      "description": "(Optional) Specify the type of installation. Uninstall and reinstall: The application is taken offline until the reinstallation process completes. In-place update: The application is available while new or updated files are added to the installation.",
      "type": "String",
      "allowedValues": [
        "Uninstall and reinstall",
        "In-place update"
      ],
      "default": "Uninstall and reinstall"
    },
    "name": {
      "description": "(Required) The package to install/uninstall.",
      "type": "String",
      "allowedPattern": "^arn:[a-z0-9][-.a-z0-9]{0,62}:[a-z0-9][-.a-z0-9]{0,62}:([a-z0-9][-.a-z0-9]{0,62})?:([a-z0-9][-.a-z0-9]{0,62})?:(package|document)\\/[a-zA-Z0-9/:.\\-_]{1,128}$|^[a-zA-Z0-9/:.\\-_]{1,128}$"
    },
    "version": {
      "description": "(Optional) The version of the package to install or uninstall. If you don't specify a version, the system installs the latest published version by default. The system will only attempt to uninstall the version that is currently installed. If no version of the package is installed, the system returns an error.",
      "type": "String",
      "default": ""
    },
    "additionalArguments": {
      "description": "(Optional) The additional parameters to provide to your install, uninstall, or update scripts.",
      "type": "StringMap",
      "displayType": "textarea",
      "default": {},
      "maxChars": 4096
    }
  }
}
Code language: JSON / JSON with Comments (json)

各パラメータに指定するべき値はCloudWatch エージェントをダウンロードして設定するを参考にして設定します。

AmazonCloudWatch-linux

次にCloudWatchエージェントを起動するためのSSMドキュメントを確認します。

Resources:
  AmazonCloudWatchManageAgentAssociation:
    Type: AWS::SSM::Association
    DependsOn:
      - CloudWatchConfigParemeter
      - AWSConfigureAWSPackageAssociation
    Properties:
      AssociationName: !Sub "${Prefix}-amazon-cloudwatch-manage-agent"
      Name: AmazonCloudWatch-ManageAgent
      OutputLocation:
        S3Location:
          OutputS3BucketName: !Ref SSMLogBucket
          OutputS3KeyPrefix: !Sub "${Prefix}/amazon-cloudwatch-manage-agent"
      Parameters:
        action:
          - configure
        mode:
          - ec2
        optionalConfigurationSource:
          - ssm
        optionalConfigurationLocation:
          - AmazonCloudWatch-linux
        optionalRestart:
          - "yes"
      Targets:
        - Key: InstanceIds
          Values:
            - !Ref Instance
      WaitForSuccessTimeoutSeconds: !Ref WaitForSuccessTimeoutSeconds
Code language: YAML (yaml)

全体の記法は先ほどと同様です。
CloudWatch Agent起動のために実行するドキュメントは、以下のように言及されています。

[Command document] リストで、[AmazonCloudWatch-ManageAgent] を選択します。

CloudWatch エージェントの起動

上記に従い、NameプロパティにAmazonCloudWatch-ManageAgentを指定します。

Parametersプロパティで本ドキュメントを実行するためのパラメータを指定します。以下にAmazonCloudWatch-ManageAgentのパラメータに関する記述を引用します。

{
  "parameters": {
    "action": {
      "description": "The action CloudWatch Agent should take.",
      "type": "String",
      "default": "configure",
      "allowedValues": [
        "configure",
        "configure (append)",
        "configure (remove)",
        "start",
        "status",
        "stop"
      ]
    },
    "mode": {
      "description": "Controls platform-specific default behavior such as whether to include EC2 Metadata in metrics.",
      "type": "String",
      "default": "ec2",
      "allowedValues": [
        "ec2",
        "onPremise",
        "auto"
      ]
    },
    "optionalConfigurationSource": {
      "description": "Only for 'configure' related actions. Use 'ssm' to apply a ssm parameter as config. Use 'default' to apply default config for amazon-cloudwatch-agent. Use 'all' with 'configure (remove)' to clean all configs for amazon-cloudwatch-agent.",
      "type": "String",
      "allowedValues": [
        "ssm",
        "default",
        "all"
      ],
      "default": "ssm"
    },
    "optionalConfigurationLocation": {
      "description": "Only for 'configure' related actions. Only needed when Optional Configuration Source is set to 'ssm'. The value should be a ssm parameter name.",
      "type": "String",
      "default": "",
      "allowedPattern": "[a-zA-Z0-9-\"~:_@./^(*)!<>?=+]*$"
    },
    "optionalOpenTelemetryCollectorConfigurationSource": {
      "description": "Only for 'configure' related actions. Use 'ssm' to apply a ssm parameter as config. Use 'default' to apply default config for amazon-cloudwatch-agent. Use 'all' with 'configure (remove)' to clean all configs for amazon-cloudwatch-agent. It does not support MacOS instance.",
      "type": "String",
      "allowedValues": [
        "ssm",
        "default",
        "all"
      ],
      "default": "ssm"
    },
    "optionalOpenTelemetryCollectorConfigurationLocation": {
      "description": "Only for 'configure' related actions. Only needed when Optional Configuration Source is set to 'ssm'. The value should be a ssm parameter name. It does not support MacOS instance.",
      "type": "String",
      "default": "",
      "allowedPattern": "[a-zA-Z0-9-\"~:_@./^(*)!<>?=+]*$"
    },
    "optionalRestart": {
      "description": "Only for 'configure' related actions. If 'yes', restarts the agent to use the new configuration. Otherwise the new config will only apply on the next agent restart.",
      "type": "String",
      "default": "yes",
      "allowedValues": [
        "yes",
        "no"
      ]
    }
  }
}
Code language: JSON / JSON with Comments (json)

各パラメータに指定するべき値はCloudWatch エージェントの起動を参考にして設定します。

VPCエンドポイント

今回の構成では、プライベートサブネット内にインスタンスを配置しているため、VPCエンドポイント経由で各種サービスにアクセスする必要があります。

yum実行用エンドポイント

先述の通り、Amazon Linux 2の場合は、yumをS3バケットに対して実行することができます。そのためにS3用VPCエンドポイント(com.amazonaws.${AWS::Region}.s3)を作成します。

SSM用エンドポイント

3つのエンドポイントを作成します。

  • com.amazonaws.${AWS::Region}.ssm
  • com.amazonaws.${AWS::Region}.ec2messages
  • com.amazonaws.${AWS::Region}.ssmmessages

上2つがSSMドキュメントを実行するために必要です。加えて、今回はSSM Session Managerを使用するため、3つ目のエンドポイントも作成します。

CloudWatchエージェントでメトリクス配信用のエンドポイント

3つのエンドポイントを作成します。

  • com.amazonaws.${AWS::Region}.monitoring
  • com.amazonaws.${AWS::Region}.ec2
  • com.amazonaws.${AWS::Region}.logs

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • S3バケット名:fa-015
  • CloudWatch Logsロググループ名:fa-015
  • インスタンス:i-058d2a76a7fb6ac06

AWS Management Consoleからも、リソースの作成状況を確認します。まずSSMドキュメントの実行状況を確認します。

Two SSM documents were running.

確かに2つのコマンドが実行され、正常に完了していることがわかります。


続いてS3バケットにアクセスし、SSM Run Command実行時のログを確認します。
まずCloudWatch Agentのインストールの実行結果です。S3バケットにログが出力されます。

Detail of SSM 2.

ファイルの中身は以下の通りです。

Initiating arn:aws:ssm:::package/AmazonCloudWatchAgent 1.247350.0b251780 install
Plugin aws:runShellScript ResultStatus Success
install output: Running sh install.sh
create group cwagent, result: 0
create user cwagent, result: 0

Successfully installed arn:aws:ssm:::package/AmazonCloudWatchAgent 1.247350.0b251780
Code language: plaintext (plaintext)

正常にインストールされたことがわかります。

次にCloudWatch Agent起動の実行結果です。

Detail of SSM 3.

ファイルの中身は以下の通りです。

****** processing amazon-cloudwatch-agent ******
/opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-dir /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d --download-source ssm:AmazonCloudWatch-linux --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml --multi-config default
Region: ap-northeast-1
credsConfig: map[]
Successfully fetched the config and saved in /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/ssm_AmazonCloudWatch-linux.tmp
Start configuration validation...
/opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --input-dir /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml --multi-config default
Valid Json input schema.
I! Detecting run_as_user...
No csm configuration found.
Configuration validation first phase succeeded
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
Configuration validation second phase succeeded
Configuration validation succeeded
amazon-cloudwatch-agent has already been stopped
Code language: plaintext (plaintext)

インスタンスにアクセスし、CloudWatch Agentの起動を確認する

一応、インスタンスにアクセスし、CloudWatch Agentの起動状況を確認します。
インスタンスへのアクセスは、SSM Session Managerを使用します。

% aws ssm start-session --target i-058d2a76a7fb6ac06

Starting session with SessionId: root-0e251c4db3512cf60
sh-4.2$
Code language: Bash (bash)

SSM Session Managerを使用したインスタンスへのアクセスに関する詳細は、以下のページをご確認ください。

あわせて読みたい
LinuxインスタンスにSSM Session Manager経由でアクセスする 【LinuxインスタンスにSSM Session Manager経由でアクセスする】 EC2インスタンスにSSM Session Manager経由でアクセスする構成を確認します。 Session Manager は完全...

アクセスできましたので、起動状況を確認します。

sh-4.2$ sudo systemctl status amazon-cloudwatch-agent -l
● amazon-cloudwatch-agent.service - Amazon CloudWatch Agent
   Loaded: loaded (/etc/systemd/system/amazon-cloudwatch-agent.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2022-03-05 06:32:47 UTC; 10min ago
 Main PID: 1344 (amazon-cloudwat)
   CGroup: /system.slice/amazon-cloudwatch-agent.service
           └─1344 /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml -envconfig /opt/aws/amazon-cloudwatch-agent/etc/env-config.json -pidfile /opt/aws/amazon-cloudwatch-agent/var/amazon-cloudwatch-agent.pid

Mar 05 06:32:47 ip-10-0-1-55.ap-northeast-1.compute.internal systemd[1]: Started Amazon CloudWatch Agent.
Mar 05 06:32:47 ip-10-0-1-55.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[1344]: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json does not exist or cannot read. Skipping it.
Mar 05 06:32:47 ip-10-0-1-55.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[1344]: Valid Json input schema.
Mar 05 06:32:47 ip-10-0-1-55.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[1344]: I! Detecting run_as_user...
Code language: Bash (bash)

「active (running)」とありますので、正常に動作していることがわかります。

CloudWatch Agentで配信されたログを確認する

実際に配信されたデータを確認します。今回は/var/log/messagesを配信するように設定していますので、本当に配信されたかを確認します。
まずロググループ内のストリームの状況を確認します。

A stream is created in CloudWatch Logs.

ロググループ名やストリーム名は、CloudWatch Agentのコンフィグで指定した通りです。

次にストリームに配信されているログを確認します。

Logs are delivered to CloudWatch Logs.

正常に/var/log/messagesが配信されていることがわかります。

CloudWatch Agentで配信されたメトリクスを確認する

最後にメトリクスを確認します。
AWS Management Consoleにて、以下にアクセスします。

CloudWatch > メトリクス > 全てのメトリクス > CWAgent

Metrics are delivered to CloudWatch.

上記の通り、メトリクスが配信され、グラフが作成されました。

まとめ

LinuxインスタンスにSSMを使用して、CloudWatch Agentをインストールする手順を確認しました

CloudWatch Agentを使用することで、ログおよびメトリクスの配信ができることを確認しました。