Starting EC2 instances by tag & EC2 Filters

3 minute read

May 2019

Overview

I had previously written about shutting down Azure VMs with a PowerShell script using Azure Automation runbook and recently needed to fix a broken script at work that started certain EC2 instances. The broken script was storing all of the EC2 instances in a variable then filtering by tag, but when I rewrote the script I used the Format parameter of the Get-EC2Instance Cmdlet which filters the objects on the AWS side and testing on the dev account showed a large performance gain and also easier to read and understand. Below the script are a few helpful filters for EC2 Instances, Volumes and Snapshots.

All examples run on PowerShell Core installed on a Mac with the AWSPowerShell Core module:

PSVersion                      6.1.1
PSEdition                      Core
OS                             Darwin 18.5.0
Platform                       Unix
AWSLambdaPSCore                1.2.0.0
AWSPowerShell.NetCore          3.3.485.0  

Daily On script

The script has one parameter, the AWS region (set to eu-west-1 as the default as this is where the majority of the instances are).

Instances the are required to start up in the morning are tagged with the key pair: DailyOn = True.

instance tagged with daily on

Using the AWS filter to get instances with the specified tags, instances are added to the ec2List variable. The instances in the list are iterated over and any that are not in the state of running are started. Instances that are already running are written to the output (it’s currently run in TeamCity and the output appears in the ‘build’ log). That’s it, nice and simple and wouldn’t take much changing to shutdown instances too (it could shutdown all instances except those with a LeaveOn = True tag).

instance tagged with daily on

Using AWS EC2 Filters

As I wrote this script, I took a look again at the EC2 filter parameter.

The filter can be defined in two ways, as Filter object type or supplied directly to the parameter as hashtable or array of hashtables.

Filter Name and Value values are case sensitive!!

EC2 Filter Object

$filter = New-Object -TypeName Amazon.EC2.Model.Filter
$filter.Name = 'virtualization-type'
$filter.Value = 'hvm'
(Get-EC2Instance -Filter $filter).count

instance tagged with daily on

Hashtable filter

(Get-EC2Instance -Filter @{name = 'virtualization-type'; values = 'hvm' }).count

Array of Hashtables = multiple filter

# Multiple filters
(Get-EC2Instance -Filter @(@{name = 'availability-zone'; values = 'eu-west-1b' } ; @{name ='tag:DailyOn'; values = 'True'})).count

instance tagged with daily on

Examples of filters

EC2 Instances

Get instance by name tag value

Get-EC2Instance -Filter @{name = 'tag:Name'; values = 'AWS-Matt-Test'}

Count number of instances in each AZ

(Get-EC2Instance -Filter @{name = 'availability-zone'; values = 'eu-west-1a' }).count

instance tagged with daily on

Search by key

(Get-EC2Instance -Filter @{name ='tag-key'; values = 'LeaveOn'}).count

instance tagged with daily on

(Get-EC2Instance -Filter @{name ='reason'; values = 'User*'}).count
(Get-EC2Instance -Filter @{name ='reason'; values = '*ser*'}).count

filter by reason

Search for a key with no value

(Get-EC2Instance -Filter @{name ='reason'; values = ''}).count

filter by reason

Platform type

(Get-EC2Instance -Filter @{name ='platform'; values = 'windows'}).count

filter by platform

Instance type

(Get-EC2Instance -Filter @{name ='instance-type'; values = 't2.medium'}).count
(Get-EC2Instance -Filter @{name ='instance-type'; values = '*'}).count

ec2 filtered by type

EC2 Volumes

# Get vol mounted at sda1 for an instance (normally O/S drive)
Get-EC2Volume -Filter @(@{ Name = 'attachment.instance-id' ; Values = "$($ec2Instance.Instances.instanceid)"} ;
    @{Name = 'attachment.device' ; values = '/dev/sda1'})

Get-EC2Volume -Filter @( @{ Name = 'attachment.instance-id' ; Values = "$($ec2Instance.Instances.instanceid)"} ; 
    @{Name = 'attachment.device' ; values = '/dev/sda2'})

volume filtered by attachment

EC2 Images

# https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Image.html
# OwnerID '801119661308' = Amazon Windows
# OwnerID '099720109477' = Canonical
# OwnerID '137112412989' = Amazon linux

# Filter by image id - handy to get owner info, name details etc
Get-EC2Image -Filter @{ Name="image-id"; Values="ami-01ac8cd0e2853e2be" }

# Windows
#2019 Full
Get-EC2Image -Filter @(@{ Name="platform"; Values="windows" } ; @{Name='owner-id' ; Values = '801119661308'} ; @{Name='name'; Values = 'Windows_Server-2019-English-Full-Base-*'})

#2019 Core
Get-EC2Image -Filter @(@{ Name="platform"; Values="windows" } ; @{Name='owner-id' ; Values = '801119661308'} ; @{Name='name'; Values = 'Windows_Server-2019-English-Core-Base-*'})

# Ubuntu

Get-EC2Image -Filter @(@{Name='owner-id' ; Values = '099720109477'} ; @{Name='name'; Values = '*ubuntu-bionic-18.04-amd64-server-*'})

Get-EC2Image -Filter @(@{Name='owner-id' ; Values = '099720109477'} ; @{Name='name'; Values = '*ubuntu-xenial-16.04-amd64-server-*'})

# Amazon
Get-EC2Image -Filter @(@{Name='owner-id' ; Values = '137112412989'} ; @{Name='name'; Values = '*amzn2-ami-hvm-2.0.2019*'})

Time difference between a filter and getting all instances (only 68 instances in this case)

instance tagged with daily on

Summary

Updating the script to turn on EC2 instances was a fun exercise that didn’t take too long. The script is basic but does the job well. The AWS filters are handy to use to speed up the filtering of EC2 objects and very useful to find volumes and images. Before I would get all instances / volumes / images from AWS and use PowerShell to sort and filter etc but now I’ve learnt more about filtering and how filtering at the API makes manipulating with PowerShell quicker due to less objects being sent in the pipeline and to sort etc.