From 2b50c06ee663b01bb84b4ee2517056799697e7ba Mon Sep 17 00:00:00 2001 From: Atharv Kirtikar <42913997+wi0lono@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:33:10 +0530 Subject: [PATCH 1/4] Added pwr-studio-hld.drawio --- docs/assets/pwr-studio-hld.drawio | 85 +++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/assets/pwr-studio-hld.drawio diff --git a/docs/assets/pwr-studio-hld.drawio b/docs/assets/pwr-studio-hld.drawio new file mode 100644 index 0000000..53ba6bb --- /dev/null +++ b/docs/assets/pwr-studio-hld.drawio @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 48774840973d4c9c351f0404e24976470f332b85 Mon Sep 17 00:00:00 2001 From: Atharv Kirtikar Date: Tue, 30 Jul 2024 19:33:20 +0530 Subject: [PATCH 2/4] Trying out bicep (not working yet) --- .gitignore | 2 + deployments/bicep/README.md | 5 + deployments/bicep/main.bicep | 75 +++++++++++ deployments/bicep/modules/engine.bicep | 121 ++++++++++++++++++ deployments/bicep/modules/eventhub.bicep | 65 ++++++++++ deployments/bicep/modules/postgres.bicep | 85 +++++++++++++ deployments/bicep/modules/server.bicep | 152 +++++++++++++++++++++++ deployments/bicep/modules/storage.bicep | 110 ++++++++++++++++ 8 files changed, 615 insertions(+) create mode 100644 deployments/bicep/README.md create mode 100644 deployments/bicep/main.bicep create mode 100644 deployments/bicep/modules/engine.bicep create mode 100644 deployments/bicep/modules/eventhub.bicep create mode 100644 deployments/bicep/modules/postgres.bicep create mode 100644 deployments/bicep/modules/server.bicep create mode 100644 deployments/bicep/modules/storage.bicep diff --git a/.gitignore b/.gitignore index 0712879..cb961fc 100644 --- a/.gitignore +++ b/.gitignore @@ -171,3 +171,5 @@ studio/dist .env-dev .env-prod dump.sql +mainTemplate.parameters.json +*.bicepparam \ No newline at end of file diff --git a/deployments/bicep/README.md b/deployments/bicep/README.md new file mode 100644 index 0000000..f210526 --- /dev/null +++ b/deployments/bicep/README.md @@ -0,0 +1,5 @@ +```bash +az deployment group create --name ExampleDeployment --resource-group jb-studio-test --parameters storage.bicepparam + +az deployment group create --resource-group jb-studio-test --template-file ./main.bicep --parameters main.bicepparam +``` \ No newline at end of file diff --git a/deployments/bicep/main.bicep b/deployments/bicep/main.bicep new file mode 100644 index 0000000..285a8d0 --- /dev/null +++ b/deployments/bicep/main.bicep @@ -0,0 +1,75 @@ +// create bicep version of the stuff above + +param resourceNamePrefix string +param location string +param availabilityZones array +param postgresAdminUser string + +@secure() +param postgresAdminPassword string + +param postgresDatabaseName string +param cpu string = '0.5' +param memory string = '1Gi' + +var eventhubNamespace = '${resourceNamePrefix}-eventhub-namespace' +var publicIpName = '${resourceNamePrefix}-public-ip' +var containerAppEnvironmentName = '${resourceNamePrefix}-container-app-environment' +var containerAppName = '${resourceNamePrefix}-container-app' +var presetEnvironmentVariables = [] + + +// deploy the files ./eventhub.bicep and postgres.bicep + +module eventhub './modules/eventhub.bicep' = { + name: '${resourceNamePrefix}-eventhub' + params: { + eventHubNamespace: eventhubNamespace + location: location + } +} + +module postgres './modules/postgres.bicep' = { + name: '${resourceNamePrefix}-postgres' + params: { + resourceNamePrefix: resourceNamePrefix + location: location + postgresAdminUser: postgresAdminUser + postgresAdminPassword: postgresAdminPassword + postgresDatabaseName: postgresDatabaseName + } +} + +module storage './modules/storage.bicep' = { + name: '${resourceNamePrefix}-storage' + params: { + location: location + resourceNamePrefix: resourceNamePrefix + } +} + + +// deploy the files ./server.bicep and ./engine.bicep + +module server './modules/server.bicep' = { + name: '${resourceNamePrefix}-server' + params: { + location: location + resourceNamePrefix: resourceNamePrefix + postgresServerName: postgres.outputs.postgresqlServerIP + eventhubNamespace: eventhub.outputs.kafkaBroker + } +} + +module engine './modules/engine.bicep' = { + name: '${resourceNamePrefix}-engine' + params: { + location: location + resourceNamePrefix: resourceNamePrefix + postgresServerName: postgres.outputs.postgresqlServerIP + eventhubNamespace: eventhub.outputs.kafkaBroker + } +} + +output eventhubNamespace string = eventhub.outputs.kafkaBroker +output postgresqlServerName string = postgres.outputs.postgresqlServerIP diff --git a/deployments/bicep/modules/engine.bicep b/deployments/bicep/modules/engine.bicep new file mode 100644 index 0000000..5bf593e --- /dev/null +++ b/deployments/bicep/modules/engine.bicep @@ -0,0 +1,121 @@ +param availabilityZones array +param location string +param containerName string +param imageName string + +@allowed([ + 'Linux' + 'Windows' +]) +param osType string +param numberCpuCores string +param memory string + +@allowed([ + 'OnFailure' + 'Always' + 'Never' +]) +param restartPolicy string + +@allowed([ + 'Standard' + 'Confidential' +]) +param sku string +param imageRegistryLoginServer string +param imageUsername string + +@secure() +param imagePassword string +param KAFKA_BROKER string +param KAFKA_USE_SASL string +param KAFKA_CONSUMER_USERNAME string + +@secure() +param KAFKA_CONSUMER_PASSWORD string +param KAFKA_ENGINE_TOPIC string + +@secure() +param AZURE_OPENAI_API_KEY string +param AZURE_OPENAI_API_VERSION string +param AZURE_OPENAI_ENDPOINT string +param FAST_MODEL string +param SLOW_MODEL string +param ports array + +resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-preview' = { + location: location + name: containerName + zones: availabilityZones + properties: { + containers: [ + { + name: containerName + properties: { + image: imageName + resources: { + requests: { + cpu: int(numberCpuCores) + memoryInGB: json(memory) + } + } + environmentVariables: [ + { + name: 'KAFKA_BROKER' + value: KAFKA_BROKER + } + { + name: 'KAFKA_USE_SASL' + value: KAFKA_USE_SASL + } + { + name: 'KAFKA_CONSUMER_USERNAME' + value: KAFKA_CONSUMER_USERNAME + } + { + name: 'KAFKA_CONSUMER_PASSWORD' + secureValue: KAFKA_CONSUMER_PASSWORD + } + { + name: 'KAFKA_ENGINE_TOPIC' + value: KAFKA_ENGINE_TOPIC + } + { + name: 'AZURE_OPENAI_API_KEY' + value: AZURE_OPENAI_API_KEY + } + { + name: 'AZURE_OPENAI_API_VERSION' + value: AZURE_OPENAI_API_VERSION + } + { + name: 'AZURE_OPENAI_ENDPOINT' + value: AZURE_OPENAI_ENDPOINT + } + { + name: 'FAST_MODEL' + value: FAST_MODEL + } + { + name: 'SLOW_MODEL' + value: SLOW_MODEL + } + ] + ports: ports + } + } + ] + restartPolicy: restartPolicy + osType: osType + sku: sku + imageRegistryCredentials: [ + { + server: imageRegistryLoginServer + username: imageUsername + password: imagePassword + } + ] + } + tags: {} +} diff --git a/deployments/bicep/modules/eventhub.bicep b/deployments/bicep/modules/eventhub.bicep new file mode 100644 index 0000000..9ca866f --- /dev/null +++ b/deployments/bicep/modules/eventhub.bicep @@ -0,0 +1,65 @@ +@description('The name of the Event Hub namespace.') +param eventHubNamespace string + +@description('The location for the resources.') +param location string + +resource eventhubNamespace_resource 'Microsoft.EventHub/namespaces@2024-01-01' = { + name: eventHubNamespace + location: location + sku: { + name: 'Standard' + tier: 'Standard' + capacity: 1 + } + properties: { + minimumTlsVersion: '1.2' + publicNetworkAccess: 'Enabled' + disableLocalAuth: false + zoneRedundant: true + isAutoInflateEnabled: true + maximumThroughputUnits: 5 + kafkaEnabled: true + } +} + +resource eventhubNamespace_sendlisten 'Microsoft.EventHub/namespaces/authorizationrules@2024-01-01' = { + parent: eventhubNamespace_resource + name: 'sendlisten' + properties: { + rights: [ + 'Send' + 'Listen' + ] + } +} + +resource eventhubNamespace_pwr 'Microsoft.EventHub/namespaces/eventhubs@2024-01-01' = { + parent: eventhubNamespace_resource + name: 'pwr' + properties: { + retentionDescription: { + cleanupPolicy: 'Delete' + retentionTimeInHours: 1 + } + messageRetentionInDays: 1 + partitionCount: 3 + status: 'Active' + } +} + +resource eventhubNamespace_pwr_Default 'Microsoft.EventHub/namespaces/eventhubs/consumergroups@2024-01-01' = { + parent: eventhubNamespace_pwr + name: '$Default' + properties: {} +} + +resource eventhubNamespace_pwr_cooler_group_id 'Microsoft.EventHub/namespaces/eventhubs/consumergroups@2024-01-01' = { + parent: eventhubNamespace_pwr + name: 'cooler_group_id' + properties: {} +} + +output kafkaConnectionUsername string = '$ConnectionString' +output kafkaConnectionPassword string = eventhubNamespace_sendlisten.listKeys().primaryConnectionString +output kafkaBroker string = '${eventHubNamespace}.servicebus.windows.net:9093' diff --git a/deployments/bicep/modules/postgres.bicep b/deployments/bicep/modules/postgres.bicep new file mode 100644 index 0000000..c162622 --- /dev/null +++ b/deployments/bicep/modules/postgres.bicep @@ -0,0 +1,85 @@ +@description('The prefix used by all resources created by this template.') +param resourceNamePrefix string + +@description('The location for the resources.') +param location string + +@description('The administrator username for the PostgreSQL Flexible Server.') +param postgresAdminUser string + +@description('The administrator password for the PostgreSQL Flexible Server.') +@secure() +param postgresAdminPassword string + +@description('The name of the database to create in the PostgreSQL Flexible Server.') +param postgresDatabaseName string + +var postgresqlServerName = '${resourceNamePrefix}-postgresql-server' + +resource postgresqlServer 'Microsoft.DBforPostgreSQL/flexibleServers@2023-12-01-preview' = { + name: postgresqlServerName + location: location + properties: { + replica: { + role: 'Primary' + } + storage: { + iops: 120 + tier: 'P4' + storageSizeGB: 32 + autoGrow: 'Enabled' + } + network: { + publicNetworkAccess: 'Enabled' + } + dataEncryption: { + type: 'SystemManaged' + } + authConfig: { + activeDirectoryAuth: 'Disabled' + passwordAuth: 'Enabled' + } + version: '16' + administratorLogin: postgresAdminUser + administratorLoginPassword: postgresAdminPassword + availabilityZone: '1' + backup: { + backupRetentionDays: 7 + geoRedundantBackup: 'Disabled' + } + highAvailability: { + mode: 'Disabled' + } + maintenanceWindow: { + customWindow: 'Disabled' + dayOfWeek: 0 + startHour: 0 + startMinute: 0 + } + replicationRole: 'Primary' + } + sku: { + name: 'Standard_D2ds_v4' + tier: 'GeneralPurpose' + } +} + +resource postgresAllowAllAzureIPs 'Microsoft.DBforPostgreSQL/flexibleServers/firewallRules@2023-12-01-preview' = { + parent: postgresqlServer + name: 'AllowAllAzureIPs' + properties: { + startIpAddress: '0.0.0.0' + endIpAddress: '0.0.0.0' + } +} + +resource postgresqlServerName_postgresDatabase 'Microsoft.DBforPostgreSQL/flexibleServers/databases@2023-12-01-preview' = { + parent: postgresqlServer + name: postgresDatabaseName + properties: { + charset: 'UTF8' + collation: 'en_US.utf8' + } +} + +output postgresqlServerIP string = postgresqlServer.properties.fullyQualifiedDomainName diff --git a/deployments/bicep/modules/server.bicep b/deployments/bicep/modules/server.bicep new file mode 100644 index 0000000..26c8ebd --- /dev/null +++ b/deployments/bicep/modules/server.bicep @@ -0,0 +1,152 @@ +param availabilityZones array +param location string +param containerName string +param imageName string + +@allowed([ + 'Linux' + 'Windows' +]) +param osType string +param numberCpuCores string +param memory string + +@allowed([ + 'OnFailure' + 'Always' + 'Never' +]) +param restartPolicy string + +@allowed([ + 'Standard' + 'Confidential' +]) +param sku string +param imageRegistryLoginServer string +param imageUsername string + +@secure() +param imagePassword string +param SERVER_HOST string +param dbConnectionString string +param AAD_APP_CLIENT_ID string +param AAD_APP_TENANT_ID string +param ISSUER string +param KAFKA_BROKER string +param KAFKA_USE_SASL string +param KAFKA_ENGINE_TOPIC string +param KAFKA_PRODUCER_USERNAME string + +@secure() +param KAFKA_PRODUCER_PASSWORD string +param KAFKA_CONSUMER_USERNAME string + +@secure() +param KAFKA_CONSUMER_PASSWORD string +param ipAddressType string +param ports array + +resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-preview' = { + location: location + name: containerName + zones: availabilityZones + properties: { + containers: [ + { + name: containerName + properties: { + image: imageName + resources: { + requests: { + cpu: int(numberCpuCores) + memoryInGB: json(memory) + } + } + environmentVariables: [ + { + name: 'SERVER_HOST' + value: SERVER_HOST + } + { + name: 'DB_CONNECTION_STRING' + value: dbConnectionString + } + { + name: 'AAD_APP_CLIENT_ID' + value: AAD_APP_CLIENT_ID + } + { + name: 'AAD_APP_TENANT_ID' + value: AAD_APP_TENANT_ID + } + { + name: 'ISSUER' + value: ISSUER + } + { + name: 'KAFKA_BROKER' + value: KAFKA_BROKER + } + { + name: 'KAFKA_USE_SASL' + value: KAFKA_USE_SASL + } + { + name: 'KAFKA_ENGINE_TOPIC' + value: KAFKA_ENGINE_TOPIC + } + { + name: 'KAFKA_PRODUCER_USERNAME' + value: KAFKA_PRODUCER_USERNAME + } + { + name: 'KAFKA_PRODUCER_PASSWORD' + secureValue: KAFKA_PRODUCER_PASSWORD + } + { + name: 'KAFKA_CONSUMER_USERNAME' + value: KAFKA_CONSUMER_USERNAME + } + { + name: 'KAFKA_CONSUMER_PASSWORD' + secureValue: KAFKA_CONSUMER_PASSWORD + } + ] + ports: ports + command: [ + 'uvicorn' + 'app.main:app' + '--workers' + '1' + '--host' + '0.0.0.0' + '--port' + '80' + ] + } + } + ] + restartPolicy: restartPolicy + osType: osType + sku: sku + imageRegistryCredentials: [ + { + server: imageRegistryLoginServer + username: imageUsername + password: imagePassword + } + ] + ipAddress: { + type: ipAddressType + ports: ports + } + subnetIds: [ + { + // generate dynamically instead of hardcoding + id: 'sss' + } + ] + } + tags: {} +} diff --git a/deployments/bicep/modules/storage.bicep b/deployments/bicep/modules/storage.bicep new file mode 100644 index 0000000..bd43e04 --- /dev/null +++ b/deployments/bicep/modules/storage.bicep @@ -0,0 +1,110 @@ +@description('The prefix used by all resources created by this template.') +param resourceNamePrefix string + +@description('The location for the resources.') +param location string + +var storageAccountName = '${resourceNamePrefix}storageaccount' +var storageContainerName = '${resourceNamePrefix}-storage-container' + +resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + dnsEndpointType: 'Standard' + defaultToOAuthAuthentication: false + publicNetworkAccess: 'Enabled' + allowCrossTenantReplication: false + minimumTlsVersion: 'TLS1_2' + allowBlobPublicAccess: true + allowSharedKeyAccess: true + networkAcls: { + bypass: 'AzureServices' + virtualNetworkRules: [] + ipRules: [] + defaultAction: 'Allow' + } + supportsHttpsTrafficOnly: true + encryption: { + requireInfrastructureEncryption: false + services: { + file: { + keyType: 'Account' + enabled: true + } + blob: { + keyType: 'Account' + enabled: true + } + } + keySource: 'Microsoft.Storage' + } + accessTier: 'Hot' + } +} + +resource storageAccountName_default 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = { + parent: storageAccount + name: 'default' + sku: { + name: 'Standard_LRS' + } + properties: { + changeFeed: { + enabled: false + } + restorePolicy: { + enabled: false + } + containerDeleteRetentionPolicy: { + enabled: true + days: 7 + } + cors: { + corsRules: [] + } + deleteRetentionPolicy: { + allowPermanentDelete: false + enabled: true + days: 7 + } + isVersioningEnabled: false + } +} + +resource storageAccountName_default_storageContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-05-01' = { + parent: storageAccountName_default + name: storageContainerName + properties: { + immutableStorageWithVersioning: { + enabled: false + } + defaultEncryptionScope: '$account-encryption-key' + denyEncryptionScopeOverride: false + publicAccess: 'None' + } +} + +resource storageAccountName_default_web 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-05-01' = { + parent: storageAccountName_default + name: '$web' + properties: { + immutableStorageWithVersioning: { + enabled: false + } + defaultEncryptionScope: '$account-encryption-key' + denyEncryptionScopeOverride: false + publicAccess: 'Container' + } + dependsOn: [ + storageAccountName_default_storageContainer + ] +} + +output AZURE_STORAGE_ACCOUNT_URL string = storageAccount.properties.primaryEndpoints.blob +output AZURE_STORAGE_ACCOUNT_KEY string = listKeys(storageAccountName, '2023-05-01').keys[0].value +output AZURE_STORAGE_CONTAINER string = storageContainerName From a73d2eb73455f7f0937b127cddb38e2c43a4106f Mon Sep 17 00:00:00 2001 From: Atharv Kirtikar Date: Thu, 1 Aug 2024 16:12:15 +0530 Subject: [PATCH 3/4] 10 percent --- .gitignore | 2 +- deployments/bicep/README.md | 2 +- deployments/bicep/main.bicep | 92 +++++++++++++++---- .../modules/{ => containers}/engine.bicep | 46 +++------- .../modules/{ => containers}/server.bicep | 68 ++++---------- deployments/bicep/modules/eventhub.bicep | 2 +- deployments/bicep/modules/storage.bicep | 3 - deployments/bicep/modules/vnet.bicep | 47 ++++++++++ 8 files changed, 156 insertions(+), 106 deletions(-) rename deployments/bicep/modules/{ => containers}/engine.bicep (79%) rename deployments/bicep/modules/{ => containers}/server.bicep (69%) create mode 100644 deployments/bicep/modules/vnet.bicep diff --git a/.gitignore b/.gitignore index cb961fc..56d9d2f 100644 --- a/.gitignore +++ b/.gitignore @@ -171,5 +171,5 @@ studio/dist .env-dev .env-prod dump.sql -mainTemplate.parameters.json +*.parameters.json *.bicepparam \ No newline at end of file diff --git a/deployments/bicep/README.md b/deployments/bicep/README.md index f210526..519a325 100644 --- a/deployments/bicep/README.md +++ b/deployments/bicep/README.md @@ -1,5 +1,5 @@ ```bash az deployment group create --name ExampleDeployment --resource-group jb-studio-test --parameters storage.bicepparam -az deployment group create --resource-group jb-studio-test --template-file ./main.bicep --parameters main.bicepparam +az deployment group create --resource-group jbstudiotest --template-file ./main.bicep --parameters main.bicepparam ``` \ No newline at end of file diff --git a/deployments/bicep/main.bicep b/deployments/bicep/main.bicep index 285a8d0..043f706 100644 --- a/deployments/bicep/main.bicep +++ b/deployments/bicep/main.bicep @@ -2,7 +2,6 @@ param resourceNamePrefix string param location string -param availabilityZones array param postgresAdminUser string @secure() @@ -12,19 +11,42 @@ param postgresDatabaseName string param cpu string = '0.5' param memory string = '1Gi' -var eventhubNamespace = '${resourceNamePrefix}-eventhub-namespace' -var publicIpName = '${resourceNamePrefix}-public-ip' -var containerAppEnvironmentName = '${resourceNamePrefix}-container-app-environment' -var containerAppName = '${resourceNamePrefix}-container-app' -var presetEnvironmentVariables = [] +@secure() +param AZURE_OPENAI_API_KEY string +param AZURE_OPENAI_API_VERSION string +param AZURE_OPENAI_ENDPOINT string +param FAST_MODEL string = 'gpt-4-turbo' +param SLOW_MODEL string = 'gpt-4-turbo' + +param pwrEngineImageName string +param pwrServerImageName string +@secure() +param imagePassword string +param imageRegistryLoginServer string +param imageUsername string + +param AAD_APP_CLIENT_ID string +param AAD_APP_TENANT_ID string +param ISSUER string + +param SERVER_HOST string + +// deploy ./vnet.bicep + +module vnet './modules/vnet.bicep' = { + name: '${resourceNamePrefix}-vnet' + params: { + vnetName: '${resourceNamePrefix}-vnet' + } +} // deploy the files ./eventhub.bicep and postgres.bicep module eventhub './modules/eventhub.bicep' = { name: '${resourceNamePrefix}-eventhub' params: { - eventHubNamespace: eventhubNamespace + eventHubNamespace: '${resourceNamePrefix}-eventhub-namespace' location: location } } @@ -51,25 +73,61 @@ module storage './modules/storage.bicep' = { // deploy the files ./server.bicep and ./engine.bicep -module server './modules/server.bicep' = { - name: '${resourceNamePrefix}-server' +module engine './modules/containers/engine.bicep' = { + name: '${resourceNamePrefix}-engine' params: { location: location - resourceNamePrefix: resourceNamePrefix - postgresServerName: postgres.outputs.postgresqlServerIP - eventhubNamespace: eventhub.outputs.kafkaBroker + AZURE_OPENAI_API_KEY: AZURE_OPENAI_API_KEY + AZURE_OPENAI_API_VERSION: AZURE_OPENAI_API_VERSION + AZURE_OPENAI_ENDPOINT: AZURE_OPENAI_ENDPOINT + FAST_MODEL: FAST_MODEL + SLOW_MODEL: SLOW_MODEL + + containerName: '${resourceNamePrefix}-pwr-engine' + imageName: pwrEngineImageName + imagePassword: imagePassword + imageRegistryLoginServer: imageRegistryLoginServer + imageUsername: imageUsername + KAFKA_BROKER: eventhub.outputs.kafkaBroker + KAFKA_CONSUMER_PASSWORD: eventhub.outputs.kafkaConnectionPassword + KAFKA_CONSUMER_USERNAME: eventhub.outputs.kafkaConnectionUsername + memory: memory + numberCpuCores: cpu + subnetId: vnet.outputs.defaultSubnetId } } -module engine './modules/engine.bicep' = { - name: '${resourceNamePrefix}-engine' + + +module server './modules/containers/server.bicep' = { + name: '${resourceNamePrefix}-server' params: { location: location - resourceNamePrefix: resourceNamePrefix - postgresServerName: postgres.outputs.postgresqlServerIP - eventhubNamespace: eventhub.outputs.kafkaBroker + + containerName: '${resourceNamePrefix}-pwr-server' + AAD_APP_CLIENT_ID: AAD_APP_CLIENT_ID + AAD_APP_TENANT_ID: AAD_APP_TENANT_ID + ISSUER: ISSUER + // construct a full db string using the postgress params and the output server ip + dbConnectionString: 'postgresql://${postgresAdminUser}:${postgresAdminPassword}@${postgres.outputs.postgresqlServerIP}:5432/${postgresDatabaseName}' + SERVER_HOST: SERVER_HOST + + imageName: pwrServerImageName + imagePassword: imagePassword + imageRegistryLoginServer: imageRegistryLoginServer + imageUsername: imageUsername + KAFKA_BROKER: eventhub.outputs.kafkaBroker + KAFKA_PRODUCER_PASSWORD: eventhub.outputs.kafkaConnectionPassword + KAFKA_PRODUCER_USERNAME: eventhub.outputs.kafkaConnectionUsername + memory: memory + numberCpuCores: cpu + subnetId: vnet.outputs.defaultSubnetId + } } + + output eventhubNamespace string = eventhub.outputs.kafkaBroker output postgresqlServerName string = postgres.outputs.postgresqlServerIP + diff --git a/deployments/bicep/modules/engine.bicep b/deployments/bicep/modules/containers/engine.bicep similarity index 79% rename from deployments/bicep/modules/engine.bicep rename to deployments/bicep/modules/containers/engine.bicep index 5bf593e..cb64a72 100644 --- a/deployments/bicep/modules/engine.bicep +++ b/deployments/bicep/modules/containers/engine.bicep @@ -1,53 +1,32 @@ -param availabilityZones array param location string param containerName string -param imageName string +param subnetId string -@allowed([ - 'Linux' - 'Windows' -]) -param osType string param numberCpuCores string param memory string -@allowed([ - 'OnFailure' - 'Always' - 'Never' -]) -param restartPolicy string - -@allowed([ - 'Standard' - 'Confidential' -]) -param sku string param imageRegistryLoginServer string param imageUsername string - @secure() param imagePassword string +param imageName string + param KAFKA_BROKER string -param KAFKA_USE_SASL string param KAFKA_CONSUMER_USERNAME string @secure() param KAFKA_CONSUMER_PASSWORD string -param KAFKA_ENGINE_TOPIC string @secure() param AZURE_OPENAI_API_KEY string param AZURE_OPENAI_API_VERSION string param AZURE_OPENAI_ENDPOINT string -param FAST_MODEL string -param SLOW_MODEL string -param ports array +param FAST_MODEL string = 'gpt-4-turbo' +param SLOW_MODEL string = 'gpt-4-turbo' resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-preview' = { location: location name: containerName - zones: availabilityZones properties: { containers: [ { @@ -67,7 +46,7 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ } { name: 'KAFKA_USE_SASL' - value: KAFKA_USE_SASL + value: 'true' } { name: 'KAFKA_CONSUMER_USERNAME' @@ -79,7 +58,7 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ } { name: 'KAFKA_ENGINE_TOPIC' - value: KAFKA_ENGINE_TOPIC + value: 'pwr_engine' } { name: 'AZURE_OPENAI_API_KEY' @@ -102,13 +81,13 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ value: SLOW_MODEL } ] - ports: ports + ports: [{port: 80, protocol: 'TCP'}] } } ] - restartPolicy: restartPolicy - osType: osType - sku: sku + restartPolicy: 'OnFailure' + osType: 'Linux' + sku: 'Standard' imageRegistryCredentials: [ { server: imageRegistryLoginServer @@ -116,6 +95,9 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ password: imagePassword } ] + subnetIds: [ + {id: subnetId} + ] } tags: {} } diff --git a/deployments/bicep/modules/server.bicep b/deployments/bicep/modules/containers/server.bicep similarity index 69% rename from deployments/bicep/modules/server.bicep rename to deployments/bicep/modules/containers/server.bicep index 26c8ebd..c74c5be 100644 --- a/deployments/bicep/modules/server.bicep +++ b/deployments/bicep/modules/containers/server.bicep @@ -1,56 +1,32 @@ -param availabilityZones array param location string param containerName string -param imageName string +param subnetId string -@allowed([ - 'Linux' - 'Windows' -]) -param osType string param numberCpuCores string param memory string -@allowed([ - 'OnFailure' - 'Always' - 'Never' -]) -param restartPolicy string - -@allowed([ - 'Standard' - 'Confidential' -]) -param sku string param imageRegistryLoginServer string +param imageName string param imageUsername string - @secure() param imagePassword string + param SERVER_HOST string param dbConnectionString string + param AAD_APP_CLIENT_ID string param AAD_APP_TENANT_ID string param ISSUER string + param KAFKA_BROKER string -param KAFKA_USE_SASL string -param KAFKA_ENGINE_TOPIC string param KAFKA_PRODUCER_USERNAME string - @secure() param KAFKA_PRODUCER_PASSWORD string -param KAFKA_CONSUMER_USERNAME string -@secure() -param KAFKA_CONSUMER_PASSWORD string -param ipAddressType string -param ports array resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-preview' = { location: location name: containerName - zones: availabilityZones properties: { containers: [ { @@ -90,11 +66,11 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ } { name: 'KAFKA_USE_SASL' - value: KAFKA_USE_SASL + value: 'true' } { name: 'KAFKA_ENGINE_TOPIC' - value: KAFKA_ENGINE_TOPIC + value: 'pwr_engine' } { name: 'KAFKA_PRODUCER_USERNAME' @@ -104,16 +80,7 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ name: 'KAFKA_PRODUCER_PASSWORD' secureValue: KAFKA_PRODUCER_PASSWORD } - { - name: 'KAFKA_CONSUMER_USERNAME' - value: KAFKA_CONSUMER_USERNAME - } - { - name: 'KAFKA_CONSUMER_PASSWORD' - secureValue: KAFKA_CONSUMER_PASSWORD - } ] - ports: ports command: [ 'uvicorn' 'app.main:app' @@ -124,12 +91,13 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ '--port' '80' ] + ports: [{port: 80, protocol: 'TCP'}, {port: 3000, protocol: 'TCP'}] } } ] - restartPolicy: restartPolicy - osType: osType - sku: sku + restartPolicy: 'OnFailure' + osType: 'Linux' + sku: 'Standard' imageRegistryCredentials: [ { server: imageRegistryLoginServer @@ -137,16 +105,14 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ password: imagePassword } ] - ipAddress: { - type: ipAddressType - ports: ports - } subnetIds: [ - { - // generate dynamically instead of hardcoding - id: 'sss' - } + {id: subnetId} ] } tags: {} } + + +// output the private IP adress assigned to the container group from the subnet + +output containerIP string = container.properties.ipAddress.ip diff --git a/deployments/bicep/modules/eventhub.bicep b/deployments/bicep/modules/eventhub.bicep index 9ca866f..ac2ec0d 100644 --- a/deployments/bicep/modules/eventhub.bicep +++ b/deployments/bicep/modules/eventhub.bicep @@ -36,7 +36,7 @@ resource eventhubNamespace_sendlisten 'Microsoft.EventHub/namespaces/authorizati resource eventhubNamespace_pwr 'Microsoft.EventHub/namespaces/eventhubs@2024-01-01' = { parent: eventhubNamespace_resource - name: 'pwr' + name: 'pwr_engine' properties: { retentionDescription: { cleanupPolicy: 'Delete' diff --git a/deployments/bicep/modules/storage.bicep b/deployments/bicep/modules/storage.bicep index bd43e04..db6f0ed 100644 --- a/deployments/bicep/modules/storage.bicep +++ b/deployments/bicep/modules/storage.bicep @@ -50,9 +50,6 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = { resource storageAccountName_default 'Microsoft.Storage/storageAccounts/blobServices@2023-05-01' = { parent: storageAccount name: 'default' - sku: { - name: 'Standard_LRS' - } properties: { changeFeed: { enabled: false diff --git a/deployments/bicep/modules/vnet.bicep b/deployments/bicep/modules/vnet.bicep new file mode 100644 index 0000000..ad1f0ce --- /dev/null +++ b/deployments/bicep/modules/vnet.bicep @@ -0,0 +1,47 @@ +@description('The name of the virtual network.') +param vnetName string + + +// create a virtual network with two subnets +resource pwrStudioVnet 'Microsoft.Network/virtualNetworks@2023-11-01' = { + name: vnetName + location: 'centralindia' + properties: { + addressSpace: { + addressPrefixes: [ + '10.0.0.0/16' + ] + } + subnets: [ + { + name: 'default' + properties: { + addressPrefix: '10.0.0.0/24' + delegations: [ + { + name: 'Microsoft.ContainerInstance/containerGroups' + properties: { + serviceName: 'Microsoft.ContainerInstance/containerGroups' + } + } + ] + } + } + { + name: 'gateway' + properties: { + addressPrefix: '10.0.1.0/24' + } + } + ] + } +} + + +// output the subnets as well as network info + +output defaultSubnetId string = pwrStudioVnet.properties.subnets[0].id +output gatewaySubnetId string = pwrStudioVnet.properties.subnets[1].id + +// output network info too +output vnetId string = pwrStudioVnet.id From 2e1a1c968fe27833dffe2951fb348f3d1ad6bff2 Mon Sep 17 00:00:00 2001 From: Atharv Kirtikar Date: Fri, 30 Aug 2024 19:52:46 +0530 Subject: [PATCH 4/4] Gateway not working yet --- deployments/bicep/README.md | 2 +- deployments/bicep/main.bicep | 29 +++- .../bicep/modules/containers/engine.bicep | 4 - deployments/bicep/modules/gateway.bicep | 162 ++++++++++++++++++ 4 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 deployments/bicep/modules/gateway.bicep diff --git a/deployments/bicep/README.md b/deployments/bicep/README.md index 519a325..00f073f 100644 --- a/deployments/bicep/README.md +++ b/deployments/bicep/README.md @@ -1,5 +1,5 @@ ```bash az deployment group create --name ExampleDeployment --resource-group jb-studio-test --parameters storage.bicepparam -az deployment group create --resource-group jbstudiotest --template-file ./main.bicep --parameters main.bicepparam +az deployment group create --resource-group jbstudiotest1 --template-file ./main.bicep --parameters main.bicepparam ``` \ No newline at end of file diff --git a/deployments/bicep/main.bicep b/deployments/bicep/main.bicep index 043f706..7d37c7a 100644 --- a/deployments/bicep/main.bicep +++ b/deployments/bicep/main.bicep @@ -31,6 +31,11 @@ param ISSUER string param SERVER_HOST string +param keyVaultName string + +@description('The secret url for the certificate in Azure Key Vault.') +@secure() +param keyVaultSecretId string // deploy ./vnet.bicep @@ -71,6 +76,16 @@ module storage './modules/storage.bicep' = { } +// create a public ip that will later be used for a load balancer + +resource publicIp 'Microsoft.Network/publicIPAddresses@2020-11-01' = { + name: '${resourceNamePrefix}-public-ip' + location: location + properties: { + publicIPAllocationMethod: 'Dynamic' + } +} + // deploy the files ./server.bicep and ./engine.bicep module engine './modules/containers/engine.bicep' = { @@ -93,7 +108,6 @@ module engine './modules/containers/engine.bicep' = { KAFKA_CONSUMER_USERNAME: eventhub.outputs.kafkaConnectionUsername memory: memory numberCpuCores: cpu - subnetId: vnet.outputs.defaultSubnetId } } @@ -127,6 +141,19 @@ module server './modules/containers/server.bicep' = { } +// create a load balancer that will be used to route traffic to the containers +// module gateway './modules/gateway.bicep' = { +// name: '${resourceNamePrefix}-gateway' +// params: { +// resourceNamePrefix: resourceNamePrefix +// location: location +// subnetId: vnet.outputs.gatewaySubnetId +// publicIpId: publicIp.id +// backendIPAddress: server.outputs.containerIP +// keyVaultName: keyVaultName +// keyVaultSecretId: keyVaultSecretId +// } +// } output eventhubNamespace string = eventhub.outputs.kafkaBroker output postgresqlServerName string = postgres.outputs.postgresqlServerIP diff --git a/deployments/bicep/modules/containers/engine.bicep b/deployments/bicep/modules/containers/engine.bicep index cb64a72..11b725e 100644 --- a/deployments/bicep/modules/containers/engine.bicep +++ b/deployments/bicep/modules/containers/engine.bicep @@ -1,6 +1,5 @@ param location string param containerName string -param subnetId string param numberCpuCores string param memory string @@ -95,9 +94,6 @@ resource container 'Microsoft.ContainerInstance/containerGroups@2022-10-01-previ password: imagePassword } ] - subnetIds: [ - {id: subnetId} - ] } tags: {} } diff --git a/deployments/bicep/modules/gateway.bicep b/deployments/bicep/modules/gateway.bicep new file mode 100644 index 0000000..494cf10 --- /dev/null +++ b/deployments/bicep/modules/gateway.bicep @@ -0,0 +1,162 @@ +@description('The resource ID of the subnet to which the Application Gateway should be connected.') +param subnetId string + +@description('The private IP address of the backend server.') +param backendIPAddress string + +@description('The secret url for the certificate in Azure Key Vault.') +@secure() +param keyVaultSecretId string + +param location string = resourceGroup().location +param resourceNamePrefix string +param publicIpId string + +param keyVaultName string + +var managedIdentityName = '${resourceNamePrefix}-gateway-identity' + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: managedIdentityName + location: location +} + +// assign the identity to keyvault with name +resource keyVaultAccess 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: '${keyVaultName}/add' + properties: { + accessPolicies: [ + { + tenantId: subscription().tenantId + objectId: managedIdentity.properties.principalId + permissions: { + keys: ['get', 'list'] + secrets: ['get', 'list'] + } + } + ] + } +} + + +resource appGateway 'Microsoft.Network/applicationGateways@2020-06-01' = { + name: '${resourceNamePrefix}-appGateway' + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + // add the reference to the managed identity + '${managedIdentity.id}': {} + } + + } + properties: { + sku: { + name: 'Standard_v2' + tier: 'Standard_v2' + capacity: 2 + } + gatewayIPConfigurations: [ + { + name: 'appGatewayIpConfig' + properties: { + subnet: { + id: subnetId + } + } + } + ] + frontendIPConfigurations: [ + { + name: 'appGatewayFrontendIP' + properties: { + publicIPAddress: { + id: publicIpId + } + } + } + ] + frontendPorts: [ + { + name: 'frontendPortHttps' + properties: { + port: 443 + } + } + ] + backendAddressPools: [ + { + name: 'backendPool' + properties: { + backendAddresses: [ + { + ipAddress: backendIPAddress + } + ] + } + } + ] + backendHttpSettingsCollection: [ + { + name: 'backendHttpSettings' + properties: { + port: 80 + protocol: 'Http' + cookieBasedAffinity: 'Disabled' + pickHostNameFromBackendAddress: false + requestTimeout: 20 + } + } + ] + httpListeners: [ + { + name: 'httpsListener' + properties: { + frontendIPConfiguration: { + id: resourceId( + 'Microsoft.Network/applicationGateways/frontendIPConfigurations', + 'appGateway', + 'appGatewayFrontendIP' + ) + } + frontendPort: { + id: resourceId('Microsoft.Network/applicationGateways/frontendPorts', 'appGateway', 'frontendPortHttps') + } + protocol: 'Https' + sslCertificate: { + id: resourceId('Microsoft.Network/applicationGateways/sslCertificates', 'appGateway', 'sslCertificate') + } + } + } + ] + requestRoutingRules: [ + { + name: 'routingRule' + properties: { + ruleType: 'Basic' + httpListener: { + id: resourceId('Microsoft.Network/applicationGateways/httpListeners', 'appGateway', 'httpsListener') + } + backendAddressPool: { + id: resourceId('Microsoft.Network/applicationGateways/backendAddressPools', 'appGateway', 'backendPool') + } + backendHttpSettings: { + id: resourceId( + 'Microsoft.Network/applicationGateways/backendHttpSettingsCollection', + 'appGateway', + 'backendHttpSettings' + ) + } + } + } + ] + sslCertificates: [ + { + name: 'sslCertificate' + properties: { + keyVaultSecretId: keyVaultSecretId + } + } + ] + } +}