Azure Terraform:禁用公网访问的SQL Server导入bacpac方案
解决方案
针对禁用公网访问的Azure SQL Server,通过Terraform导入BACPAC文件且不开启公网访问,有以下几种可行方案:
方案1:托管身份+存储私有端点(推荐)
利用SQL Server的系统托管身份访问配置了私有端点的存储账户,全程在VNet内部完成数据传输:
- 为SQL Server启用系统分配托管身份,并赋予该身份对目标Blob容器的
Storage Blob Data Reader权限。 - 给存储账户创建私有端点,确保SQL Server所在VNet能通过私有DNS解析存储账户的私有域名(如
{storage-account}.privatelink.blob.core.windows.net)。 - 在Terraform的
azurerm_mssql_database资源中,使用Identity认证类型指定存储的私有端点URL。
示例代码片段:
resource "azurerm_mssql_server" "sql_server" { name = "private-sql-server" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location version = "12.0" administrator_login = "sqladmin" administrator_login_password = "StrongPass123!" public_network_access_enabled = false # 启用系统托管身份 identity { type = "SystemAssigned" } } # 给SQL Server身份分配Blob读取权限 resource "azurerm_role_assignment" "sql_blob_reader" { scope = azurerm_storage_container.bacpac_container.id role_definition_name = "Storage Blob Data Reader" principal_id = azurerm_mssql_server.sql_server.identity[0].principal_id } resource "azurerm_mssql_database" "imported_db" { name = "imported-db" server_id = azurerm_mssql_server.sql_server.id collation = "SQL_Latin1_General_CP1_CI_AS" license_type = "LicenseIncluded" import { # 使用存储账户的私有端点URL storage_uri = "https://${azurerm_storage_account.bacpac_storage.name}.privatelink.blob.core.windows.net/${azurerm_storage_container.bacpac_container.name}/backup.bacpac" storage_authentication_type = "Identity" # 采用托管身份认证 } }
方案2:Terraform外部数据源调用Azure CLI
如果受限于网络或配置,可通过external数据源在能访问SQL私有端点的环境(如VNet内的虚拟机、Azure DevOps私有代理)执行Azure CLI的导入命令:
data "external" "import_bacpac" { program = [ "az", "sql", "db", "import", "--resource-group", azurerm_resource_group.rg.name, "--server", azurerm_mssql_server.sql_server.name, "--name", "imported-db", "--storage-uri", "https://${azurerm_storage_account.bacpac_storage.name}.blob.core.windows.net/${azurerm_storage_container.bacpac_container.name}/backup.bacpac", "--storage-key", azurerm_storage_account.bacpac_storage.primary_access_key, "--admin-user", azurerm_mssql_server.sql_server.administrator_login, "--admin-password", azurerm_mssql_server.sql_server.administrator_login_password, "--no-wait" ] depends_on = [azurerm_mssql_server.sql_server, azurerm_storage_container.bacpac_container] } # 创建空数据库并依赖导入操作完成 resource "azurerm_mssql_database" "imported_db" { name = "imported-db" server_id = azurerm_mssql_server.sql_server.id collation = "SQL_Latin1_General_CP1_CI_AS" license_type = "LicenseIncluded" depends_on = [data.external.import_bacpac] }
注意:执行Terraform的环境必须处于能访问SQL Server私有端点的网络中,且已完成Azure CLI身份认证。
方案3:切换至SQL托管实例(若架构允许)
如果业务架构允许,将SQL Server替换为Azure SQL托管实例——它本身部署在VNet内,默认可访问同VNet/对等VNet内的存储账户(只需存储账户防火墙允许VNet访问),此时Terraform的azurerm_mssql_managed_database资源的import块可直接完成导入,无需额外配置私有端点。
核心注意事项
- 确保SQL Server VNet与存储私有端点VNet处于同一网络或已对等连接。
- 私有DNS区域需正确配置,保证SQL Server能解析存储的私有域名。
- AzureRM Provider 3.31版本已支持
storage_authentication_type = "Identity",无需升级版本。
内容的提问来源于stack exchange,提问作者Lukas Hankeln
相关产品推荐
相关产品推荐

