Terraform을 배포하기 위한 Azure DevOps 파이프라인 실패

Terraform Plan을 실행한 후 배포를 진행하는 Azure DevOps 파이프라인을 구성했습니다.

Plan 작업은 정상적으로 수행되고, 승인 단계에서 잠시 멈춘 다음, 다시 Init을 시도하고 배포 단계로 넘어가려 할 때 아래와 같은 오류가 발생합니다:

Terraform을 다시 설치하는 작업을 추가하려고 했지만, 효과가 없었습니다.

빌드 파이프라인에서 무엇이 잘못되었는지 아시겠나요?

오류 메시지:

Starting: Terraform Init
==============================================================================
Task         : Terraform
Description  : Execute terraform commands to manage resources on AzureRM, Amazon Web Services(AWS) and Google Cloud Platform(GCP). v4.241.11
Version      : 4.241.33
Author       : Microsoft Corporation
Help         : [Learn more about this task](https://aka.ms/devlabs/ado/tf/task/v4)
==============================================================================
##[error]Error: **Failed to find terraform tool in paths
Finishing: Terraform Init**

Pipeline:

pr: none
trigger: none

stages:
- stage:
  displayName: Terraform Plan
  jobs:
  - job: TerraformPlan 
    displayName: Terraform Plan
    condition: succeeded()
    pool: azc-vmss-man-ado-uks-001
    steps:
    - task: TerraformInstaller@1
      inputs:
        terraformVersion: 'latest'
    - task: TerraformTaskV4@4
      displayName: Terraform Init 
      inputs:
        provider: 'azurerm'
        command: 'init'
        workingDirectory: '$(System.DefaultWorkingDirectory)/projects/skeleton'
        backendAzureRmUseEnvironmentVariablesForAuthentication: false
        backendAzureRmUseEntraIdForAuthentication: false
        backendServiceArm: 'azure-dev'
        backendAzureRmResourceGroupName: 'azc-rg-dev-devops-uks-001'
        backendAzureRmStorageAccountName: 'azcstordevterfrmuks001'
        backendAzureRmContainerName: 'terraform'
        backendAzureRmKey: 'skeleton'
    - task: TerraformTaskV4@4
      displayName: Terraform Plan
      inputs:
          provider: 'azurerm'
          command: 'plan'
          workingDirectory: '$(System.DefaultWorkingDirectory)/projects/skeleton'
          commandOptions: '-var-file=./tfvars/dev.tfvars -out=deployment.tfplan -input=false -out=deployment.tfplan'
          environmentServiceNameAzureRM: 'azure-dev'
- stage:
  displayName: Terraform Apply
  jobs:
    - deployment: Apply
      pool: azc-vmss-man-ado-uks-001
      environment: azure-spoke-dev-app-skeleton
      displayName: Terraform Apply
      condition: succeeded()
      strategy:
        runOnce:
          deploy:
            steps:
              - task: TerraformTaskV4@4
                displayName: Terraform Init 
                inputs:
                  provider: 'azurerm'
                  command: 'init'
                  workingDirectory: '$(System.DefaultWorkingDirectory)/projects/skeleton'
                  backendAzureRmUseEnvironmentVariablesForAuthentication: false
                  backendAzureRmUseEntraIdForAuthentication: false
                  backendServiceArm: 'azure-dev'
                  backendAzureRmResourceGroupName: 'azc-rg-dev-devops-uks-001'
                  backendAzureRmStorageAccountName: 'azcstordevterfrmuks001'
                  backendAzureRmContainerName: 'terraform'
                  backendAzureRmKey: 'skeleton'

              - task: TerraformTaskV4@4
                displayName: Terraform Plan
                inputs:
                  provider: 'azurerm'
                  command: 'plan'
                  workingDirectory: '$(System.DefaultWorkingDirectory)/projects/skeleton'
                  commandOptions: '-var-file=./tfvars/dev.tfvars -out=deployment.tfplan -input=false -out=deployment.tfplan'
                  environmentServiceNameAzureRM: 'azure-dev'
                                  
              - task: TerraformTaskV4@4
                inputs:
                  provider: 'azurerm'
                  command: 'apply'
                  workingDirectory: '$(System.DefaultWorkingDirectory)/projects/skeleton'
                  commandOptions: '-input=false deployment.tfplan'
                  environmentServiceNameAzureRM: 'azure-dev'

Based on your description, it appeared that your pipeline was running on VMSS self-hosted agents. If you have configured more than one instance for your VMSS resource, the two agent jobs in this pipeline may have been running on different agent machines.

Even if both jobs run on the same VMSS instance, you still need to add the TerraformInstaller@1 task for each agent job. This task simply downloads Terraform into $(Agent.ToolsDirectory) for use in subsequent steps within the same job — it does not install Terraform globally on the agent machine. The only exception is if your VMSS instances were scaled out using an image that already included the Terraform toolset.

Additionally, unlike a traditional job, where the first default step is - checkout: self, a deployment job starts with - download: current by default to download artifacts published in the current run. Since no pipeline artifacts were published before the deployment: Apply job, if it ran on a different agent machine than the job: TerraformPlan, it had no access to the Terraform templates needed for initialization, planning, or applying changes.

To help you troubleshoot and resolve this issue, I suggest adding the following three steps to your deployment: Apply job. These steps ensure that Terraform is installed, the templates are checked out from your repository, and the necessary requirments are verified before running terraform init.

...
          steps:
          - checkout: self
          - task: TerraformInstaller@1
            inputs:
              terraformVersion: 'latest'
          - script: |
              terraform -version
              echo "Agent.Name - $(Agent.Name)"
              echo "Agent.MachineName - $(Agent.MachineName)"
              echo "System.DefaultWorkingDirectory - $(System.DefaultWorkingDirectory)"
              tree $(System.DefaultWorkingDirectory)
...
1 Like

Try adding a step to install Terraform in the second stage - Terraform Apply as well. Your code only installs it in the first stage.

Since the second stage is a Deployment stage you should add a step to explicitly checkout your repo.

- task: TerraformInstaller@1
  inputs:
    terraformVersion: 'latest'