After reading numerous articles and stumbling into the rabbit hole of not being able to use Elastic Premium Function Apps in restrictive network settings, we cracked it. We have a full solution on how to get this working properly, in a single location for future reference for all.
We were deploying a series of Azure Functions in a Virtual Network (VNET) configuration and began securing down all of the Storage Accounts and Functions to only be accessible from within the network. Whilst doing so, we started to notice some of our deployments began to fail. Most of these were the expected deployment IP addresses not added to target resources, but then some more failures appeared. These were 503 errors from Kudu, stating a failure in deploying after trying to run for a long time.
After some Googling, it became apparent that this was something a lot of other people were struggling with. Most leading to a Microsoft learn article answer pointing to an open issue that has remained open for 2 years for:
Failing deployments on Azure Functions when Storage Accounts are network restricted.
And guess what...
The issue is simply this, the Azure Function as part of it's deployment will try and create (or validate) that a File Share is setup and correctly configured on the Storage Account. This is to allow for function app code and configurations to be stored in event-driven scaling plans and is required for Consumption and Elastic Premium plan apps. In our situation, we are on Elastic Premium.
You may not have even discovered that this is an issue at the moment as the Function can start without it but normally will be inconsistent.
In our scenario, we hadn't configured the Azure File connection, but when we tried we ran into a lot of 403 errors in the Storage Account, effectively saying that Firewall rules were blocking the share from being created. As our storage account is locked down to VNET access and is configured to use managed identity for blob access, we presumed that this was the issue, but enabling access keys and setting the connection string with the keys we were still stumped.
From previous experiences, it's known that when using VNETs and Functions, you need to set some specific Environment variables like so for most of the connectivity and features to work properly:
vnetRouteAllEnabled = true
WEBSITE_VNET_ROUTE_ALL = 1 // Deprecated
However, after going through the long list of Function App settings we were then getting failures even saving the Function App Settings. With a number of 403 errors being raised yet again about access being restricted for the storage account. This is when we went through the list again and considered adding all of the so-called "Deprecated" settings. And voila, that allowed the App Settings to be saved and we were able to see more log errors in the Storage Account where more requests are being attempted and failing. We added these settings in the end.
vnetContentShareEnabled = true
vnetRouteAllEnabled = true
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING = {Storage Account Connection String With Key}
WEBSITE_CONTENTOVERVNET = 1 // Deprecated
WEBSITE_CONTENTSHARE = {Function App Name (without spaces/special characters)}
WEBSITE_DNS_SERVER = 168.63.129.16 // Azure DNS (Change to own if needed)
WEBSITE_VNET_ROUTE_ALL = 1 // Deprecated
At this stage, we resorted to created a private endpoint for the storage account (this article is a good guide, BUT MAKE SURE TO CREATE FOR THE FILES SUB-RESOURCE INSTEAD/ASWELL). This is key, we created the private endpoint and then attempted to save the App Settings, and yet we still were getting failures. A quick curl telnet://{storageaccountdomain}:445 (SMB protocol port) from the Kudo tools of the function revealed that we had connectivity but the share wasn't being created.
Our thinking lead us to the point that the Function can talk and communicate on the protocol, it just can't create the File Share initially which took us back to the first article we found (which was titled with same DevOps error we were experiencing Deployment of Azure Function App Fails with "Kudu")which talks about making the initial File Share directory. We quickly created this an we started having Files flow through a Storage Account Private Endpoint from a Private Azure Function into the File Share. Eureka!
For us, we're going to stop pulling our hair out finally over this issue and set this up as our new standard for all our Elastic Premium functions going forward, but I do hope that raising our journey and resolution that it will find many other people going through the same pain and having a clear road to resolution.
I hope that Microsoft also sees this article and understands that there are possible gaps or inconsistencies in the documentation, and that even if this route is not truly intended, as it works, either document it, or leave it to exist. Please don't patch this unless there is a clear, validated approach for all going forward.
Anyway, the fix instructions are at the bottom here if it's been a bit difficult to follow along. Thanks for reading and happy fixing!
vnetContentShareEnabled = true
vnetRouteAllEnabled = true
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING = {Storage Account Connection String With Key}
WEBSITE_CONTENTOVERVNET = 1 // Deprecated
WEBSITE_CONTENTSHARE = {Function App Name (without spaces/special characters)}
WEBSITE_DNS_SERVER = 168.63.129.16 // Azure DNS (Change to own if needed)
WEBSITE_VNET_ROUTE_ALL = 1 // Deprecated
At dotnet, we blend innovation, creativity, and technology to craft transformative digital solutions. From consultancy and engineering to data analytics, cloud hosting, and innovation, we offer a spectrum of services. Partner with us and embark on a journey of digital excellence.