ARM脚本ServerLess SignalR,上游设置为功能应用程序



我有一个带有上游设置的"ServerLess"SignalR资源,可以与后台功能应用程序对话。一切都在起作用。问题是如何自动创建这些资源,因为两者之间似乎存在循环引用。

SignalR上游设置需要功能应用程序中的"signal_extension"应用程序密钥才能包含在上游URL模板中。相反,函数应用程序需要"AzureSignalRConnectionString"应用程序设置。因此循环引用。

更复杂的是,"signal_extension"应用程序密钥似乎只有在您将signalr触发的函数部署到Function App时才会创建。是否可以在ARM模板创建时在功能应用程序中"手动"设置随机化的应用程序密钥,然后用于构建SignalR资源上游设置?

我曾尝试使用listkeys/listsecrets在ARM模板中"转储"一个正在工作的函数应用程序作为输出,但主机/应用程序密钥似乎没有暴露。

是否可以为这些资源的创建编写脚本(使用ARM或Azure CLI)?

经过一些实验,我想我已经解决了这个问题。以下是步骤:

  1. 在ARM模板中,创建Function App和SignalR。使功能应用程序依赖于Signal。将SignalR-AzureSignalRConnectionString应用程序设置注入函数应用程序。

  2. 将功能代码部署到功能应用程序。

  3. 使用Azure CLI提取"signal_extension":

    az函数应用程序密钥列表--名称<函数app_name&gt--资源组&lt;resource_group>

  4. 获取生成的systemKeys/signer_extension值,并将其放入另一个Azire CLI命令中:

    az信号器上游更新--name<signal_name&gt--资源组&lt;resource_group&gt--template url template=";https://<函数app_name>。azurewebsites.net/runtime/webhooks/signer?code=<来自步骤3的代码";

至少这些都可以在DevOps管道中编写脚本。

使用Azure Bicep,我成功地在一个步骤中使其工作:
仅在windows上测试了功能应用v4 dotnet6

  • 创建存储帐户
  • 创建应用程序服务计划(windows)
  • 创建没有应用程序设置的功能应用程序
  • 创建signalr_extension系统密钥
  • 使用signalr_extension系统密钥创建signalR服务
  • 使用AzureSignalRConnectionString连接字符串部署功能应用程序appsettings

main.bicep:

param location string = resourceGroup().location
param storageName string
param appServicePlanName string
param functionAppName string
param signalRName string
// Create storage
resource storage 'Microsoft.Storage/storageAccounts@2021-09-01' = {
name: storageName
location: location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
properties: {
supportsHttpsTrafficOnly: true
minimumTlsVersion: 'TLS1_2'
}
}
// Create serverless app service plan
resource appServicePlan 'Microsoft.Web/serverfarms@2021-03-01' = {
name: appServicePlanName
location: location
sku: {
name: 'Y1'
tier: 'Dynamic'
size: 'Y1'
family: 'Y'
capacity: 0
}
properties: {
reserved: false
}
}
// Create the function app without the app settings
resource functionApp 'Microsoft.Web/sites@2021-03-01' = {
name: functionAppName
location: location
kind: 'functionapp'
properties: {
serverFarmId: appServicePlan.id
clientAffinityEnabled: false
clientCertEnabled: false
httpsOnly: true
siteConfig: {
ftpsState: 'Disabled'
minTlsVersion: '1.2'
cors: {
allowedOrigins: [
'https://portal.azure.com'
]
supportCredentials: false
}
}
}
}
// Create the signalr key
var signalrKeyName = 'signalr_extension'
resource signalRKey 'Microsoft.Web/sites/host/systemkeys@2021-03-01' = {
name: '${functionApp.name}/default/${signalrKeyName}'
properties: {
name: signalrKeyName
}
}
// Create the signalR service and inject the signalr_extension key
resource signalR 'Microsoft.SignalRService/signalR@2022-02-01' = {
name: signalRName
location: location
dependsOn: [
signalRKey
]
sku: {
name: 'Free_F1'
tier: 'Free'
capacity: 1
}
properties: {
features: [
{
flag: 'ServiceMode'
value: 'Serverless'
}
{
flag: 'EnableConnectivityLogs'
value: 'true'
}
]
cors: {
allowedOrigins: [
'*'
]
}
tls: {
clientCertEnabled: false
}
upstream: {
templates: [
{
hubPattern: '*'
eventPattern: '*'
categoryPattern: '*'
auth: {
type: 'None'
}
urlTemplate: 'https://${functionApp.name}.azurewebsites.net/runtime/webhooks/signalr?code=${listKeys(resourceId('Microsoft.Web/sites/host', functionApp.name, 'default'), '2022-03-01').systemkeys.signalr_extension}'
}
]
}
}
}
// Deploy the app settings at the end with the storage and signalR connectionstring
resource functionAppAppSettings 'Microsoft.Web/sites/config@2020-09-01' = {
name: '${functionApp.name}/appsettings'
properties: {
FUNCTIONS_EXTENSION_VERSION: '~4'
FUNCTIONS_WORKER_RUNTIME: 'dotnet'
WEBSITE_RUN_FROM_PACKAGE: '1'
AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, '2019-06-01').keys[0].value};EndpointSuffix=core.windows.net;'
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, '2019-06-01').keys[0].value};EndpointSuffix=core.windows.net;'
WEBSITE_CONTENTSHARE: functionApp.name
AzureSignalRConnectionString: listkeys(signalR.id, signalR.apiVersion).primaryConnectionString
}
}

最新更新