Last active
October 21, 2025 14:28
-
-
Save maskati/e56d1bf6b4cc0e14f77d409e7f158e45 to your computer and use it in GitHub Desktop.
Revisions
-
maskati revised this gist
Oct 21, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,7 +7,7 @@ Microsoft recently released in public preview Private Link Service [Direct Conne > [!IMPORTANT] > To use direct connect you need to enable the feature flag `Microsoft.Network/AllowPrivateLinkserviceUDR` on your subscription e.g. using `az feature register --namespace Microsoft.Network --name AllowPrivateLinkserviceUDR`. Review the [direct connect prerequisites](https://learn.microsoft.com/en-us/azure/private-link/configure-private-link-service-direct-connect#prerequisites) for more details. [](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fgistcdn1.captainz.cc%2Fmaskati%2Fe56d1bf6b4cc0e14f77d409e7f158e45%2Fraw%2Fd1a9c37821fda09b6cd83aedf82fba728cecb970%2Farm.json) The example deploys the following: -
maskati created this gist
Oct 21, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,54 @@ Until recently Azure Private Link has been restricted to [specific Microsoft enabled resource types](https://learn.microsoft.com/en-us/azure/private-link/private-endpoint-overview#private-link-resource) or your own [Azure VM hosted resources](https://learn.microsoft.com/en-us/azure/private-link/private-link-service-overview). A notable limitation has been the requirement for the destination to be a [Standard Load Balancer with a backend pool configured by NIC](https://learn.microsoft.com/en-us/azure/private-link/private-link-service-overview#limitations). This excluded services such as [VNet integrated Azure Container Instances](https://learn.microsoft.com/en-us/azure/container-instances/container-instances-virtual-network-concepts), which do not support private endpoints and also do not provision a NIC in the VNet and therefore could only be routed by IP address. Microsoft recently released in public preview Private Link Service [Direct Connect](https://learn.microsoft.com/en-us/azure/private-link/configure-private-link-service-direct-connect). Direct Connect allows connectivity to any privately routable destination IP address. To demonstrate this new feature we can publish a private Azure Container Instance over Azure Private Link Service direct connect. > [!IMPORTANT] > To use direct connect you need to enable the feature flag `Microsoft.Network/AllowPrivateLinkserviceUDR` on your subscription e.g. using `az feature register --namespace Microsoft.Network --name AllowPrivateLinkserviceUDR`. Review the [direct connect prerequisites](https://learn.microsoft.com/en-us/azure/private-link/configure-private-link-service-direct-connect#prerequisites) for more details. [](https://portal.azure.com/#create/Microsoft.Template/uri/) The example deploys the following: ```mermaid flowchart LR subgraph VNET1["vnet-pls: 10.0.0.0/16"] subgraph SN1["subnet-aci: 10.0.1.0/24"] ACI1["Container Instance / nginx 10.0.1.4"] end subgraph SN2["subnet-pls: 10.0.2.0/24"] subgraph PLS["Private Link Service"] NAT1["NAT IP 10.0.2.4"] NAT2["NAT IP 10.0.2.5"] end end NAT1 -- "Direct connect" --> ACI1 NAT2 -- "Direct connect" --> ACI1 end subgraph VNET2["vnet-pe: 10.0.0.0/16"] subgraph SN3["subnet-aci: 10.0.1.0/24"] ACI2["Container Instance / client 10.0.1.4"] end subgraph SN4["subnet-pe: 10.0.2.0/24"] PE["Private Endpoint 10.0.2.4"] end end subgraph DNS["DNS: directconnect.test"] A["A ping -> 10.0.2.4"] end ACI2 -- "curl http://ping.directconnect.test" --> PE PE -- "Private Endpoint Connection" --> PLS VNET2 --- DNS DNS -.- PE ``` We can verify connectivity by running a curl command using [az container exec](https://learn.microsoft.com/en-us/cli/azure/container?view=azure-cli-latest#az-container-exec) (see the `curlCommand` deployment output parameter), noting that connections are distributed across private link service NAT addresses: ```sh ~ % az container exec --ids '/subscriptions/.../resourceGroups/.../providers/Microsoft.ContainerInstance/containerGroups/aci-pe' --exec-command 'curl http://ping.directconnect.test.' 2025-10-21T10:32:14+00:00 remote_addr=10.0.2.4 ~ % az container exec --ids '/subscriptions/.../resourceGroups/.../providers/Microsoft.ContainerInstance/containerGroups/aci-pe' --exec-command 'curl http://ping.directconnect.test.' 2025-10-21T10:32:20+00:00 remote_addr=10.0.2.5 ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,441 @@ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", "version": "0.38.33.27573", "templateHash": "18102201612663974453" } }, "parameters": { "location": { "type": "string", "allowedValues": [ "northcentralus", "eastus", "centralus", "southcentralus", "westus", "westus2", "westus3", "asiasoutheast", "australiaeast", "spaincentral" ] } }, "variables": { "$fxv#0": "d29ya2VyX3Byb2Nlc3NlcyAxOwoKZXZlbnRzIHsKICAgIHdvcmtlcl9jb25uZWN0aW9ucyAxMDI0Owp9CgpodHRwIHsKICAgIGRlZmF1bHRfdHlwZSB0ZXh0L3BsYWluOwogICAgc2VydmVyIHsKICAgICAgICBsaXN0ZW4gODA7CiAgICAgICAgbG9jYXRpb24gLyB7CiAgICAgICAgICAgICMgcmVtb3RlX2FkZHIgaXMgdGhlIHByaXZhdGUgbGluayBzZXJ2aWNlIG5hdGVkIGlwCiAgICAgICAgICAgIHJldHVybiAyMDAgIiR0aW1lX2lzbzg2MDEgcmVtb3RlX2FkZHI9JHJlbW90ZV9hZGRyXG4iOwogICAgICAgIH0KICAgIH0KfQo=", "vnetPlsAddressPrefix": "10.0.0.0/16", "vnetPeAddressPrefix": "10.0.0.0/16" }, "resources": { "vnetPls::subnetAci": { "existing": true, "type": "Microsoft.Network/virtualNetworks/subnets", "apiVersion": "2024-10-01", "name": "[format('{0}/{1}', 'vnet-pls', 'subnet-aci')]", "dependsOn": [ "vnetPls" ] }, "vnetPls::subnetPls": { "existing": true, "type": "Microsoft.Network/virtualNetworks/subnets", "apiVersion": "2024-10-01", "name": "[format('{0}/{1}', 'vnet-pls', 'subnet-pls')]", "dependsOn": [ "vnetPls" ] }, "vnetPe::subnetAci": { "existing": true, "type": "Microsoft.Network/virtualNetworks/subnets", "apiVersion": "2024-10-01", "name": "[format('{0}/{1}', 'vnet-pe', 'subnet-aci')]", "dependsOn": [ "vnetPe" ] }, "vnetPe::subnetPe": { "existing": true, "type": "Microsoft.Network/virtualNetworks/subnets", "apiVersion": "2024-10-01", "name": "[format('{0}/{1}', 'vnet-pe', 'subnet-pe')]", "dependsOn": [ "vnetPe" ] }, "dnsDirectConnectTest::linkVnetPe": { "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", "apiVersion": "2024-06-01", "name": "[format('{0}/{1}', 'directconnect.test', 'link-vnet-pe')]", "location": "global", "properties": { "registrationEnabled": false, "virtualNetwork": { "id": "[resourceId('Microsoft.Network/virtualNetworks', 'vnet-pe')]" } }, "dependsOn": [ "dnsDirectConnectTest", "vnetPe" ] }, "vnetPls": { "type": "Microsoft.Network/virtualNetworks", "apiVersion": "2024-10-01", "name": "vnet-pls", "location": "[parameters('location')]", "properties": { "addressSpace": { "addressPrefixes": [ "[variables('vnetPlsAddressPrefix')]" ] }, "subnets": [ { "name": "subnet-aci", "properties": { "addressPrefix": "[cidrSubnet(variables('vnetPlsAddressPrefix'), 24, 1)]", "delegations": [ { "name": "dMicrosoft.ContainerInstance/containerGroups", "properties": { "serviceName": "Microsoft.ContainerInstance/containerGroups" } } ] } }, { "name": "subnet-pls", "properties": { "addressPrefix": "[cidrSubnet(variables('vnetPlsAddressPrefix'), 24, 2)]", "privateLinkServiceNetworkPolicies": "Disabled" } } ] } }, "aciPls": { "type": "Microsoft.ContainerInstance/containerGroups", "apiVersion": "2025-09-01", "name": "aci-pls", "location": "[parameters('location')]", "properties": { "sku": "Standard", "osType": "Linux", "restartPolicy": "OnFailure", "ipAddress": { "type": "Private", "ports": [ { "port": 80 } ] }, "subnetIds": [ { "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-pls', 'subnet-aci')]" } ], "volumes": [ { "name": "nginxconfvolume", "secret": { "nginx.conf": "[variables('$fxv#0')]" } } ], "containers": [ { "name": "nginx", "properties": { "image": "mcr.microsoft.com/azurelinux/base/nginx:1.25", "command": [ "nginx", "-g", "daemon off;", "-c", "/mnt/nginx.conf" ], "resources": { "requests": { "cpu": "[json('0.1')]", "memoryInGB": "[json('0.1')]" } }, "ports": [ { "port": 80 } ], "volumeMounts": [ { "name": "nginxconfvolume", "mountPath": "/mnt" } ] } } ] }, "dependsOn": [ "vnetPls" ] }, "plsDirectConnect": { "type": "Microsoft.Network/privateLinkServices", "apiVersion": "2024-10-01", "name": "pls-directconnect", "location": "[parameters('location')]", "properties": { "destinationIPAddress": "[reference('aciPls').ipAddress.ip]", "enableProxyProtocol": false, "ipConfigurations": [ { "name": "ipconfig1", "properties": { "primary": true, "privateIPAddressVersion": "IPv4", "privateIPAllocationMethod": "Static", "privateIPAddress": "[cidrHost(reference('vnetPls::subnetPls').addressPrefix, 3)]", "subnet": { "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-pls', 'subnet-pls')]" } } }, { "name": "ipconfig2", "properties": { "primary": false, "privateIPAddressVersion": "IPv4", "privateIPAllocationMethod": "Static", "privateIPAddress": "[cidrHost(reference('vnetPls::subnetPls').addressPrefix, 4)]", "subnet": { "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-pls', 'subnet-pls')]" } } } ] }, "dependsOn": [ "aciPls", "vnetPls", "vnetPls::subnetPls" ] }, "vnetPe": { "type": "Microsoft.Network/virtualNetworks", "apiVersion": "2024-10-01", "name": "vnet-pe", "location": "[parameters('location')]", "properties": { "addressSpace": { "addressPrefixes": [ "[variables('vnetPeAddressPrefix')]" ] }, "subnets": [ { "name": "subnet-aci", "properties": { "addressPrefix": "[cidrSubnet(variables('vnetPeAddressPrefix'), 24, 1)]", "delegations": [ { "name": "Microsoft.ContainerInstance/containerGroups", "properties": { "serviceName": "Microsoft.ContainerInstance/containerGroups" } } ] } }, { "name": "subnet-pe", "properties": { "addressPrefix": "[cidrSubnet(variables('vnetPeAddressPrefix'), 24, 2)]" } } ] } }, "aciPe": { "type": "Microsoft.ContainerInstance/containerGroups", "apiVersion": "2025-09-01", "name": "aci-pe", "location": "[parameters('location')]", "properties": { "sku": "Standard", "osType": "Linux", "restartPolicy": "Never", "ipAddress": { "type": "Private", "ports": [ { "port": 65534, "protocol": "UDP" } ] }, "subnetIds": [ { "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-pe', 'subnet-aci')]" } ], "containers": [ { "name": "azurelinux", "properties": { "image": "mcr.microsoft.com/azurelinux/base/core:3.0", "command": [ "sleep", "infinity" ], "resources": { "requests": { "cpu": "[json('0.1')]", "memoryInGB": "[json('0.1')]" } }, "ports": [ { "port": 65534, "protocol": "UDP" } ] } } ] }, "dependsOn": [ "vnetPe" ] }, "peDirectConnect": { "type": "Microsoft.Network/privateEndpoints", "apiVersion": "2024-10-01", "name": "pe-directconnect", "location": "[parameters('location')]", "properties": { "subnet": { "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-pe', 'subnet-pe')]" }, "privateLinkServiceConnections": [ { "name": "pls-connection", "properties": { "privateLinkServiceId": "[resourceId('Microsoft.Network/privateLinkServices', 'pls-directconnect')]", "requestMessage": "Approve connection for direct connect" } } ] }, "dependsOn": [ "plsDirectConnect", "vnetPe" ] }, "dnsDirectConnectTest": { "type": "Microsoft.Network/privateDnsZones", "apiVersion": "2024-06-01", "name": "directconnect.test", "location": "global" }, "dns": { "type": "Microsoft.Resources/deployments", "apiVersion": "2025-04-01", "name": "[format('dns-{0}', uniqueString('dns', deployment().name))]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { "dnsAName": { "value": "ping" }, "dnsRid": { "value": "[resourceId('Microsoft.Network/privateDnsZones', 'directconnect.test')]" }, "nicRid": { "value": "[reference('peDirectConnect').networkInterfaces[0].id]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", "version": "0.38.33.27573", "templateHash": "12135959616729773951" } }, "parameters": { "nicRid": { "type": "string", "minLength": 116, "metadata": { "description": "The resource ID of the private endpoint network interface" } }, "dnsRid": { "type": "string", "minLength": 116, "metadata": { "description": "The resource ID of the private DNS zone" } }, "dnsAName": { "type": "string", "minLength": 1, "maxLength": 253, "metadata": { "description": "The A record name to create in the private DNS zone" } } }, "resources": [ { "type": "Microsoft.Network/privateDnsZones/A", "apiVersion": "2024-06-01", "name": "[format('{0}/{1}', split(parameters('dnsRid'), '/')[8], parameters('dnsAName'))]", "properties": { "aRecords": [ { "ipv4Address": "[reference(resourceId('Microsoft.Network/networkInterfaces', split(parameters('nicRid'), '/')[8]), '2024-10-01').ipConfigurations[0].properties.privateIPAddress]" } ], "ttl": 300 } } ], "outputs": { "ipAddress": { "type": "string", "value": "[reference(resourceId('Microsoft.Network/networkInterfaces', split(parameters('nicRid'), '/')[8]), '2024-10-01').ipConfigurations[0].properties.privateIPAddress]" }, "fqdn": { "type": "string", "value": "[reference(resourceId('Microsoft.Network/privateDnsZones/A', split(parameters('dnsRid'), '/')[8], parameters('dnsAName')), '2024-06-01').fqdn]" } } } }, "dependsOn": [ "dnsDirectConnectTest", "peDirectConnect" ] } }, "outputs": { "curlCommand": { "type": "string", "value": "[format('az container exec --ids ''{0}'' --exec-command ''curl http://{1}''', resourceId('Microsoft.ContainerInstance/containerGroups', 'aci-pe'), reference('dns').outputs.fqdn.value)]" } } }