Full CloudWatch Monitoring for EC2

Set up a live monitoring stack with dashboards and email alerts for EC2.

Introduction

30 Second Summary

Imagine your server silently running out of memory at 2 AM. Without monitoring, you find out from frustrated users the next morning instead of from an automated alert that lets you fix it before anyone notices.

In this project, you will set up a production-grade monitoring stack for an EC2 instance using Amazon CloudWatch. You'll install a CloudWatch Agent to collect OS-level metrics, build a real-time dashboard, and create alarms that email you when something goes wrong.

What You'll Build

When you finish, you'll stress-test your instance and watch a CloudWatch alarm fire, delivering an email alert to your inbox while your monitoring dashboard displays the CPU spike in real time.

By the end of this project, you'll have:

  • A live monitoring dashboard where you can see CPU, memory, disk, and network health for your instance at a glance.
  • Automated email alerts that notify you the moment CPU spikes above 80% or disk fills past 90%.
  • Custom OS-level metrics flowing into CloudWatch that AWS does not collect by default, giving you full visibility into memory and disk usage.
  • Secret Mission: Query your metrics and create alarms from the command line using the AWS CLI.

Are there any prerequisites?

You'll need an AWS account (free tier eligible). Everything else happens in the AWS Console and a browser-based terminal, so there's nothing to install on your local machine.

Before We Start

Before We Start...

Before we dive in, let's lock in what you're about to build and why it matters. Understanding the goal upfront helps you connect each step to the bigger picture of production monitoring.

Launch an EC2 Instance with Monitoring Permissions

To monitor an EC2 instance with CloudWatch, the instance needs permission to send metric data to AWS on your behalf. Without the right permissions attached, the CloudWatch Agent will silently fail to send data.

In this step, you'll create an IAM role that grants those permissions, launch an EC2 instance with the role attached, and connect to it using a browser-based terminal.

In this step, get ready to:
  • Create an IAM role with the CloudWatchAgentServerPolicy attached.
  • Launch a t2.micro EC2 instance with the role and correct security group.
  • Connect to the instance via EC2 Instance Connect.
Create an IAM role for CloudWatch

An IAM role lets an AWS service act with specific permissions without needing long-term credentials. Your EC2 instance will assume this role so the CloudWatch Agent can publish metrics on your behalf.

  • In the AWS Console search bar at the top, type IAM and select the IAM service.
  • In the left navigation pane, click Roles.
  • Click Create role.
  • For Trusted entity type, select AWS service.
  • Under Use case, choose EC2.
  • Click Next.
  • In the search box on the Add permissions page, type CloudWatchAgentServerPolicy.
  • Select the checkbox next to CloudWatchAgentServerPolicy.
  • Click Next.
  • For Role name, enter EC2-CloudWatch-Role.
  • Click Create role.

You should see a green success banner at the top of the page confirming the role was created.

What is CloudWatchAgentServerPolicy?

This is an AWS-managed policy that grants the CloudWatch Agent permission to publish metrics and logs to CloudWatch. By attaching it to a role your EC2 instance assumes, the agent running inside the instance can send data without needing API keys stored on the machine.

Don't see the policy in the search results?

Make sure you typed the full name CloudWatchAgentServerPolicy with no spaces. The search is case-sensitive. If nothing shows, clear the search box, press Enter, then try again.

Still stuck? Help me find the CloudWatchAgentServerPolicy in IAM.

Launch a t2.micro EC2 instance

Now you'll launch an instance using the Amazon Linux 2023 AMI and attach the IAM role you just created. You'll also configure a security group that allows browser-based terminal access through EC2 Instance Connect.

  • In the AWS Console search bar, type EC2 and select the EC2 service.
  • Click Launch instance.
  • For Name, enter CloudWatch-Demo.
  • Under Application and OS Images, confirm Amazon Linux 2023 AMI is selected (it is the default).
  • Under Instance type, confirm t2.micro is selected (free tier eligible).
  • Under Key pair (login), select Proceed without a key pair (Not recommended) from the dropdown.

Why no key pair?

EC2 Instance Connect pushes a temporary SSH key to the instance metadata each time you connect through the browser. This means you don't need to manage a .pem file on your local machine.

Next, configure the security group to allow EC2 Instance Connect to reach your instance.

  • Under Network settings, click Edit.
  • For Security group name, enter EC2-Instance-Connect-SG.
  • Under Inbound security groups rules, confirm the first rule has Type set to SSH.
  • Change the Source type dropdown to Custom.
  • In the search field next to the source, type ec2-instance-connect.
  • Select the prefix list that appears in the dropdown. It will be named with your region, such as com.amazonaws.us-east-1.ec2-instance-connect.

What is a prefix list?

A prefix list is a collection of IP address ranges managed by AWS. By selecting the EC2 Instance Connect prefix list, you allow only the AWS-managed IP addresses used by EC2 Instance Connect to reach your instance on port 22.

This is more secure than opening SSH to the entire internet (0.0.0.0/0).

  • Scroll down and expand the Advanced details section.
  • For IAM instance profile, select EC2-CloudWatch-Role from the dropdown.
  • Click Launch instance.

You should see a success message with your new instance ID. Click View all instances to return to the Instances dashboard.

Instance not launching?

If you get an error about instance limits, your account may have reached the maximum number of running instances in this region. Try a different region or terminate unused instances.

If the IAM role does not appear in the dropdown, go back to the IAM console and confirm you created the role with the EC2 use case (not a generic role).

Need more help? Help me troubleshoot my EC2 instance launch.

Connect to your instance with EC2 Instance Connect
  • Wait for the Instance state column to show Running (refresh the page if needed).
  • Select the checkbox next to your instance.
  • Click the Connect button near the top of the page.
  • On the Connect page, select the EC2 Instance Connect tab.
  • Leave the username as ec2-user (the default for Amazon Linux 2023).
  • Click Connect.

A new browser tab opens with a terminal. You should see a prompt ending in $ as ec2-user.

Connection failing or timing out?

Double-check that your security group's inbound rule uses the EC2 Instance Connect prefix list as the source, not your personal IP or 0.0.0.0/0. The prefix list is required for browser-based connections.

Also confirm the instance has a public IPv4 address. Instances in the default VPC get one automatically, but custom VPCs may not.

Still stuck? Help me connect to my EC2 instance using EC2 Instance Connect.

Now verify that your IAM role is correctly attached to the instance.

What do you expect to see when you check the instance's IAM role in the EC2 console?

  • Go back to the EC2 Instances page and select your instance.
  • In the details pane at the bottom, click the Security tab.
  • Find the IAM Role field and click the EC2-CloudWatch-Role link.

This opens the IAM role summary. Under Permissions policies, you should see CloudWatchAgentServerPolicy listed. This confirms the instance has everything it needs to send metrics to CloudWatch.

Your instance is live and has permission to talk to CloudWatch. Next up, you'll explore what CloudWatch already monitors by default and discover a critical gap.

Explore Default Monitoring and Discover the Gap

Your EC2 instance is running and you're connected via the browser terminal. Before installing any monitoring tools, let's see what AWS already provides out of the box.

CloudWatch automatically collects metrics from every EC2 instance at 5-minute intervals. Let's explore what's available and whether it covers everything you'd need to monitor an instance in production.

In this step, get ready to:
  • Explore the default EC2 metrics in the CloudWatch console.
  • Search for memory and disk metrics and discover they're missing.
  • Run OS-level commands to confirm the data exists but CloudWatch can't see it.
Find your instance's default metrics

Every EC2 instance automatically reports a handful of metrics to CloudWatch. Let's see exactly which ones are available for your instance.

  • Switch to the browser tab with the AWS Management Console.
  • In the search bar at the top, type CloudWatch and select the CloudWatch service.
  • In the left navigation pane, click Metrics, then All metrics.
  • In the Browse tab, click the AWS/EC2 namespace.
  • Click Per-Instance Metrics.
  • Find your instance in the list. You should see metrics including CPUUtilization, NetworkIn, and NetworkOut.
  • Select the checkbox next to CPUUtilization to graph it. You should see a line chart appear at the top of the page with at least one data point.

What are these metrics?

These default metrics come from the hypervisor that manages your instance. AWS can measure CPU usage, network traffic, and disk I/O at the hypervisor level without needing anything installed inside the instance.

EC2 basic monitoring reports these metrics at 5-minute intervals at no extra charge.

Don't see any metrics yet?

EC2 basic monitoring reports at 5-minute intervals. If your instance was launched less than 5 minutes ago, wait a few minutes and refresh the page. Your first data point should appear shortly.

Also confirm you're looking at the correct AWS Region in the top-right corner of the console. It should match the region where you launched your instance.

help me find my EC2 instance metrics in CloudWatch

Search for memory and disk metrics

You can see CPU and network data. But what about memory usage and disk space? These are critical for monitoring an instance in production. Let's search for them.

  • Clear any existing search in the Browse tab by clicking the X next to any active filters or navigating back to All metrics.
  • In the search field, type mem and press Enter.

Before you look at the results, what do you expect to find? Do you think CloudWatch tracks how much memory your instance is using?

You'll see zero results. No memory metrics exist anywhere in CloudWatch for your instance.

  • Clear the search field, type disk, and press Enter.

Again, zero results. CloudWatch has no disk usage metrics for your instance either.

Why are memory and disk missing?

EC2's built-in monitoring only covers hypervisor-level metrics. The hypervisor can see CPU cycles and network packets flowing, but it cannot look inside the operating system to measure how much RAM is in use or how full the disk is.

This is the monitoring gap. Memory and disk are two of the most important things to watch on a production server, and CloudWatch simply cannot see them without help from inside the instance.

Confirm the data exists at the OS level

Your instance clearly has memory and disk. The operating system knows exactly how much of each is in use. Let's prove it.

  • Switch back to your EC2 Instance Connect browser terminal.
  • Check your instance's memory usage by running this command:
free -m

You should see a table showing total memory, used memory, free memory, and other values, all reported in megabytes.

  • Check your instance's disk usage by running this command:
df -h

You should see a table listing each filesystem, its size, how much is used, and the percentage full.

What does this prove?

Your instance has detailed memory and disk data available right now. The operating system tracks it continuously. CloudWatch just can't access it because nothing inside the instance is sending that data up to AWS.

The CloudWatch Agent bridges this gap. It runs inside your instance, reads OS-level metrics like memory and disk, and publishes them to CloudWatch on your behalf. That's what you'll install in the next step.

You've confirmed the gap. CloudWatch gives you CPU and network metrics for free, but memory and disk are invisible. In the next step, you'll install the CloudWatch Agent to fill this gap and start reporting the OS-level data that production monitoring demands.

Install and Configure the CloudWatch Agent

In the previous step, you discovered that CloudWatch cannot see your instance's memory or disk usage. The data exists inside your operating system, but AWS has no way to reach it from the outside.

The CloudWatch Agent solves this. It runs inside your instance, reads OS-level metrics like memory consumption and disk space, and publishes them directly to CloudWatch. In this step, you will install the agent, configure exactly which metrics it collects, and start it up.

In this step, get ready to:
  • Install the CloudWatch Agent package on your instance.
  • Create a JSON configuration file specifying CPU, memory, disk, and swap metrics.
  • Start the agent and confirm custom metrics appear in CloudWatch.
Install the CloudWatch Agent package

The CloudWatch Agent is available as a package in Amazon Linux 2023 repositories. A single yum command installs it.

  • In your EC2 Instance Connect terminal, install the agent by running this command:
sudo yum install amazon-cloudwatch-agent -y

What does this command do?

This downloads and installs the CloudWatch Agent binary to /opt/aws/amazon-cloudwatch-agent/ on your instance. The -y flag automatically confirms the installation so you do not have to type yes.

  • Wait for the command to finish. You should see Complete! at the end of the output.

Not seeing Complete?

If you see a permissions error, make sure you included sudo at the start of the command. The agent must be installed as root.

If you see a network timeout, your instance may not have internet access. Confirm your instance is in a public subnet with an internet gateway attached.

Help me troubleshoot my CloudWatch Agent installation

Create the agent configuration file

The agent needs a JSON configuration file that tells it which metrics to collect. You will configure it to gather CPU, memory, disk, and swap metrics at 60-second intervals.

  • Create the configuration file by running this command:
sudo tee /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json > /dev/null << 'EOF'
{
  "metrics": {
    "metrics_collected": {
      "cpu": {
        "totalcpu": true,
        "measurement": ["usage_idle", "usage_iowait", "usage_user", "usage_system"]
      },
      "mem": {
        "measurement": ["used_percent"]
      },
      "disk": {
        "measurement": ["used_percent"],
        "resources": ["/"]
      },
      "swap": {
        "measurement": ["used_percent"]
      }
    },
    "metrics_collection_interval": 60,
    "append_dimensions": {
      "InstanceId": "${aws:InstanceId}"
    }
  }
}
EOF

What does this configuration do?

  • cpu collects four CPU metrics (idle, iowait, user, system) with totalcpu: true so it reports a combined total rather than per-core values.
  • mem collects used_percent so you can see what percentage of RAM is in use.
  • disk collects used_percent for only the root partition (/). Limiting to one partition keeps your metric count within the free tier.
  • swap tracks swap memory usage as a percentage.
  • metrics_collection_interval: 60 sets a 60-second polling interval.
  • append_dimensions tags every metric with your instance's ID so CloudWatch can identify which instance the data came from.
  • Verify the file was created correctly by running:
cat /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
  • You should see the full JSON configuration printed in your terminal, matching the content from the command above.

Seeing "No such file or directory"?

This means the tee command did not run successfully. Make sure you copied the entire command including the EOF at the end. The heredoc syntax requires EOF on its own line with no spaces before it.

Help me fix my CloudWatch Agent config file creation

✔️ Awesome, I've got everything!

Great. Make sure the JSON output from cat matches the config you pasted. If it does, you are ready to start the agent.

ⓧ I'd like to double check the full code

The file at /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json should contain exactly this:

{
  "metrics": {
    "metrics_collected": {
      "cpu": {
        "totalcpu": true,
        "measurement": ["usage_idle", "usage_iowait", "usage_user", "usage_system"]
      },
      "mem": {
        "measurement": ["used_percent"]
      },
      "disk": {
        "measurement": ["used_percent"],
        "resources": ["/"]
      },
      "swap": {
        "measurement": ["used_percent"]
      }
    },
    "metrics_collection_interval": 60,
    "append_dimensions": {
      "InstanceId": "${aws:InstanceId}"
    }
  }
}
Start the agent and verify metrics appear

With the configuration file in place, you can now start the agent. It will immediately begin collecting metrics and publishing them to CloudWatch under the CWAgent namespace.

  • Start the CloudWatch Agent by running this command:
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

What does this command do?

  • -a fetch-config tells the agent to load the configuration file you just created.
  • -m ec2 tells the agent it is running on an EC2 instance (not an on-premises server).
  • -s starts the agent after loading the configuration.
  • -c file:... points to the local configuration file path.

Before you check the agent's status, what do you expect the output to tell you? Think about whether the agent should be running or stopped at this point.

  • Check the agent status by running:
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status

You should see a JSON response containing "status": "running". This confirms the agent is actively collecting and publishing metrics.

Status showing "stopped"?

If the agent is not running, it usually means there is a problem with the configuration file. Check for JSON syntax errors by running:

cat /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log | tail -20

Look for error messages mentioning invalid JSON or missing fields. The most common cause is a missing comma or bracket in the configuration file. Delete the file, re-run the tee command from the previous substep, and start the agent again.

Help me troubleshoot my CloudWatch Agent not starting

  • Wait 2-3 minutes for the agent to publish its first batch of metrics.
  • In the AWS Console, navigate to CloudWatch by searching for it in the top search bar.
  • In the left sidebar, click All metrics under Metrics.
  • Look for a new namespace called CWAgent in the list of namespaces.
  • Click CWAgent, then click the dimension grouping that appears (such as InstanceId).
  • Confirm you can see mem_used_percent listed among the available metrics.

Why a new namespace?

The default EC2 metrics you saw earlier live in the AWS/EC2 namespace. Metrics collected by the CloudWatch Agent are published to the CWAgent namespace by default. This keeps custom metrics separate from the built-in hypervisor metrics.

Not seeing the CWAgent namespace?

It can take up to 5 minutes for the first data points to appear. Refresh the metrics page and check again.

If the namespace still does not appear, make sure your instance's IAM role (EC2-CloudWatch-Role) has the CloudWatchAgentServerPolicy policy attached. Without this permission, the agent runs but silently fails to publish data.

Help me find my CWAgent metrics in CloudWatch

Your instance is now reporting OS-level metrics to CloudWatch. Next up, you will build a dashboard that brings all these metrics together into a single monitoring view.

Build a Monitoring Dashboard

Your CloudWatch Agent is now streaming CPU, memory, disk, and swap metrics into the CWAgent namespace every 60 seconds. The data exists, but finding it means clicking through namespace lists and hunting for individual metric names.

A CloudWatch dashboard solves this by grouping your most important metrics into a single-pane view. In this step, you will build a four-widget dashboard that shows CPU, memory, disk, and network health at a glance.

In this step, get ready to:
  • Create a CloudWatch dashboard and add a CPU usage widget.
  • Add memory, disk, and network widgets to complete the view.
  • Arrange all four widgets in a 2x2 grid and confirm live data is flowing.
Create the dashboard and add a CPU widget

You will start with a fresh dashboard and immediately add a widget that graphs your instance's CPU usage over time.

  • In the AWS Console, navigate to the CloudWatch service.
  • In the left navigation pane, choose Dashboards.
  • Click Create dashboard.
  • Enter EC2-Health as the dashboard name, then click Create dashboard.
  • In the Add to this dashboard dialog that appears, select Line, then click Next.
  • In the Browse tab, select the CWAgent namespace.
  • Select Per-Instance Metrics (or the dimension that includes your instance ID).
  • Check the boxes for cpu_usage_user and cpu_usage_system for your instance.
  • Click Create widget.

You should see a line chart appear on your dashboard showing two CPU metric lines. If your instance has been running for a few minutes, you will see data points already plotted.

What are these CPU metrics?

The cpu_usage_user metric shows how much CPU time is spent running your applications. The cpu_usage_system metric shows CPU time spent on operating system tasks (kernel processes, I/O handling).

Together, they tell you whether your instance is under load and where that load is coming from.

Don't see CWAgent in the namespace list?

The CWAgent namespace only appears after the agent has successfully published at least one data point. If you just started the agent, wait 2-3 minutes and refresh the page.

Also confirm the agent is still running by switching to your Instance Connect terminal and running sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status.

Help me troubleshoot why CWAgent metrics are not appearing in CloudWatch

Add memory, disk, and network widgets

Your CPU widget is live. Now you will add three more widgets to cover the remaining health indicators.

  • On your dashboard, click the + symbol to add a new widget.
  • Select Line, then click Next.
  • In the Browse tab, select CWAgent > your instance dimension.
  • Check the box for mem_used_percent and click Create widget.

A second line chart now shows your memory usage as a percentage. On a fresh t2.micro, expect to see values around 20-30%.

  • Click the + symbol again to add another widget.
  • Select Line, then click Next.
  • In the Browse tab, select CWAgent > your instance dimension.
  • Check the box for disk_used_percent and click Create widget.

Your third widget now shows disk utilization for the root partition. This metric is critical for catching runaway log files or unexpected storage consumption.

  • Click the + symbol one more time for the final widget.
  • Select Line, then click Next.
  • This time, in the Browse tab, select the AWS/EC2 namespace (not CWAgent).
  • Select Per-Instance Metrics, then check the boxes for NetworkIn and NetworkOut for your instance.
  • Click Create widget.

You now have four widgets on your dashboard covering CPU, memory, disk, and network.

Why is network in AWS/EC2 instead of CWAgent?

Network metrics like NetworkIn and NetworkOut are measured at the hypervisor level by AWS, so they appear in the default AWS/EC2 namespace automatically. The CloudWatch Agent only reports OS-level metrics that AWS cannot see from outside the instance.

Arrange the widgets and save your dashboard

With all four widgets added, you will arrange them into a clean 2x2 grid so CPU and memory sit on top, with disk and network below.

  • Drag the widgets by their title bars to arrange them in a 2x2 grid: CPU (top-left), Memory (top-right), Disk (bottom-left), Network (bottom-right).
  • Resize any widget that looks too narrow by dragging its bottom-right corner until all four are roughly equal size.
  • Click Save dashboard in the top-right area of the page.

Before you check the final result, what do you expect to see across the four widgets? Think about which ones should show activity and which should be nearly flat.

Look at your saved dashboard. You should see four widgets updating with live data: the CPU lines near the bottom (low usage on an idle instance), memory around 20-30%, disk showing a steady percentage, and network showing small spikes from your SSH session.

What does a healthy idle instance look like?

On a t2.micro with no application running, CPU stays below 5%, memory hovers around 20-30%, disk stays constant, and network shows tiny blips from your Instance Connect session. If any metric looks wildly different, that is a signal worth investigating.

Widgets show 'No data available'?

If a widget shows no data, confirm you selected the correct instance ID when browsing metrics. Each metric is associated with a specific instance dimension.

For the network widget specifically, make sure you selected AWS/EC2 as the namespace, not CWAgent. Network metrics live in the default EC2 namespace.

My CloudWatch dashboard widgets aren't showing data. Help me troubleshoot.

Your monitoring dashboard is live. You now have a single view that shows your instance's health across four key dimensions. Next up, you will create alarms that proactively notify you when something goes wrong, so you do not have to watch this dashboard 24/7.

Create Alarms with Email Notifications

Your dashboard gives you a real-time view of your instance's health. But it only helps if someone is staring at it the moment something goes wrong.

Alarms solve this by watching your metrics around the clock and proactively notifying you when a threshold is breached. This is the difference between reactive and proactive ops. In this step, you'll wire up CloudWatch alarms to an SNS email notification so your inbox lights up the moment CPU spikes or disk fills up.

In this step, get ready to:
  • Create an SNS topic and subscribe your email address.
  • Create two CloudWatch alarms (CPU and disk) that notify your topic.
  • Trigger the CPU alarm with a stress test and receive an email notification.
Create an SNS topic and email subscription

Before an alarm can notify you, it needs a delivery channel. That channel is an SNS topic, which acts as a mailing list that forwards messages to all its subscribers.

  • In the AWS Management Console, type SNS in the top search bar and select Simple Notification Service.
  • In the left navigation pane, click Topics.
  • Click Create topic.
  • For Type, select Standard.
  • For Name, enter EC2-Monitoring-Alerts.
  • Scroll down and click Create topic.

You should see your new topic's detail page with its ARN displayed. Now add your email as a subscriber.

  • On the topic detail page, click Create subscription.
  • For Protocol, select Email.
  • For Endpoint, enter an email address you can access right now.
  • Click Create subscription.

You must confirm the subscription

Check your email inbox for a message from "AWS Notifications". Open it and click Confirm subscription. Until you confirm, no alerts will be delivered. Check your spam folder if you do not see it within a minute.

  • After confirming, return to the SNS console and refresh the Subscriptions page. Your subscription's Status column should now show Confirmed.

What is SNS?

Amazon Simple Notification Service (SNS) is a pub/sub messaging service. You publish a message to a topic, and SNS fans it out to every subscriber (email, SMS, Lambda, HTTP, etc.). CloudWatch alarms use SNS as their delivery mechanism for notifications.

Create CloudWatch alarms for CPU and disk

With your notification channel ready, you can now create alarms that watch your CWAgent metrics and fire when thresholds are breached.

  • Navigate to the CloudWatch console by typing CloudWatch in the top search bar.
  • In the left navigation pane, click Alarms, then All alarms.
  • Click Create alarm.
  • Click Select metric.
  • Under Custom namespaces, click CWAgent.
  • Click the dimension group that shows your instance ID (for example InstanceId).
  • Find and select the checkbox next to cpu_usage_user.
  • Click Select metric.

You are now on the Specify metric and conditions page. Configure the alarm threshold here.

  • Under Period, select 1 minute.
  • Under Conditions, choose Greater than.
  • For the threshold value, enter 80.
  • Expand Additional configuration. For Datapoints to alarm, set both values to 1 out of 1.
  • Click Next.

Now connect the alarm to your SNS topic.

  • Under Notification, ensure In alarm is selected as the trigger state.
  • For Select an SNS topic, choose Select an existing SNS topic.
  • Select EC2-Monitoring-Alerts from the dropdown.
  • Click Next.
  • For Alarm name, enter CPU-High.
  • Click Next.
  • Review the alarm summary under Preview and create, then click Create alarm.

You should see your new CPU-High alarm in the list with a state of OK (it may briefly show Insufficient data until the first evaluation period completes). Now create the second alarm for disk.

  • Click Create alarm again.
  • Click Select metric, navigate to CWAgent namespace, then your instance dimension.
  • Select the checkbox next to disk_used_percent and click Select metric.
  • Set Period to 1 minute.
  • Under Conditions, choose Greater than, and enter 90 as the threshold.
  • Expand Additional configuration and set Datapoints to alarm to 1 out of 1.
  • Click Next.
  • Under Notification, select EC2-Monitoring-Alerts as your SNS topic.
  • Click Next.
  • For Alarm name, enter Disk-High.
  • Click Next, then click Create alarm.

You should now see both CPU-High and Disk-High listed in your alarms, both in OK state.

Why two separate alarms?

Each alarm watches a single metric against a single threshold. CPU spikes and disk filling up are different failure modes with different causes and different responses. Separate alarms let you diagnose at a glance which specific resource is under pressure.

Don't see your CWAgent metrics when selecting?

Make sure you are browsing the CWAgent namespace under Custom namespaces, not the AWS/EC2 namespace. If CWAgent does not appear at all, the agent may have stopped. Return to your EC2 Instance Connect terminal and check the agent status.

Help me find my CWAgent metrics in CloudWatch

Trigger the CPU alarm with a stress test

Your alarms are watching, but they are in the calm OK state because nothing is wrong yet. Time to simulate a CPU spike and prove the entire notification chain works end to end.

  • Switch back to your EC2 Instance Connect browser terminal.

Before you run the next command, make a prediction: do you expect the CPU-High alarm to fire immediately, or will there be a delay? Why?

  • Install the stress utility and run a 2-minute CPU stress test by running this command:
sudo yum install stress -y && stress --cpu 1 --timeout 120

What does this command do?

The stress tool artificially saturates one CPU core for 120 seconds. This pushes cpu_usage_user well above the 80% threshold you configured. After the stress test finishes, CPU returns to normal.

Because your alarm evaluates every 1 minute with 1 datapoint required, CloudWatch needs at least one full 1-minute period where CPU exceeds 80% before it transitions to In alarm. This means you will see the alarm fire within about 1-2 minutes of starting the stress test.

  • While the stress test runs, return to the CloudWatch console and navigate to Alarms, then All alarms.
  • Refresh the page every 30 seconds or so. Within 1-2 minutes, CPU-High should transition from OK to In alarm (shown in red).
  • Check your email inbox. You should receive a notification from "AWS Notifications" with the subject line containing your alarm name.

What should I see?

In the CloudWatch Alarms console, your CPU-High alarm displays a red In alarm badge. Your Disk-High alarm stays green in OK state (disk usage is well below 90%). In your email, you receive a message detailing the alarm name, region, metric, and threshold that was breached.

Not seeing the alarm fire?

If the alarm stays in Insufficient data, wait a full 2-3 minutes. The agent collects data every 60 seconds, and the alarm needs one full period to evaluate.

If you confirmed the subscription but got no email, check your spam or junk folder. Also confirm the subscription status shows Confirmed in the SNS console.

Help me troubleshoot my CloudWatch alarm not firing

You now have a complete monitoring stack: metrics flowing from your instance, a dashboard for visual health checks, and alarms that email you the moment something goes wrong. Next up, you will extend this setup with a bonus challenge from the command line.

Secret mission

Go CLI

In production, you won't always click through the AWS console. In this secret mission, you'll install the AWS CLI on your Windows machine and use it to query your metrics and create a brand-new alarm entirely from the command line.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project uses AWS free tier resources, so there are no ongoing costs as long as your EC2 instance stays within the 750 hours/month t2.micro allowance during your first 12 months.

Cost warning

If your AWS free tier period has expired, a running t2.micro instance costs approximately $0.0116/hour (US East). Terminate the instance when you are done to avoid charges.

Resources you used:

  • 1 x t2.micro EC2 instance (free tier eligible, accumulates hours while running).
  • 1 x IAM role (EC2-CloudWatch-Role) with CloudWatchAgentServerPolicy attached.
  • 1 x CloudWatch dashboard (EC2-Health).
  • 3 x CloudWatch alarms (CPU-High, Disk-High, Memory-High).
  • 1 x SNS topic (EC2-Monitoring-Alerts) with email subscription.
  • AWS CLI v2 installed on your local Windows machine.

Keep everything running

No action needed. Choose this if you are still actively building or experimenting with CloudWatch monitoring.

  • Your t2.micro instance continues running at no cost while you remain within the free tier (first 12 months, 750 hours/month of t2.micro).
  • Your CloudWatch dashboard, alarms, and custom metrics persist at no cost within free tier limits (3 dashboards, 10 alarm metrics, 10 custom metrics).
  • The AWS CLI remains installed on your local machine. You can continue using it for other AWS projects.

Pause - I'll come back to this later

Stop the instance to eliminate compute charges while keeping your setup intact. The CloudWatch Agent stops collecting metrics while the instance is stopped.

  • In the EC2 console, select your instance, then choose Instance state > Stop instance.
  • Your dashboard, alarms, SNS topic, and IAM role all remain in place at no cost.
  • When you return, select the instance and choose Instance state > Start instance. The CloudWatch Agent resumes automatically.

Delete - I don't want to use this again

Remove all project resources to ensure $0 going forward. Follow each step below.

  • Terminate the EC2 instance: In the EC2 console, select your instance, then choose Instance state > Terminate instance. Confirm the termination.
  • Delete the CloudWatch dashboard: In the CloudWatch console, choose Dashboards in the left navigation pane. Select EC2-Health, then choose Delete. Confirm the deletion.
  • Delete the CloudWatch alarms: In the CloudWatch console, choose Alarms > All alarms. Select CPU-High, Disk-High, and Memory-High. Choose Actions > Delete. Confirm the deletion.
  • Delete the SNS topic: In the SNS console, choose Topics. Select EC2-Monitoring-Alerts, then choose Delete. Type the topic name to confirm.
  • Delete the IAM role: In the IAM console, choose Roles. Search for EC2-CloudWatch-Role. Select it, then choose Delete. Type the role name to confirm.
  • Uninstall the AWS CLI (optional): On your Windows machine, open Programs and Features (search for it in the Start menu or run appwiz.cpl from a command prompt). Select AWS Command Line Interface, then choose Uninstall. Optionally delete the .aws folder at %UserProfile%\.aws to remove stored credentials.

Nice Work!

Nice Work!

You just built a production-grade monitoring stack for an EC2 instance using Amazon CloudWatch. You can now see exactly what is happening inside your instance in real time and get alerted the moment something goes wrong.

You've learned how to:

  • Discovered that EC2's default monitoring misses memory and disk metrics, then filled the gap by installing and configuring the CloudWatch Agent with a custom JSON config file.
  • Built a 4-widget CloudWatch dashboard displaying real-time CPU, memory, disk, and network health for your instance in a single view.
  • Created CloudWatch alarms wired to SNS email notifications, then triggered them with a stress test to prove the entire alerting pipeline works end to end.
  • Secret Mission: Installed the AWS CLI on your local machine and replicated monitoring tasks from the command line, including querying metrics and creating a new alarm programmatically.

Ready to quiz yourself?