Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Systems ManagerとEventBridgeでCloudWatchエージェントの導入・設定を完全自動化

By Nikhil PawarMar 28, 20247 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

Photo by Alexander+Supertramp from Shutterstock

本記事では、Systems Managerのオートメーションランブックを使い、EC2インスタンス(Linux)でカスタムメモリメトリクスを取得するためのCloudWatchエージェントのインストールと設定を完全に自動化する方法を解説します。カスタムランブックでCloudWatchエージェントの導入と設定を自動化し、AWS EventBridgeで人手を介さずにオートメーションを起動する仕組みを構築します。

基本アーキテクチャ図

自動化の概要

本構成では、AWS CloudFormationテンプレートで以下のステップを実行するためのリソースをデプロイします。

  1. AWS Systems Managerがオートメーションドキュメントを実行するためのIAMロールを作成 — Systems Managerが対象EC2インスタンス上でランブックを実行するには実行ロールが必要です。あわせて、EC2インスタンスがCloudWatchへメトリクスを書き込むための権限も付与します。
  2. CloudWatchエージェント設定ファイルをSystems Manager Parameter Storeにアップロード — CloudFormationテンプレートにより、カスタムCloudWatch設定ファイルをSystems Manager Parameter Storeへアップロードします。各インスタンスはこの設定ファイルを取得してCloudWatchエージェントを構成します。
  3. Systems Managerのオートメーションドキュメントを作成 — CloudFormationで、CloudWatchエージェントをインストール・設定するためのカスタムランブックを作成します。
  4. EventBridgeルールがSystems Managerオートメーションを呼び出すためのIAMロールを作成 — EventBridgeからSystems Managerのオートメーションワークフローを起動し、CloudWatchエージェントの導入・設定を行うには、Invokeロールが必要です。
  5. EventBridgeルールを作成 — CloudFormationで、EC2インスタンスの「running」イベントを抽出してSSMオートメーションを起動するEventBridgeルールを作成します。
  6. (オプション)SQSデッドレターキューを作成 — EventBridgeルールのデッドレターキューとして利用する標準SQSキューで、EventBridge起動時に発生したエラー情報を捕捉します。

CloudFormationテンプレート

AWSTemplateFormatVersion: '2010-09-09'
Description: A template to create an AWS Systems Manager Automation Document that installs Amazon CloudWatch agent, sets up necessary permissions, and configures CloudWatch agent to publish memory metrics to CloudWatch and trigger SSM automation with eventbridge rule
Resources:
  SsmAutomationRole:
    Type: AWS::IAM::Role
    Properties:
      Description: IAM role for AWS Systems Manager to execute automation document
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ssm.amazonaws.com
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                aws:SourceAccount: !Sub ${AWS::AccountId}
              ArnLike:
                aws:SourceArn: !Sub arn:${AWS::Partition}:ssm:*:${AWS::AccountId}:automation-execution/*
      ManagedPolicyArns:
        - !Sub arn:${AWS::Partition}:iam::aws:policy/service-role/AmazonSSMAutomationRole
      Path: /
      Policies:
        - PolicyName: SsmMemMetricIamPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - iam:GetRole
                  - iam:GetInstanceProfile
                  - iam:GetPolicy
                  - iam:AttachRolePolicy
                  - iam:ListInstanceProfiles
                  - ec2:DescribeInstances
                Resource: '*'
  CloudWatchAgentConfigFile:
    Type: AWS::SSM::Parameter
    Properties:
      Name: CloudwatchAgentConfigForMemoryMetricsLinux.json
      Description: Store CloudWatch Agent configuration file as AWS Systems Manager Parameter
      Type: String
      Value: |
        {
            "agent": {
                    "metrics_collection_interval": 60,
                    "run_as_user": "cwagent"
            },
            "metrics": {
                    "append_dimensions": {
                        "InstanceId": "${aws:InstanceId}"
                    },
                    "metrics_collected": {
                    "mem": {
                            "measurement": [\
                                "mem_used_percent"\
                            ],
                            "metrics_collection_interval": 60
                    }
                }
            }
        }
  SystemManagersMemoryMetricsRunbook:
    Type: AWS::SSM::Document
    Properties:
      DocumentFormat: YAML
      DocumentType: Automation
      Name: CloudwatchAgent_Install_Configure_MemoryMetrics_OnEC2Linux
      Content:
        description: Install CloudWatch Agent, Add permissions to target instances and configure CloudWatch agent to publish metrics
        schemaVersion: '0.3'
        assumeRole: !Sub ${SsmAutomationRole.Arn}
        parameters:
          InstanceId:
            type: String
            description: Select instances
        mainSteps:
          - name: Attach_CloudWatchAgent_ServerPolicy_to_instance_role
            action: aws:executeScript
            onFailure: Abort
            isCritical: true
            timeoutSeconds: 600
            description: |
              ## Find the attached role, attach CloudWatchAgentServer managed policy to the role
            inputs:
              Runtime: python3.8
              Handler: attach_cloudwatch_agent_managed_policy
              InputPayload:
                InstanceIds: '{{InstanceId}}'
              Script: |
                import boto3
                ec2_client = boto3.client('ec2')
                iam_client = boto3.client('iam')
                current_session = boto3.session.Session()
                current_region = current_session.region_name
                partition = current_session.get_partition_for_region(current_region)
                cloudwatchagent_policy_arn = f'arn:{partition}:iam::aws:policy/CloudWatchAgentServerPolicy'
                def attach_cloudwatch_agent_managed_policy(event,context):
                  instance_id = event['InstanceIds']
                  response = ec2_client.describe_instances(InstanceIds=[instance_id])
                  iam_role = response['Reservations'][0]['Instances'][0]['IamInstanceProfile']['Arn']
                  role_name=iam_role.split('/')[-1]
                  iam_client.attach_role_policy(RoleName=role_name, PolicyArn=cloudwatchagent_policy_arn)
          - name: Install_cloudWatchAgent_onTargetInstance
            action: aws:runCommand
            onFailure: Abort
            inputs:
              Parameters:
                action:
                  - Install
                installationType:
                  - Uninstall and reinstall
                name:
                  - AmazonCloudWatchAgent
              DocumentName: AWS-ConfigureAWSPackage
              InstanceIds:
                - '{{InstanceId}}'
          - name: Configure_CloudWatchAgen_onTargetInstance
            action: aws:runCommand
            inputs:
              DocumentName: AmazonCloudWatch-ManageAgent
              InstanceIds:
                - '{{InstanceId}}'
              Parameters:
                action: configure
                mode: ec2
                optionalConfigurationSource: ssm
                optionalConfigurationLocation: CloudwatchAgentConfigForMemoryMetricsLinux.json
                optionalRestart: 'yes'
  AutomationIAMRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: Amazon_EventBridge_Invoke_Start_Automation_Execution
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonSSMAutomationRole  # AmazonSSMAutomationRole managed policy
  EventRule:
     Type: AWS::Events::Rule
     Properties:
       EventBusName: default
       EventPattern:
         source:
           - aws.ec2
         detail-type:
           - EC2 Instance State-change Notification
         detail:
           state:
             - running
       Name: cloudwatch-install-configure-rule
       State: ENABLED
       Targets:
         - Id: cloudwatch-ssm-document
           #Arn: >-
            # arn:aws:ssm:us-east-1:XXXXXXXXXXX:automation-definition/CloudwatchAgent_Install_Configure_MemoryMetrics_OnEC2Linux
            #arn:${Partition}:ssm:${Region}:${Account}:document/${DocumentName}
           Arn: !Sub arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/CloudwatchAgent_Install_Configure_MemoryMetrics_OnEC2Linux
           RoleArn: !Sub ${AutomationIAMRole.Arn}
           InputTransformer:
             InputPathsMap:
               instance: $.detail.instance-id
             InputTemplate: '{"InstanceId":[<instance>]}'
           DeadLetterConfig:
             Arn: !Sub ${SQSQueue.Arn}
  SQSQueue:
    Type: AWS::SQS::Queue
    Properties:
      MaximumMessageSize: 262144 #integer value from 1,024 bytes (1 KiB) to 262,144 bytes (256 KiB). The default value is 262,144 (256 KiB).
      MessageRetentionPeriod: 345600 # 4 Days
      QueueName: DLQ-for-event-bridge

Outputs:
  SsmAutomationRoleName:
    Description: Name of the SSM Automation IAM Role
    Value: !Ref SsmAutomationRole
  IAMRoleArn:
    Description: ARN of the created IAM role
    Value: !GetAtt AutomationIAMRole.Arn
  IAMRoleName:
    Description: Name of the created IAM role
    Value: !Ref AutomationIAMRole
  AutomationIAMRoleArn:
    Description: EventBridge Invokation role name to Start Automation Execution
    Value: !GetAtt AutomationIAMRole.Arn
  SQSQueueArn:
    Description: SQS Queue to capture EventBridge execution errors
    Value: SQSQueue.Arn

手順

1. 上記のCloudFormationスタックをCLIまたはコンソールから作成します。

ステップ1

2. デプロイされたSystems Managerオートメーションドキュメントを確認します。このカスタムドキュメントは次の3ステップで構成されています。

  1. 対象インスタンスにアタッチされているロールを特定し、そのインスタンスロールにCloudWatchAgentServerマネージドポリシーをアタッチします。
  2. 対象インスタンスにCloudWatchエージェントをインストールします。
  3. CloudWatchエージェントを設定し、CloudWatchへメトリクスを送信できるようにします。

ステップ2

3. Amazon EventBridgeルールを確認します。

ステップ3

イベントパターン — 以下のイベントパターンで、発生する「running」状態のイベントを抽出します。

Event
{
  "detail-type": ["EC2 Instance State-change Notification"],
  "source": ["aws.ec2"],
  "detail": {
    "state": ["running"]
  }
}

さらに、Input Transformerを使った以下のEventBridgeの入力変換で、対象インスタンスのIDを取り出します。

Input transformer

Input path
 {
   "instance": "$.detail.instance-id"
 }

Input template
 {
   "InstanceId":[<instance>]
 }

4. 新しいインスタンスを作成します。

- テスト用EC2インスタンスには、Systems Managerが通信できるよう、AWS Systems Manager Agent(SSM Agent)をインストールしておく必要があります。加えて、EC2インスタンスからパブリックのSystems Managerサービスエンドポイント、またはSystems Manager向けのAWS PrivateLink VPCエンドポイントへネットワーク接続できる必要があります。(注:本記事ではAmazon Linux 2023 AMIを使い、デフォルトVPCで起動しています)

- AWSマネージドポリシーAmazonSSMManagedInstanceCoreをアタッチしたロールEC2ssmCoreRoleを作成し、Systems ManagerがEC2インスタンスを管理できるようにします。続いてインスタンスプロファイルを作成し、このロールを紐づけます。最後にテスト用インスタンス(t2.micro)を起動します。今回は以下のサンプルCloudFormationテンプレートでテストインスタンスを起動しました。

AWSTemplateFormatVersion: 2010-09-09
Description: CloudFormation template to create EC2 instance with SSM role

Parameters:
  LatestAmiId:
    Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'

Resources:
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: EC2ssmCoreRole
      Description: IAM role to allow Systems Manager to manage the EC2 instance
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref EC2Role
      InstanceProfileName: EC2ssmCoreRole

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref LatestAmiId
      InstanceType: t2.micro
      IamInstanceProfile: !Ref EC2InstanceProfile
      Tags:
        - Key: Name
          Value: "Test-instance"
        - Key: Env
          Value: "test-environment"

Outputs:
  EC2ssmCoreRoleName:
    Description: Name of the SSM Automation IAM Role
    Value: !Ref EC2Role

  EC2ssmCoreRoleArn:
    Description: ARN of the created IAM role
    Value: !GetAtt EC2Role.Arn

  EC2InstanceId:
    Description: Instance Id
    Value: !Ref EC2Instance

5. インスタンスがrunning状態になったタイミングでEventBridgeルールが発火し、Systems Managerがオートメーションを実行してEC2インスタンスにCloudWatchエージェントを導入・設定し、メモリメトリクスが送信されることを確認します。

6. Systems Managerオートメーションの実行状況を確認します — インスタンスがrunning状態になると、ただちにEventBridgeルールが起動し、Systems Managerオートメーションドキュメントが実行されます。

ステップ6

7. オートメーション実行のステータスと進捗を確認します。次の3ステップが実行されます。

- インスタンスロールへのCloudWatch Agent Serverポリシーのアタッチ

- 対象インスタンスへのCloudWatchエージェントのインストール

- Systems Manager Parameter Storeから設定ファイルを取得し、CloudWatchエージェントを設定してカスタムメモリメトリクスを送信

ステップ7

ステップ7

8. CloudWatchエージェントが正しくインストール・設定され、CloudWatchへカスタムメモリメトリクスが送信されていることを確認します。

ステップ8

まとめ — 本記事では、Systems Manager AutomationとAWS EventBridgeを組み合わせることで、新たに作成したEC2インスタンスに対し、手作業を一切挟まずにCloudWatchエージェントの導入・設定とCloudWatchへのカスタムメモリメトリクス送信を完全自動化する方法を紹介しました。