Browse PowerShell Azure VM SKUs and Marketplace Images with Get-AzVMSku
- Christoffer Windahl Madsen
- Jun 29
- 12 min read
Hi all - It has been such a long time since my last post - Apologies, I have been very busy with life the past year but I am now finally ready to once again embark on an exciting topic!
Today we will be looking into the world of the PowerShell module "Get-AzVMSku" The first and only module that allows you to see Microsoft Azure Virtual Machine Image SKUs and offerings directly from your terminal.
Now... When do you need this kind-of information ? Well - Everytime you need to deploy an Azure Virtual Machine from ANY vendor available from the Azure Market place using Infrastructure-as-code regardless of language.
Topics in chronological order of this post:
Chapter 1 - Getting started with the module
First of - The module must be run using PowerShell Core, because the underlying dependencies cannot run using native PowerShell.
Install PowerShell to be used to get Azure VM SKUs
To get help on how-to install PowerShell Core (For any operating-sytem), please visit => Microsoft official documentation on PSCore
With that installed - Simply open the terminal, and make sure that indeed it is PowerShell Core running and NOT 5.1. Also - If your running from a Linux or MacOS operating-system, you simly open the terminal and type "pwsh" To execute PowerShell Core (Make sure to have the executable in your PATH environmental variable)

Install the module directly via PSGallery - Then verify that the module is installed:

There is a full helper-file attached to the module, which we wont go over in this blog, but it contains all possible parameters that can be set + Plenty of examples. To see this in its entirety run:

With the module successfully installed we need to make sure we have an active Azure context, otherwise the module will throw an error asking for an active Azure context. Use command "Connect-AzAccount" Or its alias "Login-AzAccount" To make sure a valid context is present in the terminal.
Now - Finishing this chapter the module offers 2 different show-commands to help us understand:
What locations we can parse to the "Location" Parameter - We CANT simply use the command "Get-AzLocation" Because the underlying API's used to retrieve VM information does NOT support all regions.
Azure Virtual machine family information - Meaning the module can spit out the family-names and descriptions about them directly from Microsoft.
If we run the switch "ShowLocations" We will get: (Requires Az context)

To engage the switch 'ShowLocations" You must be logged in to a valid Azure context as described a little above, otherwise the module will throw an error.
And finally, lets see the last show-command for 'ShowVMCategories"

The 'ShowLocations' Switch will always tell us exactly what locations are allowed by the module, please remember to always use the names from column 'Name to use' Or the underlying Microsoft API will throw an error. For the other show-command, we can directly use information about the different family-names to search for only specific VMs when running the module in mode of retrieving VM image information. We have a filter parameter named 'VMPattern' Available which will be show-cased in this image
Now with the introduction done, lets dive into how to actually retrieve VM image.
Chapter 2 - Using Get-AzVmSku interactively
The only required parameter is "Location" - We will parse "westeurope" What will happen next is that since we do not parse any filter information, the module will retrieve every single possible Azure Market place publishers / vendors for Virtual machine images, which at the time of writing is 2366

Whats important to note is because we do not provide ANY parameters to help search for something specific, the module is forced to interactively show you what is essentially a catalogue of all possible options available - If we then select one, lets say 1 for "netfoundryinc"

We end up being asked about what specific version we would like. Now, what we essentially have here is a tool to dynamically look through every single possible vendor, their SKUs, offerings and their respective versions - Essentially giving us a cool and new way of peaking into the "belly of the beast" When it comes to the Azure Image Market place for Virtual machines.
The above example did only have 1 specific SKU that can be chosen from the vendor "netfoundryinc" Which makes the modul simply auto-select it and forwarding to the selection of version which as it can be seen above, have multiple options. After selecting a wanted version, say 1 again - The module will output:

The return-object can conviently be parsed to a variable to use the return-data for any data-analysis later OR to parse any potential agreement stored in the return to the PowerShell Cmdlet "Set-AzVMSku" Which is a function that ships with the module-package and can assist you by seemingsly accepting the terms of any Azure Virtual Machine image which is required before it can be used in a deployment to Azure. We will cover this and much more in Chapter 3C.
Now... With the base understanding of how the module functions - Lets dive deeper and look at how we can use filters to make the search for specific vendors we might be interested in as looking through over 2300 vendors at once can be very overwhelming.
Chapter 3 - Deep-diving into the modules capabilities
While the above chapter focused on the overall browsing experience that the module can offer - Seeing its possible to go through every single option in the Azure Market Place we can on the contrary also focus on only specific vendors.
Chapter 3 A - Using the module with filters
Let's say we are very interested in Networking vendors, maybe even more specifically Palo-Alto. How can we try to filter through and see what they offer of Images? We cant even be sure that the vendor-name is actually Palo-Alto, so what do we do ?
Using filters - PublisherName & OfferName
Well - Lets see what happens if we use parameter "PublisherName" Which can accept parts of a vendor-name as we wont always know the EXACT name the vendor might have in Azure - The module will then do different wildcard searches and return a specific list based on the name we provided:

Nice - Seems the 'palo' Keyword hit spot-on as only 1 Publisher / vendor match is found. As seen the actual name for the provider in Azure is called 'paloaltonetworks' Which the module is helping us find - Moreover we can now explore the concrete offerings from the vendor.
Going deeper in the example, lets say we want to look at 'panorama' So we select that 5 from the menu:

Notice that we have to "cut" The output because the possible versions for Palo-alto Panorama in the Azure Market place is 38 versions long... We can actually filter this even more, so that the output and choices becomes more bearable - Lets take a step back by running the command again BUT adding parameters 'OfferName' & 'Top10NewestVersions'
The 'OfferName' Parameter is a string-filter just like 'PublisherName' And will use wild-card searches. Since we know from the above search, the offer-name 'panorama' Should find the exact product we are looking for - If we combine that with switch Top10NewestVersions we essentially tell the module: Give me this specific offer, but ONLY show me the 10 newest versions and omit the rest:

Now both the list of versions is decreased to the 10 newest but also the module skipped all the way to directly decide on a version because we entered more filter-information. And this gives a lot of flexibility to us - We can use the module from searching through the entire vendor-list, then recall to look more specifically. Basically we can start looking very broadly because we do not know exact names in the Azure Market place, then quickly "zoom in" On what we want to find.
Looking at VM information returned from the module
Speaking of "zoom-in" More than filters for Publisher and Offer, we can look at filtering specific VM-sizes and their quotas which comes in the output when running the module to retrieve Image information.
As mentioned in the introduction we can use the parameter 'VMPattern' To specify only VM sizes / families which we want to see in the output, if we omit the filter-name, every single possible VM-size available in the location specified will be returned.
So, how does this VM output look? And what can it generally tell us?

If we dive a little deeper and take a look at the 'VMSizes' Propertery - Its a simple array of PSCustomObject

So the module shows important details of each specific Azure VM-size which we can use to determine what VM matches our infrastructure requirements. Whats important to note here is that in Azure we work with whats called 'quotas' Which is Microsofts way of saying 'your specific Azure Subscription has x amount of CPU cores of each Virtual machine-family available'. This information about quotas is extremely important when planning our sizes of VMs, because just looking at sizes and deciding has the risk of Azure simply denying us the deployment due to missing quotas...
To get answers about quotas, we have another property available from the return-output of the module called 'VMQuotas'

As seen on the screenshot above a lot of information is derived from the module regarding VM-quotas in Azure. The first and most important information bit is the nested property 'vCPUsAvailable' Which tells us whether we have ANY available CPU-cores for this VM-family on the current Azure Subscription, if the number is 0, we can ask for a quota increase directly in Azure.
Furthermore, we can see the following nested properties:
ArchitectureDescription => Same description as can be derived from show-command 'ShowVMCategories'
vCPUPercentUsage => A calculation of how many %. of the total cores available for a given Azure Virtual machine family is actively in use on the Azure Subscription
VMSizeDistribution => The module calculates how many of each VM size of a given family can be created BEFORE reaching the quota core limit on the VM family as a whole
All the above information from this section of the blog-post describes retrieving ALL possible Azure Virtual machine information, but what if you want to filter on it? Or even completely ignore VM data ?
As stated earlier, we have the parameter 'VMPattern' Available which works on the same wildcard strategy as defined in Chapter 3 A which we can use to control what Virtual machine-sizes we want from the module.
Say we ONLY want VM-sizes containing D (General purpose VM's):

Same - If we take a look at the nested property 'VMQuotas' ONLY D related families are present:

As a final note on this chapter - We can also entirely skip the module working with anything VMsize / VMquota related by using parameter 'NoVMInformation' Which will DRASTICALLY decrease the module time to execute.
Chapter 3 B - Automation scenarios
As already show-cased the module is more than capable of "browsing" Through the different vendors available in the Azure Market place, but what about scenarios where something like a pipeline is to execute the module? In this scenario, we cannot rely on interactively responding to whatever the module needs an answer to, as this will break automatic flows.
To completely avoid any interaction we have different parameters that can assist us:
PublisherName => Just like in chapter 2, we must filter on vendors
OfferName => Also have to filter on vendor-offers
NewestSkus => Tell the module to take the newest possible SKU from a specific Offer
NewestSkusVersions => Tell the module to take the newest possible version of a SKU
NoInteractive => Force the module to throw an error the moment an interaction is required on some specific data being processed
This switch is essentially designed so that a controlled error can be thrown before something like a pipeline simply fails due to the module waiting for an interactive response
Lets built on the examples shown in chapter 3 A - But now we add functionality to proof it can run and simply complete computation and output the information we need in order to actually built an Azure VM

Whats important to note is the fact we need to know both a 'PublisherName' And 'OfferName' That is unique enough to only match 1 element each, otherwise the switch 'NoInteractive' Will force the module to fail. Also - The switch itself is not actually needed and is only there to ENFORCE the module NOT to ask for choices in case the information provided isn't unique enough. If we remove the flag from the example above, the module will still behave exactly the same and simply output the result directly, but ONLY because our information provided is unique-enough.
Say we change the 'OfferName' Parameter from 'panorama' To something like 'flex' Which contains more than 1 result, how will the error look ?

Notice how the error specifies which specific filter that causes the issue of requring user-input to continue which in this case is 'Image Offer' Which we control via the filter-name of 'OfferName' If we remove the switch 'NoInteractive' We can see exactly what the module will ask about, essentially showing us how we can make the filter more unique to be ready for Automation:

Arh, so as we can see - The error stemmed from the fact that the 'OfferName' Pattern of 'flex' Results in 2 possible options, hence why the module will always fail when using the switch 'NoInteractive' This means for this specific scenario, we need to make our filter even more unique, lets pick 'airs' And see if it will run without any interaction now:

Yep - That did it, and that specific module-call can be directly used in any Automation-tooling that supports PowerShell Core. As a final note for this chapter, the parameters 'NewestSKUs' And 'NewestSKUsVersions' Will always be needed in these scenarios, otherwise most SKUs and version's will contain more than 1 option, leading to errors, but with these switches set, the module will always auto-select the newest of each.
Notice how the output from the screenshot says 'Image agreement: True' - This basically tells us that this specific image has a legal-agreement bound to it, which MUST be accepted before an actual deployment with set image can take place - If we do not accept the terms first, any deployment using the image will fail. Luckily the module ships with a simple builtin function to handle exactly that called 'Set-AzVMSku' Which we will cover now in the next chapter.
Chapter 3 C - Accepting Azure Market place terms
So far we have only talked about 'Get-AzVMSku' But this function has a brother called 'Set-AzVMSku' Which can help us accept Azure Market place terms which are always required in order to deploy any image (that has terms) on any Azure Virtual machine... So, how do we do that?
Simple - Just pipe the module-call from Get-AzVMSku directly to Set like so:

The 'Set-AzVMSku' Module will ALWAYS post ALL legal terms present for ANY Azure Image with active terms that must be accepted - It is highly adviced to follow each policy link to read what is being accepted BEFORE proceeding.
If we press "y" To the above, we get:

The image can now be deployed to Azure - In case of Automation scenarios as talked about in Chapter 3 B, we can use the parameter "Force" To auto-accept any VM Image agreement.
As a final note on this chapter, incase a variable is defined to capture the output of 'Get-AzVMSku' If used directly with a pipe to 'Set-AzVMSku' We must use the parameter 'Passthru' To capture the return AFTER the agreement as been accepted, like so:

Chapter 4 - Conclusion
This module is the solution to any IT professionals nightmare of having to otherwise use Microsofts default method of retrieving all information required to deploy ANY Azure Virtual machine image contained in the Azure Market place. Before the development of this module, you risked being stuck having a hard-time figuring out exactly what vendor names are, what they offer and all information contained beneath that.
We now have a central solution that contains everything we need to always know what to exactly type in the infrastructure-as-code definitions for any given image that we want to deploy to an Azure Virtual machine. Furthermore, the module also retrieves and calculates our current Azure Subscription quotas which we need to know about before even attempting to deploy anything in the first place. Finally, with the addition of the helper-function 'Set-AzVMSku' We can seemingsly accept any Image terms directly in a one-liner making sure ALL perquisites are in place before we go from finding our next Azure image and to having it living directly on an Azure Virtual machine.
It has never been easier to gather everything required to both plan, design and deploy Azure Virtual machines using infrastructure-as-code and the only thing we need to get started is PowerShell core, an active Azure Subscription and the module-package 'Get-AzVMSku' Which is directly accessible via Microsofts public PowerShell gallery repository but also on Github.
Thank you so much for reading along and again - I expect this wont be the only post coming concerning this module and its capabilities.
If you're interested in Terraform, PowerShell or Automation in general, dont forget to browse the blog as it contains many different posts about many cool topics.
Comments