Happy Dussehra! May good always win. Happy Diwali! Wishing you a bright year ahead. Merry Christmas! Warm wishes from Vizag. Happy New Year! Here’s to a great year ahead.

Archive ยท AWS

CloudWatch Agent: Memory and Disk Metrics

Install the unified CloudWatch agent on Amazon Linux 2 with the right IAM role, collect memory, disk and swap metrics, store config in SSM, and alarm on them.

3 min read

  • CloudWatch Agent
  • Amazon Linux 2
  • IAM role CloudWatchAgentServerPolicy
  • SSM Parameter Store

By default EC2 reports CPU, network and status checks to CloudWatch, but it cannot see inside the operating system, so there is no memory or disk-space metric. The unified CloudWatch agent runs on the instance and publishes those, plus log files, as custom metrics.

State of AWS on this date. The unified agent (amazon-cloudwatch-agent) replaces the older monitoring scripts and the separate CloudWatch Logs agent. It runs on Linux and Windows. Custom metrics are billed per metric per month, so collect what you will alarm on.

How data gets to CloudWatch

flowchart TB
  CFG[Agent config JSON<br/>in SSM Parameter Store] --> AG
  subgraph EC2[EC2 instance with instance profile]
    AG[amazon-cloudwatch-agent] --> M1[mem and swap from /proc]
    AG --> M2[disk and diskio from filesystems]
    AG --> LG[tail log files]
  end
  ROLE[IAM role CloudWatchAgentServerPolicy] -.->|permissions| AG
  AG -->|PutMetricData| CWM[CloudWatch metrics<br/>namespace CWAgent]
  AG -->|PutLogEvents| CWL[CloudWatch Logs groups]
  CWM --> AL[Alarms on mem and disk above 80%]
  AL --> SNS[SNS topic ops-alerts]

1. Give the instance permission

Create an IAM role for EC2 with the AWS-managed policies CloudWatchAgentServerPolicy (publish metrics and logs) and, if you will pull config from Systems Manager, AmazonSSMManagedInstanceCore. Attach it as the instance profile; no keys are stored on the server.

aws iam create-role --role-name cw-agent-role --assume-role-policy-document file://ec2-trust.json
aws iam attach-role-policy --role-name cw-agent-role --policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
aws iam create-instance-profile --instance-profile-name cw-agent-profile
aws iam add-role-to-instance-profile --instance-profile-name cw-agent-profile --role-name cw-agent-role
aws ec2 associate-iam-instance-profile --instance-id i-0abc123 --iam-instance-profile Name=cw-agent-profile

2. Install and configure

sudo yum install -y amazon-cloudwatch-agent
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard     # optional guided config

A hand-written config, /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json:

{
  "agent": { "metrics_collection_interval": 60, "run_as_user": "cwagent" },
  "metrics": {
    "append_dimensions": { "InstanceId": "${aws:InstanceId}", "AutoScalingGroupName": "${aws:AutoScalingGroupName}" },
    "metrics_collected": {
      "mem":  { "measurement": ["mem_used_percent"] },
      "swap": { "measurement": ["swap_used_percent"] },
      "disk": {
        "measurement": ["used_percent", "inodes_free"],
        "resources": ["/", "/data"],
        "ignore_file_system_types": ["tmpfs", "devtmpfs"]
      }
    }
  },
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          { "file_path": "/var/log/messages", "log_group_name": "web/messages", "log_stream_name": "{instance_id}" }
        ]
      }
    }
  }
}

Start it and check:

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
tail -n 30 /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log
aws cloudwatch list-metrics --namespace CWAgent --query 'Metrics[].MetricName' --output text | tr '\t' '\n' | sort -u

Metrics appear in the CWAgent namespace within a couple of minutes, with dimensions you chose (instance ID, device, filesystem path).

3. Keep one config for many servers

Store the JSON in SSM Parameter Store and have every instance fetch it:

aws ssm put-parameter --name AmazonCloudWatch-linux-web --type String --value file://amazon-cloudwatch-agent.json --overwrite
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:AmazonCloudWatch-linux-web -s

Put the install and fetch commands in your AMI build or user data, and use the Systems Manager State Manager to keep every instance on the same config.

4. Alarms on what the agent reports

aws cloudwatch put-metric-alarm --alarm-name web01-mem-high \
  --namespace CWAgent --metric-name mem_used_percent \
  --dimensions Name=InstanceId,Value=i-0abc123 \
  --statistic Average --period 300 --evaluation-periods 3 --threshold 85 \
  --comparison-operator GreaterThanThreshold --treat-missing-data breaching \
  --alarm-actions arn:aws:sns:ap-south-1:111111111111:ops-alerts

Dimensions must match exactly what the agent publishes, including device, fstype and path for disk metrics; list them with list-metrics and copy. breaching for missing data turns a dead agent or instance into an alert.

Troubleshooting

Symptom Check
No metrics appear Instance profile attached? agent.log shows AccessDenied? Outbound HTTPS to CloudWatch endpoints allowed?
Disk metrics missing The resources path must be a mount point; use "*" for all
Alarm shows no data Dimension mismatch, or the wrong region
High cost Too many custom metrics: restrict resources, intervals and measurements

Remember the agent must also be installed and configured through your build process, or new instances will silently lack monitoring.