You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:53:16