Problem
An application needs to know if itself is running in Azure VM, so that it can apply special logic and optimization for Azure.
Solution
You can check if your code is running on an Azure VM by querying the Azure Instance Metadata Service.
The Azure Instance Metadata Service (IMDS) provides information about currently running virtual machine instances. You can use it to manage and configure your virtual machines. This information includes the SKU, storage, network configurations, and upcoming maintenance events.
The service URL is: http://169.254.169.254/metadata/instance?api-version=2021-02-01
Test
Access from outside Azure VM:
Access within Azure Windows VM:
Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -NoProxy -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | ConvertTo-Json -Depth 64
From a Linux VM:
curl -s -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | jq
It proves the service endpoint can only be reachable from Azure VM.
Example Code
PowerShell
$metadataServiceUrl = "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
$headers = @{
"Metadata" = "true"
}
try {
$response = Invoke-RestMethod -Uri $metadataServiceUrl -Headers $headers -Method Get
Write-Host "Successfully retrieved metadata: "
Write-Output $response
}
catch {
Write-Host "Error retrieving metadata. This may not be an Azure VM or the service may not be available."
}
C#
internal class Program
{
static readonly HttpClient httpClient = new HttpClient();
private static async Task Main(string[] args)
{
try
{
string url = "http://169.254.169.254/metadata/instance?api-version=2021-02-01";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Add("Metadata", "true");
HttpResponseMessage response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
string responseData = await response.Content.ReadAsStringAsync();
Console.WriteLine("This code is running on an Azure VM.");
Console.WriteLine(responseData);
}
else
{
Console.WriteLine("This code is not running on an Azure VM.");
}
}
catch (HttpRequestException e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
}
}
Note
Please note the following points when using the above code:
- The Metadata header is necessary to retrieve the information; without it, the request will be denied.
- The IP address
169.254.169.254
is a link-local address used by the Azure Instance Metadata Service. This address is only reachable from within the VM. - You should use the latest
api-version
parameter value that is supported. At the time this blog post is written, the latest version is2021-02-01
, but you should check the Azure documentation for any updates.
Comments