microsoft / microsoft/azure-container-apps
Feature Request: Cost effective way of pairing AFD with external ACA apps
@cachai2 is already working on this.
Since Mar 6, 2023.
- Dominant language
- Bicep
- Stars
- 445
- Forks
- 54
- Avg merge
- 5h 14m
- Merged PRs (30d)
- 3
Description
DISCLAIMER
I originally raised what follows through an Azure support ticket. Ultimately, they directed me to post my situation and my suggestion as a feature request on this repository.
Is your feature request related to a problem? Please describe.
It doesn't seem possible to use Azure Front Door for globally routing to regional ACA instances in such a way that allows the container app to eventually spin down to an idle state when there is low-to-no real user traffic. This is because each regional ACA instance is busy serving health probe requests issued from AFD before the container app has a chance to enter its idle state. As such, for each regional ACA instance the replicas are always in an active state and thus getting charged at the active usage rate. This means that in some situations your monthly charges incurred on your ACA instances basically come from solely responding to AFD health probe requests, which erodes some of the cost benefits of running external services in ACA.
Describe the solution you'd like.
It would be nice if there was a more cost effective way to pair AFD with ACA such that the container apps in the backend origin group actually have a chance to spin down to idle (and thus only get charged at the idle usage rate). To draw a comparison to Azure API Management, APIM service instances have a /status-0123456789abcdef default health endpoint (described here) that an AFD profile can use for sending probes and make routing decisions based on, e.g., lowest latency.
As a rough idea, it would be nice if an ACA environment offered a similar default endpoint that things like AFD can probe for the purposes of making routing decisions. The ideal situation would also not necessarily cause the request to reach the container app hosted in the ACA environment and cause it to enter into an active state. This would allow the container app to ideally enter in an idle state and remain in that state until a "real" request comes in, where "real" in this case basically means something that isn't a probe.
Describe alternatives you've considered.
I've looked at reducing the polling frequency of AFD's health probes. The longest duration I can set between probes in my AFD profile is roughly every four minutes. Even at this interval, a new round of health probes reaches my container app before it has a chance to spin any of its replicas down to idle.
More far out thoughts I've considered include possibly fronting my ACA instances with Azure Traffic Manager instead of AFD. My thought (not sure if it's right or not) was that by configuring a TCP probe instead of an HTTP probe via TM, I would avoid causing my container apps to transition from idle to active when TM sends its probe requests. Then my AFD origin would just include the FQDN of my TM instance. I haven't had a chance to see if 1) this deployment architecture would even work and 2) if it even improves my cost situation.
Additional context.
In my particular case, I'm working on a web application that will ultimately be deployed to different Azure regions to both reduce latency for my users as well as address data regionality concerns. I've been working with ACA to host different parts of that web application along with its APIs. In each supported region, I deploy an ACA environment with the set of ACA apps I need to run.
In each environment, there are two core services. The first is the Portal Host, which is an ASP.NET Core Razor pages app that essentially authenticates users and serves up an index page based on the modules they are authorized to access. The second is the Portal Services, which uses ASP.NET Core's minimal APIs to define a number of core APIs used by both the web app running in the user's browser as well as by other backend services. Beyond these two, there are other ACA apps hosting other APIs used by the portal.
I use AFD to handle routing user requests to the correct ACA app based on lowest latency to the backend origin. If the request path starts with /api, the request routes to a regional consumption tier APIM instance that then determines which ACA app is responsible for handling the request. If the request doesn't start with /api, then AFD forwards the request to the Portal Host app, assuming that it's basically a request for the portal's page itself.
The following illustrates this in a very simplified way, with one set of regional ACA + APIM instances shown.

Since one of my AFD origin groups basically contains the FQDNs for my Portal Host apps, AFD health probe requests are sent directly to them. As a consequence, my Portal Host container app gets about 100+ health probe requests from AFD's edge locations every 2-4 minutes. In a dev instance of this portal that sees almost no monthly traffic (it's a new product), this has the effect of keeping two replicas in that container app running constantly doing nothing but serving AFD probe requests. The following is from a 10-minute window for my Portal Host container app that I pulled while working through my Azure support ticket:

As you can see, two replicas are running constantly getting billed at the active usage rate. The only requests sent during this time were the AFD requests.
In contrast, the following shows the same metrics over a 1-hour period for my Portal Services app. The pair of requests this chart shows were issued from my Portal Host app. These occurred when I navigated to my dev portal instance in my browser. The salient point here is that the Portal Services container app spun up when the request came in, handled it, then spun back down after some duration. These metrics were pulled before I configured my API container apps to spin to idle instead of spin to zero.

Regardless though, my Portal Services app is charged for active usage only for the time it needs to handle real user requests, which is not the case for my Portal Host app. The latter is charged for active usage all the time where the vast majority of those requests are simply health probes from AFD. The real impact of this for me is driven home once I look at the difference in costs between the two container apps:

This was for my dev instance from which I pulled the above metrics. In this instance, I have a single Azure region configured. For our actual production scenario, we would be deploying to 5-6 different Azure regions, so rough math would suggest the cost numbers scaling linearly from there, and perhaps more so if a particular regional instance has more traffic (resulting in more ACA replicas spinning up).
When looking at these numbers, it seems at best odd that despite these container apps serving the same number of real user requests over the same time period that one of these (the portal host) would cost 1000x more than the other (the portal services). It seems like there should be a more cost-effective way of hosting external ACA apps that use Azure Front Door for global routing, ingress, and WAF protection, which I imagine would be at least a decently common enough use case for the two services.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.