Monitor EC2 with CloudWatch Alarms
Learn to monitor EC2 instances using CloudWatch alarms. This AWS tutorial covers setting up alarms for CPU utilization, status checks, and more, with hands-on steps and troubleshooting tips.
Focus: monitor ec2 with cloudwatch alarms
Your EC2 instance is running smoothly — until one morning you wake up to a flood of support tickets from users who couldn't reach your website. The root cause? CPU spiked to 100% at 3 AM, the instance froze, and nobody got notified. This scenario is all too common when you rely on reactive monitoring. In this lesson, you'll learn how to monitor EC2 with CloudWatch alarms so you can catch problems before they become outages. We'll cover the core concepts, walk through a hands-on setup, and give you troubleshooting tips to keep your infrastructure resilient — all practical and immediately applicable.
The problem this lesson solves
Manual monitoring doesn't scale. When you have a handful of instances, you might check CloudWatch metrics dashboard once in a while. But as your fleet grows, so does the chance of missing a critical anomaly. Without automated alerts, you're always one misconfiguration away from an outage that could have been avoided with a simple alarm.
The pain points are real:
- Silent failures: A crashed process or exhausted disk doesn't send you a message.
- Slow incident response: By the time users complain, your instance may have been down for hours.
- Wasted costs: Over-provisioned instances run 24/7 because you never noticed low utilization.
- Sleepless nights: Without alarms, you're constantly refreshing the console, half-expecting trouble.
CloudWatch alarms solve this by continuously monitoring metrics — like CPU utilization, status checks, or disk I/O — and triggering notifications (via SNS, email, or Lambda) when thresholds are breached. This lesson gives you the exact steps to set up a reliable monitoring system for your EC2 instances.
Core concept / mental model
Think of CloudWatch as the central nervous system of your AWS environment. Every EC2 instance sends a stream of signals (metrics) to CloudWatch — like heart rate and blood pressure — at regular intervals. An alarm is like a personal health monitor that watches one signal and alerts you when it goes outside a healthy range.
Key definitions
- Metric: A time-ordered set of data points, e.g.,
CPUUtilizationat 5-minute intervals. - Namespace: A container for metrics, e.g.,
AWS/EC2. - Dimension: A key-value pair that identifies the metric's source, e.g.,
InstanceId=i-1234567890abcdef0. - Alarm state:
OK,ALARM, orINSUFFICIENT_DATA(not enough data to judge). - Threshold: The value that triggers the alarm, e.g., CPU > 80% for 2 consecutive periods.
How alarms fit into monitoring
flowchart LR
A[EC2 Instance] -->|sends metrics every 1-5 min| B[CloudWatch]
B -->|metric data| C[Alarm]
C -->|state change| D[SNS Topic]
D -->|email / SMS / Lambda| E[You / Automation]
Pro tip: Metrics for the EC2 namespace are free — you don't pay extra for the data itself. You only pay for alarms and API requests beyond the free tier.
Why alarms matter
Alarms give you proactive visibility. Instead of stumbling onto a problem, you receive a clear, actionable notification. With CloudWatch alarms, you can automate a response — like triggering an Auto Scaling action or running a Lambda function to stop a zombie process — without human intervention.
How it works step by step
Here's the logical flow of setting up an alarm and reacting to a state change:
- Choose a metric — Decide what to monitor. Start with
CPUUtilizationandStatusCheckFailed(these cover the most common failures). - Define the alarm conditions — Pick a threshold, evaluation period, and number of datapoints that must breach the threshold before the alarm triggers.
- Configure an action — Protect yourself by connecting the alarm to an SNS topic (for email/SMS) or a Lambda function (for auto-remediation).
- Set the alarm state — Once created, the alarm transitions between
OK,ALARM, andINSUFFICIENT_DATAbased on incoming metric data. - Test and verify — Simulate a breach (e.g., run a CPU stress test) to confirm you get notified.
Cause → Effect: If CPU usage exceeds 80% for 5 straight minutes (the condition), the alarm state flips to ALARM, which publishes a message to the SNS topic, which sends an email to your ops team.
Hands-on walkthrough
Let's set up a CloudWatch alarm for a running EC2 instance. We'll do it two ways: via the AWS Console and via the AWS CLI for automation.
Prerequisites
- An AWS account with an EC2 instance running (any Linux or Windows AMI).
- AWS CLI installed and configured (for the CLI method).
Method 1: AWS Console
- Open the EC2 console and select your instance.
- Click the Monitoring tab, then Create alarm.
- Metric:
CPUUtilization - Conditions: threshold > 80%, for 2 consecutive periods of 5 minutes.
3. Click Next and create a new SNS topic (e.g.,
ec2-cpu-alerts), add your email, and confirm the subscription. 4. Review and create the alarm.
Method 2: AWS CLI
First, create an SNS topic and subscribe your email:
# Create the SNS topic
TOPIC_ARN=$(aws sns create-topic --name ec2-cpu-alerts --query 'TopicArn' --output text)
# Subscribe your email (you'll need to confirm via the email link)
aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol email --notification-endpoint you@example.com
# Get your EC2 instance ID (if you don't have it)
INSTANCE_ID=$(aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" --query 'Reservations[0].Instances[0].InstanceId' --output text)
Now create the alarm using put-metric-alarm:
aws cloudwatch put-metric-alarm \
--alarm-name "cpu-high" \
--alarm-description "Alert when CPU > 80% for 10 minutes" \
--metric-name CPUUtilization \
--namespace AWS/EC2 \
--statistic Average \
--period 300 \
--evaluation-periods 2 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--alarm-actions "$TOPIC_ARN" \
--dimensions "Name=InstanceId,Value=$INSTANCE_ID"
This alarm will flip to ALARM if average CPU stays above 80% for two consecutive 5-minute periods.
Test your alarm
To verify the alarm works, deliberately stress the CPU:
# SSH into the instance and run a stress test (install 'stress' if needed)
sudo apt-get install -y stress # Ubuntu/Debian
stress --cpu 4 --timeout 300
After about 10 minutes, the alarm should transition to ALARM and you'll receive an email. If you don't, check the Troubleshooting section below.
Automate remediation with Lambda (advanced)
Instead of just notifying, you can have the alarm trigger a Lambda function to stop or reboot the instance. For example, an AWS Lambda function that reboots an unhealthy instance when a status check fails:
import boto3
import os
def lambda_handler(event, context):
ec2 = boto3.client('ec2')
instance_id = event['detail']['dimensions']['InstanceId']
print(f'Rebooting instance {instance_id} due to alarm trigger')
ec2.reboot_instances(InstanceIds=[instance_id])
return {'statusCode': 200}
Attach this Lambda as the alarm action (instead of SNS), and you have automated self-healing.
Compare options / when to choose what
There are several ways to monitor EC2 — CloudWatch alarms aren't your only choice. Here's a comparison to help you decide:
| Approach | Best for | Pros | Cons |
|---|---|---|---|
| CloudWatch alarms | General-purpose threshold alerts | Native, cheap, integrates with SNS/Lambda | Limited to simple thresholds, no anomaly detection |
| CloudWatch anomaly detection | Baselines that change over time | Automatically adapts to patterns | Extra cost, requires more data |
| AWS CloudTrail | Auditing API calls, not metrics | Security-focused, logs actions | Not suitable for performance monitoring |
| Third-party tools (e.g., Datadog) | Complex monitoring, dozens of metrics | Rich dashboards, advanced alerting | Additional cost, setup overhead |
When to choose which: Start with CloudWatch alarms — they're free (for basic metrics) and simpler. Upgrade to anomaly detection if your workloads have time-based patterns (e.g., high CPU during business hours only). Move to a third-party tool if you need multi-cloud visibility or extremely granular alerting.
Troubleshooting & edge cases
Even with a straightforward setup, things can go wrong. Here are the most common issues and how to fix them:
-
No email received
-
Check your SNS subscription status: the subscription confirmation email must be accepted (the status in SNS should be
Confirmed). -
Ensure the alarm's action points to the correct SNS topic ARN. Use
aws sns list-topicsandaws sns get-topic-attributesto verify. -
Alarm stuck in
INSUFFICIENT_DATA -
This often means CloudWatch hasn't received enough metric data. Wait at least 10 minutes after instance launch. If it persists, confirm the instance is sending metrics (it does by default for
basicmonitoring every 5 minutes; for 1-minute intervals, enable detailed monitoring). -
Alarm triggers too easily (false positives)
-
Lower the evaluation periods or increase the threshold. For example, use
evaluation-periods 3instead of 2, or raise the threshold to 90%. -
Instance doesn't appear in the metric selector
-
Ensure the instance is running — stopped instances won't emit metrics. Also, check you're in the correct region.
-
CLI command fails with
InvalidParameterValue -
Double-check the dimension syntax:
--dimensions "Name=InstanceId,Value=$INSTANCE_ID"(no spaces after commas). -
Alarm action doesn't trigger Lambda
-
Verify the Lambda execution role has
cloudwatch:DescribeAlarmsandec2:RebootInstancespermissions. Also test the Lambda manually with a sample event.
Pro tip: Always set up a test alarm for a non-critical metric (e.g., NetworkOut > 0) to verify your SNS pipeline works before you rely on it in production.
What you learned & what's next
You now understand how to monitor EC2 with CloudWatch alarms end to end. You can:
- Explain the role of CloudWatch metrics, namespaces, and dimensions.
- Create alarms for CPU utilization and status checks via console or CLI.
- Connect alarms to SNS notifications and Lambda-based auto-remediation.
- Troubleshoot common alarm issues like missing emails and
INSUFFICIENT_DATA.
This proactive monitoring gives you peace of mind and faster incident response.
Next lesson: Now that your instances are watched, learn to react automatically by integrating CloudWatch with Auto Scaling — so your app not only alerts on high load, but scales out to handle it. That's the natural next step in the AWS Tutorial path.
Keep practicing: try adding a status check alarm for your instance today, and see how quickly you get notified when you stop it.
Practice recap
To solidify your skills, create a second alarm for StatusCheckFailed_System on the same instance, point it to a separate SNS topic, and then stop the instance manually to watch the alarm fire (and receive the notification). This teaches you how system status checks behave differently from CPU alarms.
Common mistakes
- Putting the alarm and the EC2 instance in different AWS regions — either setup fails or metrics stay INSUFFICIENT_DATA.
- Not confirming the SNS email subscription — the alarm triggers, but you never get notified.
- Setting the threshold too low (e.g., 10% CPU) causing constant false alarms and alert fatigue.
- Using evaluation periods of 1 — a single 5-minute spike triggers an outage response in production.
- Using the wrong dimension syntax in the CLI — missing or incorrect InstanceId causes the alarm to apply to no instance.
Variations
- Use CloudWatch anomaly detection to automatically learn your normal CPU baseline and alert on unusual deviations.
- Use a Lambda function as the alarm action to automatically reboot or stop an unhealthy instance instead of just sending an email.
- For HTTP/TCP endpoint checks, use Route 53 health checks integrated with CloudWatch alarms to monitor from outside AWS.
Real-world use cases
- A web app on a single EC2 instance: alarms on CPU > 80% and status check failure → email to the operations team so they can jump in before customers see downtime.
- A cost-conscious startup: alarm on low CPU utilization (<10% for a week) triggers a Lambda to stop the instance, cutting monthly compute spend.
- A Dev/Test environment: alarm on a
StatusCheckFailed_Systemmetric automatically reboots the instance via Lambda, keeping the test pipeline green.
Key takeaways
- CloudWatch alarms watch a metric (like CPUUtilization) and transition between OK, ALARM, and INSUFFICIENT_DATA based on your threshold.
- You can create alarms via the AWS Console or the CLI — the CLI makes them repeatable and infrastructure-as-code friendly.
- Connect your alarm to an SNS topic or Lambda function to get notified or automatically remediate issues.
- Basic monitoring gives you 5-minute metric intervals; enable detailed monitoring for 1-minute granularity (at an extra cost).
- Troubleshoot efficiently by verifying the SNS subscription, region, and instance state before going deeper.
- Start with CPU and status check alarms — they cover the most common failure modes for EC2 instances.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.