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

Sponsored

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., CPUUtilization at 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, or INSUFFICIENT_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:

  1. Choose a metric — Decide what to monitor. Start with CPUUtilization and StatusCheckFailed (these cover the most common failures).
  2. Define the alarm conditions — Pick a threshold, evaluation period, and number of datapoints that must breach the threshold before the alarm triggers.
  3. Configure an action — Protect yourself by connecting the alarm to an SNS topic (for email/SMS) or a Lambda function (for auto-remediation).
  4. Set the alarm state — Once created, the alarm transitions between OK, ALARM, and INSUFFICIENT_DATA based on incoming metric data.
  5. 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

  1. Open the EC2 console and select your instance.
  2. 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-topics and aws sns get-topic-attributes to 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 basic monitoring 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 3 instead 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:DescribeAlarms and ec2:RebootInstances permissions. 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

  1. Use CloudWatch anomaly detection to automatically learn your normal CPU baseline and alert on unusual deviations.
  2. Use a Lambda function as the alarm action to automatically reboot or stop an unhealthy instance instead of just sending an email.
  3. 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_System metric 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.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.