'Access Azure Instance Metadata Service (169.254.169.254) from Windows docker container

Azure VM can query the Instance Metadata Service located at 169.254.159.254 for data. However this does not work from within a Windows container running on the VM.

How can a Windows container query the Instance Metadata Service that's only accessible from the host VM?

For example when using a Windows container like this: docker run -it --rm mcr.microsoft.com/windows/servercore:ltsc2019

And querying for data like this: Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri http://169.254.169.254/metadata/instance?api-version=2019-06-01

Results in this:

At line:1 char:1
+ Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri http ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand


Solution 1:[1]

I am afraid that we can't access the Azure Instance Metadata Service endpoint from the Windows container on the Azure VM because the container on the docker is isolated within a different network from the VM network and the IMDS is only available from a non-routable IP address from within the VM level.

Azure's IMDS is a REST Endpoint that is available at a well-known non-routable IP address (169.254.169.254), it can be accessed only from within the VM. Communication between the VM and IMDS never leaves the Host.

and

The Instance Metadata Service endpoint is accessible only from within the running virtual machine instance on a non-routable IP address. In addition, any request with an X-Forwarded-For header is rejected by the service.

The following diagram describes the integrated Containers with your existing VM. Get more details here.

enter image description here

When you generate a containerized application on the Azure VM, the container communicates with the outside of this container via a default docker virtualized nat NIC. For example, on the Azure VM, there is an extra IP address 172.22.48.1 used for docker instances connecting with guest OS in the network 172.18.4.0/24.

enter image description here

Edit

From Known issues and FAQ,

Metadata calls must be made from the primary IP address assigned to the primary network card of the VM.

When you call metadata from your container on the Azure VM, it's actually using a NAT nic (it's having a different MAC address from primary nic)instead of the primary nic.

Solution 2:[2]

It is possible to reach IMDS via an l2bridge (tried on a 2022 datacenter server). Create the network as

docker network create -d l2bridge --subnet $localContainerSubnet -o com.docker.network.windowsshim.dnsservers=$dnsServer --gateway $containerGw -o com.docker.network.windowsshim.enable_outboundnat=true <network_name>

where the variables $dnsServer, $localContainerSubnet, $containerGw are the same as the host's network (subnet is in CIDR format).

For details see this blog post and comment on creating an l2bridge on the same subnet.

After creating the network run the container with --network <network_name>.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Jimmy Bahuleyan