Provide optional parameters to support AZ redundancy for MySQL and Web App and HA for MySQL (#89)

* Add MySQL High Availability support; AZ support for MySQL and App Svc
* Add support for adding an NSG to all subnets
* Default to P0v3 App Service tier.
* Correct REDCap capitalization
* Update API version of Microsoft.Web provider
* Remove allowed values for environment param
* Add support for specifying REDCap version downloaded from community
* Set default MySQL SKU to B1ms
This commit is contained in:
Sven Aelterman 2024-11-12 11:24:04 -06:00 коммит произвёл GitHub
Родитель 7434d50392
Коммит 2c53bebb26
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
8 изменённых файлов: 108 добавлений и 27 удалений

Просмотреть файл

@ -48,6 +48,8 @@ To deploy the REDCap source to Azure App Service, you must supply your REDCap Co
(1) Review <https://learn.microsoft.com/azure/mysql/flexible-server/concepts-service-tiers-storage> for details on available features, regions, and pricing models for Azure DB for MySQL.
Advanced deployments can enable high availability for the MySQL Flexible Server and availability zone redundancy for the MySQL Flexible Server and web app. These capabilities can be controlled using parameters for the Bicep deployment.
<!--(2) SendGrid is a paid service with a free tier offering 25k messages per month, with additional paid tiers offering more volume, whitelisting, custom domains, etc. There is a limit of two instances per subscription using the free tier. For more information see <https://docs.microsoft.com/en-us/azure/store-sendgrid-php-how-to-send-email#create-a-sendgrid-account>. The service will be accessed initially using the password you enter in the deployment template. You can click "Manage" on the SendGrid service after deployment to administrate the service in their portal, including options to create an API key that can be used for access instead of the password.
If after deployment, you would instead like to use a different SMTP relay, edit the values "smtp_fqdn_name", "smtp_port", "smtp_user_name", and "smtp_password" to point to your preferred endpoint. You can then delete the SendGrid service from this resource group.

Просмотреть файл

@ -18,8 +18,8 @@ param vnetAddressSpace = '10.0.0.0/24'
// Do not specify a URL if you are using this option. The deployment script will download the zip file from the REDCap community.
param redcapZipUrl = '<Valid Redcap Zip URL>'
// -- OR --
param redcapCommunityUsername = '<Valid Redcap Community Username>'
param redcapCommunityPassword = '<Valid Redcap Community Password>'
param redcapCommunityUsername = '<Valid REDCap Community Username>'
param redcapCommunityPassword = '<Valid REDCap Community Password>'
// These values are used to configure the App Service Deployment Center.
// The defaults below are the Microsoft-maintained Azure REDCap PaaS repository.
@ -41,4 +41,26 @@ param smtpFromEmailAddress = '<Specify valid SMTP From Email Address>'
// A new password is generated for each deployment and stored in Key Vault.
param sqlPassword = ''
param appServiceTimeZone = 'UTC'
// param existingVirtualNetworkId = '/subscriptions/c236b7b3-dec1-47a6-856c-8c1f45d88575/resourceGroups/redcap-networkexisting-test-rg-cnc-01/providers/Microsoft.Network/virtualNetworks/redcap-existing-demo-vnet-cnc-01'
// param existingPrivateDnsZonesResourceGroupId = '/subscriptions/c236b7b3-dec1-47a6-856c-8c1f45d88575/resourceGroups/redcap-networkexisting-test-rg-cnc-01'
// param subnets = {
// PrivateLinkSubnet: {
// existingSubnetName: 'PlSubnet'
// }
// MySQLFlexSubnet: {
// existingSubnetName: 'SqlSubnet'
// }
// IntegrationSubnet: {
// existingSubnetName: 'WebAppSubnet'
// }
// }
// param mySqlSkuTier = 'GeneralPurpose'
// param mySqlHighAvailability = 'Enabled'
// param mySqlSkuName = 'Standard_D4ds_v4'
// param availabilityZonesEnabled = true
// param mySqlStorageSizeGB = 200
// param mySqlStorageIops = 1200
// param appServiceTimeZone = 'UTC'

Просмотреть файл

@ -4,11 +4,11 @@ targetScope = 'subscription'
param location string = 'eastus'
@description('The environment designator for the deployment. Replaces {env} in namingConvention.')
@allowed([
'test'
'demo'
'prod'
])
// @allowed([
// 'test'
// 'demo'
// 'prod'
// ])
param environment string = 'demo'
@description('The workload name. Replaces {workloadName} in namingConvention.')
param workloadName string = 'redcap'
@ -34,6 +34,8 @@ param redcapCommunityUsername string
@description('REDCap Community site password for downloading the REDCap zip file.')
@secure()
param redcapCommunityPassword string
@description('The version of REDCap to download from the REDCap Community. This is not used when specifying a ZIP URL.')
param redcapVersion string = ''
@description('Github Repo URL where build scripts are downloaded from')
param scmRepoUrl string = 'https://github.com/microsoft/azure-redcap-paas'
@description('Github Repo Branch where build scripts are downloaded from')
@ -49,6 +51,25 @@ param enableAppServicePrivateEndpoint bool = true
@secure()
param sqlPassword string
@description('Whether High Availability is enabled for the MySQL Flexible Server. Zone redundant or same zone HA is determined by the value of availabilityZonesEnabled.')
@allowed([
'Enabled'
'Disabled'
])
param mySqlHighAvailability string = 'Disabled'
param mySqlSkuName string = 'Standard_B1ms'
@allowed([
'GeneralPurpose'
'MemoryOptimized'
'Burstable'
])
param mySqlSkuTier string = 'Burstable'
@description('The size of the MySQL Flexible Server storage in GB. This cannot be scaled down after server creation.')
param mySqlStorageSizeGB int = 20
param mySqlStorageIops int = 396
@description('The MySQL Flexible Server admin user account name. Defaults to \'sqladmin\'.')
param sqlAdmin string = 'sqladmin'
@ -59,6 +80,10 @@ param smtpPort string = ''
@description('The email address to use as the sender for outgoing emails.')
param smtpFromEmailAddress string = ''
param appServiceSkuName string = 'P0v3'
@description('Determines whether availability zone redundancy is enabled for the MySQL Flexible Server and the app service. The region must support availability zones.')
param availabilityZonesEnabled bool = false
param existingPrivateDnsZonesResourceGroupId string = ''
param existingVirtualNetworkId string = ''
@ -358,10 +383,10 @@ module mySqlModule './modules/sql/main.bicep' = {
customTags: {
workloadType: 'mySqlFlexibleServer'
}
skuName: 'Standard_B1ms'
SkuTier: 'Burstable'
StorageSizeGB: 20
StorageIops: 396
skuName: mySqlSkuName
SkuTier: mySqlSkuTier
StorageSizeGB: mySqlStorageSizeGB
StorageIops: mySqlStorageIops
peSubnetId: empty(existingVirtualNetworkId)
? virtualNetworkModule.outputs.subnets.MySQLFlexSubnet.id
: '${existingVirtualNetworkId}/subnets/${subnets.MySQLFlexSubnet.existingSubnetName}'
@ -373,6 +398,9 @@ module mySqlModule './modules/sql/main.bicep' = {
// TODO: Consider using workloadname + 'db'
databaseName: 'redcapdb'
highAvailability: mySqlHighAvailability
availabilityZonesEnabled: availabilityZonesEnabled
roles: rolesModule.outputs.roles
uamiId: uamiModule.outputs.id
@ -405,8 +433,7 @@ module webAppModule './modules/webapp/main.bicep' = {
webAppName: webAppName
appServicePlanName: planName
location: location
// Deploy as P0V3 to ensure the deployment runs on a scale unit that supports P_v3 for future upgrades. GH issue #50
skuName: 'P0V3'
skuName: appServiceSkuName
peSubnetId: privateEndpointSubnetId
appInsights_connectionString: monitoring.outputs.appInsightsResourceId
appInsights_instrumentationKey: monitoring.outputs.appInsightsInstrumentationKey
@ -429,6 +456,7 @@ module webAppModule './modules/webapp/main.bicep' = {
redcapCommunityUsernameSecretRef: kvSecretReferencesModule.outputs.keyVaultRefs[1]
redcapCommunityPasswordSecretRef: kvSecretReferencesModule.outputs.keyVaultRefs[0]
redcapVersion: redcapVersion
storageAccountKeySecretRef: kvSecretReferencesModule.outputs.keyVaultRefs[4]
storageAccountContainerName: storageAccountModule.outputs.containerName
@ -451,6 +479,7 @@ module webAppModule './modules/webapp/main.bicep' = {
uamiId: uamiModule.outputs.id
availabilityZonesEnabled: availabilityZonesEnabled
enablePrivateEndpoint: enableAppServicePrivateEndpoint
timeZone: appServiceTimeZone

Просмотреть файл

@ -13,6 +13,7 @@ param subnets object
param tags object
param customDnsIPs array
param networkSecurityGroupId string = ''
var subnetDefsArray = items(subnets)
@ -30,6 +31,11 @@ resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-05-01' = {
name: subnet.key
properties: {
addressPrefix: subnet.value.addressPrefix
networkSecurityGroup: !empty(networkSecurityGroupId)
? {
id: networkSecurityGroupId
}
: null
serviceEndpoints: subnet.value.?serviceEndpoints
delegations: contains(subnet.value, 'delegation') && !empty(subnet.value.delegation)
? [

Просмотреть файл

@ -36,6 +36,14 @@ param skuName string = 'Standard_B1ms'
])
param SkuTier string
@allowed([
'Enabled'
'Disabled'
])
param highAvailability string = 'Disabled'
param availabilityZonesEnabled bool = false
@description('Azure database for MySQL storage Size ')
param StorageSizeGB int = 20
@ -81,6 +89,9 @@ module mysqlDbserver './sql.bicep' = {
database_charset: database_charset
database_collation: database_collation
highAvailability: (highAvailability == 'Enabled') ? true : false
availabilityZonesEnabled: availabilityZonesEnabled
roles: roles
uamiId: uamiId
uamiPrincipalId: uamiPrincipalId

Просмотреть файл

@ -6,7 +6,7 @@ param tags object
// TODO: skuName and SkuTier are related; should be specified as a single object param, IMHO
@description('Azure database for MySQL sku name ')
param skuName string = 'Standard_B1s'
param skuName string = 'Standard_B1ms'
@description('Azure database for MySQL pricing tier')
@allowed([
@ -53,11 +53,9 @@ param geoRedundantBackup string = 'Disabled'
param backupRetentionDays int = 7
@allowed([
'Enabled'
'Disabled'
])
param highAvailability string = 'Disabled'
param highAvailability bool = false
param availabilityZonesEnabled bool = false
@allowed([
'Enabled'
@ -90,7 +88,9 @@ resource server 'Microsoft.DBforMySQL/flexibleServers@2022-09-30-preview' = {
geoRedundantBackup: geoRedundantBackup
}
highAvailability: {
mode: highAvailability
mode: (highAvailability && availabilityZonesEnabled)
? 'ZoneRedundant'
: (highAvailability) ? 'SameZone' : 'Disabled'
}
network: {
delegatedSubnetResourceId: peSubnetId
@ -143,7 +143,7 @@ resource dbConfigDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10
scriptContent: 'az mysql flexible-server parameter set -g ${resourceGroup().name} --server-name ${server.name} --name sql_generate_invisible_primary_key --value OFF'
}
tags: tags
dependsOn: [ uamiMySqlRoleAssignmentModule ]
dependsOn: [uamiMySqlRoleAssignmentModule]
}
output mySqlServerName string = server.name

Просмотреть файл

@ -15,6 +15,8 @@ param privateDnsZoneName string
param virtualNetworkId string
param integrationSubnetId string
param availabilityZonesEnabled bool = false
param smtpFQDN string = ''
param smtpPort string = ''
param smtpFromEmailAddress string = ''
@ -33,6 +35,7 @@ param scmRepoUrl string
param scmRepoBranch string
@secure()
param redcapZipUrl string
param redcapVersion string = ''
#disable-next-line secure-secrets-in-params
param redcapCommunityUsernameSecretRef string
#disable-next-line secure-secrets-in-params
@ -78,6 +81,7 @@ module appService 'webapp.bicep' = {
redcapZipUrl: redcapZipUrl
redcapCommunityUsernameSecretRef: redcapCommunityUsernameSecretRef
redcapCommunityPasswordSecretRef: redcapCommunityPasswordSecretRef
redcapVersion: redcapVersion
scmRepoUrl: scmRepoUrl
scmRepoBranch: scmRepoBranch
@ -93,6 +97,7 @@ module appService 'webapp.bicep' = {
uamiId: uamiId
availabiltyZonesEnabled: availabilityZonesEnabled
enablePrivateEndpoint: enablePrivateEndpoint
timeZone: timeZone

Просмотреть файл

@ -21,6 +21,7 @@ param redcapZipUrl string
param redcapCommunityUsernameSecretRef string
#disable-next-line secure-secrets-in-params
param redcapCommunityPasswordSecretRef string
param redcapVersion string = ''
param scmRepoUrl string
param scmRepoBranch string
param prerequisiteCommand string
@ -28,6 +29,7 @@ param prerequisiteCommand string
param appInsights_connectionString string
param appInsights_instrumentationKey string
param availabiltyZonesEnabled bool = false
param enablePrivateEndpoint bool
param smtpFQDN string = ''
@ -45,23 +47,23 @@ param minTlsVersion string = '1.2'
param uamiId string
resource appSrvcPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
resource appSrvcPlan 'Microsoft.Web/serverfarms@2023-12-01' = {
name: appServicePlanName
location: location
tags: tags
sku: {
name: skuName
//tier: skuTier
}
kind: 'linux'
properties: {
reserved: true
zoneRedundant: availabiltyZonesEnabled
}
}
var DBSslCa = '/home/site/wwwroot/DigiCertGlobalRootCA.crt.pem'
resource webApp 'Microsoft.Web/sites@2022-03-01' = {
resource webApp 'Microsoft.Web/sites@2023-12-01' = {
name: webAppName
location: location
tags: tags
@ -101,6 +103,10 @@ resource webApp 'Microsoft.Web/sites@2022-03-01' = {
name: 'redcapAppZip'
value: redcapZipUrl
}
{
name: 'zipVersion'
value: redcapVersion
}
{
name: 'redcapCommunityUsername'
value: redcapCommunityUsernameSecretRef
@ -179,7 +185,7 @@ resource webApp 'Microsoft.Web/sites@2022-03-01' = {
// SCM Basic Authentication is required when using the App Service Build Service
// Per https://learn.microsoft.com/en-us/azure/app-service/deploy-continuous-deployment?tabs=github%2Cappservice#what-are-the-build-providers
resource basicScmCredentials 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-01-01' = {
resource basicScmCredentials 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-12-01' = {
parent: webApp
name: 'scm'
properties: {
@ -187,7 +193,7 @@ resource basicScmCredentials 'Microsoft.Web/sites/basicPublishingCredentialsPoli
}
}
resource sourcecontrol 'Microsoft.Web/sites/sourcecontrols@2022-09-01' = {
resource sourcecontrol 'Microsoft.Web/sites/sourcecontrols@2023-12-01' = {
parent: webApp
name: 'web'
properties: {