Immer wieder gibt es die Diskussion sind die Azure Reserved Instances (RI) oder der Azure Saving Plan (SP) die bessere Option für den Betrieb einer Applikation auf Basis von IaaS in Azure. Es gibt nicht die eine Antwort auf diese Frage. Im folgenden werden die beiden Optionen Reserved Instance und Saving Plan gegen übergestellt und anhand von Szenarien bewertet.

Kurze Begriffsklärung:

Azure Reserved Instance

Bei einer Reserved Instance handelt es sich im ein Commitment für einer Bestimmte VM in einer bestimmten Region für eine bestimmte Zeit. Also z.B. eine D8s_v5 VM in Westeuropa für drei Jahre. Diese Reservierung kann dann monatlich über 3 Jahre gezahlt werden und bietet ein Rabat von bis zu 72%. In diesem konkreten Beispiel liegt der Preisvorteil bei ~62% Rabatt. Wichtig dabei ist, die Reservierung muss bezahlt werden, egal ob Sie genutzt wird oder nicht. Auf MS Learn findet mal unter folgendem Link eine detaillierte Dokumentation zu dem Thema: Kostensparen mit reservierten Azure-VM-Instanzen

Azure Saving Plan

Bei einem Savin Plan wird im Gegensatz zu einer Reserved Instance nicht eine konkrete VM in einer konkreten Region reserviert, sondern nur eine Summe EUR an Compute. Dies kann dann flexibel für unterschiedliche VMs oder auch andere Compute Services genutzt werden. Die reservierte Summe wird dann monatlich abgerechnet, egal ob Sie vollständig genutzt wurde oder nicht. Sollte man mehr verbrauchen, als man committet hat, wird zum Pay-as-you-go Preis abgerechnet. Zu den Saving Plans ist die Dokumentation an folgender Stelle: Was sind Azure-Sparpläne für Compute?

Szenarios

Um eine mögliche gute Vergleichbarkeit zu bekommen, gehen wir von folgenden Szenarien aus und bewerten die Kosten der jeweiligen Lösung. Stellen wir uns vor wir haben ein Zeiterfassungssystem. Dieses System wird primär in den Zeiten zwischen 6:00 Uhr und 18:00 Uhr benötigt.

  • Szenario A: Der Workload läuft 12 Stunden am Tag und könnte theoretisch komplett abgeschaltet werden in den anderen 12 Stunden
  • Szenario B: Der Workload läuft 12 Stunden am Tag, muss aber in den anderen 12 Stunden weiterhin verfügbar sein, gern aber mit weniger Leistung.
  • Szenario C: Der Workload läuft nur 21 Werktage 12 Stunden und könnte in der restlichen Zeit durch eine leistungsschwächere VM ersetzt werden.
AnnahmeWertEinheit
Kalkulatorische Stunden pro Monat730Stunden
30 Tage 6:00 - 18:00 Uhr360Stunden
21 Arbeitstage 6:00 - 18:00 Uhr252Stunden

Als Basis für die VM-Preise wurden die Daten aus dem Azure Preiskalkulator genommen (Region “westeurope”):

VM TypePay-as-you-go (PAYG)RISP
D8s_v50,438 EUR/h0,166 EUR/h0,240 EUR/h
D4s_v50,213 EUR/h0,083 EUR/h0,0120 EUR/h
B4s_v20,183 EUR/h0,069 EUR/h0,097 EUR/h

Alle Preise sind nur der Compute-Preis, also ohne Betriebssystemkosten. Preisrechner vom 10/05/2023.

Szenario A

Wenn das Zeiterfassungssystem wirklich komplett ausgeschaltet werden könnte in den Zeiten, wo es nicht genutzt wird, ergeben sich folgende Preise in einem Monat für die VM:

KonstellationPreis
VM D8s_v5 als RI121,18 EUR/Monat
VM D8s_v5 30 Tage 12 Stunden/Tag (PAYG)157,68 EUR/Monat
VM D8s_v5 21 Tage 12 Stunden/Tag (PAYG)110,38 EUR/Monat

Damit wird klar, dass es sich nur dann lohnen würde, den Pay-as-you-go Preis zu nehmen, wenn wir in den Bereich von 21 Tagen 12h am Tag kommen. Der RI-Rabatt von 62% auf den Pay-as-you-go Preis der VM zahlt sich ab ~350 Stunden Betriebszeit der VM aus.

Szenario B

Der Workload läuft 12 Stunden am Tag, muss aber in den anderen 12 Stunden weiterhin verfügbar sein, gern aber mit weniger Leistung.

Wenn alles im PAYG-Preis abgebildet wird und 12 Stunde eine D8s_v5 und 12 Stunden eine D4s_v5 genutzt werden:

VM-GrößePreis
D8s_v5157,68 EUR/Monat
D4s_v581,03 EUR/Monat
Summe Workload238,71 EUR/Monat
Differenz zur RI+ 97%

Wenn alle Preise über einen Saving Plan abgedeckt werden:

VM-GrößePreis
D8s_v586,40 EUR/Monat
D4s_v544,40 EUR/Monat
Summe Workload130,80 EUR/Monat
Differenz zur RI+ 8%

Wenn alle Preise über einen Saving Plan abgedeckt werden und als Downsizing VM kann eine B-Series verwendet werden:

VM GrößePreis
D8s_v586,40 EUR/Monat
B4s_v235,89 EUR/Monat
Summe Workload122,29 EUR/Monat
Differenz zur RI+ 0,92%

Damit sind wir schon fast auf dem Preis einer RI.

Szenario C

Der Workload läuft nur 21 Werktage 12 Stunden und könnte in der restlichen Zeit durch eine leistungsschwächere VM ersetzt werden.

Wenn alles im PAYG-Preis abgebildet wird und 21 Arbeitstage für 12 Stunde eine D8s_v5 genutzt wird. In den restlichen Stunden wird dann auf eine D4s_v5 verändert:

VM-GrößePreis
D8s_v5110,37 EUR/Monat
D4s_v5104,68 EUR/Monat
Summe Workload215,05 EUR/Monat
Differenz zur RI+ 77%

Wenn alle Preise über einen Saving Plan abgedeckt werden:

VM-GrößePreis
D8s_v560,48 EUR/Monat
D4s_v557,36 EUR/Monat
Summe Workload117,84 EUR/Monat
Differenz zur RI- 2,8%

Dann noch erweitert um eine B-Serie VM anstatt der D4s_v5 im Saving Plan:

VM-GrößePreis
D8s_v560,48 EUR/Monat
B4s_v246,37 EUR/Monat
Summe Workload106,85 EUR/Monat
Differenz zur RI- 11,8%

Die letzten beiden Konstellationen erzeugen eine Ersparnis gegenüber der reinen RI für eine VM Größe.

Wenn man die Betrachtung nicht nur mit dem reinen Compute macht, sondern auch die Windows Lizenzen mit einkalkuliert verändert sich das Bild deutlich. Dann wird schon PAYG 30 Tage 12 Stunden in Benutzung ansonsten aus mit der gleichen VM-Größe günstiger als eine RI der gleichen VM Größe.

KonstellationHochrechnung
RI D8s_v5376,68 EUR/Monat
PAYG 30 Tage 12 Stunden291,56 EUR/Monat
PAYG 21 Tage 12 Stunden198,58 EUR/Monat

Inkl. Betriebssystem und ausgeschaltet, wenn nicht benötigt.

KonstellationSzenario BSzenario C
D8s_v5 + D4s_v5 PAYG429,46 EUR/Monat386,91 EUR/Monat
D8s_v5 + D4s_v5 SP321,55 EUR/Monat289,69 EUR/Monat
D8s_v5 + B4s_v2 SP253,84 EUR/Monat202,22 EUR/Monat

In der Spitze erreicht man eine Ersparnis von über 46% gegenüber der Reserved Instance. Hier spielt der Vorteil im Preis für das OS bei einer B-Series VM die entscheidende Rolle.

Umsetzung

Um dies auch mal praktisch umzusetzen ist hier ein kurzes Beispiel der Umsetzung.

Deployment einer VM

Der bicep-Code um eine VM bereitzustellen kann hier kopiert werden:

@description('Location to deploy the vNet and the VM')
param location string = 'westeurope'

@description('Name of the VM')
param vmName string = 'vm-sizingdemo01'

@description('Admin username for the VM')
param adminUsername string = 'demouser'

@description('Admin password for the VM')
@secure() 
param adminPassword string = 'Pass!word123'

@description('Name of the vNet')
param vnetName string = 'vnet-sizingdemo'

@description('Name of the subnet')
param subnetName string = 'snet-sizingdemo'

@description('Name of the automation account')
param automationAccountName string = 'aa-sizingdemo'


resource vnet 'Microsoft.Network/virtualNetworks@2020-11-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: subnetName
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
    ]
  }
}

resource publicIp 'Microsoft.Network/publicIPAddresses@2020-11-01' = {
  name: '${vmName}-pip'
  location: location
  properties: {
    publicIPAllocationMethod: 'Dynamic'
  }
}

resource nic 'Microsoft.Network/networkInterfaces@2020-11-01' = {
  name: '${vmName}-nic'
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig'
        properties: {
          subnet: {
            id: vnet.properties.subnets[0].id
          }
          publicIPAddress: {
            id: publicIp.id
          }
        }
      }
    ]
  }
}

resource vm 'Microsoft.Compute/virtualMachines@2020-12-01' = {
  name: vmName
  location: location
  dependsOn: [
    nic
  ]
  properties: {
    hardwareProfile: {
      vmSize: 'Standard_D8s_v5'
    }
    storageProfile: {
      imageReference: {
        publisher: 'MicrosoftWindowsServer'
        offer: 'WindowsServer'
        sku: '2019-Datacenter'
        version: 'latest'
      }
      osDisk: {
        name: '${vmName}-osdisk'
        caching: 'ReadWrite'
        createOption: 'FromImage'
        diskSizeGB: 128
      }
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPassword
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: nic.id
        }
      ]
    }
  }
}

resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' = {
  name: automationAccountName
  location: location
  properties: {
    sku: {
      name: 'Basic'
    }
  }
}

Die Parameter sollten nach eigenen Vorstellungen angepasst werden, insbesondere das Kennwort für den administrativen Zugang. Im Azure Portal ist dann folgendes bereitgestellt:

Azure Resourcegroup

Automation Account

Der Automation Account braucht dann noch eine Berechtigung, um auf der Subscription oder Resourcegroup die VM in der Größe verändern zu können. Dazu ist in diesem Beispiel der Automation Account “aa-sizimgdemo” mit einer System Assigned Identity und dem entsprechendem Azure Role Assignment versehen worden (vgl. MS Learn):

Azure Automation Account

Runbook erstellen und mit einem Schedule verbinden

Das Runbook auf Basis von Powershell zum Verändern der VM-Größe in diesem beschriebenen Szenario würde dann wie folgt aussehen:

# Set variables
$resourceGroup = "rg-sizingdemo"
$vm = "vm-sizingdemo01"
# Set desired VM-Sizes
$normalsize = "Standard_D8s_v5"
$smallersize = "Standard_B4s_v2"

# login to Azure
Disable-AzContextAutosave -Scope Process
Connect-AzAccount -Identity

# check if the desired VM size is available
$availableSizes = Get-AzVMSize  -ResourceGroupName $resourceGroup -VMName $vm | Select-Object -ExpandProperty Name

if($availableSizes -notcontains $normalsize) {
    Write-Host "The desired normal VM size is not available."
    exit 1
}

if($availableSizes -notcontains $smallersize) {
    Write-Host "The desired smaller VM size is not available."
    exit 1
}

# Check current Size
$updatevm = Get-AzVM -ResourceGroupName $resourceGroup -Name $vm
$actualsize = $updatevm.HardwareProfile.VmSize
Write-Host "Current Size is $actualsize"

$targetsize = ($actualsize -eq $normalsize) ? $smallersize : $normalsize

# Deallocate the VM
Stop-AzVM -ResourceGroupName $resourceGroup -Name $vm -StayProvisioned -Force 
Write-Host "The VM is deallocated."

Write-Host "Target Size is $targetsize"
$updatevm.HardwareProfile.VmSize = $targetsize

# Resize the VM
Update-AzVM -ResourceGroupName $resourceGroup -VM $updatevm
Write-Host "New Size is $targetsize"

# Start the VM
Start-AzVM -ResourceGroupName $resourceGroup -Name $vm
Write-Host "The VM is started."

HINWEIS: Mittlerweile gibt es eine Extension für Visual Studio Code um sowohl das Runbook als auch den Schedule und die komplette Konfiguration direkt in VS Code zu machen.

HINWEIS: Es handelt sich nur um eine exemplarische Umsetzung. Für den produktiven Betrieb empfiehlt sich eine Lösung, die das Resizing z.B. anhand von Tags automatisiert. Beispiele dafür finden sich in der Runbook Gallery oder unter aka.ms/AzureAutomationGitHub.