Skip to content

Commit

Permalink
Merge pull request #5483 from dfe-analytical-services/EES-XXXX-add-pe…
Browse files Browse the repository at this point in the history
…r-environment-scaling-and-workload-profiles

Ees xxxx add per environment scaling and workload profiles
  • Loading branch information
duncan-at-hiveit authored Dec 31, 2024
2 parents 8cf86df + 3ddcaff commit dd62dd3
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ResourceNames } from '../../types.bicep'
import { ResourceNames, ContainerAppResourceConfig } from '../../types.bicep'

@description('Specifies common resource naming variables.')
param resourceNames ResourceNames
Expand Down Expand Up @@ -30,6 +30,9 @@ param apiAppRegistrationClientId string
@description('Specifies the Application Insights connection string for this Container App to use for its monitoring.')
param appInsightsConnectionString string

@description('Resource limits and scaling configuration.')
param resourceAndScalingConfig ContainerAppResourceConfig

@description('Whether to create or update Azure Monitor alerts during this deploy')
param deployAlerts bool

Expand Down Expand Up @@ -145,6 +148,12 @@ module apiContainerAppModule '../../components/containerApp.bicep' = {
]
requireAuthentication: false
}
cpuCores: resourceAndScalingConfig.cpuCores
memoryGis: resourceAndScalingConfig.memoryGis
minReplicas: resourceAndScalingConfig.minReplicas
maxReplicas: resourceAndScalingConfig.maxReplicas
scaleAtConcurrentHttpRequests: resourceAndScalingConfig.scaleAtConcurrentHttpRequests
workloadProfileName: resourceAndScalingConfig.workloadProfileName
tagValues: tagValues
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ResourceNames } from '../../types.bicep'
import { ResourceNames, ContainerAppWorkloadProfile } from '../../types.bicep'

@description('Specifies common resource naming variables.')
param resourceNames ResourceNames
Expand All @@ -9,6 +9,9 @@ param location string
@description('Specifies the Application Insights key that is associated with this resource.')
param applicationInsightsKey string

@description('Specifies the workload profiles for this Container App Environment - the default Consumption plan is always included')
param workloadProfiles ContainerAppWorkloadProfile[] = []

@description('Specifies a set of tags with which to tag the resource in Azure.')
param tagValues object

Expand All @@ -33,7 +36,6 @@ module containerAppEnvironmentModule '../../components/containerAppEnvironment.b
subnetId: subnet.id
logAnalyticsWorkspaceName: resourceNames.sharedResources.logAnalyticsWorkspace
applicationInsightsKey: applicationInsightsKey
tagValues: tagValues
azureFileStorages: [
{
storageName: resourceNames.publicApi.publicApiFileShare
Expand All @@ -43,6 +45,8 @@ module containerAppEnvironmentModule '../../components/containerAppEnvironment.b
accessMode: 'ReadWrite'
}
]
workloadProfiles: workloadProfiles
tagValues: tagValues
}
}

Expand Down
5 changes: 5 additions & 0 deletions infrastructure/templates/public-api/ci/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ parameters:
- name: deployDataProcessor
displayName: Does the Data Processor need creating or updating?
default: true
- name: deployDocsSite
displayName: Does the Public API static docs site need creating or updating?
default: true
- name: deployAlerts
displayName: Whether to create or update Azure Monitor alerts during this deploy.
default: false
Expand Down Expand Up @@ -58,6 +61,8 @@ variables:
value: ${{ parameters.deployContainerApp }}
- name: deployDataProcessor
value: ${{ parameters.deployDataProcessor }}
- name: deployDocsSite
value: ${{ parameters.deployDocsSite }}
- name: deployAlerts
value: ${{ parameters.deployAlerts }}
- name: awaitActiveOrchestrations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ parameters:
jobs:
- deployment: DeployPublicApiDocs
displayName: Deploy Public API docs
condition: and(succeeded(), eq(variables.deployDocsSite, true))
dependsOn: ${{ parameters.dependsOn }}
environment: ${{ parameters.environment }}
strategy:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
deployPsqlFlexibleServer: false
deployContainerApp: false
deployDataProcessor: false
deployDocsSite: false
deployAlerts: false
dataProcessorExists: false

Expand Down Expand Up @@ -68,6 +69,7 @@ jobs:
deployPsqlFlexibleServer: $(deployPsqlFlexibleServer)
deployContainerApp: $(deployContainerApp)
deployDataProcessor: $(deployDataProcessor)
deployDocsSite: $(deployDocsSite)
deployAlerts: $(deployAlerts)
dataProcessorExists: $(dataProcessorExists)

Expand Down
3 changes: 3 additions & 0 deletions infrastructure/templates/public-api/ci/tasks/deploy-bicep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ parameters:
default: true
- name: deployDataProcessor
type: string
- name: deployDocsSite
type: string
- name: deployAlerts
type: string
- name: dataProcessorExists
Expand Down Expand Up @@ -55,6 +57,7 @@ steps:
deployPsqlFlexibleServer=${{ parameters.deployPsqlFlexibleServer }} \
deployContainerApp=${{ parameters.deployContainerApp }} \
deployDataProcessor=${{ parameters.deployDataProcessor }} \
deployDocsSite=${{ parameters.deployDocsSite }} \
deployAlerts=${{ parameters.deployAlerts }} \
dataProcessorFunctionAppExists=${{ parameters.dataProcessorExists }} \
dataProcessorAppRegistrationClientId='$(dataProcessorAppRegistrationClientId)' \
Expand Down
60 changes: 27 additions & 33 deletions infrastructure/templates/public-api/components/containerApp.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -25,37 +25,31 @@ param corsPolicy {
allowedOrigins: string[]?
}

@description('Name of the workload profile under which this Container App will be deployed. Defaults to Consumption.')
param workloadProfileName string = 'Consumption'

@description('Number of CPU cores the container can use. Can be with a maximum of two decimals.')
@allowed([
'1'
'2'
'3'
'4'
])
param cpuCore string = '4'

@description('Amount of memory (in gibibytes, GiB) allocated to the container up to 4GiB. Can be with a maximum of two decimals. Ratio with CPU cores must be equal to 2.')
@allowed([
'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
])
param memorySize string = '8'
@minValue(1)
@maxValue(8)
param cpuCores int = 4

@description('Amount of memory (in gibibytes, GiB) allocated to the container up to 32GiB. Can be with a maximum of two decimals. Ratio with CPU cores must be equal to 2.')
@minValue(1)
@maxValue(32)
param memoryGis int = 8

@description('Minimum number of replicas that will be deployed')
@minValue(0)
@maxValue(25)
param minReplica int = 1
param minReplicas int = 1

@description('Maximum number of replicas that will be deployed')
@minValue(0)
@maxValue(25)
param maxReplica int = 3
@maxValue(1000)
param maxReplicas int = 3

@description('Number of concurrent requests required in order to trigger scaling out.')
@minValue(1)
param scaleAtConcurrentHttpRequests int?

@description('Specifies the database connection string')
param appSettings {
Expand Down Expand Up @@ -113,7 +107,7 @@ param tagValues object

var containerImageName = '${acrLoginServer}/${containerAppImageName}'

resource containerApp 'Microsoft.App/containerApps@2023-11-02-preview' = {
resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
name: containerAppName
location: location
identity: {
Expand Down Expand Up @@ -160,29 +154,29 @@ resource containerApp 'Microsoft.App/containerApps@2023-11-02-preview' = {
image: containerImageName
env: appSettings
resources: {
cpu: json(cpuCore)
memory: '${memorySize}Gi'
cpu: json(string(cpuCores))
memory: '${memoryGis}Gi'
}
volumeMounts: volumeMounts
}
]
scale: {
minReplicas: minReplica
maxReplicas: maxReplica
rules: [
minReplicas: minReplicas
maxReplicas: maxReplicas
rules: scaleAtConcurrentHttpRequests != null ? [
{
name: 'http-requests'
http: {
metadata: {
concurrentRequests: '10'
concurrentRequests: string(scaleAtConcurrentHttpRequests)
}
}
}
]
] : []
}
volumes: volumes
}
workloadProfileName: 'Consumption'
workloadProfileName: workloadProfileName
}
tags: tagValues
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ContainerAppWorkloadProfile } from '../types.bicep'

@description('Specifies the location of the Container App Environment - defaults to that of the Resource Group')
param location string

Expand All @@ -13,14 +15,8 @@ param logAnalyticsWorkspaceName string
@description('Specifies the Application Insights key that is associated with this resource')
param applicationInsightsKey string

@description('Specifies the workload profiles for this Container App Environment - defaults to Consumption')
param workloadProfiles {
name: string
workloadProfileType: string
}[] = [{
name: 'Consumption'
workloadProfileType: 'Consumption'
}]
@description('Specifies the workload profiles for this Container App Environment - the default Consumption plan is always included')
param workloadProfiles ContainerAppWorkloadProfile[] = []

@description('Specifies a set of tags with which to tag the resource in Azure')
param tagValues object
Expand Down Expand Up @@ -57,7 +53,12 @@ resource containerAppEnvironment 'Microsoft.App/managedEnvironments@2024-03-01'
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
}
}
workloadProfiles: workloadProfiles
workloadProfiles: union([{
name: 'Consumption'
workloadProfileType: 'Consumption'
}],
workloadProfiles
)
}
tags: tagValues

Expand Down
24 changes: 21 additions & 3 deletions infrastructure/templates/public-api/main.bicep
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { abbreviations } from 'abbreviations.bicep'
import { IpRange, PrincipalNameAndId, StaticWebAppSku } from 'types.bicep'
import { ContainerAppResourceConfig, IpRange, PrincipalNameAndId, StaticWebAppSku, ContainerAppWorkloadProfile } from 'types.bicep'

@description('Environment : Subscription name e.g. s101d01. Used as a prefix for created resources.')
param subscription string = ''
Expand Down Expand Up @@ -78,6 +78,9 @@ param deployContainerApp bool = true
@description('Does the Data Processor need creating or updating?')
param deployDataProcessor bool = true

@description('Does the Public API static docs site need creating or updating?')
param deployDocsSite bool = true

param deployAlerts bool = false

@description('Public URLs of other components in the service.')
Expand Down Expand Up @@ -107,6 +110,19 @@ param devopsServicePrincipalId string = ''
@description('Specifies whether or not test Themes can be deleted in the environment.')
param enableThemeDeletion bool = false

@description('Specifies the workload profiles for this Container App Environment - the default Consumption plan is always included')
param publicApiContainerAppWorkloadProfiles ContainerAppWorkloadProfile[] = []

@description('Resource configuration for the Public API Container App.')
param publicApiContainerAppConfig ContainerAppResourceConfig = {
cpuCores: 4
memoryGis: 8
minReplicas: 0
maxReplicas: 3
scaleAtConcurrentHttpRequests: 10
workloadProfileName: 'Consumption'
}

var tagValues = union(resourceTags ?? {}, {
Environment: environmentName
DateProvisioned: dateProvisioned
Expand Down Expand Up @@ -254,6 +270,7 @@ module containerAppEnvironmentModule 'application/shared/containerAppEnvironment
location: location
resourceNames: resourceNames
applicationInsightsKey: appInsightsModule.outputs.appInsightsKey
workloadProfiles: publicApiContainerAppWorkloadProfiles
tagValues: tagValues
}
dependsOn: [
Expand Down Expand Up @@ -286,6 +303,7 @@ module apiAppModule 'application/public-api/publicApiApp.bicep' = if (deployCont
dockerImagesTag: dockerImagesTag
appInsightsConnectionString: appInsightsModule.outputs.appInsightsConnectionString
deployAlerts: deployAlerts
resourceAndScalingConfig: publicApiContainerAppConfig
tagValues: tagValues
}
dependsOn: [
Expand All @@ -295,7 +313,7 @@ module apiAppModule 'application/public-api/publicApiApp.bicep' = if (deployCont
}

// Deploy Public API docs.
module docsModule 'application/public-api/publicApiDocs.bicep' = {
module docsModule 'application/public-api/publicApiDocs.bicep' = if (deployDocsSite) {
name: 'publicApiDocsModuleDeploy'
params: {
appSku: docsAppSku
Expand All @@ -307,7 +325,7 @@ module docsModule 'application/public-api/publicApiDocs.bicep' = {
var docsRewriteSetName = '${publicApiResourcePrefix}-docs-rewrites'

// Create an Application Gateway to serve public traffic for the Public API Container App.
module appGatewayModule 'application/shared/appGateway.bicep' = if (deployContainerApp) {
module appGatewayModule 'application/shared/appGateway.bicep' = if (deployContainerApp && deployDocsSite) {
name: 'appGatewayModuleDeploy'
params: {
location: location
Expand Down
16 changes: 16 additions & 0 deletions infrastructure/templates/public-api/parameters/main-dev.bicepparam
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,20 @@ param postgreSqlSkuName = 'Standard_B1ms'
param postgreSqlStorageSizeGB = 32
param postgreSqlAutoGrowStatus = 'Disabled'

param publicApiContainerAppConfig = {
cpuCores: 4
memoryGis: 8
minReplicas: 1
maxReplicas: 100
scaleAtConcurrentHttpRequests: 5
workloadProfileName: 'Consumption'
}

param publicApiContainerAppWorkloadProfiles = [{
name: 'D8'
workloadProfileType: 'D8'
minimumCount: 0
maximumCount: 10
}]

param enableThemeDeletion = true
18 changes: 18 additions & 0 deletions infrastructure/templates/public-api/types.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,21 @@ type KeyVaultRole = 'Secrets User' | 'Certificate User'

@export()
type StaticWebAppSku = 'Free' | 'Standard'

@export()
type ContainerAppResourceConfig = {
workloadProfileName: string
cpuCores: int
memoryGis: int
minReplicas: int
maxReplicas: int
scaleAtConcurrentHttpRequests: int?
}

@export()
type ContainerAppWorkloadProfile = {
name: string
workloadProfileType: 'D4' | 'D8' | 'D16' | 'D32' | 'E4' | 'E8' | 'E16' | 'E32'
minimumCount: int
maximumCount: int
}

0 comments on commit dd62dd3

Please sign in to comment.