Terraform 核心语法与资源管理
· 阅读需 9 分钟
本文将深入介绍 Terraform 的核心语法 HCL(HashiCorp Configuration Language)以及资源管理的核心概念,包括 Resource、Data Source、Provider 等重要组件的使用方法。
HCL 语法基础
HCL(HashiCorp Configuration Language)是 Terraform 使用的声明式配置语言,具有简洁易读的特点。
1. 基本语法结构
# 这是注释
# 块的基本结构: <块类型> "<块标签>" "<名称>" {
# <参数> = <值>
# }
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1d0"
instance_type = "t2.micro"
tags = {
Name = "HelloWorld"
}
}
2. 数据类型
# 字符串
variable "region" {
type = string
default = "us-west-2"
description = "AWS region"
}
# 数字
variable "instance_count" {
type = number
default = 1
}
# 布尔值
variable "enable_monitoring" {
type = bool
default = true
}
# 列表
variable "availability_zones" {
type = list(string)
default = ["us-west-2a", "us-west-2b", "us-west-2c"]
}
# 映射
variable "tags" {
type = map(string)
default = {
Environment = "dev"
Project = "webapp"
}
}
# 对象
variable "server_config" {
type = object({
name = string
instance_type = string
monitoring = bool
})
default = {
name = "web-server"
instance_type = "t2.micro"
monitoring = true
}
}
3. 表达式和函数
# 字符串插值
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
tags = {
Name = "${var.project_name}-${var.environment}-web"
}
}
# 条件表达式
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.environment == "prod" ? "t3.medium" : "t2.micro"
monitoring = var.environment == "prod" ? true : false
}
# 循环表达式 - for
locals {
server_names = [for i in range(var.server_count) : "server-${i}"]
uppercase_tags = {
for k, v in var.tags : k => upper(v)
}
}
# 常用函数
locals {
# 字符串函数
formatted_name = format("%s-%s", var.project, var.environment)
upper_env = upper(var.environment)
# 列表函数
zone_count = length(var.availability_zones)
first_zone = element(var.availability_zones, 0)
# 映射函数
merged_tags = merge(var.default_tags, var.custom_tags)
# 文件函数
user_data = file("${path.module}/scripts/init.sh")
}
核心概念详解
1. Provider(提供者)
Provider 是 Terraform 与各种服务提供商交互的插件。
# Provider 配置
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.1"
}
}
required_version = ">= 1.0"
}
# 配置 AWS Provider
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Environment = var.environment
ManagedBy = "Terraform"
}
}
}
# 多个 Provider 实例(别名)
provider "aws" {
alias = "east"
region = "us-east-1"
}
provider "aws" {
alias = "west"
region = "us-west-2"
}
# 使用别名 Provider
resource "aws_instance" "east_server" {
provider = aws.east
ami = "ami-0c55b159cbfafe1d0"
instance_type = "t2.micro"
}
2. Resource(资 源)
Resource 是 Terraform 配置的核心,代表基础设施中的一个组件。
# 基本资源定义
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.project_name}-vpc"
}
}
# 子网资源
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.project_name}-public-${count.index + 1}"
Type = "Public"
}
}
# 安全组
resource "aws_security_group" "web" {
name_prefix = "${var.project_name}-web-"
vpc_id = aws_vpc.main.id
description = "Security group for web servers"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
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"
}
}
3. Data Source(数据源)
Data Source 用于查询和引用现有资源的信息。
# 查询最新的 Amazon Linux AMI
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# 查询可用区
data "aws_availability_zones" "available" {
state = "available"
}
# 查询当前 AWS 账户信息
data "aws_caller_identity" "current" {}
# 查询现有 VPC
data "aws_vpc" "existing" {
filter {
name = "tag:Name"
values = ["existing-vpc"]
}
}
# 使用 Data Source 的数据
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
subnet_id = aws_subnet.public[0].id
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "${var.project_name}-web"
AMI = data.aws_ami.amazon_linux.name
}
}
资源依赖关系
1. 隐式依赖
Terraform 会自动检测资源之间的依赖关系。
# VPC 必须先创建
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
# 子网依赖于 VPC(隐式依赖)
resource "aws_subnet" "web" {
vpc_id = aws_vpc.main.id # 这里引用了 VPC 的 ID
cidr_block = "10.0.1.0/24"
}
# 实例依赖于子网(隐式依赖)
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1d0"
subnet_id = aws_subnet.web.id # 这里引用了子网的 ID
}
2. 显式依赖
使用 depends_on 明确指定依赖关系。
# S3 存储桶
resource "aws_s3_bucket" "logs" {
bucket = "${var.project_name}-logs-${random_id.bucket_suffix.hex}"
}
# 随机 ID 生成器
resource "random_id" "bucket_suffix" {
byte_length = 4
}
# EC2 实例显式依赖 S3 存储桶
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t2.micro"
# 显式依赖:确保 S3 存储桶创建完成后再创建实例
depends_on = [
aws_s3_bucket.logs,
aws_security_group.web
]
user_data = <<-EOF
#!/bin/bash
aws s3 cp /var/log/messages s3://${aws_s3_bucket.logs.bucket}/
EOF
}
生命周期管理
1. 生命周期规则
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
# 生命周期配置
lifecycle {
# 创建新资源后再销毁旧资源
create_before_destroy = true
# 防止资源被销毁
prevent_destroy = false
# 忽略特定属性的变化
ignore_changes = [
tags,
user_data,
]
}
tags = {
Name = "web-server"
}
}
# 防止关键资源被意外删除
resource "aws_s3_bucket" "important_data" {
bucket = "critical-data-bucket"
lifecycle {
prevent_destroy = true
}
}