Terraform远程状态配置鸡生蛋问题 Azure场景下最优实现方案咨询
认知澄清
首先你对Terraform的核心理解是正确的,IaC的目标就是尽可能替代手动资源操作,官方文档要求手动预配状态存储资源,本质是为了解决**「鸡生蛋」的引导悖论**:
Terraform执行任何计划/应用操作前,都需要先读取现有状态文件判断资源差异,如果把存储状态的云资源也写在同一个Terraform配置中,第一次执行时状态存储资源还不存在,状态文件没有地方存放,流程无法推进,所以这是启动阶段的特殊场景,不属于设计矛盾。
绿地场景的最优实现方案
针对你当前无任何预配资源、要部署Azure静态网站的场景,有两种完全符合IaC理念、无冗余手动操作的方案,比文档里的手动敲命令方式更规范:
方案1:两级Terraform配置法(最推荐)
把资源拆成两个独立的Terraform项目,全程用Terraform管理所有资源:
- 第一级是极简的「引导配置」,仅包含远程状态需要的3个资源:资源组、存储账户、存储容器,这部分第一次执行时用本地状态,资源创建完成后可以把这部分的状态文件加密后提交到Git(该类资源变更频率极低,风险可控),也可以手动执行一次
terraform init -migrate-state把引导配置的状态也迁移到刚创建好的存储容器中。
引导配置示例代码:
terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>3.0" } } } provider "azurerm" { features {} } # 状态存储专用资源组,和业务资源隔离 resource "azurerm_resource_group" "tfstate" { name = "rg-tfstate-<环境标识,比如prod/test>" location = "<Azure区域,比如chinanorth3>" } # 状态存储账户,强制开启版本控制和软删除防止状态丢失 resource "azurerm_storage_account" "tfstate" { name = "sttfstate<全局唯一后缀,比如公司名缩写+环境标识>" resource_group_name = azurerm_resource_group.tfstate.name location = azurerm_resource_group.tfstate.location account_tier = "Standard" account_replication_type = "GRS" enable_blob_versioning = true blob_soft_delete_retention_days = 7 } # 状态存储专用容器 resource "azurerm_storage_container" "tfstate" { name = "tfstate" storage_account_name = azurerm_storage_account.tfstate.name container_access_type = "private" }
- 第二级是业务配置,也就是你用来部署Azure静态网站的主配置,直接在terraform块中声明azurerm后端,使用第一级创建好的存储资源存储状态即可,后续所有业务资源变更都不需要再操作引导配置。
后端配置示例:
terraform { backend "azurerm" { resource_group_name = "rg-tfstate-<环境标识>" storage_account_name = "sttfstate<全局唯一后缀>" container_name = "tfstate" key = "prod/static-website.tfstate" } # 其余provider、变量、资源配置省略 }
方案2:自动化脚本引导法
如果不想维护两级配置,可以把预配状态存储的PowerShell命令封装成可执行脚本提交到Git,第一次部署前执行一次脚本即可,全程无手动点选操作,也符合自动化要求。
示例脚本(PowerShell):
# 配置参数 $rgName = "rg-tfstate-prod" $location = "chinanorth3" $storageAccountName = "sttfstateprod<唯一后缀>" $containerName = "tfstate" # 创建资源 New-AzResourceGroup -Name $rgName -Location $location New-AzStorageAccount -ResourceGroupName $rgName -Name $storageAccountName -SkuName Standard_GRS -Location $location -EnableBlobVersioning $true -BlobSoftDeleteRetentionDays 7 New-AzStorageContainer -Name $containerName -Context (New-AzStorageContext -StorageAccountName $storageAccountName -UseConnectedAccount) -Permission Off
实操建议
你当前是静态网站这类复杂度不高的项目,优先选方案1,所有资源都纳入Terraform管理,后续扩容多环境、多业务项目时也可以直接复用这套状态存储资源,不需要再做引导操作。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

