尝试让azurerm_linux_function_app
与azurerm_storage_account_network_rules
和azurerm_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}