Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Installation et configuration automatisées de l'agent CloudWatch via Systems Manager et EventBridge

By Nikhil PawarMar 28, 20247 min read

Cette page est également disponible en English, Deutsch, Español, Italiano, 日本語 et Português.

Photo de Alexander+Supertramp sur Shutterstock

Dans cet article, nous allons automatiser de bout en bout l'installation et la configuration de l'agent CloudWatch sur une instance EC2 (Linux) afin de collecter des métriques mémoire personnalisées, à l'aide d'un runbook d'automatisation Systems Manager. Nous nous appuierons sur un runbook personnalisé pour installer et configurer l'agent CloudWatch, ainsi que sur AWS EventBridge pour déclencher l'automatisation sans intervention humaine.

Schéma d'architecture

Vue d'ensemble de l'automatisation

Pour cette automatisation, nous utiliserons un template AWS CloudFormation qui déploie les ressources nécessaires en réalisant les étapes suivantes :

  1. Créer un rôle IAM permettant à AWS Systems Manager d'exécuter le document d'automatisation — un rôle d'exécution est nécessaire pour que Systems Manager puisse exécuter le runbook en votre nom sur les instances EC2 cibles, et pour accorder à ces instances les permissions d'écrire des métriques dans CloudWatch.
  2. Téléverser le fichier de configuration de l'agent CloudWatch dans le Parameter Store de Systems Manager — le template CloudFormation se charge de pousser le fichier de configuration personnalisé dans le Parameter Store. Les instances iront ensuite y récupérer ce fichier pour configurer l'agent CloudWatch.
  3. Créer le document d'automatisation Systems Manager — avec CloudFormation, nous construirons un runbook personnalisé pour installer et configurer l'agent CloudWatch.
  4. Créer un rôle IAM pour la règle EventBridge afin qu'elle puisse invoquer l'automatisation Systems Manager — un rôle d'invocation est nécessaire pour qu'EventBridge puisse déclencher le workflow d'automatisation Systems Manager qui installe et configure l'agent CloudWatch.
  5. Créer la règle EventBridge — CloudFormation crée une règle EventBridge qui filtre les événements running des instances EC2 et déclenche l'automatisation SSM.
  6. Optionnel (créer une SQS Dead Letter Queue) — il s'agit d'une file SQS standard qui sert de Dead Letter Queue pour la règle EventBridge, afin de capturer les détails des erreurs survenues lors des déclenchements EventBridge.

Template 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

Étapes :

1. Créez la stack CloudFormation ci-dessus via la CLI ou la console :

Étape 1

2. Vérifiez le document d'automatisation Systems Manager déployé. Ce document personnalisé comporte 3 étapes :

  1. Identifier le rôle attaché à l'instance cible et y associer la managed policy CloudWatchAgentServer.
  2. Installer l'agent CloudWatch sur l'instance cible.
  3. Configurer l'agent CloudWatch pour qu'il publie ses métriques vers CloudWatch.

Étape 2

3. Vérifiez la règle Amazon EventBridge :

Étape 3

Event Pattern — le pattern d'événement ci-dessous filtre les événements de statut running à mesure qu'ils se produisent.

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

Quant à la transformation d'entrée EventBridge, elle s'appuie sur l'Input Transformer ci-dessous pour récupérer l'ID de l'instance cible.

Input transformer

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

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

4. Créez une nouvelle instance :

- l'instance EC2 de test doit disposer de l'AWS Systems Manager Agent (SSM Agent) pour pouvoir communiquer avec Systems Manager. Les instances EC2 doivent par ailleurs avoir une connectivité réseau vers les endpoints publics de Systems Manager ou vers les endpoints VPC AWS PrivateLink pour Systems Manager. (Note : j'ai utilisé l'AMI Amazon Linux 2023, lancée dans le VPC par défaut.)

- créez un rôle EC2ssmCoreRole avec la managed policy AWS AmazonSSMManagedInstanceCore pour permettre à Systems Manager de gérer l'instance EC2. Créez ensuite un instance profile et associez-y le rôle. Pour finir, lancez une instance de test (t2.micro). J'ai utilisé l'exemple de template CloudFormation ci-dessous pour la lancer.

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. Vérifiez que la règle EventBridge a bien été déclenchée au passage de l'instance à l'état running, et que Systems Manager a exécuté l'automatisation pour installer et configurer l'agent CloudWatch sur l'instance EC2 afin de publier les métriques mémoire.

6. Contrôlez l'exécution de l'automatisation Systems Manager — dès que l'instance passe à l'état running, la règle EventBridge déclenche l'exécution du document d'automatisation Systems Manager.

Étape 6

7. Suivez le statut et la progression de l'exécution — l'automatisation enchaîne 3 étapes :

- attacher la policy CloudWatch Agent Server au rôle de l'instance ;

- installer l'agent CloudWatch sur l'instance cible ;

- configurer l'agent CloudWatch en récupérant le fichier de configuration depuis le Parameter Store de Systems Manager afin de publier des métriques mémoire personnalisées.

Étape 7

Étape 7

8. Vérifiez que l'agent CloudWatch est bien installé et configuré pour publier des métriques mémoire personnalisées dans CloudWatch.

Étape 8

Conclusion — pour conclure, nous avons vu comment automatiser de bout en bout l'installation et la configuration de l'agent CloudWatch et publier des métriques mémoire personnalisées dans CloudWatch grâce à Systems Manager Automation et AWS EventBridge, sans aucune étape manuelle pour les nouvelles instances EC2.