We are trying to deploy Azure Linux App Service, that also has mounted storage. Here's our ARM template
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"Environment": {
"type": "String",
"allowedValues": [
"dev",
"stg",
"prd"
]
},
"Region": {
"type": "string",
"allowedValues": [
"eu",
"we"
]
},
"MagentoMediaFileShareName": {
"type": "string"
},
"StorageAccountName": {
"type": "string"
},
"StorageAccountAccessKey": {
"type": "securestring"
},
"MagentoMediaMountPath": {
"type": "string",
"defaultValue": "/var/www/html/pub/external_media"
}
},
"variables": {
"Location": "[resourceGroup().location]",
"ResourcePrefix": "[format('ariva-{0}-{1}-magento', parameters('Environment'), parameters('Region'))]",
"WebSiteName": "[concat(variables('ResourcePrefix'), '-web')]",
"ServicePlanId": "[format('/subscriptions/{0}/resourceGroups/ariva-{1}-{2}/providers/Microsoft.Web/serverfarms/ariva-{1}-{2}-asp', subscription().subscriptionId, parameters('Environment'), parameters('Region'))]"
},
"resources": [
{
"type": "Microsoft.Web/sites",
"apiVersion": "2020-12-01",
"name": "[variables('WebSiteName')]",
"location": "[variables('Location')]",
"kind": "app,linux,container",
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(variables('WebSiteName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(variables('WebSiteName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"serverFarmId": "[variables('ServicePlanId')]",
"reserved": true,
"isXenon": false,
"hyperV": false,
"siteConfig": {
"numberOfWorkers": 1,
"linuxFxVersion": "DOCKER|mcr.microsoft.com/appsvc/staticsite:latest",
"acrUseManagedIdentityCreds": false,
"alwaysOn": false,
"http20Enabled": false,
"functionAppScaleLimit": 0,
"minimumElasticInstanceCount": 1
},
"scmSiteAlsoStopped": false,
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"clientCertMode": "Required",
"hostNamesDisabled": false,
"customDomainVerificationId": "1071794BD68C78EC0A4569F03C034F6E1B21BD4E6D35725D99523AC00AE12AA1",
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"keyVaultReferenceIdentity": "SystemAssigned",
"httpsOnly": false,
"redundancyMode": "None",
"storageAccountRequired": false
}
},
{
"type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies",
"apiVersion": "2020-12-01",
"name": "[concat(variables('WebSiteName'), '/ftp')]",
"location": "[variables('Location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
],
"properties": {
"allow": true
}
},
{
"type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies",
"apiVersion": "2020-12-01",
"name": "[concat(variables('WebSiteName'), '/scm')]",
"location": "[variables('Location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
],
"properties": {
"allow": true
}
},
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2020-12-01",
"name": "[concat(variables('WebSiteName'), '/web')]",
"location": "[variables('Location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
],
"properties": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.0",
"linuxFxVersion": "DOCKER|mcr.microsoft.com/appsvc/staticsite:latest",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2019",
"httpLoggingEnabled": false,
"acrUseManagedIdentityCreds": false,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"publishingUsername": "[concat('$', variables('WebSiteName'))]",
"azureStorageAccounts": {
"magento-media": {
"type": "AzureFiles",
"accountName": "[parameters('StorageAccountName')]",
"shareName": "[parameters('MagentoMediaFileShareName')]",
"mountPath": "[parameters('MagentoMediaMountPath')]",
"accessKey": "[parameters('StorageAccountAccessKey')]"
}
},
"scmType": "None",
"use32BitWorkerProcess": true,
"webSocketsEnabled": true,
"alwaysOn": true,
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false
}
],
"loadBalancing": "LeastRequests",
"experiments": {
"rampUpRules": []
},
"autoHealEnabled": false,
"vnetRouteAllEnabled": false,
"vnetPrivatePortsCount": 0,
"localMySqlEnabled": false,
"ipSecurityRestrictions": [
{
"ipAddress": "Any",
"action": "Allow",
"priority": 1,
"name": "Allow all",
"description": "Allow all access"
}
],
"scmIpSecurityRestrictions": [
{
"ipAddress": "Any",
"action": "Allow",
"priority": 1,
"name": "Allow all",
"description": "Allow all access"
}
],
"scmIpSecurityRestrictionsUseMain": false,
"http20Enabled": true,
"minTlsVersion": "1.2",
"scmMinTlsVersion": "1.0",
"ftpsState": "AllAllowed",
"preWarmedInstanceCount": 0,
"functionAppScaleLimit": 0,
//"healthCheckPath": "/health_check.php",
"functionsRuntimeScaleMonitoringEnabled": false,
"minimumElasticInstanceCount": 1
}
},
{
"type": "Microsoft.Web/sites/hostNameBindings",
"apiVersion": "2020-12-01",
"name": "[concat(variables('WebSiteName'), '/', variables('WebSiteName'), '.azurewebsites.net')]",
"location": "[variables('Location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('WebSiteName'))]"
],
"properties": {
"siteName": "[variables('WebSiteName')]",
"hostNameType": "Verified"
}
}
]
}
If we execute this exact template, we will receive the following error
{
"status": "Failed",
"error": {
"code": "BadRequest",
"message": "Required parameter AccessKey is missing.",
"details": [
{
"message": "Required parameter AccessKey is missing."
},
{
"code": "BadRequest"
},
{}
]
}
}
We receive the same error if we have storage manually mounted through portal and try to change the configurations or add deployment slots.
As soon as I remove the mounted storage configuration, everything works just fine.
We need to have this in our DevOps pipeline, it's not acceptable that we unmount-remount the storage manually before and after the deployments. That would cause major issues and downtime. What can we do to overcome the issue?
UPDATE 1
I've tried to create a totally separate web app and storage account all manually. As soon as I hooked the storage mount and tried to enable health checks for instance, I got the same error. I think there's a bug in Azure.
UPDATE 2
Here is the template that deploys the dependent storage account
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"Environment": {
"type": "String",
"allowedValues": [
"dev",
"stg",
"prd"
]
},
"Region": {
"type": "string",
"allowedValues": [
"eu",
"we"
]
}
},
"variables": {
"Location": "[resourceGroup().location]",
"StorageAccountName": "[format('ariva{0}{1}magentostorage', parameters('Environment'), parameters('Region'))]",
"MagentoMediaFileShareName": "magento-media"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-04-01",
"name": "[variables('StorageAccountName')]",
"location": "[variables('Location')]",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "StorageV2",
"properties": {
"allowCrossTenantReplication": true,
"minimumTlsVersion": "TLS1_2",
"allowBlobPublicAccess": true,
"allowSharedKeyAccess": true,
"networkAcls": {
"resourceAccessRules": [],
"bypass": "AzureServices",
"virtualNetworkRules": [],
"ipRules": [],
"defaultAction": "Allow"
},
"supportsHttpsTrafficOnly": true,
"encryption": {
"services": {
"file": {
"keyType": "Account",
"enabled": true
},
"blob": {
"keyType": "Account",
"enabled": true
}
},
"keySource": "Microsoft.Storage"
},
"accessTier": "Hot"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices",
"apiVersion": "2021-04-01",
"name": "[concat(variables('StorageAccountName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"properties": {
"changeFeed": {
"enabled": false
},
"restorePolicy": {
"enabled": false
},
"containerDeleteRetentionPolicy": {
"enabled": true,
"days": 7
},
"cors": {
"corsRules": []
},
"deleteRetentionPolicy": {
"enabled": true,
"days": 7
},
"isVersioningEnabled": false
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices",
"apiVersion": "2021-04-01",
"name": "[concat(variables('StorageAccountName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"properties": {
"shareDeleteRetentionPolicy": {
"enabled": true,
"days": 7
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/queueServices",
"apiVersion": "2021-04-01",
"name": "[concat(variables('StorageAccountName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
],
"properties": {
"cors": {
"corsRules": []
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/tableServices",
"apiVersion": "2021-04-01",
"name": "[concat(variables('StorageAccountName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
],
"properties": {
"cors": {
"corsRules": []
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices/shares",
"apiVersion": "2021-04-01",
"name": "[concat(variables('StorageAccountName'), '/default/', variables('MagentoMediaFileShareName'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/fileServices', variables('StorageAccountName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('StorageAccountName'))]"
],
"properties": {
"accessTier": "TransactionOptimized",
"shareQuota": 5120,
"enabledProtocols": "SMB"
}
}
],
"outputs": {
"MagentoMediaFileShareName": {
"type": "string",
"value": "[variables('MagentoMediaFileShareName')]"
},
"StorageAccountName": {
"type": "string",
"value": "[variables('StorageAccountName')]"
},
"StorageAccountAccessKey": {
"type": "securestring",
"value": "[listKeys(variables('StorageAccountName'), '2019-04-01').keys[0].value]"
}
}
}
UPDATE 3 - temporary workaround
We were able to find a temporary workaround. Instead of deploying the file mount through the ARM template, we've removed that bit from ARM template, after, we use the following build step in our DevOps pipeline to mount the storage through azure CLI
- task: AzureCLI@2
displayName: 'Attach media volume'
inputs:
azureSubscription: '${{ parameters.azureSubscription }}'
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
az webapp config storage-account add `
--resource-group ${{ parameters.resourceGroup }} `
--name "$(WebSiteName)" `
--access-key "$(StorageAccountAccessKey)" `
--custom-id magento-media `
--storage-type AzureFiles `
--share-name "$(MagentoMediaFileShareName)" `
--account-name "$(StorageAccountName)" `
--mount-path "/var/www/html/pub/external_media"
This doesn't solve the problem of course.
azureStorageAccounts
is not part of Microsoft.Web sites/config 2020-12-01 however it is under Microsoft.Web sites 2020-12-01 SiteConfig
property. This may be the reason accessKey wasn't found, wasn't uploaded. I would move azureStorageAccounts
under siteConfig