Skip to main content
Home
badllama.com
  • Search
  • Log In

Create an HA pair using only an Elastic IP

cpeters's picture

Sat, 03/19/2016 - 01:32 by cpeters

This Powershell script is designed to run on two machines, and to transfer the elastic IP to the running instance should one fail. This script is loosely based on https://aws.amazon.com/articles/2127188135977316 but has several key differences:

  1. This provides HA for the public elastic IP without need for an elastic load balancer
  2. This script runs in windows as a scheduled task at startup under the SYSTEM account.
  3. This script logs errors to the event viewer

Some Caveats:

  • The script is designed to run according to your RTO -- I have this script executing every 60 seconds using the task scheduler.
  • In order to use the ec2 commands as written, you will need to auto-assign public IP addresses to the HA partners
  • This script does not differentiate console errors from console output. I may add that in a later version
  • This script does not account for more than one elastic network interface
  • This script does not account for more than one private or public IP address
  • This script doesn't have an AZ preference, but it should prefer the AZ with the active RDS instance. I may add this later
  • This architecture is not disaster proof. Elastic IPs can only exist within a single region, so if the whole region goes out, so will your solution.
  • The script has to declare two system variables in order for the SYSTEM account to be able to run these tasks, but they get re-declared every time the script runs, which really isn't necessary.
#Environment Variables required for EC2
setx EC2_HOME "C:\Program Files\ec2-api-tools-1.7.5.1"
setx JAVA_HOME "C:\Program Files (x86)\Java\jre1.8.0_71"

function catchOutput ($test) #Sends either the command line error or the output to the Event Viewer.
{
    #Write-EventLog -LogName Application -Source HA_Monitor -EntryType Information -EventID 0 -Message "$test"
    return $test
}
function writeMessage($str) #sends a message to the Event Viewer.
{
    Write-EventLog -LogName Application -Source HA_Monitor -EntryType Information -EventID 1 -Message "$str"
}

writeMessage("Running Heartbeat script.")
#$EC2_HOME = catchOutput(Get-ChildItem Env:EC2_HOME | out-string -stream) 
#$JAVA_HOME = catchOutput(Get-ChildItem Env:JAVA_HOME | out-string -stream)

#Static Confugration Data
$primaryAID = "eipalloc-893690ed"
$partnerIID = "i-4be48693"

#Fetch local data
$instanceID = Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/instance-id
$availabilityZone = Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/placement/availability-zone
$region = "$availabilityZone" -replace "[a-z]$",""
$MyVIP = Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/public-ipv4

$VIP = catchOutput(ec2-describe-addresses $primaryAID --region $region 2>&1) | %{ $_.split("`t")[1]}
$HA_Partner_IP = catchOutput(ec2-describe-instances $partnerIID --region $region 2>&1) | findstr "PRIVATEIPADDRESS" | %{ $_.split("`t")[1]}


if ($myVIP -ne $VIP) {
    $pingResult = catchOutput(ping -n 3 -w 3 $HA_Partner_IP 2>&1)
    if ($pingResult | select-string -pattern "100`% loss") {
        $rval = catchOutput(ec2-associate-address --region $region -a $primaryAID -i $instanceID --allow-reassociation 2>&1)
        writeMessage("Partner reports offline.  Successfully obtained primary public IP $VIP")
    }
    elseif ($pingResult | select-string -pattern "0`% loss") {
        writeMessage("Partner reports online; no action necessary")
    }
    else {
        writeMessage("Partner state unknown.")
    }
}
else {
    writeMessage("The local node $instanceID already possesses the primary public IP $VIP")

}
writeMessage("Hearbeat Complete")
Tags: 
aws Windows Powershell HA
Powered by Backdrop CMS