跳至主要内容

在 Azure 上使用 Terraform:面向初学者的 IaC 实战指南

本教程演示如何将 Terraform 与 Azure 结合,自动化基础设施、提高一致性,并按最佳实践实现安全、可扩展的部署。
· 13分钟 阅读

使用 AI 探索

如果您曾在 Azure 门户里一通点点点,想手动把云端资源拼起来——我也经历过,而且很快就会觉得繁琐。这时 Terraform 就派上用场了。它是一款基础设施即代码(IaC)工具,允许您用几行代码就能定义并管理云端环境。

在本教程中,我们将聚焦于在 Azure 上使用 Terraform。我会带您了解 Terraform 是什么、它如何融入 Azure 生态,以及如何通过实战示例上手。我们还会介绍一些最佳实践,帮助您从一开始就构建安全可靠的部署。

如果您对 Azure 生态完全陌生,这条 Azure 基础学习路径能为您系统性介绍核心服务与基本原理。

为什么在 Azure 上使用 Terraform?

Terraform 由 HashiCorp 开发,是一款开源 IaC 工具,使用声明式语法来定义与管理云基础设施。与 Microsoft Azure 搭配使用时,您可以在可读性强的配置文件中脚本化虚拟网络、VM、数据库等资源。

为何要将 Terraform 与 Azure 结合?核心在于一致性、可扩展性与速度。无论是启用一台 VM,还是编排复杂的多层应用,Terraform 都能简化流程并降低人为失误。

如果您完全不熟悉 Terraform,这份 Terraform 新手指南讲解了基础概念以及如何用它实现基础设施即代码。

Azure 上的 Terraform 核心概念

Terraform 与 Azure 的集成提供了一系列直观而强大的功能。下面我们来看看关键组件与常见的 Terraform 资源类型。

声明式的基础设施管理

Terraform 的声明式方式让您可以在 .tf 文件中使用 HashiCorp 配置语言(HCL)定义目标 Azure 基础设施形态。 

例如,您可以指定 Azure VM 的规格、位置与网络设置,Terraform 则负责创建方式的细节。示例如下:

resource "azurerm_virtual_machine" "example" {
  name                  = "my-vm"
  location              = "East US"
  resource_group_name   = "my-resource-group"
  vm_size               = "Standard_D2s_v3"
  network_interface_ids = [azurerm_network_interface.example.id]
  # ... other necessary configurations like OS disk, admin details
}

上述定义保证了幂等性——多次运行同一份代码会得到同样的结果,不会产生重复或错误。 

现在,让我们分解支撑这种声明式方式的核心 Terraform 概念。

Terraform 状态(.tfstate)

terraform.tfstate 文件是 Terraform 声明式模型的核心。它是一个 JSON 文件,记录了当前在 Azure 上已部署的资源、其配置与关联关系。 

当您运行 terraform apply 时,Terraform 会将 .tf 文件(期望状态)与 .tfstate 文件(实际状态)进行对比,以确定应进行哪些变更。例如,若您在代码中更新了 VM 的规格,Terraform 会检查 .tfstate 并仅在 Azure 中修改该属性。 

该文件可本地存储,但团队协作时请使用 Azure Blob 存储,以便协作与状态锁定,避免冲突。

Terraform 变量(.tfvars)

变量让配置更灵活、可复用。通过在 variables.tf 和 terraform.tfvars 中定义,您可以参数化资源名称或区域等值。 

例如:

# variables.tf
variable "location" {
  type        = string
  default     = "East US"
  description = "The Azure region where resources will be deployed."
}

# terraform.tfvars (for a specific environment, e.g., production)
location = "West US"

# main.tf
resource "azurerm_resource_group" "example" {
  name     = "my-rg"
  location = var.location
}

terraform.tfvars 会覆盖默认值,因此您无需修改核心 .tf 文件,就能在不同区域部署同一套代码。可以用于管理多个环境(如开发、生产)。

Terraform 配置文件(.tf)

这些文件中编写您的基础设施代码(HCL),定义资源、提供商、模块等。您可以将其组织为单个 main.tf,也可拆分为多个文件(如 variables.tf、outputs.tf、network.tf、compute.tf),以提高清晰度与可维护性。

Terraform plan

在应用更改前,terraform plan 会基于 .tf 与 .tfstate 的差异,预览 Terraform 将执行的动作——创建、更新或删除资源。它相当于一次“演练”,能及早发现潜在问题,并展示详细的变更摘要。

Terraform apply

terraform apply 会执行 terraform plan 确定的变更,令 Azure 达到您期望的状态,并刷新 .tfstate 文件。应用前会提示您确认,提供一层安全防线。

工作区(Workspaces)

Terraform 工作区允许您用一套 .tf 文件管理多个环境(如开发、预生产、生产)。每个工作区都有独立的 .tfstate,因此可以基于不同配置部署相似的基础设施(例如开发与生产使用不同 VM 规格)。 

创建新工作区:

terraform workspace new production

然后切换到该工作区:

terraform workspace select production

模块(Modules)

模块是可复用的 Terraform 代码包。比如,您可以为 Azure 虚拟网络创建一个模块,并在多个项目中复用,从而减少重复并促进标准化。我们会在最佳实践部分进一步讨论模块。

这些概念——.tfstate、.tfvars 与声明式工作流——协同工作,确保您的 Azure 基础设施可预测、可复现、易管理。

状态管理与协作

terraform.tfstate 文件用于跟踪基础设施状态。团队协作时,将其存储在 Azure Blob 存储是关键最佳实践,可实现共享访问与版本控制。该远程后端配置确保团队成员对基础设施有一致的视图。 

状态锁定(许多远程后端如 Azure Blob 存储会自动提供)可在多人同时运行 Terraform 命令时避免冲突,确保数据一致性。

以下为配置 Azure Blob 存储后端的示例:

terraform {
  backend "azurerm" {
    resource_group_name  = "my-terraform-state-rg"
    storage_account_name = "mystorageterraformstate"
    container_name  = "tfstate"
    key  = "production/terraform.tfstate" # Path within the container
  }
}

在使用该配置运行 terraform init 之前,您需要先手动或通过另一份 Terraform 配置创建 Azure 存储帐户与容器。此设置可确保对 Azure 资源的安全、协同管理。

提供商生态与 AzureRM

azurerm 提供商是 Terraform 通往 Azure 的桥梁,将 HCL 转换为用于管理 VM、网络、数据库等服务的 API 调用。 

它支持数百种资源类型,从计算(azurerm_linux_virtual_machine、azurerm_windows_virtual_machine)到分析(azurerm_synapse_workspace)。其特性包括:

  • 覆盖面广:可管理大量 Azure 服务,包括虚拟机、存储帐户、Azure Kubernetes Service(AKS)、Azure SQL 数据库、采用 MongoDB API 的 Azure Cosmos DB、Azure Functions 等等。azurerm 提供商在积极开发中,会在新服务与功能发布后提供支持。
  • 动态函数:可使用提供商定义的函数来生成唯一名称(如 azurerm_resource_group.example.name)或获取现有资源的详情(如 data.azurerm_virtual_network.existing.id),从而实现更动态、更智能的配置。
  • 数据源:azurerm 提供商可通过数据源获取现有 Azure 资源信息。当您需要引用并非由当前 Terraform 配置创建的资源时尤为有用。比如,您可以检索现有虚拟网络的详情,以便在不重建 VNet 的前提下部署新的子网或虚拟机。

在深入 Terraform 之前,先了解如何手动配置 Azure 也很有帮助——这份入门指南将带您掌握要点。

搭建 Terraform-Azure 环境

动手实践吧!本节将带您完成在 Azure 订阅中使用 Terraform 的初始设置。

身份验证与 CLI 工具

要与 Azure 交互,您首先需要安装并配置 Azure 命令行界面(CLI)。Azure CLI 提供了身份验证与管理 Azure 资源所需的工具。安装完成后,登录您的 Azure 帐户:

az login

上述命令会打开浏览器进行交互式登录。作为快速参考,这份 Azure CLI 速查表可帮您更高效地完成命令行工作流。

对于使用 Terraform 的自动化部署(尤其在 CI/CD 流水线中),强烈建议创建并使用 Azure Active Directory(AAD)服务主体。服务主体为 Terraform 提供一种安全、可编程的方式认证访问 Azure 订阅,无需交互式登录。

要在订阅范围创建具备“参与者(Contributor)”角色的服务主体,运行:

az ad sp create-for-rbac --name "http://myTerraformServicePrincipal" --role "Contributor" --scopes "/subscriptions/<your-subscription-id>"

输出会提供 appId、password 与 tenant(租户 ID)。随后可将它们设为 Terraform 的环境变量:

export ARM_CLIENT_ID="<appId>"
export ARM_CLIENT_SECRET="<password>"
export ARM_TENANT_ID="<tenant>"
export ARM_SUBSCRIPTION_ID="<your-subscription-id>"

初始化项目

典型的 Terraform 项目有清晰的目录结构,通常为不同资源类型或模块分别创建 .tf 文件(如 main.tf、variables.tf、outputs.tf、network.tf、compute.tf)。 

开始任何 Terraform 项目前,进入项目目录并运行 terraform init。该命令会初始化工作目录、下载所需的提供商插件(如 azurerm),并按配置设置状态后端。

mkdir my-azure-terraform-project
cd my-azure-terraform-project
# Create your .tf files here
terraform init

该命令会为 Terraform 操作准备目录,确保必需插件就绪。

供应 Azure 资源

本节通过常见 Azure 资源的实战示例,演示如何使用 Terraform 进行定义与部署。

虚拟网络与子网

Terraform 擅长在 Azure 上定义与部署网络基础设施。您可以轻松定义虚拟网络(VNet)并将其划分为多个子网,以控制 IP 地址空间与网络隔离。 

Terraform 天生具备依赖管理,能保证资源按正确顺序创建;例如,只有在父级 VNet 创建成功后,子网才会被供应。示例如下:

resource "azurerm_resource_group" "network_rg" {
  name     = "my-network-rg"
  location = "East US"
}

resource "azurerm_virtual_network" "main_vnet" {
  name                = "my-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.network_rg.location
  resource_group_name = azurerm_resource_group.network_rg.name
}

resource "azurerm_subnet" "web_subnet" {
  name                 = "web-subnet"
  resource_group_name  = azurerm_resource_group.network_rg.name
  virtual_network_name = azurerm_virtual_network.main_vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

resource "azurerm_subnet" "app_subnet" {
  name                 = "app-subnet"
  resource_group_name  = azurerm_resource_group.network_rg.name
  virtual_network_name = azurerm_virtual_network.main_vnet.name
  address_prefixes     = ["10.0.2.0/24"]
}

结合 cloud-init 的虚拟机

使用 Terraform 供应虚拟机(VM)非常直接。要自动完成部署后的配置与初始化,您可以利用 cloud-init 脚本。 

cloud-init 允许在 VM 首次启动时执行脚本,从而直接在 Terraform 配置中完成安装软件、配置用户、设置服务等任务。

下面示例展示了如何供应一台 Linux VM,并通过简单的 cloud-init 脚本安装 Nginx:

resource "azurerm_resource_group" "vm_rg" {
  name     = "my-vm-rg"
  location = "East US"
}

resource "azurerm_network_interface" "vm_nic" {
  name                = "my-vm-nic"
  location            = azurerm_resource_group.vm_rg.location
  resource_group_name = azurerm_resource_group.vm_rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.web_subnet.id # Assuming web_subnet defined above
    private_ip_address_allocation = "Dynamic"
    public_ip_address_id          = azurerm_public_ip.vm_public_ip.id
  }
}

resource "azurerm_public_ip" "vm_public_ip" {
  name                = "my-vm-public-ip"
  location            = azurerm_resource_group.vm_rg.location
  resource_group_name = azurerm_resource_group.vm_rg.name
  allocation_method   = "Static"
}

resource "azurerm_linux_virtual_machine" "my_vm" {
  name                  = "my-linux-vm"
  location              = azurerm_resource_group.vm_rg.location
  resource_group_name   = azurerm_resource_group.vm_rg.name
  size                  = "Standard_B2s"
  admin_username        = "azureuser"
  admin_password        = "P@ssw0rd1234!" # In a real scenario, use Azure Key Vault or variables
  network_interface_ids = [azurerm_network_interface.vm_nic.id]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }

  # cloud-init script to install Nginx
  custom_data = base64encode(<<EOF
#cloud-config
packages:
  - nginx
runcmd:
  - systemctl start nginx
  - systemctl enable nginx
EOF
  )
}

基础设施模块化

随着 Azure 基础设施的增长,对 Terraform 配置进行模块化至关重要,可提升复用性、可维护性与可扩展性。 

模块会将一组相关资源与配置封装为可复用单元。本节将指导您如何将 Terraform 代码组织为模块,并展示如何在主配置中调用模块,从而使代码库更整洁、结构更清晰。

示例:模块结构(modules/web-app/main.tf):

# modules/web-app/main.tf
resource "azurerm_app_service_plan" "app_plan" {
  name                = var.app_service_plan_name
  location            = var.location
  resource_group_name = var.resource_group_name
  kind                = "Linux"
  sku {
    tier = "Basic"
    size = "B1"
  }
}

resource "azurerm_app_service" "app_service" {
  name                = var.app_service_name
  location            = var.location
  resource_group_name = var.resource_group_name
  app_service_plan_id = azurerm_app_service_plan.app_plan.id
}

variable "app_service_plan_name" {
  type = string
}

variable "app_service_name" {
  type = string
}

variable "location" {
  type = string
}

variable "resource_group_name" {
  type = string
}

output "app_service_default_hostname" {
  value = azurerm_app_service.app_service.default_host_name
}

示例:调用模块(根目录中的 main.tf):

resource "azurerm_resource_group" "app_rg" {
  name     = "my-webapp-rg"
  location = "East US"
}

module "my_web_app" {
  source                = "./modules/web-app" # Path to your module
  app_service_plan_name = "my-webapp-plan"
  app_service_name      = "my-unique-webapp-2025"
  location              = azurerm_resource_group.app_rg.location
  resource_group_name   = azurerm_resource_group.app_rg.name
}

output "webapp_url" {
  value = module.my_web_app.app_service_default_hostname
}

这种结构让您能轻松在不同环境或项目间复用 Web 应用的部署逻辑。

高级 Terraform 工作流

本节探讨更为灵活强大的 Terraform 功能,帮助您超越基础资源供应,提升部署的弹性与能力。

数据源与动态配置

Terraform 的数据源可获取现有资源的信息,无论是否由 Terraform 管理。这对于对接既有基础设施或进行动态查找非常有用。 

配合动态配置(如 for_each 与 count),数据源能让脚本具备高度的灵活性与自适应能力,以应对多种条件与资源可用性。

示例:使用数据源查找现有 VNet 并新增子网:

# Data source to fetch an existing Virtual Network
data "azurerm_virtual_network" "existing_vnet" {
  name                = "production-vnet"
  resource_group_name = "production-network-rg"
}

# Create a new subnet within the existing VNet
resource "azurerm_subnet" "new_app_subnet" {
  name                 = "new-app-subnet"
  resource_group_name  = data.azurerm_virtual_network.existing_vnet.resource_group_name
  virtual_network_name = data.azurerm_virtual_network.existing_vnet.name
  address_prefixes     = ["10.0.3.0/24"]
}

示例:使用 for_each 和 map 变量动态创建多台 VM:

variable "vm_configs" {
  type = map(object({
    size = string
    ip   = string
  }))
  default = {
    "web-server-01" = { size = "Standard_B1s", ip = "10.0.1.10" },
    "web-server-02" = { size = "Standard_B1s", ip = "10.0.1.11" }
  }
}

resource "azurerm_linux_virtual_machine" "web_servers" {
  for_each              = var.vm_configs
  name                  = each.key
  location              = azurerm_resource_group.main_rg.location
  resource_group_name   = azurerm_resource_group.main_rg.name
  size                  = each.value.size
  admin_username        = "azureuser"
  admin_password        = "StrongPassword!123" # Use Key Vault in production
  network_interface_ids = [azurerm_network_interface.web_servers_nic[each.key].id]

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }
}

resource "azurerm_network_interface" "web_servers_nic" {
  for_each            = var.vm_configs
  name                = "${each.key}-nic"
  location            = azurerm_resource_group.main_rg.location
  resource_group_name = azurerm_resource_group.main_rg.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.web_subnet.id
    private_ip_address_allocation = "Static"
    private_ip_address            = each.value.ip
  }
}

以策略为代码(Sentinel)

对于需要严格合规与治理的组织,HashiCorp Sentinel 提供了与 Terraform Enterprise 集成的策略即代码框架(或可适配 Terraform Cloud)。 

Sentinel 允许您在基础设施创建之前定义细粒度策略,来强制执行安全、成本与运维方面的最佳实践。 

例如,您可以设定策略以禁止创建超出某个规格的 VM,或确保所有资源都带有特定标签。预置策略还能强制执行合规标准,防止不合规的部署进入 Azure 环境。

成本优化策略

结合 Azure Policy,Terraform 可成为在 Azure 环境中实施成本控制的有力工具。 

通过定义 Azure Policy 来限制资源 SKU、强制打标签用于成本分摊,或阻止部署昂贵资源,您可以将行之有效的省成本措施直接纳入 IaC 工作流。 

Terraform 还可部署与管理 Azure Policy,确保治理规则有版本控制并得到一致应用。

示例:使用 Terraform 部署 Azure 策略定义:

resource "azurerm_resource_group" "policy_rg" {
  name     = "azure-policy-rg"
  location = "global" # Policies are global resources
}

resource "azurerm_policy_definition" "deny_large_vms" {
  name         = "deny-large-vm-skus"
  policy_type  = "Custom"
  mode         = "All"
  display_name = "Deny creation of large VM SKUs (E-series)"
  description  = "This policy denies the creation of Azure Virtual Machines with SKUs from the E-series for cost management."

  policy_rule = <<POLICY_RULE
{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Compute/virtualMachines"
      },
      {
        "field": "Microsoft.Compute/virtualMachines/sku.name",
        "like": "Standard_E*"
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}
POLICY_RULE
}

resource "azurerm_policy_assignment" "deny_large_vms_assignment" {
  name                 = "deny-large-vm-skus-assignment"
  scope                = "/subscriptions/${data.azurerm_subscription.current.id}" # Assign to entire subscription
  policy_definition_id = azurerm_policy_definition.deny_large_vms.id
  display_name         = "Deny large VM SKUs"
}

data "azurerm_subscription" "current" {}

通过这种组合,您可以自动执行组织层面的成本策略,防止超支并提升资源效率。

CI/CD 集成

本节介绍如何将 Terraform 集成到持续集成/持续交付(CI/CD)流水线中,实现自动化且可靠的部署,让基础设施变更无缝融入软件开发生命周期。

Azure DevOps 流水线

Azure DevOps 为构建 CI/CD 流水线提供了强大的平台。常见工作流包括:

  1. 初始化:terraform init 下载提供商并设置后端。
  2. 计划:terraform plan -out 生成并保存执行计划。
  3. 审阅(人工批准):在应用前,由人工审阅生成的计划。
  4. 应用:terraform apply tfplan 执行变更。

您可以通过这篇教程了解 Azure DevOps 如何支持端到端的应用部署 CI/CD 工作流:动手实践教程。

GitHub Actions

GitHub Actions 提供了在 GitHub 仓库内直接自动化 Terraform 工作流的灵活方式。它使用 YAML 文件定义工作流,可响应 push 或 pull request 等事件。

以下是使用 GitHub Actions 进行基础 Terraform 部署的步骤:

  1. 定义触发条件:通常为特定分支(如 main)上的 on: push。
  2. 检出代码:使用 actions/checkout@v3。
  3. 配置 Azure 凭据:通过 GitHub Secrets 设置环境变量(如 AZURE_CLIENT_ID、AZURE_CLIENT_SECRET、AZURE_TENANT_ID、AZURE_SUBSCRIPTION_ID)。
  4. 安装 Terraform:使用 hashicorp/setup-terraform@v2。
  5. Terraform init:初始化工作目录。
  6. Terraform plan:创建并输出执行计划。
  7. Terraform apply(条件执行):应用变更,通常需要人工批准或在特定分支上触发。

示例:GitHub Actions 工作流 YAML(.github/workflows/terraform-azure.yml):

name: 'Terraform Azure CI/CD'

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

env:
  ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
  ARM_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
  ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
  ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
  TF_STATE_RG: 'my-terraform-state-rg'
  TF_STATE_SA: 'mystorageterraformstate'
  TF_STATE_CONTAINER: 'tfstate'
  TF_STATE_KEY: 'production/terraform.tfstate'

jobs:
  terraform:
    name: 'Terraform Actions'
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: './terraform' # Assuming Terraform files are in a 'terraform' folder

    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2
      - name: Terraform Init
        id: init
        run: terraform init -backend-config="resource_group_name=${{ env.TF_STATE_RG }}" -backend-config="storage_account_name=${{ env.TF_STATE_SA }}" -backend-config="container_name=${{ env.TF_STATE_CONTAINER }}" -backend-config="key=${{ env.TF_STATE_KEY }}"
      - name: Terraform Plan
        id: plan
        run: terraform plan -no-color
      - name: Terraform Apply
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: terraform apply -auto-approve

安全与合规

本节重点介绍在 Azure 上使用 Terraform 时的安全与合规考量,强调在敏感数据与网络访问方面的安全实践。

集成 Azure Key Vault

在 Terraform 配置中管理 API 密钥、连接字符串、数据库凭据、证书等敏感数据,若处理不当会有风险。Azure Key Vault 提供安全、集中的秘钥、密钥与证书存储与管理方案。 

示例:从 Key Vault 检索数据库密码:

# Data source to retrieve an existing Azure Key Vault
data "azurerm_key_vault" "my_key_vault" {
  name                = "my-secure-keyvault"
  resource_group_name = "my-secrets-rg"
}

# Data source to retrieve a specific secret from the Key Vault
data "azurerm_key_vault_secret" "db_password" {
  name         = "DbPassword"
  key_vault_id = data.azurerm_key_vault.my_key_vault.id
}

resource "azurerm_sql_server" "example" {
  administrator_login          = "sqladmin"
  administrator_login_password = data.azurerm_key_vault_secret.db_password.value # Securely retrieve password
}

这种方式确保敏感数据不会直接暴露在 Terraform 代码或状态文件中,符合安全最佳实践。

网络安全组(NSG)

网络安全组(NSG)是执行流量规则与保护 Azure 虚拟网络的基石。它相当于虚拟防火墙,可根据您定义的规则允许或拒绝到达 Azure 资源的入站与出站流量。

示例:为 Web 应用配置 NSG:

resource "azurerm_network_security_group" "web_nsg" {
  name                = "web-nsg"
  location            = azurerm_resource_group.network_rg.location
  resource_group_name = azurerm_resource_group.network_rg.name

  security_rule {
    name                       = "AllowHTTPInbound"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }
  security_rule {
    name                       = "AllowSSHInbound"
    priority                   = 120
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "YourTrustedIPRange" # IMPORTANT: Restrict to known IPs
    destination_address_prefix = "*"
  }
}

# Associate NSG with a subnet 
resource "azurerm_subnet_network_security_group_association" "web_subnet_nsg_association" {
  subnet_id                 = azurerm_subnet.web_subnet.id
  network_security_group_id = azurerm_network_security_group.web_nsg.id
}

企业级部署最佳实践

本节总结在企业环境中大规模部署与管理 Terraform 的关键最佳实践,聚焦架构设计、维护与监控。

参考架构

若要实现稳健高效的 Azure 部署,请让 Terraform 配置与 Azure Well-Architected Framework 对齐。该框架为高质量、安全、具成本效益的云解决方案提供蓝图,指导您在可靠性、安全性、成本优化、卓越运维与性能效率方面进行 Terraform 设计。

状态文件卫生

Terraform 状态文件是您的基础设施“单一事实源”。请通过以下方式确保其完整性与安全性:

  • 远程存储:团队协作时务必使用 Azure Blob 存储等远程后端管理状态。
  • 加密与访问控制:确认远程状态已静态加密,并使用严格的 Azure RBAC 控制访问。
  • 状态锁定与版本控制:利用内置的状态锁定防冲突,并为存储容器开启版本控制,以便历史追踪与回滚。

监控与漂移检测

通过主动监控“配置漂移”(偏离 Terraform 定义的未授权变更),保持基础设施一致性。

  • 主动检测:在 CI/CD 流水线中定期运行 terraform plan(如每晚)以识别变更。
  • Azure 监控:使用 Azure Monitor 与 Log Analytics 跟踪资源健康与事件。
  • 自动化修复:制定流程(人工或自动)重新运行 terraform apply,将漂移的资源恢复到与 IaC 一致。

若要进一步监控与优化基础设施,Azure Monitor 提供了宝贵洞见——这份指南将带您上手。

结语

到这里就告一段落了!现在,您已经了解 Terraform 如何让 Azure 资源管理更高效、更可预测。我们看到了如何借助 Azure DevOps 与 GitHub Actions 将自动化引入工作流,以及如何通过 Azure Key Vault 与网络安全组来保障安全。

我们也回顾了一些重要的最佳实践——例如采用参考架构、谨慎管理状态文件,并通过监控与漂移检测密切关注变更。

借助这些工具与技巧,您已迈向在 Azure 上构建更加可靠且可扩展的基础设施。

想要验证您的技能?这份 Terraform 面试题可帮助您为求职或认证做好准备!

FAQs

在 Azure 上使用 Terraform 的主要好处是什么?

在 Azure 上使用 Terraform 能在基础设施部署中带来一致性、可扩展性与速度。它允许您将云资源定义为代码,减少手工错误,支持可重复部署,并让复杂环境的管理更轻松。

Terraform 如何管理我在 Azure 上的基础设施状态?

Terraform 使用状态文件(.tfstate)来跟踪已部署的 Azure 资源。该文件将 Terraform 配置与实际基础设施进行映射,让 Terraform 能了解当前状态,并在后续部署时确定需要进行的更改。

我能用 Terraform 同时处理新部署与管理现有 Azure 资源吗?

当然可以!Terraform 非常适合从零开始供应新基础设施。它也能将现有 Azure 资源导入到状态中,之后您就可以用 Terraform 配置进行统一管理。

Terraform 如何集成到 Azure 部署的 CI/CD 流水线?

Terraform 可与 Azure DevOps Pipelines 与 GitHub Actions 等主流 CI/CD 平台集成。典型流水线包括 terraform init(初始化)、terraform plan(展示拟议更改)与 terraform apply(将更改应用到 Azure)。这种自动化可确保基础设施部署一致且可靠。

在 Azure 上使用 Terraform 时有哪些关键的安全考量?

关键考量包括使用 Azure Key Vault 安全管理敏感数据(如 API 密钥或密码),避免将其硬编码。另外,通过 Terraform 正确配置网络安全组(NSG)也至关重要,用于控制网络流量并对 Azure 资源执行最小权限访问。

Karen Zhang

作者

Karen Zhang

Karen 是一名数据工程师,热衷于构建可扩展的数据平台。她拥有使用 Terraform 进行基础设施自动化的经验,并很乐于通过博客文章和教程分享她的所学。Karen 也是一位社区建设者,热衷于促进数据专业人士之间的联结。

主题