我在GitLab CI/CD流水线中尝试使用Terraform创建Azure的ResourceGroup

总结

让我们将基础设施也转换为IaC(代码),并进行CI!因此,我使用GitLab CI/CD流水线在Azure上创建了一个ResourceGroup。

执行环境 (shí

macOS Monterey 12.3.1 -> macOS 蒙特利12.3.1
python 3.8.12 -> Python 3.8.12
Azure CLI 2.34.1 -> Azure 命令行界面 2.34.1

事前准备

この記事 にあるように Terraform用のサービスプリンシパルが準備されており、以下のシークレット情報を入手できていること

ARM_TENANT_ID
ARM_SUBSCRIPTION_ID
ARM_CLIENT_ID
ARM_CLIENT_SECRET


在Gitlab中的准备工作

创建Gitlab的个人访问令牌

    • Gitlab CI/CD の job を実行する権限を有するアクセストークンを発行します(git clone/push時に必要)

サインインアカウントの「Edit profile」-「Access token」を選択
「Token name」に一意の名称を入力後、「Select scopes」で、「api」を選択する
「Create personal access token」ボタンを押す
画面上部に表示される「パーソナルアクセストークン」をどこかにコピーしておく

创建Gitlab仓库

    GitlabにてTerraformのコードを管理するリポジトリ(プライベートリポジトリで可)を作成し、ローカルで git clone します

将秘密信息注册到Gitlab。

スクリーンショット 2022-09-14 21.59.36.png

需要的代码 de

Terraform代碼

这次是由以下三个代码组成的(只是创建资源组而已。。。)

# プロバイダーの定義
terraform {
  required_providers {
    azurerm = "~> 2.33"
  }

  # tfstateファイルを gitlab に保存
  backend "http" {
  }
}

provider "azurerm" {
  features {}
  tenant_id       = var.ARM_TENANT_ID
  subscription_id = var.ARM_SUBSCRIPTION_ID
  client_id       = var.ARM_CLIENT_ID
  client_secret   = var.ARM_CLIENT_SECRET
}

# リソースグループ
resource "azurerm_resource_group" "this" {
  name     = var.resource_group_name
  location = var.region
  tags     = var.tags_def
}
# 環境変数(Azureサービスプリンシパル)
variable "ARM_TENANT_ID" {}
variable "ARM_SUBSCRIPTION_ID" {}
variable "ARM_CLIENT_ID" {}
variable "ARM_CLIENT_SECRET" {}

# タグ情報
variable "tags_def" {
  default = {
    owner       = "ituru"
    period      = "2022-09-16"
    CostCenter  = "PSG2"
    Environment = "GitLab"
  }
}

# 各種パラメータ
variable "region" {}              // 利用リージョン
variable "resource_group_name" {} // リソースグループ名
# パラメータ値の定義
region              = "japaneast"       // 利用リージョン
resource_group_name = "rg_ituru_github" // リソースグループ名

创建 Gitlab CI/CD 的 yaml 文件

在存储库的根目录下创建一个名为 .gitlab-ci.yml 的文件。在这里,我们将编写 Gitlab CI/CD 管道的代码。请参考 GitLab CI/CD 管道设置参考文档 来了解如何编写。

## https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml
include:
  - template: Terraform/Base.gitlab-ci.yml

variables:
  TF_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/tfstate_filename

cache:
  key: tfstate_filename
  paths:
    - .terraform

before_script:
  - export TF_VAR_ARM_TENANT_ID=${ARM_TENANT_ID}
  - export TF_VAR_ARM_SUBSCRIPTION_ID=${ARM_SUBSCRIPTION_ID}
  - export TF_VAR_ARM_CLIENT_ID=${ARM_CLIENT_ID}
  - export TF_VAR_ARM_CLIENT_SECRET=${ARM_CLIENT_SECRET}
  - printenv

stages:
  - prepare
  - validate
  - build
  - deploy
  - cleanup

init:
  stage: prepare
  script:
    - gitlab-terraform init
  rules:
    - if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
      when: always
    - if: '$CI_COMMIT_BRANCH == "main"'

validate:
  stage: validate
  script:
    - gitlab-terraform validate
  rules:
    - if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
      when: always
    - if: '$CI_COMMIT_BRANCH == "main"'

plan:
  stage: build
  script:
    - gitlab-terraform plan
    - gitlab-terraform plan-json
  artifacts:
    name: plan
    paths:
      - plan.cache
    reports:
      terraform: plan.json
  rules:
    - if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
      when: always
    - if: '$CI_COMMIT_BRANCH == "main"'

apply:
  stage: deploy
  script:
    - gitlab-terraform apply
  dependencies:
    - plan
  rules:
    - if: '$CI_MERGE_REQUEST_IID && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
      when: never
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual

destroy:
  stage: cleanup
  script: 
    - gitlab-terraform destroy
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual

.gitlab-ci.yml的说明

包括

使用 GitHub 上提供的模板,利用 Terraform 执行环境的容器。

变量

在执行Job时,创建了一个名为tfstate的文件夹,并将其位置作为变量嵌入到HTTP端点中。

缓存

这是为了确保可以在不同阶段之间使用terraform执行结果(tfstate文件)的配置。

预设脚本 (yù shè

读取该存储库中的设置变量,并将其定义为环境变量。

阶段

在流水线中设置每个阶段。
由于使用Terraform,所以配置为init > validate > plan > apply > destory。

开始

这是一个初始化terraform的步骤。
当主分支的合并请求被批准(主分支被更新)时,会自动执行。

验证

当主分支的合并请求被批准(主分支被更新)时,将自动执行terraform validate阶段。

计划

这是进行 terraform plan 的阶段。
当主分支的合并请求被批准(主分支被更新)时,会自动执行。
terraform plan 的执行结果将保存为 JSON 文件到 artifacts 中。

申请

这是terraform apply的阶段。
需要手动执行。

摧毁

这是一个执行terraform destroy的阶段。
需要手动执行。


尝试进行git push操作。

现在准备工作已完成。通过进行 git push,将会执行 terraform plan 并在 Azure 上创建 ResourceGroup。

推动

git add .
git commit -m "Actions commit"
git push -u origin main

行动

スクリーンショット 2022-09-15 1.26.15.png

创建和删除 Azure 资源

手动执行创建资源(阶段:部署)和删除资源(阶段:清理)的CI/CD流水线任务。

创建资源

在CI/CD流水线的任务中,执行terraform apply(阶段:部署)会创建资源组。您可以确认资源已经成功创建。

$ az group show --name rg_ituru_gitlab
{
  "id": "/subscriptions/xxxxxxxx-1717-4343-9797-zzzzzzzzzzzz/resourceGroups/rg_ituru_gitlab",
  "location": "japaneast",
  "managedBy": null,
  "name": "rg_ituru_gitlab",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": {
    "CostCenter": "PSG2",
    "Environment": "GitLab",
    "owner": "ituru",
    "period": "2022-09-16"
  },
  "type": "Microsoft.Resources/resourceGroups"
}
スクリーンショット 2022-09-15 1.54.16.png

删除资源

当在 CI/CD流程的作业中执行terrafrom destroy(cleanup阶段),将删除ResourceGroup。可以确认资源已成功删除。

$ az group show --name rg_ituru_gitlab
(ResourceGroupNotFound) Resource group 'rg_ituru_gitlab' could not be found.
Code: ResourceGroupNotFound
Message: Resource group 'rg_ituru_gitlab' could not be found.

总结

我已经简单理解了使用 GitLab CI/CD 管道来通过 Terraform 创建和删除 Azure 资源的实现方法。顺便提一句,我也在尝试在 GitHub Actions 上做类似的事情。

    • GitHub Actions から Terraform で Azure の ResourceGroup を作成してみました

 

    • GitHub Actions から Terraform で Azure の ResourceGroup を更新(変更)してみました

 

    GitHub Actions から Terraform destroy してみました

请读这篇文章。

我参考了以下文章并表示感谢:
使用 Terraform 和 GitLab CI 进行基础设施CI/CD入门
Terraform 项目的 .gitlab-ci.yml 模板
尝试使用 GitLab 管理 terraform 的 tfstate
一个关于零基础的软件工程师在 GitLab 上尝试使用 HTTPS 克隆和推送的文章
一个知识零的软件工程师在没有源代码的情况下构建 GitLab 的CI/CD流水线(DAG)的讨论
预定义变量参考资料

广告
将在 10 秒后关闭
bannerAds