Azure High Availability

Availability Sets

Just like on-premise, Microsoft have a need to update their environment and are subject to failures e.g. hardware. To protect against this you can use Availability Sets with Update and Fault Domains.

Update Domain

An update domain is basically like a deployment group. All computers in the update domain can be updated / restarted at the same time. Therefore, to prevent an outage to your application / service, you should span your virtual machines across multiple update domains.

Fault Domain

Each fault domain effectively shares the same fabric e.g. Network, Storage. In the event of a failure, all resources in that fault domain could be affected. To achieve Microsoft’s published SLA, you need to ensure that your virtual machines span across multiple fault domains.

Below is an example of an environment which consists of Web, File and Databases.

Fault Domain 1Fault Domain 2Fault Domain 3
Web 1
Update Domain 1
Web 2
Update Domain 2
File 1
Update Domain 2
File2
Update Domain 1
DB 1
Update Domain 3
DB2
Update Domain 2

If Fault Domain 1 was to go down, the service would continue to operate as there is a Web And File VM in another domain.

At the time of writing this post, Microsoft offer the following SLAs

WSUS – Remove all or past deadlines from WSUS

<#
.SYNOPSIS
Use to remove all or past deadlines from WSUS

.PARAMETER WsusServer
Name of the remote machine running WSUS server. Defaults to localhost. 

.PARAMETER UseSecureConnection
If set to true, uses SSL instead of HTTP.

.PARAMETER port
The port number.

.PARAMETER OnlyPast
If set it will only remove past deadlines and leave future ones. If not set all deadlines will be removed.

#>
param(
    [parameter(Mandatory=$false)][string]$WsusServer = 'localhost',
    [parameter(Mandatory=$false)][boolean]$UseSecureConnection = $false,
    [parameter(Mandatory=$false)][int]$port = 8530,
    [parameter(Mandatory=$false)][switch]$OnlyPast
)

# Load WSUS assemblies
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")

# Connect to the WSUS Server and create the wsus object
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($wsusServer,$UseSecureConnection, $port)

# create datetime object to check if Deadline is set
if($OnlyPast){
    $deadline = Get-Date 
} else {
    $deadline = Get-Date '12/31/9999 11:59:59 PM'
}

Write-Progress -Activity "Getting all updates" -Status "...this many take some time" -PercentComplete 1 -id 1

# Get all approved updates, this can take a while depending on how many updates are in your catalog
$LatestRevision = $wsus.GetUpdates([Microsoft.UpdateServices.Administration.ApprovedStates]::LatestRevisionApproved,[DateTime]::MinValue,[DateTime]::MaxValue,$null,$null)

Write-Progress -Activity "Getting all updates" -Status "...this many take some time" -PercentComplete 50 -id 1
$HasStaleUpdate = $wsus.GetUpdates([Microsoft.UpdateServices.Administration.ApprovedStates]::HasStaleUpdateApprovals,[DateTime]::MinValue,[DateTime]::MaxValue,$null,$null)

$AllUpdates = @($LatestRevision) + @($HasStaleUpdate)

# Check each update approval for deadlines
$wp=1
foreach($update in $AllUpdates){
    Write-Progress -Activity "Checking for deadlines" -Status "$wp of $($AllUpdates.count)" -PercentComplete $(($wp/$($AllUpdates.count))*100) -id 1;$wp++
    
    # If deadline found reapprove without a deadline to remove it
    $update.GetUpdateApprovals() | %{
        if($_.Deadline -lt $deadline -and $_.Action -eq 'Install'){
            $_ | FT @{l='Title';e={$update.Title}}, Deadline
            $group = $wsus.GetComputerTargetGroup($_.ComputerTargetGroupId)
            $update.Approve([Microsoft.UpdateServices.Administration.UpdateApprovalAction]::Install,$group) | Out-Null
        }
    }
}

https://gist.github.com/mdowst/3737d6e69ac20c5b9d69357a289c0bc6