azurerm_linut_function_app创建存储文件共享失败-检查存储帐户是否可访问-azurerm_pri



尝试让azurerm_linux_function_appazurerm_storage_account_network_rulesazurerm_private_endpoint一起工作。

Terraform v1.3.7
on darwin_arm64
+ provider registry.terraform.io/hashicorp/azurerm v3.38.0

这就是我正在尝试的。

provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "func_rg" {
name     = "func"
location = "eastus"
}
# Create the network VNET
resource "azurerm_virtual_network" "func" {
name                = "func_vnet"
address_space       = ["10.0.0.0/16"]
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
}
# Create a subnet for endpoint
resource "azurerm_subnet" "endpoint_subnet" {
name                                      = "endpoint_subnet"
address_prefixes                          = ["10.0.0.0/24"]
virtual_network_name                      = azurerm_virtual_network.func.name
resource_group_name                       = azurerm_resource_group.func_rg.name
private_endpoint_network_policies_enabled = true
}
# Create subnet for functions
resource "azurerm_subnet" "func_subnet" {
name                 = "func_subnet"
resource_group_name  = azurerm_resource_group.func_rg.name
virtual_network_name = azurerm_virtual_network.func.name
address_prefixes     = ["10.0.1.0/24"]
service_endpoints    = ["Microsoft.Storage"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
}
}
}
# Create nsg for subnets
resource "azurerm_network_security_group" "func" {
name                = "func_nsg"
location            = azurerm_resource_group.func_rg.location
resource_group_name = azurerm_resource_group.func_rg.name
}
# Associate nsg with func subnet
resource "azurerm_subnet_network_security_group_association" "func" {
subnet_id                 = azurerm_subnet.func_subnet.id
network_security_group_id = azurerm_network_security_group.func.id
}
# Associate nsg with endpoint subnet
resource "azurerm_subnet_network_security_group_association" "endpoint" {
subnet_id                 = azurerm_subnet.endpoint_subnet.id
network_security_group_id = azurerm_network_security_group.func.id
}
# Create blob Private DNS Zone
resource "azurerm_private_dns_zone" "blob_dns_zone" {
name                = "privatelink.blob.core.windows.net"
resource_group_name = azurerm_resource_group.func_rg.name
}
# Create file Private DNS Zone
resource "azurerm_private_dns_zone" "file_dns_zone" {
name                = "privatelink.file.core.windows.net"
resource_group_name = azurerm_resource_group.func_rg.name
}
# Create table Private DNS Zone
resource "azurerm_private_dns_zone" "table_dns_zone" {
name                = "privatelink.table.core.windows.net"
resource_group_name = azurerm_resource_group.func_rg.name
}
# Create queue Private DNS Zone
resource "azurerm_private_dns_zone" "queue_dns_zone" {
name                = "privatelink.queue.core.windows.net"
resource_group_name = azurerm_resource_group.func_rg.name
}
# Create blob Private DNS Zone Network Link
resource "azurerm_private_dns_zone_virtual_network_link" "blob_vnl" {
name                  = "blob_vnl"
resource_group_name   = azurerm_resource_group.func_rg.name
private_dns_zone_name = azurerm_private_dns_zone.blob_dns_zone.name
virtual_network_id    = azurerm_virtual_network.func.id
}
# Create file Private DNS Zone Network Link
resource "azurerm_private_dns_zone_virtual_network_link" "file_vnl" {
name                  = "file_vnl"
resource_group_name   = azurerm_resource_group.func_rg.name
private_dns_zone_name = azurerm_private_dns_zone.file_dns_zone.name
virtual_network_id    = azurerm_virtual_network.func.id
}
# Create table Private DNS Zone Network Link
resource "azurerm_private_dns_zone_virtual_network_link" "table_vnl" {
name                  = "table_vnl"
resource_group_name   = azurerm_resource_group.func_rg.name
private_dns_zone_name = azurerm_private_dns_zone.table_dns_zone.name
virtual_network_id    = azurerm_virtual_network.func.id
}
# Create queue Private DNS Zone Network Link
resource "azurerm_private_dns_zone_virtual_network_link" "queue_vnl" {
name                  = "queue_vnl"
resource_group_name   = azurerm_resource_group.func_rg.name
private_dns_zone_name = azurerm_private_dns_zone.queue_dns_zone.name
virtual_network_id    = azurerm_virtual_network.func.id
}
resource "azurerm_storage_account" "func" {
name                     = "rdtestfuncsa"
resource_group_name      = azurerm_resource_group.func_rg.name
location                 = azurerm_resource_group.func_rg.location
account_tier             = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_storage_account_network_rules" "func" {
storage_account_id = azurerm_storage_account.func.id
default_action             = "Deny"
ip_rules                   = ["***.***.***.***"]
virtual_network_subnet_ids = [azurerm_subnet.func_subnet.id]
bypass                     = ["Metrics", "Logging", "AzureServices"]
}
resource "azurerm_storage_container" "func" {
name                 = "func-sc"
storage_account_name = azurerm_storage_account.func.name
container_access_type = "private"
}
# Create Private Endpints
resource "azurerm_private_endpoint" "file_endpoint" {
name                = "rdtest_file_pe"
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
subnet_id           = azurerm_subnet.endpoint_subnet.id
private_service_connection {
name                           = "rdtest_file_psc"
private_connection_resource_id = azurerm_storage_account.func.id
is_manual_connection           = false
subresource_names              = ["file"]
}
}
resource "azurerm_private_endpoint" "blob_endpoint" {
name                = "rdtest_blob_pe"
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
subnet_id           = azurerm_subnet.endpoint_subnet.id
private_service_connection {
name                           = "rdtest_blob_psc"
private_connection_resource_id = azurerm_storage_account.func.id
is_manual_connection           = false
subresource_names              = ["blob"]
}
}
resource "azurerm_private_endpoint" "table_endpoint" {
name                = "rdtest_table_pe"
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
subnet_id           = azurerm_subnet.endpoint_subnet.id
private_service_connection {
name                           = "rdtest_table_psc"
private_connection_resource_id = azurerm_storage_account.func.id
is_manual_connection           = false
subresource_names              = ["table"]
}
}
resource "azurerm_private_endpoint" "queue_endpoint" {
name                = "rdtest_queue_pe"
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
subnet_id           = azurerm_subnet.endpoint_subnet.id
private_service_connection {
name                           = "rdtest_queue_psc"
private_connection_resource_id = azurerm_storage_account.func.id
is_manual_connection           = false
subresource_names              = ["queue"]
}
}
# Create DNS A Records
resource "azurerm_private_dns_a_record" "blob_dns_a" {
name                = "rdfunctestblobdns"
zone_name           = azurerm_private_dns_zone.blob_dns_zone.name
resource_group_name = azurerm_resource_group.func_rg.name
ttl                 = 300
records             = [azurerm_private_endpoint.blob_endpoint.private_service_connection.0.private_ip_address]
}
resource "azurerm_private_dns_a_record" "file_dns_a" {
name                = "filedns"
zone_name           = azurerm_private_dns_zone.file_dns_zone.name
resource_group_name = azurerm_resource_group.func_rg.name
ttl                 = 300
records             = [azurerm_private_endpoint.file_endpoint.private_service_connection.0.private_ip_address]
}
resource "azurerm_private_dns_a_record" "table_dns_a" {
name                = "tabledns"
zone_name           = azurerm_private_dns_zone.table_dns_zone.name
resource_group_name = azurerm_resource_group.func_rg.name
ttl                 = 300
records             = [azurerm_private_endpoint.table_endpoint.private_service_connection.0.private_ip_address]
}
resource "azurerm_private_dns_a_record" "queue_dns_a" {
name                = "queuedns"
zone_name           = azurerm_private_dns_zone.queue_dns_zone.name
resource_group_name = azurerm_resource_group.func_rg.name
ttl                 = 300
records             = [azurerm_private_endpoint.queue_endpoint.private_service_connection.0.private_ip_address]
}
resource "azurerm_service_plan" "func" {
name                = "func_sp"
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
os_type             = "Linux"
sku_name            = "EP1"
}
resource "azurerm_linux_function_app" "func" {
name                       = "rd-test-func"
resource_group_name        = azurerm_resource_group.func_rg.name
location                   = azurerm_resource_group.func_rg.location
virtual_network_subnet_id  = azurerm_subnet.func_subnet.id
storage_account_name       = azurerm_storage_account.func.name
storage_account_access_key = azurerm_storage_account.func.primary_access_key
service_plan_id            = azurerm_service_plan.func.id
site_config {
application_stack {
node_version = 16
}
}
}

我从配置中得到这个错误

│ Error: creating Linux Function App: (Site Name "rd-test-func" / Resource Group "func"): web.AppsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="BadRequest" Message="Creation of storage file share failed with: 'The remote server returned an error: (403) Forbidden.'. Please check if the storage account is accessible." Details=[{"Message":"Creation of storage file share failed with: 'The remote server returned an error: (403) Forbidden.'. Please check if the storage account is accessible."},{"Code":"BadRequest"},{"ErrorEntity":{"Code":"BadRequest","ExtendedCode":"99022","Message":"Creation of storage file share failed with: 'The remote server returned an error: (403) Forbidden.'. Please check if the storage account is accessible.","MessageTemplate":"Creation of storage file share failed with: '{0}'. Please check if the storage account is accessible.","Parameters":["The remote server returned an error: (403) Forbidden."]}}]
│ 
│   with azurerm_linux_function_app.func,
│   on main.tf line 236, in resource "azurerm_linux_function_app" "func":
│  236: resource "azurerm_linux_function_app" "func" {
│ 
│ creating Linux Function App: (Site Name "rd-test-func" / Resource Group "func"): web.AppsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="BadRequest" Message="Creation of storage
│ file share failed with: 'The remote server returned an error: (403) Forbidden.'. Please check if the storage account is accessible." Details=[{"Message":"Creation of storage file share failed with: 'The remote server
│ returned an error: (403) Forbidden.'. Please check if the storage account is accessible."},{"Code":"BadRequest"},{"ErrorEntity":{"Code":"BadRequest","ExtendedCode":"99022","Message":"Creation of storage file share
│ failed with: 'The remote server returned an error: (403) Forbidden.'. Please check if the storage account is accessible.","MessageTemplate":"Creation of storage file share failed with: '{0}'. Please check if the
│ storage account is accessible.","Parameters":["The remote server returned an error: (403) Forbidden."]}}]

如果我取出azurerm_storage_account_network_rules(我需要它来实现合规性),配置将进行部署,但在同步触发器时发布函数失败。

func azure functionapp publish rd-test-func
Getting site publishing info...
Uploading package...
Uploading 1.35 KB [###############################################################################]
Upload completed successfully.
Deployment completed successfully.
Syncing triggers...
Syncing triggers...
Syncing triggers...
Syncing triggers...
Syncing triggers...
Syncing triggers...
Error calling sync triggers (BadRequest).

如果我也从azurerm_linux_function_app中删除virtual_network_subnet_id = azurerm_subnet.func_subnet.id,函数将发布,但我需要通过专用端点或网络规则连接函数应用程序。

有人知道如何让它发挥作用吗?

发现azurerm_service_plan需要sku_name = "B1"或更好的azurerm_storage_account_network_rules才能与vnet集成。以下内容适用于B1、S1和P1v2。

provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "func_rg" {
name     = "func"
location = "eastus"
}
resource "azurerm_virtual_network" "func" {
name                = "func_vnet"
address_space       = ["10.0.0.0/16"]
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
}
resource "azurerm_subnet" "func_subnet" {
name                 = "func_subnet"
resource_group_name  = azurerm_resource_group.func_rg.name
virtual_network_name = azurerm_virtual_network.func.name
address_prefixes     = ["10.0.1.0/24"]
service_endpoints    = ["Microsoft.Storage"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
}
}
}
resource "azurerm_storage_account" "func" {
name                     = "rdtestfuncsa"
resource_group_name      = azurerm_resource_group.func_rg.name
location                 = azurerm_resource_group.func_rg.location
account_tier             = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_storage_account_network_rules" "func" {
storage_account_id = azurerm_storage_account.func.id
default_action             = "Deny"
ip_rules                   = ["***.***.***.***"]
virtual_network_subnet_ids = [azurerm_subnet.func_subnet.id]
bypass                     = ["Metrics", "Logging", "AzureServices"]
}
resource "azurerm_service_plan" "func" {
name                = "func_sp"
resource_group_name = azurerm_resource_group.func_rg.name
location            = azurerm_resource_group.func_rg.location
os_type             = "Linux"
sku_name            = "B1"
}
resource "azurerm_linux_function_app" "func" {
name                       = "rd-test-func"
resource_group_name        = azurerm_resource_group.func_rg.name
location                   = azurerm_resource_group.func_rg.location
virtual_network_subnet_id  = azurerm_subnet.func_subnet.id
storage_account_name       = azurerm_storage_account.func.name
storage_account_access_key = azurerm_storage_account.func.primary_access_key
service_plan_id            = azurerm_service_plan.func.id
site_config {
application_stack {
node_version = 16
}
}
}

以下内容应该有效。

你需要为函数内容预先创建一个共享,你可以随意命名。然后将以下作为应用程序设置添加到功能配置中。

这些设置中的更多信息以及您需要它们的原因https://learn.microsoft.com/en-us/azure/azure-functions/functions-app-settings#website_contentshare

应用程序设置(_S)

WEBSITE_CONTENTAZUREFILECONNECTIONSTRING = azurerm_storage_account.func.primary_connection_string    
AzureWebJobsStorage                      = azurerm_storage_account.func.primary_connection_string
WEBSITE_CONTENTSHARE                     = {name of pre-created share}

最新更新