Azure DevOps中CDKTF部署多市场Azure资源互扰问题及解决
问题:CDKTF部署多Market Azure资源时互相销毁的解决办法
问题场景
在Azure DevOps管道中使用CDKTF(azurerm provider)部署Azure基础设施时,出现部署Market B的资源会销毁Market A创建的资源的问题。以下是相关简化代码与配置:
CDKTF核心代码
//code setup... class MyStack extends TerraformStack { constructor(scope: Construct, id: string, env: Environment) { super(scope, id); // Azure provider setup and backend configuration... const resGroup = new ResourceGroup(this, env.CreateId(resourceGroupId), { // Resource group configuration... }); const mainStorageAccount = new StorageAccount(this, env.CreateId(storageAccountId), { // Storage account configuration... }); const cdnProfile = new CdnProfile(this, env.CreateId(profileNameId), { // CDN profile configuration... }); const cdnEndpointConfig = { // CDN endpoint configuration... }; new CdnEndpoint(this, cdnEndpointConfig.name, cdnEndpointConfig); } } // App setup and environment variables... const app = new App(); const tfEnvironmentType = process.env.TF_ENVIRONMENT || 'test'; const market = process.env.MARKET || 'A'; let env: Environment | undefined; if (tfEnvironmentType && market) { env = new Environment(tfEnvironmentType, market); } else { console.error('One or more environment variables are missing.'); process.exit(1); // Exit the process with a non-zero status code to indicate an error } if (env) { const environmentID = env.GetID(); new MyStack(app, 'src', env); app.synth(); }
Azure DevOps管道配置
Market A部署任务
- task: AzureCLI@2 displayName: Running Deployment with Market XX inputs: azureSubscription: $(AZURE_SUBSCRIPTION) scriptType: 'bash' scriptLocation: 'inlineScript' addSpnToEnvironment: true failOnStandardError: true inlineScript: | cd infrastructure export ARM_CLIENT_ID=$servicePrincipalId export ARM_CLIENT_SECRET=$servicePrincipalKey export ARM_TENANT_ID=$tenantId export ARM_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID export MARKET=A # Set Market variable to 'A' echo "Deploying infrastructure with Market: $MARKET" npm run deploy
Market B部署任务
- task: AzureCLI@2 displayName: Running Deployment with Market DK inputs: azureSubscription: $(AZURE_SUBSCRIPTION) scriptType: 'bash' scriptLocation: 'inlineScript' addSpnToEnvironment: true failOnStandardError: true inlineScript: | cd infrastructure export ARM_CLIENT_ID=$servicePrincipalId export ARM_CLIENT_SECRET=$servicePrincipalKey export ARM_TENANT_ID=$tenantId export ARM_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID export MARKET=B # Set Market variable to 'B' echo "Deploying infrastructure with Market: $MARKET" npm run deploy
package.json脚本配置
"scripts": { "deploy": "cdktf deploy $npm_config_TF_ENVIRONMENT --auto-approve", // Other scripts... }
问题原因
默认情况下,CDKTF会使用相同的输出目录(cdktf.out)和Terraform状态文件,导致不同Market的部署共享同一个状态存储。Terraform会将不属于当前Market的资源判定为多余资源,从而执行销毁操作。
解决方案
方案1:为每个Market配置独立的Terraform状态文件
修改CDKTF的Backend配置,让每个Market使用独立的状态存储路径(以Azure Blob Storage为例),确保状态文件互相隔离:
// 在MyStack构造函数中添加Backend配置 new AzurermBackend(this, { resourceGroupName: "tf-state-resource-group", storageAccountName: "tfstateaccount123", containerName: `tfstate-${market}`, // 按Market区分容器 key: `${tfEnvironmentType}/terraform.tfstate` });
方案2:使用独立的CDKTF输出目录(用户验证有效方案)
修改package.json的脚本,为每个Market指定独立的输出目录,同时绑定对应的MARKET环境变量:
"scripts": { "deploy:A": "MARKET=A cdktf deploy $npm_config_TF_ENVIRONMENT --auto-approve --output=cdktf.out.A", "deploy:B": "MARKET=B cdktf deploy $npm_config_TF_ENVIRONMENT --auto-approve --output=cdktf.out.B", // Other scripts... }
然后修改Azure DevOps管道任务,调用对应Market的部署脚本:
Market A管道任务
- task: AzureCLI@2 displayName: 部署Market A基础设施 inputs: azureSubscription: $(AZURE_SUBSCRIPTION) scriptType: 'bash' scriptLocation: 'inlineScript' addSpnToEnvironment: true failOnStandardError: true inlineScript: | cd infrastructure export ARM_CLIENT_ID=$servicePrincipalId export ARM_CLIENT_SECRET=$servicePrincipalKey export ARM_TENANT_ID=$tenantId export ARM_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID echo "Deploying infrastructure with Market: A" npm run deploy:A
Market B管道任务
- task: AzureCLI@2 displayName: 部署Market B基础设施 inputs: azureSubscription: $(AZURE_SUBSCRIPTION) scriptType: 'bash' scriptLocation: 'inlineScript' addSpnToEnvironment: true failOnStandardError: true inlineScript: | cd infrastructure export ARM_CLIENT_ID=$servicePrincipalId export ARM_CLIENT_SECRET=$servicePrincipalKey export ARM_TENANT_ID=$tenantId export ARM_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID echo "Deploying infrastructure with Market: B" npm run deploy:B
这种方式通过独立输出目录隔离不同Market的CDKTF合成产物,避免状态文件冲突,实现按需部署不同Market的资源。
内容的提问来源于stack exchange,提问作者stela
相关产品推荐
相关产品推荐

