How to expose an ACI instance publicly while in a vnet?

jbx999 246 Reputation points
2021-03-05T18:15:18.077+00:00

I have an ACI that is running a REST API that needs to be exposed publicly, but needs to access resources inside a vnet.

For some reason, unlike normal VMs, if an ACI is inside a vnet, it cannot have a public IP address. If you try to give it a DNS name it fails.

The only option seems to be to use an Application Gateway as described here:
https://learn.microsoft.com/en-us/azure/container-instances/container-instances-application-gateway

But this approach has a fatal flaw, as indicated in the documentation itself: "If the container group is stopped, started, or restarted, the container group's private IP is subject to change. If this happens, you will need to update the application gateway configuration."

The Application Gateway has the option to select a backend pool by resource name, but this is only for normal VMs. The other option is to put in the IP address directly.

An ACI can easily get restarted without knowing. From experience, it happens relatively often that the host kills it and restarts it, possibly taking a different IP.

What is the right approach to expose a service running on an ACI instance on the internet, and at the same time have it access resources behind a vnet? The Application Gateway approach is evidently not the right approach.

Azure Container Instances
Azure Container Instances
An Azure service that provides customers with a serverless container experience.
632 questions
Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
6,823 questions
0 comments No comments
{count} vote

Accepted answer
  1. jbx999 246 Reputation points
    2021-04-04T10:42:59.323+00:00

    Turns out ACI are a half baked solution and there are no simple ways to expose a container instance while part of a vnet. The only practical solution is to use an Application Gateway, but ACIs resource IDs are not even available for backend pools, so you have to specify the IP address directly. So you need to somehow make sure that the IP address is updated each time the container is restarted, which happens a lot. One alternative one could explore is to use init containers to do this, which obviously makes something which is supposed to be simple, much more complicated and pointless.

    Furthermore, after using ACI with an Application Gateway, it turns out that the cost to operate the Application Gateway is much higher than the Container Instance itself! Might as well use a normal VM and do away with ACI and Application Gateway.

    Bottom line, do not use ACI for exposing a public service, unless you want to fight with all these issues.

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. amon 121 Reputation points Microsoft Employee
    2021-03-07T17:47:08.797+00:00

    Hi @jbx999

    My approach to solve this would be to use init containers.
    Any container group can have up to 59 init container that act the same as k8s init containers
    Once in the init container, you can pull the updated container instance private ip:

    ipAddress=$(az container show --resource-group "MyResourceGroup" --name "MyContainer" -o json --query ipAddress.ip)

    Then update the application gateway backend pool ip:

    az network application-gateway address-pool update -g MyResourceGroup --gateway-name MyAppGateway -n MyAddressPool --servers $ipAddress

    Note: every init container must exit successfully beforeyour application begins, so make sure you have a restart policy for the init containers in case it fails.
    Note 2: To give the container instance correct permissions in your Azure portal you can use managed identity and IAM.
    Note 3: A container with Azure cli: mcr.microsoft.com/azure-cli

    Here is a reference on init containers

    1 person found this answer helpful.