Monitoring with PowerShell: Monitoring B-Series VM credits

A lot of MSPs use the B-Series VMs for tasks, and why woulnd’t you? It are cheap VMs that allow you to use azure as a cost effective solution for clients. The B-Series VM are “burstable” VMs, meaning they don’t get the full CPU performance constantly.

The description of Microsoft explains it best:

The B-series burstable VMs are ideal for workloads that do not need the full performance of the CPU continuously, like web servers, small databases and development and test environments. These workloads typically have burstable performance requirements. The B-Series provides these customers the ability to purchase a VM size with a price conscience baseline performance that allows the VM instance to build up credits when the VM is utilizing less than its base performance. When the VM has accumulated credit, the VM can burst above the VM’s baseline using up to 100% of the CPU when your application requires the higher CPU performance.

Microsoft – https://azure.microsoft.com/en-us/blog/introducing-b-series-our-new-burstable-vm-size/

This is of course great for smaller servers such as domain controllers, small RemoteApp machines or generic low performance VMs, but you do need to pay attention that you don’t run out of “credits” when performance is required.

So let’s start alerting on B-Series VMs that are running out of steam. Full disclosure and credit where it’s due: A part of this script was shared with me by Andrew Cullen of Lanter Technologies, thanks for that Andrew!

The script

This script checks all the subscriptions for each VM that is in the B-series, from there on we check the current credits remaining and alert on it if those get under 90.

To fix this, you could temporarily upscale the VM to a larger series which gives you new credits, or move tasks to different VM’s if it happens a lot. This will most likely also help in the “why is my VM suddenly so slow” scenarios 😉

We’re using the secure application model and Azure Lighthouse for these tasks, as such you can load these scripts into any RMM system that is able to handle credentials securely.

######### Secrets #########
$ApplicationId = 'ApplicationID'
$ApplicationSecret = 'ApplicationSecret' | ConvertTo-SecureString -Force -AsPlainText
$TenantID = 'YourTenantID'
$RefreshToken = 'YourRefreshToken'
$UPN = "UPN-Used-To-Generate-Tokens"
######### Secrets #########

$credential = New-Object System.Management.Automation.PSCredential($ApplicationId, $ApplicationSecret)
$azureToken = New-PartnerAccessToken -ApplicationId $ApplicationID -Credential $credential -RefreshToken $refreshToken -Scopes 'https://management.azure.com/user_impersonation' -ServicePrincipal -Tenant $TenantId
$graphToken = New-PartnerAccessToken -ApplicationId $ApplicationID -Credential $credential -RefreshToken $refreshToken -Scopes 'https://graph.microsoft.com/.default' -ServicePrincipal -Tenant $TenantId

Connect-Azaccount -AccessToken $azureToken.AccessToken -GraphAccessToken $graphToken.AccessToken -AccountId $upn -TenantId $tenantID
$Subscriptions = Get-AzSubscription | Where-Object { $_.State -eq 'Enabled' } | Sort-Object -Unique -Property Id
$VMCredits = foreach ($Sub in $Subscriptions) {
    write-host "Processing client $($sub.name)"
$null = $Sub | Set-AzContext
get-azvm -status | Where-Object { $_.HardwareProfile.VmSize -like "Standard_B\*" -and $_.PowerState -like "_Running_" } | ForEach-Object {
$Credits = (Get-AzMetric -ResourceId $_.Id -MetricName "CPU Credits Remaining").data.average | Where-Object { $_ -ne "" } | select-object -last 1
[PSCustomObject]@{
VMName = $\_.Name
CreditsRemaining = $Credits
Subscription = $sub.name
}
}
}

foreach ($VMCredit in $VMCredits | where-object { $_.CreditsRemaining -lt "90" }) {
    write-host "$($VMCredit.VMname) has $($VMCredit.CreditsRemaining) credits remaining"
}

And that’s it! I hope this helps in tackling those pesky performance issues when using the cheaper VMs in Azure. As always, Happy PowerShelling

Recent Articles

Automating with PowerShell: making stolen tokens useless with Global Secure Access

Last week I watched Merill Fernando talk to Alex Pavlovsky and Marilee Tuscak from the Entra team about something I’d kinda put under the “needs a GSA licence” branch and i’d check it out later, turns out that like most people, I half-assed the documentation and it turns out it doesn’t. There’s two features that come with any P1 license; Compliant network check and Source IP Restoration. So BP, P1, or even frontline worker licenses already have this.

CIPP ❤️ #IntuneForMSPs

We’re Joining #IntuneForMSPs 🎉

Being invited by Microsoft to join a global initiative is a big moment for us, and we want to be clear about why it matters. #IntuneForMSPs is Microsoft’s program to help MSPs deliver Microsoft 365, Intune, and Copilot services at scale, and CIPP is now part of it, bringing the largest MSP community in the channel directly to Microsoft.

The return of CyberDrain CTF

CyberDrain CTF returns! (and so do I!)

It’s been since september that I actually picked up a digital pen equivalent and wrote anything down. This was due to me being busy with life but also my side projects like CIPP. I’m trying to get back into the game of scripting and blogging about these scripts. There’s still so much to automate and so little time, right? ;)