Skip to content

Instantly share code, notes, and snippets.

@shokoe
Last active September 17, 2018 22:07
Show Gist options
  • Save shokoe/6db791aa3d3e888f97a025a813727952 to your computer and use it in GitHub Desktop.
Save shokoe/6db791aa3d3e888f97a025a813727952 to your computer and use it in GitHub Desktop.
Nagios script for checking AWS reservation usage full coverage. Will alert on any wasted reservation capacity. Support latest feature from AWS - instance types inter-family conversion, includes tables with all the data. Doesn't work with region specific reservations.
#!/bin/bash
# tested with aws-cli/1.11.123 Python/2.7.9 Linux/3.16.0-4-amd64 botocore/1.5.86
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
#set -x
family_conversion="Type Factor
nano 1
micro 2
small 4
medium 8
large 16
xlarge 32
2xlarge 64
4xlarge 128
8xlarge 256
10xlarge 320
16xlarge 512
32xlarge 1024"
# based on table at http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-modifying.html#ri-modification-instancemove
# multiplied by 4 for natural numbers (nano is 0.25)
convert_family(){
sed 's#\.nano# 0.25#; s#\.micro# 0.5#; s#\.small# 1#; s#\.medium# 2#; s#\.large# 4#; s#\.xlarge# 8#; s#\.2xlarge# 16#; s#\.4xlarge# 32#; s#\.8xlarge# 64#; s#\.10xlarge# 80#; s#\.16xlarge# 128#; s#\.32xlarge# 256#;' |\
awk '{A[$1]+=$2*$3*4}; END {for (i in A) print i, A[i]}' | sort
}
print_table(){
(
echo "$1 Instances Reserved Potential Waste Status"
join -o 1.1 1.2 2.2 -a 1 -a 2 -e 0 <(echo "$2") <(echo "$3") |\
awk '{if ($3>$2) {$5=$3-$2; $4=0} else {$5="0"; $4=$2-$3}; if ($5==0) {$6="OK"} else {$6="Alert"}; print $0}'
) | column -t
}
#example:
# Type Instances Reserved Potential Waste Status
# dedicated/Linux/c4.large 5 5 0 0 OK
# dedicated/Linux/c4.xlarge 6 6 0 0 OK
# dedicated/Linux/m3.large 1 0 1 0 OK
ins_count_raw=`aws ec2 describe-instances | jq -r '.Reservations[].Instances[] | "\(.State.Name) \(.Placement.Tenancy) \(.Platform) \(.InstanceType)"' | awk '$1=="running"{if ($3=="null") $3="Linux"; print $2"/"$3"/"$4}' | sort | uniq -c | awk '{print $2, $1}' | sort`
#exmple:
# 5 dedicated/null/c4.large
# 1 dedicated/windows/m4.xlarge
# 3 default/null/m4.large
#echo "$ins_count_raw"
#echo ---
if [ -z "$ins_count_raw" ]; then
echo "Can't get instance list"
exit 2
fi
ins_count_family=`echo "$ins_count_raw" | convert_family`
#example:
# dedicated/null/c4 272
# dedicated/windows/m4 32
# default/null/m4 48
#echo "$ins_count_family"
#echo ---
res_count_raw=`aws ec2 describe-reserved-instances | jq -r '.ReservedInstances[] | "\(.State) \(.InstanceCount) \(.InstanceTenancy) \(.ProductDescription) \(.InstanceType)"' | awk '$1=="active"{if ($4=="Linux/UNIX") $4="Linux"; print $3"/"$4"/"$5" "$2}' | sort`
#example:
# 9 dedicated/Linux/m3.medium
# 5 dedicated/Linux/c4.large
# 2 default/Linux/m3.medium
#echo "$res_count_raw"
#echo ---
res_count_family=`echo "$res_count_raw" | convert_family`
#example:
# dedicated/Linux/c4 272
# dedicated/Linux/m3 72
# default/Linux/c4 16
#echo "$res_count_family"
#echo ---
family_table=`print_table "Family" "$ins_count_family" "$res_count_family"`
type_table=`print_table "Type" "$ins_count_raw" "$res_count_raw"`
if echo "$family_table" | sed 1d | grep -q "Alert"; then
msg="Found wasted reservation"
ec=2
else
msg="Reservations are in full use"
ec=0
fi
echo "$msg
<pre>
Count by instance type family (converted to nano):
$family_table
* alerts are based on this table only
* counts are noirmailzed to nano for inter family conversion
Count by specific instance type:
$type_table
* count for specific instance types
* alerts here are not crucial
Instance size conversion table (for reference):
$family_conversion
* conversion table for all types sizes
* based http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ri-modifying.html#ri-modification-instancemove
* multiplied by 4 for natural numbers (nano is originaly 0.25)
</pre>
"
exit "$ec"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment