创建第一个 Terraform 资源 #

准备工作 #

在开始之前,请确保:

text
┌─────────────────────────────────────────────────────────────┐
│                    准备工作                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ✅ 已安装 Terraform(运行 terraform version 验证)         │
│  ✅ 有一个云服务账号(AWS/Azure/GCP)                       │
│  ✅ 配置好认证凭证                                          │
│  ✅ 创建一个工作目录                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

创建项目目录 #

bash
mkdir terraform-demo
cd terraform-demo

示例一:创建本地文件 #

让我们从最简单的例子开始,创建一个本地文件。

创建配置文件 #

创建 main.tf 文件:

hcl
terraform {
  required_version = ">= 1.0.0"
  
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}

provider "local" {}

resource "local_file" "hello" {
  filename = "hello.txt"
  content  = "Hello, Terraform!"
}

初始化项目 #

bash
terraform init

输出:

text
Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/local versions matching "~> 2.0"...
- Installing hashicorp/local v2.4.1...
- Installed hashicorp/local v2.4.1 (signed by HashiCorp)

Terraform has been successfully initialized!

查看执行计划 #

bash
terraform plan

输出:

text
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.hello will be created
  + resource "local_file" "hello" {
      + content              = "Hello, Terraform!"
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "hello.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

应用变更 #

bash
terraform apply

输入 yes 确认:

text
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.hello will be created
  + resource "local_file" "hello" {
      + content              = "Hello, Terraform!"
      + directory_permission = "0777"
      + file_permission      = "0777"
      + filename             = "hello.txt"
      + id                   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

local_file.hello: Creating...
local_file.hello: Creation complete after 0s [id=abc123]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

验证结果 #

bash
cat hello.txt

输出:

text
Hello, Terraform!

查看状态 #

bash
terraform show

销毁资源 #

bash
terraform destroy

示例二:创建 AWS EC2 实例 #

让我们创建一个更实际的例子,在 AWS 上创建一个 EC2 实例。

配置 AWS 凭证 #

bash
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_DEFAULT_REGION="us-east-1"

或使用 AWS CLI 配置:

bash
aws configure

创建配置文件 #

创建 main.tf

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

provider "aws" {
  region = "us-east-1"
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  
  tags = {
    Name = "terraform-example"
  }
}

初始化并应用 #

bash
terraform init
terraform plan
terraform apply

查看输出 #

创建 outputs.tf

hcl
output "instance_id" {
  description = "ID of the EC2 instance"
  value       = aws_instance.example.id
}

output "instance_public_ip" {
  description = "Public IP of the EC2 instance"
  value       = aws_instance.example.public_ip
}

应用后查看输出:

bash
terraform output

示例三:使用变量 #

创建变量文件 #

创建 variables.tf

hcl
variable "region" {
  description = "AWS region"
  type        = string
  default     = "us-east-1"
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t2.micro"
}

variable "instance_name" {
  description = "Name tag for the instance"
  type        = string
  default     = "terraform-example"
}

更新主配置 #

更新 main.tf

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

provider "aws" {
  region = var.region
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = var.instance_type
  
  tags = {
    Name = var.instance_name
  }
}

使用变量文件 #

创建 terraform.tfvars

hcl
region        = "us-west-2"
instance_type = "t2.small"
instance_name = "my-server"

应用配置 #

bash
terraform apply -var-file="terraform.tfvars"

命令行传递变量 #

bash
terraform apply -var="instance_type=t2.medium" -var="instance_name=production-server"

示例四:创建完整的基础设施 #

让我们创建一个更完整的例子,包括 VPC、子网、安全组和 EC2 实例。

项目结构 #

text
terraform-demo/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars

main.tf #

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

provider "aws" {
  region = var.region
}

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true
  
  tags = {
    Name = "${var.project_name}-vpc"
  }
}

resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnet_cidr
  map_public_ip_on_launch = true
  availability_zone       = "${var.region}a"
  
  tags = {
    Name = "${var.project_name}-public-subnet"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
  
  tags = {
    Name = "${var.project_name}-igw"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id
  
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }
  
  tags = {
    Name = "${var.project_name}-public-rt"
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

resource "aws_security_group" "web" {
  name        = "${var.project_name}-web-sg"
  description = "Security group for web server"
  vpc_id      = aws_vpc.main.id
  
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  tags = {
    Name = "${var.project_name}-web-sg"
  }
}

resource "aws_instance" "web" {
  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = var.instance_type
  subnet_id              = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.web.id]
  
  tags = {
    Name = "${var.project_name}-web-server"
  }
}

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
  
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

variables.tf #

hcl
variable "region" {
  description = "AWS region"
  type        = string
  default     = "us-east-1"
}

variable "project_name" {
  description = "Project name for resource naming"
  type        = string
  default     = "terraform-demo"
}

variable "vpc_cidr" {
  description = "CIDR block for VPC"
  type        = string
  default     = "10.0.0.0/16"
}

variable "public_subnet_cidr" {
  description = "CIDR block for public subnet"
  type        = string
  default     = "10.0.1.0/24"
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t2.micro"
}

outputs.tf #

hcl
output "vpc_id" {
  description = "The ID of the VPC"
  value       = aws_vpc.main.id
}

output "public_subnet_id" {
  description = "The ID of the public subnet"
  value       = aws_subnet.public.id
}

output "instance_id" {
  description = "The ID of the EC2 instance"
  value       = aws_instance.web.id
}

output "instance_public_ip" {
  description = "The public IP of the EC2 instance"
  value       = aws_instance.web.public_ip
}

output "security_group_id" {
  description = "The ID of the security group"
  value       = aws_security_group.web.id
}

terraform.tfvars #

hcl
region              = "us-east-1"
project_name        = "my-project"
vpc_cidr            = "10.0.0.0/16"
public_subnet_cidr  = "10.0.1.0/24"
instance_type       = "t2.micro"

执行流程 #

bash
terraform init

terraform validate

terraform fmt

terraform plan

terraform apply

terraform output

terraform destroy

工作流程总结 #

text
┌─────────────────────────────────────────────────────────────┐
│                    Terraform 工作流程                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 编写配置                                                │
│     └── 创建 .tf 文件                                       │
│                                                             │
│  2. 初始化                                                  │
│     $ terraform init                                        │
│     └── 下载 Provider                                       │
│                                                             │
│  3. 验证                                                    │
│     $ terraform validate                                    │
│     └── 检查语法                                            │
│                                                             │
│  4. 格式化                                                  │
│     $ terraform fmt                                         │
│     └── 统一格式                                            │
│                                                             │
│  5. 计划                                                    │
│     $ terraform plan                                        │
│     └── 预览变更                                            │
│                                                             │
│  6. 应用                                                    │
│     $ terraform apply                                       │
│     └── 执行变更                                            │
│                                                             │
│  7. 销毁                                                    │
│     $ terraform destroy                                     │
│     └── 清理资源                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

常见问题 #

状态文件锁定 #

text
Error: Error acquiring the state lock

解决方案:

bash
terraform force-unlock <LOCK_ID>

Provider 认证失败 #

text
Error: error configuring Terraform AWS Provider

解决方案:

bash
aws configure
# 或设置环境变量
export AWS_ACCESS_KEY_ID="xxx"
export AWS_SECRET_ACCESS_KEY="xxx"

资源已存在 #

text
Error: Resource already exists

解决方案:

bash
terraform import aws_instance.example i-1234567890abcdef0

下一步 #

恭喜你创建了第一个 Terraform 资源!接下来学习 Provider 配置,了解如何配置不同的云服务提供商!

最后更新:2026-03-29