You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

合并至master分支后GitLab CI/CD作业找不到Terraform计划工件失败

问题:GitLab CI/CD部署作业无法找到Terraform Plan生成的工件

问题背景

我维护一套GitLab CI/CD流水线,核心作业逻辑如下:

  • terraform_plan_configuration:执行terraform plan并生成deployment_plan工件,仅在创建目标为master分支的合并请求(MR)时触发,工件保留20分钟。
  • deploy_terraform_infrastructure:执行terraform apply deployment_plan部署资源,仅在代码合并到master分支后运行。

但部署作业始终提示找不到deployment_plan文件,原以为GitLab工件可跨作业访问,实际触发文件不存在的错误。流水线YAML配置如下:

stages:
  - analysis
  - plan
  - deployment
  - release

terraform_validate_configuration:
  stage: analysis
  image:
    name: "hashicorp/terraform:1.10"
    entrypoint: [""]
  rules:
    - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
  script:
    - terraform init
    - terraform validate
  artifacts:
    paths:
      - ./.terraform/
    expire_in: "3 mins"

checkov_scan_directory:
  stage: analysis
  image:
    name: "bridgecrew/checkov:3.2.344"
    entrypoint: [""]
  rules:
    - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
  script:
    - checkov --directory ./ --soft-fail

trivy_scan_security:
  stage: analysis
  image: 
    name: "aquasec/trivy:0.58.2"
    entrypoint: [""]
  rules:
    - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
  script:
    - trivy config --format table ./

terraform_plan_configuration:
  stage: plan
  image:
    name: "hashicorp/terraform:1.10"
    entrypoint: [""]
  rules:
    - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
  dependencies:
    - terraform_validate_configuration
  script:
    - terraform init
    - terraform plan -out=deployment_plan
  artifacts:
    paths:
      - ./deployment_plan
    when: on_success
    expire_in: "20 mins"

deploy_terraform_infrastructure:
  stage: deployment
  image:
    name: "hashicorp/terraform:1.10"
    entrypoint: [""]
  rules:
    - if: $CI_COMMIT_BRANCH == "master"
  dependencies:
    - terraform_plan_configuration
    - terraform_validate_configuration
  script:
    - terraform apply deployment_plan

核心原因

GitLab中合并请求(MR)流水线分支流水线是完全独立的执行实例,工件无法跨流水线共享:

  • terraform_plan_configuration运行在MR专属流水线中,生成的deployment_plan仅属于该流水线。
  • deploy_terraform_infrastructure运行在代码合并后的master分支流水线中,无法访问MR流水线的工件。

另外,Terraform的plan输出文件和当前代码状态、后端状态严格绑定,即使手动拷贝也可能因代码或状态变化导致失效,这也是跨流水线复用plan文件的潜在风险。

解决方案

方案1:在部署作业中重新执行Plan并Apply

直接在deploy_terraform_infrastructure中重新生成plan文件,避免跨流水线依赖工件。修改后的作业配置如下:

deploy_terraform_infrastructure:
  stage: deployment
  image:
    name: "hashicorp/terraform:1.10"
    entrypoint: [""]
  rules:
    - if: $CI_COMMIT_BRANCH == "master"
  dependencies:
    - terraform_validate_configuration
  script:
    - terraform init
    - terraform plan -out=deployment_plan
    - terraform apply deployment_plan
  artifacts:
    paths:
      - ./deployment_plan
    expire_in: "20 mins"

优势:无需依赖MR流水线的工件,保证plan和apply使用的是合并后master分支的最新代码和状态,避免状态不一致问题。

方案2:将Plan和Deploy放在同一流水线中

调整触发规则,让terraform_plan_configurationdeploy_terraform_infrastructure在同一条流水线中执行(比如MR合并后的master分支流水线),但需添加保护机制避免误部署:

terraform_plan_configuration:
  stage: plan
  image:
    name: "hashicorp/terraform:1.10"
    entrypoint: [""]
  rules:
    # 保留MR触发,同时让master分支流水线也触发
    - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"
    - if: $CI_COMMIT_BRANCH == "master"
  dependencies:
    - terraform_validate_configuration
  script:
    - terraform init
    - terraform plan -out=deployment_plan
  artifacts:
    paths:
      - ./deployment_plan
    when: on_success
    expire_in: "20 mins"

deploy_terraform_infrastructure:
  stage: deployment
  image:
    name: "hashicorp/terraform:1.10"
    entrypoint: [""]
  rules:
    - if: $CI_COMMIT_BRANCH == "master"
      # 添加手动触发,避免自动部署
      when: manual
  dependencies:
    - terraform_plan_configuration
    - terraform_validate_configuration
  script:
    - terraform apply deployment_plan

优势:plan和apply在同一流水线中,工件可正常共享;添加when: manual确保部署需要人工确认,降低风险。

内容的提问来源于stack exchange,提问作者Mykoliux

火山引擎 最新活动