Azure Pipeline 管道是一个自动化过程;但是往往我们由于某种原因,需要在多个阶段之前获得批准之后再继续下一步流程,所以我们可以向Azure Pipeline 管道添加审批!批准流程可帮助我们进一步控制自己的管道;我们可以控制管道内特定阶段的 Step 开始,通过审批,并决定 Azure Pipeline 管道何时完成。
而至于为什么要添加审批流程,是因为基础设施资源的部署是需要进行评估,慎重操作。有了审批,可以查看前一阶段以确认配置代码是否正确。
--------------------Azure Terraform 系列--------------------
登录 Azure DevOps 的地址:https://www.dev.azure.com ,点击 “+ New project” 创建新的项目
输入项目描述等信息
Project name:“Terraform_CnBateBlogWeb_AutoDeploy”
Visibility 选择:“Private” ----- (根据现有项目进行设置)
Version control 选择 “Git”
Work item process:“Agile”
确认完以上信息,点击 “Create” 进行创建。
选择左侧菜单 ”Pipelines =》Environments“,点击 ”Create environment“ 创建环境
输入配置以下参数
Name:”Approve_AutoDeploy"
Resoure 选择:“None” (默认即可)
点击 “Create” 创建环境
接下来为当前 “Approve_AutoDeploy” 环境创建审批
点击红色箭头所指,选择 “Approve and checks” 添加审批请求
选择 "Approvals" ,并将自己设置为申请人
添加完成后,可看到类型为 “Approvals” 的记录,大家需要注意的是,审批的过期时间默认是 “30天”,大家可以根据实际情况更改。
选择左侧菜单 “Pipelines”,点击 “Create Pipeline“ 创建 管道作业
今天不使用经典编辑器模式,而选择 GitHub (yaml)
选择对应的 TF Code 的代码仓库
选择 “Start Pipeline” 开启新的管道构建部署代码
Azure DevOps 会为我们自动在项目根目录生成一个名称叫 “azure-pipelines.yaml” 的文件,我们将定义好的管道步骤添加到该文件中
管道步骤审批 yaml 示例代码
jobs: - deployment: terraform_apply continueOnError: false environment: 'Approve_Production' timeoutInMinutes: 120 strategy: runOnce: deploy: steps:
注意:我将在 terraform_apply 阶段之前添加一个申请请求
红色标记是需要改成自己Azure的订阅,
橙色标记是需要添加的变量:
1,管道变量:tf_version
2,秘密变量:terraform_rg,storage_account,storage_account_container,container_key,keyvault,keyvault_sc
1 # Starter pipeline 2 # Start with a minimal pipeline that you can customize to build and deploy your code. 3 # Add steps that build, run tests, deploy, and more: 4 # https://aka.ms/yaml 5 6 trigger: 7 - remote_stats 8 9 pool: 10 vmImage: ubuntu-latest 11 12 variables: 13 - name: tf_version 14 value: 'latest' 15 16 stages: 17 - stage: script 18 jobs: 19 - job: azure_cli_script 20 steps: 21 - task: AzureCLI@2 22 displayName: 'Azure CLI :Create Storage Account,Key Vault And Set KeyVault Secret' 23 inputs: 24 azureSubscription: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 25 scriptType: 'bash' 26 scriptLocation: 'inlineScript' 27 inlineScript: | 28 # create azure resource group 29 az group create --location eastasia --name $(terraform_rg) 30 31 # create azure storage account 32 az storage account create --name $(storage_account) --resource-group $(terraform_rg) --location eastasia --sku Standard_LRS 33 34 # create storage account container for tf state 35 az storage container create --name $(storage_account_container) --account-name $(storage_account) 36 37 # query storage key and set variable 38 ACCOUNT_KEY=$(az storage account keys list --resource-group $(terraform_rg) --account-name $(storage_account) --query "[?keyName == 'key1'][value]" --output tsv) 39 40 # create azure keyvault 41 az keyvault create --name $(keyvault) --resource-group $(terraform_rg) --location eastasia --enable-soft-delete false 42 43 # set keyvault secret,secret value is ACCOUNT_KEY 44 az keyvault secret set --name $(keyvault_sc) --vault-name $(keyvault) --value $ACCOUNT_KEY 45 46 - task: AzureKeyVault@2 47 displayName: 'Azure Key Vault :Get Storage Access Secret' 48 inputs: 49 azureSubscription: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 50 KeyVaultName: '$(keyvault)' 51 SecretsFilter: 'terraform-stste-storage-key' 52 RunAsPreJob: false 53 54 - stage: terraform_validate 55 jobs: 56 - job: terraform_validate 57 steps: 58 - task: TerraformInstaller@0 59 inputs: 60 terraformVersion: ${{variables.tf_version}} 61 - task: TerraformTaskV2@2 62 displayName: 'terraform init' 63 inputs: 64 provider: 'azurerm' 65 command: 'init' 66 # commandOptions: '-backend-config="access_key=$(terraform-stste-storage-key)"' 67 backendServiceArm: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 68 backendAzureRmResourceGroupName: $(terraform_rg) 69 backendAzureRmStorageAccountName: $(storage_account) 70 backendAzureRmContainerName: $(storage_account_container) 71 backendAzureRmKey: $(container_key) 72 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 73 - task: TerraformTaskV2@2 74 inputs: 75 provider: 'azurerm' 76 command: 'validate' 77 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 78 79 - stage: terraform_plan 80 dependsOn: [terraform_validate] 81 condition: succeeded('terraform_validate') 82 jobs: 83 - job: terraform_plan 84 steps: 85 - task: TerraformInstaller@0 86 inputs: 87 terraformVersion: ${{ variables.tf_version }} 88 - task: TerraformTaskV2@2 89 displayName: 'terraform init' 90 inputs: 91 provider: 'azurerm' 92 command: 'init' 93 # commandOptions: '-backend-config="access_key=$(terraform-stste-storage-key)"' 94 backendServiceArm: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 95 backendAzureRmResourceGroupName: $(terraform_rg) 96 backendAzureRmStorageAccountName: $(storage_account) 97 backendAzureRmContainerName: $(storage_account_container) 98 backendAzureRmKey: $(container_key) 99 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 100 - task: TerraformTaskV2@2 101 inputs: 102 provider: 'azurerm' 103 command: 'plan' 104 environmentServiceNameAzureRM: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 105 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 106 107 - stage: terraform_apply 108 dependsOn: [terraform_plan] 109 condition: succeeded('terraform_plan') 110 jobs: 111 - deployment: terraform_apply 112 continueOnError: false 113 environment: 'Approve_Production' 114 timeoutInMinutes: 120 115 strategy: 116 runOnce: 117 deploy: 118 steps: 119 - checkout: self 120 - task: TerraformInstaller@0 121 inputs: 122 terraformVersion: ${{ variables.tf_version }} 123 - task: TerraformTaskV2@2 124 displayName: 'terraform init' 125 inputs: 126 provider: 'azurerm' 127 command: 'init' 128 # commandOptions: '-backend-config="access_key=$(terraform-stste-storage-key)"' 129 backendServiceArm: 'Microsoft Azure Subscrription(XXXX-XXX-XX-XX-XXX)' 130 backendAzureRmResourceGroupName: $(terraform_rg) 131 backendAzureRmStorageAccountName: $(storage_account) 132 backendAzureRmContainerName: $(storage_account_container) 133 backendAzureRmKey: $(container_key) 134 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 135 - task: TerraformTaskV2@2 136 inputs: 137 provider: 'azurerm' 138 command: 'plan' 139 environmentServiceNameAzureRM: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 140 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 141 - task: TerraformTaskV2@2 142 inputs: 143 provider: 'azurerm' 144 command: 'apply' 145 commandOptions: '-auto-approve' 146 environmentServiceNameAzureRM: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 147 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 148 149 # - stage: terraform_apply 150 # dependsOn: [terraform_plan] 151 # condition: succeeded('terraform_plan') 152 # jobs: 153 # - job: terraform_apply 154 # steps: 155 # - task: TerraformInstaller@0 156 # inputs: 157 # terraformVersion: ${{ variables.tf_version }} 158 # - task: TerraformTaskV2@2 159 # displayName: 'terraform init' 160 # inputs: 161 # provider: 'azurerm' 162 # command: 'init' 163 # # commandOptions: '-backend-config="access_key=$(terraform-stste-storage-key)"' 164 # backendServiceArm: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 165 # backendAzureRmResourceGroupName: $(terraform_rg) 166 # backendAzureRmStorageAccountName: $(storage_account) 167 # backendAzureRmContainerName: $(storage_account_container) 168 # backendAzureRmKey: $(container_key) 169 # workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 170 # - task: TerraformTaskV2@2 171 # inputs: 172 # provider: 'azurerm' 173 # command: 'plan' 174 # environmentServiceNameAzureRM: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 175 # workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 176 # - task: TerraformTaskV2@2 177 # inputs: 178 # provider: 'azurerm' 179 # command: 'apply' 180 # commandOptions: '-auto-approve' 181 # environmentServiceNameAzureRM: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 182 # workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 183 184 - stage: terraform_destroy 185 dependsOn: [terraform_apply] 186 condition: succeeded('terraform_apply') 187 jobs: 188 - job: terraform_destroy 189 steps: 190 - task: TerraformInstaller@0 191 inputs: 192 terraformVersion: ${{ variables.tf_version }} 193 - task: TerraformTaskV2@2 194 displayName: 'terraform init' 195 inputs: 196 provider: 'azurerm' 197 command: 'init' 198 # commandOptions: '-backend-config="access_key=$(terraform-stste-storage-key)"' 199 backendServiceArm: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 200 backendAzureRmResourceGroupName: $(terraform_rg) 201 backendAzureRmStorageAccountName: $(storage_account) 202 backendAzureRmContainerName: $(storage_account_container) 203 backendAzureRmKey: $(container_key) 204 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 205 - task: TerraformTaskV2@2 206 inputs: 207 provider: 'azurerm' 208 command: 'plan' 209 environmentServiceNameAzureRM: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 210 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/' 211 - task: TerraformTaskV2@2 212 inputs: 213 provider: 'azurerm' 214 command: 'destroy' 215 commandOptions: '-auto-approve' 216 environmentServiceNameAzureRM: 'Microsoft Azure Subscription(XXXX-XXX-XX-XX-XXX)' 217 workingDirectory: '$(System.DefaultWorkingDirectory)/src/model/'
添加秘密变量,点击 “ Variables=》New variable”
输入机密的名称和值
Name:“terraform_rg”
Value:“Web_Test_TF_RG”
点击 “OK” 确认添加操作
按照以上方式一次添加以下机密信息
terraform_rg:"Web_Test_TF_RG"
storage_account:"cnbatetfstorage"
storage_account_container:"tf-state001"
container_key:"cnbate.tf.stats"
keyvault:"cnbate-terraform-kv001"
keyvault_sc:"terraform-stste-storage-key"
完成以上信息后,点击 ”Run” 手动触发当前 Pipeline
选择分支 ‘“remote_stats”,点击 “Run”
接下来我们就会看到整个流程步骤,以及当前运行运行的步骤,如果需要审批,流程就会暂停,等待审批完成后,再执行后续操作
点击 “Approve” 同意审批,进行下一步执行 TF Code 执行部署计划
OK,成功!!!部署完成。是✨