返回首页

如何使用Terraform与AWS:完整指南

本综合指南教你如何使用Terraform与AWS将云基础设施作为代码进行管理。涵盖提供商设置、资源定义、状态管理、安全最佳实践和CI/CD集成,你将获得生产级AWS部署的实用技能。

如何使用Terraform与AWS:分步教程
Advertisement 728x90

使用 Terraform 与 AWS 的完整指南

使用 Terraform 与 AWS 的完整指南

基础设施管理已从手动控制台点击和脆弱的脚本演变为可版本控制、可审查和可共享的声明式代码。对于在 Amazon Web Services 上构建的团队来说,Terraform 已成为基础设施即代码(IaC)的标准——而掌握如何有效使用 Terraform 与 AWS 现在已成为云工程师的核心技能。本指南将带你完成完整的工作流程,从设置 AWS Provider 到使用生产级实践部署真实资源。

你将学到什么

通过本指南,你将了解在 AWS 上使用 Terraform 的完整工作流程——从 Provider 配置和资源定义到状态管理和团队协作。你将能够使用 Terraform 的声明式方法自信地部署、更新和销毁 AWS 基础设施,并形成清晰的思维模型来构建自己的项目。你还将学习实用的防护措施,以防止代价高昂的错误,例如部署到错误的 AWS 账户。

Google AdInline article slot

理解核心概念:Provider、资源和状态

在编写任何配置之前,了解 Terraform 的基本构建块会很有帮助。与 AWS 原生的 AWS CloudFormation(假设资源在 AWS 账户内创建)不同,Terraform 是云无关的,需要你显式声明与特定 API 交互的 Provider

什么是 Provider?

Provider 是一个插件,充当 Terraform 与目标平台之间的桥梁。AWS Provider 允许 Terraform 调用 AWS API 来创建、读取、更新和删除资源。由于 Terraform 支持多个 Provider——AWS、Kubernetes、Helm,甚至第三方 SaaS 工具——你可以在同一个配置中预置 Amazon EKS 集群并将 Helm Chart 部署到其中。

资源和数据源

资源定义了基础设施的一个组件:EC2 实例、S3 存储桶或安全组。资源是声明式定义的——你指定想要什么,Terraform 会找出如何创建它。

Google AdInline article slot

另一方面,数据源查询 AWS 以获取有关现有资源的信息。例如,与其硬编码可能因区域而变化的 AMI ID,不如使用数据源动态获取最新的 Amazon Linux 2023 AMI。

状态:事实来源

Terraform 维护一个状态文件,用于跟踪其管理的资源。此状态将你的配置映射到实际基础设施,对于规划更新、检测漂移和干净地销毁资源至关重要。对于团队环境,强烈建议将状态存储在远程后端(如 Amazon S3)中,以防止冲突并确保一致性。


入门:安装工具和配置 AWS 凭证

前提条件

在编写任何配置之前,请设置好本地环境:

Google AdInline article slot
  1. Terraform CLI 1.5 或更高版本 – 下载二进制文件并将其添加到 PATH。
  2. AWS CLI – 安装并使用具有足够权限的 IAM 凭证进行配置。
  3. 一个 AWS 账户 – 使用免费套餐进行练习,以避免意外费用。

验证 AWS Provider

Terraform 的 AWS Provider 使用与 AWS CLI 相同的方法进行身份验证。最简单的方法是使用 IAM 凭证设置环境变量:

export AWS_ACCESS_KEY_ID=<your_access_key>
export AWS_SECRET_ACCESS_KEY=<your_secret_key>

或者,Terraform 可以从 ~/.aws/credentials 的默认凭证文件中读取。


第 1 步:编写你的第一个 Terraform 配置

为你的项目创建一个新目录,并定义 Provider 和资源。Terraform 配置文件使用 HashiCorp 配置语言(HCL),并以 .tf 结尾。

terraform

terraform 块配置 Terraform 本身,包括 Provider 源和版本约束。固定 Provider 版本可以防止 Provider 更新时出现意外漂移。

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  required_version = ">= 1.2"
}

source 参数指向 Terraform Registry 中的 Provider。HashiCorp 维护 AWS Provider,因此其源是 hashicorp/aws

provider

provider 块配置 AWS Provider,包括默认区域:

provider "aws" {
  region = "us-west-2"
}

定义 EC2 实例

resource 块声明一个基础设施组件。以下是使用数据源获取最新 Ubuntu AMI 来定义 EC2 实例的方法:

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
  }
}

resource "aws_instance" "app_server" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"

  tags = {
    Name = "terraform-demo"
  }
}

使用数据源获取 AMI 可以使你的配置保持动态,并跨区域可移植。


第 2 步:初始化、计划和应用

Terraform 工作流程由三个核心命令组成:

terraform init

初始化工作目录。这会下载所需的 Provider 插件并设置后端:

terraform init

Terraform 读取 required_providers 块并安装你指定的 AWS Provider 版本。

terraform plan

预览 Terraform 将对你的基础设施进行的更改:

terraform plan

计划显示添加、修改和删除——这是你在应用之前发现错误的机会。

terraform apply

应用配置以创建资源。Terraform 将再次显示计划并提示确认:

terraform apply

输入 yes 继续。Terraform 将预置 EC2 实例并输出结果。

terraform destroy

完成后,清理资源以避免费用:

terraform destroy

Terraform 根据状态文件计算要删除的内容,并提示确认。


第 3 步:添加安全组和预置逻辑

没有网络访问权限的服务器是无用的。添加一个安全组来控制入站和出站流量:

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Allow HTTP and SSH"
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"] # 限制 SSH
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

通过在 vpc_security_group_ids 参数中引用 aws_security_group.web.id,将安全组附加到你的 EC2 实例。

使用用户数据自动化软件安装

使用 EC2 用户数据在实例首次启动时安装软件。例如,在 Amazon Linux 2023 上安装 Nginx:

resource "aws_instance" "web" {
  ami                    = data.aws_ami.al2023.id
  instance_type          = "t3.micro"
  vpc_security_group_ids = [aws_security_group.web.id]
  key_name               = var.key_name

  user_data = <<-EOF
              #!/bin/bash
              dnf install -y nginx
              systemctl start nginx
              echo "<h1>Hello from Terraform</h1>" > /usr/share/nginx/html/index.html
              EOF
}

用户数据在初始启动期间运行,是一种无需额外配置管理工具即可引导实例的简单方法。


第 4 步:使用变量、输出和模块

变量实现可重用性

硬编码值会使配置变得脆弱。在 variables.tf 文件中定义变量:

variable "instance_type" {
  description = "EC2 实例类型"
  type        = string
  default     = "t2.micro"
}

variable "aws_region" {
  description = "AWS 区域"
  type        = string
  default     = "us-west-2"
}

在配置中使用 var.instance_type 引用变量。

输出显示信息

输出允许你在应用后检索信息,例如实例的公网 IP:

output "instance_public_ip" {
  description = "EC2 实例的公网 IP"
  value       = aws_instance.app_server.public_ip
}

模块实现可重用组件

模块是多个资源的容器,可以在项目之间共享。Terraform Registry 提供了数千个社区模块,你也可以编写自己的模块。使用模块可以使根配置保持简洁,并促进可重用性。


第 5 步:远程状态和团队协作

对于任何团队环境,在本地存储状态都是危险的——它可能过时或与其他用户的更改冲突。配置远程后端,通常使用 Amazon S3 和 DynamoDB 进行状态锁定:

terraform {
  backend "s3" {
    bucket         = "my-terraform-state-bucket"
    key            = "prod/terraform.tfstate"
    region         = "us-west-2"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

此配置确保状态在应用操作期间共享并锁定,防止可能损坏状态文件的并发修改。


第 6 步:安全最佳实践

将 Provider 限制到特定 AWS 账户

最危险的错误之一是在错误的 AWS 账户上运行 Terraform——例如,打算部署到开发环境,但意外使用了生产凭证。Provider 块中的 allowed_account_ids 设置创建了一个安全网:

provider "aws" {
  region  = "us-west-2"
  allowed_account_ids = ["123456789012"] # 仅此账户
}

如果你尝试使用来自不同账户的凭证运行 Terraform,计划将立即报错,防止代价高昂的错误。

使用 IAM 角色,而非静态密钥

对于 EC2 实例,始终使用 IAM 实例配置文件,而不是嵌入静态凭证。这可以提高安全性并简化凭证轮换。

版本控制和审查

所有 Terraform 配置都应存储在版本控制中。基础设施更改的拉取请求应像应用程序代码一样进行审查——这是 IaC 的核心价值。


如何在 CI/CD 流水线中使用 Terraform 与 AWS

将 Terraform 集成到 CI/CD 流水线中可以自动化部署并强制执行一致性。一个典型的 GitHub Actions 工作流程:

name: Terraform Apply
on:
  push:
    branches: [ main ]
jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: hashicorp/setup-terraform@v1
      - name: Terraform Init
        run: terraform init
      - name: Terraform Plan
        run: terraform plan
      - name: Terraform Apply
        run: terraform apply -auto-approve

这种方法消除了手动应用步骤,并确保每次主分支合并都能部署经过审查和测试的基础设施。


常见问题解答

1. Terraform 和 AWS CloudFormation 有什么区别?

Terraform 是云无关的,支持多个 Provider——AWS、Azure、Google Cloud 以及数百个其他 Provider——而 CloudFormation 仅限 AWS。Terraform 还提供了更灵活的工作流程,具有计划/应用阶段,并支持更广泛的第三方资源。

2. Terraform 将我的基础设施状态存储在哪里?

默认情况下,Terraform 将状态存储在本地 terraform.tfstate 文件中。对于生产和团队使用,你应该配置远程后端(如 Amazon S3)来集中存储状态,并通过锁定防止冲突。

3. 什么是 Terraform 模块,为什么应该使用它们?

模块是多个资源的容器,可以在项目之间重用。使用模块可以减少重复、强制执行一致性,并允许你通过 Terraform Registry 在团队之间共享基础设施模式。

4. 如何避免意外部署到错误的 AWS 账户?

在 AWS Provider 块中使用 allowed_account_ids 设置,将 Terraform 限制到特定的账户 ID。如果凭证与允许列表不匹配,Terraform 将在进行任何更改之前报错。

5. terraform planterraform apply 有什么区别?

terraform plan 预览 Terraform 将对你的基础设施进行的更改。terraform apply 执行这些更改。始终先运行计划,以在修改资源之前发现错误。


来源

  1. Terrateam, "How to deploy Nginx with Terraform on AWS" (2026)
  2. AWS Prescriptive Guidance, "Understanding Terraform resources and providers" (2024)
  3. AWS Prescriptive Guidance, "Terraform AWS Provider best practices" (2024)
  4. HashiCorp Developer, "Create infrastructure" (2025)
  5. Refine, "Getting Started with Terraform on AWS" (2024)
  6. DevelopersIO, "Terraform AWS Provider allowed_account_ids" (2025)
  7. GitHub, "terraform-basics-aws" repository

— Editorial Team

Advertisement 728x90

继续阅读