Autoscale based on SQS queue size - amazon-web-services

I have put together these commands to autoscale EC2 instances based on SQS queue size. I have run all commands and my queue is at 10 messages and a single instance hasn't been launched.
I am trying to figure out, what SQS queue my cloudwatch alarms are listening to? Also any help to indentify the issus is appreciated!
### Create Autoscaling Policy ###
aws autoscaling create-launch-configuration --launch-configuration-name my-lc --image-id ami-551c6d30 --instance-type m1.small
aws autoscaling create-auto-scaling-group --auto-scaling-group-name my-asg --launch-configuration-name my-lc --availability-zones "us-east-1a" "us-east-1c" --max-size 10 --min-size 0 --desired-capacity 0
# Scale up policy
aws autoscaling put-scaling-policy --policy-name my-sqs-scaleout-policy --auto-scaling-group-name my-asg --scaling-adjustment 1 --adjustment-type ChangeInCapacity
# Scale down policy
aws autoscaling put-scaling-policy --policy-name my-sqs-scalein-policy --auto-scaling-group-name my-asg --scaling-adjustment -1 --adjustment-type ChangeInCapacity
# Alarm to scale up
aws cloudwatch put-metric-alarm --alarm-name AddCapacityToProcessQueue --metric-name ApproximateNumberOfMessagesVisible --namespace "AWS/SQS" --statistic Average --period 120 --threshold 3 --comparison-operator GreaterThanOrEqualToThreshold --dimensions Name=QueueName,Value=my-queue --evaluation-periods 2 --alarm-actions arn:aws:autoscaling:us-east-1:850082592395:scalingPolicy:6408b62d-9363-4252-a88c-5ffab08a8cb5:autoScalingGroupName/my-asg:policyName/my-sqs-scaleout-policy
# Alarm to scale down
aws cloudwatch put-metric-alarm --alarm-name RemoveCapacityFromProcessQueue --metric-name ApproximateNumberOfMessagesVisible --namespace "AWS/SQS" --statistic Average --period 300 --threshold 1 --comparison-operator LessThanOrEqualToThreshold --dimensions Name=QueueName,Value=my-queue --evaluation-periods 2 --alarm-actions arn:aws:autoscaling:us-east-1:850082592395:scalingPolicy:4771ea64-2ebf-45ef-9328-50e058dc68b7:autoScalingGroupName/my-asg:policyName/my-sqs-scalein-policy
# Verify cloudwatch alarms
aws cloudwatch describe-alarms --alarm-names AddCapacityToProcessQueue RemoveCapacityFromProcessQueue
# Verify scaling policy
aws autoscaling describe-policies --auto-scaling-group-name my-asg
# Verify instances autoscaled
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-name my-asg

The AWS Documentation states that:
Amazon Simple Queue Service sends data to CloudWatch every 5 minutes.
Additionally, you have specified an Average metric over several periods of time. Therefore, it will require several 5-minute periods to send Amazon SQS metrics to Amazon CloudWatch.
It's possible that the metric period (120 seconds) is too short to receive multiple updates from SQS, therefore causing INSUFFICIENT_DATA errors.
Start by trying to get the Alarm to trigger with a Maximum setting and play with the time periods. Once the Alarm is successfully triggering, play with the thresholds to get the desired behaviour.

Related

Differences between AWS CloudWatch alarms created by Console vs. CLI

I Have created simple AWS cloudwatch alarm with console. It is triggered by metric "Cognito-By UserPoolAndUserPoolClient-SignInSuccesses". It works as supposed and sends an email via SNS Topic.
I tried to create same alarm with CLI, but it doesn't work. Alarm doesn't get triggered. I compared in console what is difference between those two alarms. When creating alarm with console in metric selection I see metric with information "UserPool" and "UserPoolClient". When using CLI command there isn't parameters to set those two. How could I configure new alarm with CLI so that it is identical to one created in console?
CLI command:
aws cloudwatch put-metric-alarm --alarm-name NewSignupAlarm --alarm-description "New Signup have been done." --alarm-actions arn:aws:sns:eu-west-3:681278469643:NewTestTopic --metric-name SignUpSuccesses --namespace AWS/Cognito --statistic Sum --period 300 --unit Count --evaluation-periods 1 --threshold 0 --comparison-operator GreaterThanThreshold --profile user3
These values are dimensions on the metric. You can specify them with the --dimensions parameter, like this:
--dimensions Name=UserPool,Value=eu-west-3_... Name=UserPoolClient,Value=117...
Make sure the values are exact, I used ... just to illustrate the usage.
See here for more info on all different parameters that you may need to set if you want the alarm be the same as the one created in the console:
https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/put-metric-alarm.html

Setting CloudWatch Alarm for multiple instances

I'm configuring an alarm for an instance from the Amazon CLI. for example, to trigger a notification when the cpu is idle for 5min. but I want to set this alarm for a lot of Instances.
With this Bash Script I created one alarm for one instance :
aws cloudwatch put-metric-alarm --alarm-name cpu-mon --alarm-description "Alarm when CPU exceeds 70 percent" --metric-name CPUUtilization --namespace AWS/EC2 --statistic Average --period 300 --threshold 70 --comparison-operator GreaterThanThreshold --dimensions "Name=InstanceId,Value=i-12345678" --evaluation-periods 2 --alarm-actions arn:aws:sns:us-east-1:111122223333:MyTopic --unit Percent
So, I don't see how can I use this script to choose another instances, or eventually loop on that script, in order to choose another instances.
If you have a list of instance IDs you want to create alarms for you could do something like:
#!/bin/bash
instances=(instanceId1 instanceId2 etc)
for i in "${instances[#]}"; do
aws cloudwatch put-metric-alarm \
--alarm-name cpu-mon-${i} \
--alarm-description "Alarm when CPU exceeds 70 percent" \
--metric-name CPUUtilization \
--namespace AWS/EC2 \
--statistic Average \
--period 300 \
--threshold 70 \
--comparison-operator GreaterThanThreshold \
--dimensions "Name=InstanceId,Value=${i}" \
--evaluation-periods 2 \
--alarm-actions arn:aws:sns:us-east-1:111122223333:MyTopic \
--unit Percent
done
You could also initially use the AWS CLI to grab instance IDs based on tags, instance names etc and then use those to create the alarms along the same lines.

Why am I unable to fetch metric values for EC2 instances from cloudwatch?

I am trying to get the cloudwatch metric data for CPU Utilazation of an EC2 instance i-014448f54423cc0, but i am getting the following output without any metrics data
AWS CLI COMMAND
$ aws cloudwatch get-metric-statistics --metric-name CPUUtilization --start-time 2017-03-20T23:18:00 --end-time 2017-03-25T23:18:00 --period 3600 --namespace AWS/EC2 --statistics Average --dimensions Name=i-014448f54423cc0,Value=i-abcdef
OUTPUT
-----------------------------
| GetMetricStatistics |
+--------+------------------+
| Label | CPUUtilization |
+--------+------------------+
As per the following thread on AWS forum: Link
It is said that cloudwatch metrics data can be accessed through API's only if detailed monitoring is enabled, so I tried both scenarios of with & without enabling detailed monitoring but still in both the cases the output is same
You have defined your dimension incorrectly. The dimension you are filtering (literally 'InstanceId') needs to be defined as the Name, and your value (in this case, the instance id's value) as the Value.
Example
Snippet:
Name=InstanceId,Value=i-014448f54423cc0
Full example:
aws cloudwatch get-metric-statistics --metric-name CPUUtilization --start-time 2017-03-20T23:18:00 --end-time 2017-03-25T23:18:00 --period 3600 --namespace AWS/EC2 --statistics Average --dimensions Name=InstanceId,Value=i-014448f54423cc0
Discussion
The linked AWS forum discussion isn't relevant to this situation, because detailed monitoring only enables monitoring at 1-minute granularity. Basic monitoring samples data on five-minute intervals. Since you are requesting CPUUtilization for each hour (period=3600 seconds) on a single instance, you will have data available with no need for detailed monitoring.
Further Reading
AWS Documentation - Enable or Disable Detailed Monitoring for Your Instances
AWS Documentation - Amazon EC2 Metrics and Dimensions
AWS Documentation - AWS CLI get-metric-statistics

how can I set up a cloudwatch alarms so that it only notifies once per day if alarm notification already sent

I have set up some cloudwatch alarms using the cli put-metric-alarm and all works fine. The only issue is it continues to keep sending notifications (every 5 mins) which can really clog up your inbox. Is there a way that I can prevent it from sending further notifications if an Alarm notification has already been sent for the day unless a state change has occurred?.
Here is the command I am using to create the Alarm:
aws cloudwatch put-metric-alarm --region xx-region-x
--alarm-name 'my CPU Check'
--alarm-description 'my - CPU usage'
--namespace AWS/EC2
--dimensions Name=InstanceId,Value=i-xxxxxxxx
--metric-name CPUUtilization
--statistic Average
--comparison-operator GreaterThanThreshold
--unit Percent
--period 60
--threshold 0
--evaluation-periods 3
--alarm-actions arn:aws:sns:xx-region-x:xxxxxxxxxxxx:my-topic

CloudWatch SMS notifications for EC2 instances that are not in us-east-1

I am looking to get a notification schema setup for my EC2 instances that are in the us-west-2 data center. I have read the CloudWatch and SNS docs, and I am aware that SMS notifications are only available when setting up SNS Topics in us-east-1.
I am wondering if anyone has found a way to get CloudWatch alarms for instances NOT in us-east-1 to broadcast on a topic setup in us-east-1?
It appears that the documentation is incorrect - when trying to add a new alarm in us-west-2 that points at a topic in us-east-1 for the SMS capabilities, the following error is observed (tried this today on Sept 10 2014):
A client error (ValidationError) occurred when calling the PutMetricAlarm operation: Invalid region us-east-1 specified. Only us-west-2 is supported.
This is based on running the following command using the aws cli (account number changed to 1234567890):
aws cloudwatch put-metric-alarm --alarm-name "ELB UnHealthy > 0" --alarm-description "ELB UnHealthy > 0" --actions-enabled --ok-actions arn:aws:sns:us-west-2:1234567890:EmailOnly --alarm-actions arn:aws:sns:us-east-1:1234567890:EmailAndSMS --insufficient-data-actions arn:aws:sns:us-west-2:1234567890:EmailOnly --metric-name UnHealthyHostCount --namespace AWS/ELB --statistic Average --dimensions Name=LoadBalancerName,Value=elb-name --period 60 --evaluation-periods 3 --threshold 1 --comparison-operator GreaterThanOrEqualToThreshold
I guess the previous answer was from somebody who didn't actually test this out... It's that or AWS disabled the ability to reference other region sns topics in the last few months and forgot to update their documentation...
You can set up your alarms to send notifications to a different region with the Amazon Cloudwatch CLI. You just have to create the alarm in us-west-2 by calling mon-put-metric-alarm and provide the ARN of your us-east-1 topic as alarm-actions.
export AWS_CLOUDWATCH_URL=http://monitoring.us-west-2.amazonaws.com/
mon-put-metric-alarm --alarm-name my-alarm --alarm-description "some desc"
--metric-name CPUUtilization --namespace AWS/EC2
--statistic Average --period 60 --threshold 90
--comparison-operator GreaterThanThreshold
--dimensions InstanceId=i-abcdef --evaluation-periods 3 --unit Percent
--alarm-actions arn:aws:sns:us-east-1:1234567890:my-topic
You can read the official docs here:
http://docs.aws.amazon.com/AmazonCloudWatch/latest/cli/cli-mon-put-metric-alarm.html
And find CLI setup instructions here:
http://docs.aws.amazon.com/AmazonCloudWatch/latest/cli/SetupCLI.html
If you're trying to create alarms in a region other than your default you must explicitly specify it with the --region option (despite this already being implicit in the ARN).
This isn't exactly what you asked for, but I have instances in the us-west-1 region that I needed SMS alerts for, so I found a way to get this to work. The trick is to create both the metrics and the alerts in the us-east-1 region.
On your instance in the us-west-1 region, run the following command to create a metric in the us-east-1 region and and publish a value to it.
aws cloudwatch put-metric-data
--region us-east-1 --namespace NameSpace --metric-name MetricName
--dimensions InstanceId=i-12345678 --value 10
Next, in the us-east-1 region, create an SNS topic, along with associated SMS subscription(s).
Finally, in the us-east-1 region, the topic you created will be visible. create an alarm based on that metric, specifying the SNS topic you just created.
This alarm will now send SMS notifications via SNS when triggered.
I had thought there might be an additional cost of sending the metric data from us-west-1 to us-east-1, but it turns out that the cost is zero for the number of metrics and frequency I used, which was a single metric sent once per minute.