Hello Friends, I worked on a project requiring many temporary VMs.In that project, I had to find a way to reduce the cost of the VMs. I knew there were several different ways to reduce the cost of temporary Virtual Machines. The first option was on the table Spot Virtual Machines, and we could take advantage of the unused capacity in Azure. Regarding pricing, Spot VMs are tremendously cheaper than regular VMs. However, there is a catch: Spot VMs can be evicted at anytime. We can use Spot VMs for workloads that can be interrupted, such as batch jobs, render farms, and fault-tolerant applications. In this article, I will show you how to deploy Spot VMs with PowerShell. Let's dive in!
💬What is Spot VMs?
Spot VMs are Azure Virtual Machines that can be provisioned at a discounted price compared to regular VMs, and they are available in all Azure regions except the Azure China 21Vianet. However, there are VM Sizes that are not supported for Azure Spot Virtual Machines.
🔐Limitations of Azure Spot Virtual Machines
Let's take a closer look at the limitations of Azure Spot Virtual Machines. First, B-Series and promo versions of any size, such as (DV2, NC, H promo sizes), aren't supported for Spot VMs. If you're trying to use the capability of Spot VMs with subscription types such as EA, CSP, and Sponsored, you will be able to use it. However, if you're using a subscription type such as MSDN, Pay-As-You-Go, or Visual Studio Dev Essentials, you won't be able to use Spot VMs.
Regarding pricing, Spot VMs are variable, and the price can change anytime. The cost of Spot VMs is based on the current demand for the VM size in the region. You can have various options if you want to learn more about price changes. You can get data from Azure Portal and hit Azure Retail Price API to query the prices.
⚙️How to query the prices of Spot VMs?
I've written a PowerShell function that can dynamically query spot prices for the specified region and SKU type. You can use this function to query the prices of Spot VMs. Let's take a look at the function. First, we need to specify the region name and SKU type. After that, we will query the prices of Spot VMs with the help of Azure Retail Price API. If the query is successful, we will get the prices of Spot VMs. Let's take a look at the function.
Function Get-SpotInstanceCost {
<#
.SYNOPSIS
This function will retrieve the Spot Instance cost for the specified region and SKU type.
#>
param (
[Parameter()]
[string]
$RegionName,
[Parameter()]
[string]
$SkuType,
[Parameter()]
[string]
$SubscriptionId
)
$table = @()
$params = @{
'Method' = "Get"
'Uri' = "https://prices.azure.com/api/retail/prices?`$filter=armRegionName eq '$($regionName)' and armSkuName eq '$($SkuType)' and priceType eq 'Consumption' and contains(meterName, 'Spot')"
'Headers' = @{ "Content-Type" = "application/json" }
}
try {
$getSpotPrice = Invoke-RestMethod @params
if ($getSpotPrice.Items.Count -gt 0) {
$spotPrices = $getSpotPrice.Items
ForEach($row in $spotPrices) {
$obj = [PSCustomObject]@{
productName = $row.productName
sku = $row.armSkuName
serviceFamily = $row.serviceFamily
currencyCode = $row.currencyCode
retailPrice = $row.armRegionName
unitPrice = $row.unitPrice.ToString("N5")
montlyPrice = ($row.unitPrice * 730).toString("N5")
effectiveStartDate = $row.effectiveStartDate
}
$table += $obj
}
return $table | Format-Table -AutoSize
}
else {
Write-Output "[Error] - Unable to retrieve the Spot Price for the VM SKU: $SkuType"
return
}
}
catch {
Write-Output "[Error] - $($_.Exception.Message)"
return
}
}
It is straightforward to use this function. The function is not expecting you to be authenticated to Azure. You can use this function without your Azure credentials.
Get-SpotInstanceCost -regionName "uksouth" -SkuType "Standard_D2s_v3"
Example output of the function:
Ace! As you can see, the output of the function is a table. We quickly ran an example query for getting the price of Spot VMs with the help of Azure Retail Price API. End of the day, you always need to remember that whatever you're running workload on Spot VMs, they will be interruptible.
Another way to query the pricing history of Spot VMs is Azure Resource Graph.
SpotResources
| where type =~ 'microsoft.compute/skuspotpricehistory/ostype/location'
| where sku.name in~ ('Standard_D2s_v3')
| where location in~ ('uksouth')
| project skuName = tostring(sku.name), osType = tostring(properties.osType), location, latestSpotPriceUSD = todouble(properties.spotPrices[0].priceUSD)
| order by latestSpotPriceUSD asc
Anyway, you will get the same result. So, you can use either Azure Resource Graph or Azure Retail Price API to query the pricing history of Spot VMs. It is up to you.
💡Understanding of the Eviction Type and Policy
There are two types of Eviction
Capacity Only eviction
- Triggered when the capacity of the VM is no longer available in the region.Price or capacity eviction
- Azure will evict the VM when exceeding the maximum price you set or compute capacity disappears. In this option, you will be able to set a max price of VM
In the sense of Azure Spot Virtual Machines, you need to understand the eviction policy. There are two types of eviction policies. The first is Stop / Deallocate, and the second is Delete. If you're using Deallocate eviction policy, your VM will be deallocated, and you will be charged for the compute time. Deallocated VMs can be re-deploy later on. The second eviction policy is Delete. If you use the Delete eviction policy, your VM will be deleted, and you will not be charged for the compute time.
The rate of Eviction percentage is different for each region. You can check the eviction rates for each region using the below query of Resource Graph.
SpotResources
| where type =~ 'microsoft.compute/skuspotevictionrate/location'
| where sku.name in~ ('Standard_D2s_v3')
| where location in~ ('uksouth')
| project skuName = tostring(sku.name), location, spotEvictionRate = tostring(properties.evictionRate)
| order by skuName asc, location asc
Stay tuned for the next blog post. I will be focusing on the Stop / Deallocate eviction policy.