Terraform 基础
Terraform 是 HashiCorp 开发的基础设施即代码(Infrastructure as Code, IaC)工具,使用声明式配置语言 HCL(HashiCorp Configuration Language)来定义和管理云资源。通过 Terraform,你可以用代码描述完整的基础设施架构,实现版本控制和可重复部署。
安装 Terraform
Section titled “安装 Terraform”通过官方仓库安装
Section titled “通过官方仓库安装”# 安装 DNF 插件(提供 config-manager)sudo dnf install -y dnf-plugins-core
# 添加 HashiCorp 官方仓库sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
# 安装 Terraformsudo dnf install -y terraform
# 验证安装terraform version# 下载最新版本(访问 https://developer.hashicorp.com/terraform/install 确认最新版本号)TERRAFORM_VERSION="1.9.0" # 示例版本,请替换为官网最新版本号wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip
# 解压并安装sudo dnf install -y unzipunzip terraform_${TERRAFORM_VERSION}_linux_amd64.zipsudo mv terraform /usr/local/bin/sudo chmod +x /usr/local/bin/terraform
# 验证terraform version启用命令自动补全
Section titled “启用命令自动补全”# 安装自动补全terraform -install-autocomplete
# 重新加载 shellsource ~/.bashrcHCL 语法基础
Section titled “HCL 语法基础”Terraform 配置文件使用 .tf 扩展名,采用 HCL 语法。
# 注释以 # 开头
# 块(Block)结构resource "类型" "名称" { 参数1 = "值1" 参数2 = 123
# 嵌套块 nested_block { key = "value" }}
# 字符串插值variable "name" { default = "myserver"}
resource "example" "demo" { name = "prefix-${var.name}"}# 字符串name = "web-server"
# 数字count = 3
# 布尔值enabled = true
# 列表availability_zones = ["cn-hangzhou-a", "cn-hangzhou-b"]
# 映射(Map)tags = { Name = "web-server" Environment = "production" Team = "ops"}Provider 配置
Section titled “Provider 配置”Provider 是 Terraform 与云平台交互的插件。
AWS 示例
Section titled “AWS 示例”terraform { required_version = ">= 1.5.0"
required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } }}
provider "aws" { region = "ap-northeast-1" # 东京区域 access_key = var.aws_access_key secret_key = var.aws_secret_key
# 或者使用环境变量(推荐): # export AWS_ACCESS_KEY_ID="your-access-key" # export AWS_SECRET_ACCESS_KEY="your-secret-key"}terraform { required_version = ">= 1.5.0"
required_providers { alicloud = { source = "aliyun/alicloud" version = "~> 1.220" } }}
provider "alicloud" { region = "cn-hangzhou" access_key = var.alicloud_access_key secret_key = var.alicloud_secret_key}AWS EC2 实例示例
Section titled “AWS EC2 实例示例”# variables.tf - 变量定义variable "aws_access_key" { description = "AWS Access Key" type = string sensitive = true}
variable "aws_secret_key" { description = "AWS Secret Key" type = string sensitive = true}
variable "instance_type" { description = "EC2 实例类型" type = string default = "t3.micro"}
variable "instance_count" { description = "实例数量" type = number default = 1}# main.tf - 主配置文件# 查询最新的 AlmaLinux 9 AMIdata "aws_ami" "almalinux9" { most_recent = true owners = ["764336703387"] # AlmaLinux 官方
filter { name = "name" values = ["AlmaLinux OS 9*x86_64*"] }
filter { name = "virtualization-type" values = ["hvm"] }}
# 创建安全组resource "aws_security_group" "web" { name = "web-sg" description = "Allow HTTP and SSH"
ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] description = "SSH" }
ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] description = "HTTP" }
ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] description = "HTTPS" }
egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] }
tags = { Name = "web-security-group" }}
# 创建 EC2 实例resource "aws_instance" "web" { count = var.instance_count ami = data.aws_ami.almalinux9.id instance_type = var.instance_type
vpc_security_group_ids = [aws_security_group.web.id]
user_data = <<-EOF #!/bin/bash dnf install -y nginx systemctl enable --now nginx echo "<h1>Server ${count.index + 1}</h1>" > /usr/share/nginx/html/index.html EOF
tags = { Name = "web-server-${count.index + 1}" Env = "production" }}# outputs.tf - 输出定义output "instance_public_ips" { description = "实例公网 IP 列表" value = aws_instance.web[*].public_ip}
output "instance_ids" { description = "实例 ID 列表" value = aws_instance.web[*].id}
output "ami_id" { description = "使用的 AMI ID" value = data.aws_ami.almalinux9.id}阿里云 ECS 实例示例
Section titled “阿里云 ECS 实例示例”# main.tf - 阿里云 ECS 示例variable "alicloud_access_key" { type = string sensitive = true}
variable "alicloud_secret_key" { type = string sensitive = true}
# 查询可用区data "alicloud_zones" "default" { available_resource_creation = "VSwitch"}
# 查询镜像data "alicloud_images" "almalinux" { name_regex = "^almalinux_9" most_recent = true owners = "system"}
# 创建 VPCresource "alicloud_vpc" "main" { vpc_name = "tf-demo-vpc" cidr_block = "172.16.0.0/16"}
# 创建交换机resource "alicloud_vswitch" "main" { vswitch_name = "tf-demo-vsw" vpc_id = alicloud_vpc.main.id cidr_block = "172.16.1.0/24" zone_id = data.alicloud_zones.default.zones[0].id}
# 创建安全组resource "alicloud_security_group" "web" { name = "tf-demo-sg" vpc_id = alicloud_vpc.main.id}
resource "alicloud_security_group_rule" "allow_ssh" { type = "ingress" ip_protocol = "tcp" port_range = "22/22" security_group_id = alicloud_security_group.web.id cidr_ip = "0.0.0.0/0"}
resource "alicloud_security_group_rule" "allow_http" { type = "ingress" ip_protocol = "tcp" port_range = "80/80" security_group_id = alicloud_security_group.web.id cidr_ip = "0.0.0.0/0"}
# 创建 ECS 实例resource "alicloud_instance" "web" { instance_name = "tf-demo-ecs" image_id = data.alicloud_images.almalinux.images[0].id instance_type = "ecs.t6-c1m1.large" security_groups = [alicloud_security_group.web.id] vswitch_id = alicloud_vswitch.main.id internet_max_bandwidth_out = 10 system_disk_size = 40
user_data = base64encode(<<-EOF #!/bin/bash dnf install -y nginx systemctl enable --now nginx EOF )
tags = { Name = "web-server" Env = "demo" }}
output "public_ip" { value = alicloud_instance.web.public_ip}Plan / Apply / Destroy 工作流
Section titled “Plan / Apply / Destroy 工作流”# 进入项目目录cd /opt/terraform/myproject
# 初始化(下载 Provider 插件)terraform init
# 升级 Provider 版本terraform init -upgrade查看执行计划
Section titled “查看执行计划”# 查看计划(预览将要执行的变更)terraform plan
# 将计划保存到文件terraform plan -out=tfplan
# 使用变量文件terraform plan -var-file="production.tfvars"
# 传递单个变量terraform plan -var="instance_count=3"# 应用变更(会要求确认)terraform apply
# 使用保存的计划文件(无需确认)terraform apply tfplan
# 自动确认(用于 CI/CD)terraform apply -auto-approve
# 使用变量文件terraform apply -var-file="production.tfvars"# 销毁所有资源terraform destroy
# 自动确认销毁terraform destroy -auto-approve
# 仅销毁指定资源terraform destroy -target=aws_instance.web其他常用命令
Section titled “其他常用命令”# 格式化配置文件terraform fmt
# 递归格式化terraform fmt -recursive
# 验证配置语法terraform validate
# 查看当前状态terraform show
# 列出所有资源terraform state list
# 查看特定资源的详细信息terraform state show aws_instance.web[0]
# 刷新状态(同步远端实际状态)terraform refresh
# 生成依赖关系图terraform graph | dot -Tpng > graph.png使用 .tfvars 文件管理不同环境的变量:
instance_type = "t3.large"instance_count = 3instance_type = "t3.micro"instance_count = 1# 使用不同环境的变量terraform apply -var-file="production.tfvars"terraform apply -var-file="staging.tfvars"通过环境变量传递敏感信息:
# Terraform 会自动读取 TF_VAR_ 前缀的环境变量export TF_VAR_aws_access_key="AKIAIOSFODNN7EXAMPLE"export TF_VAR_aws_secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
terraform applyState 状态管理
Section titled “State 状态管理”Terraform 状态文件(terraform.tfstate)记录了基础设施的当前状态。在团队协作中,应使用远程后端存储状态文件。
本地状态(默认)
Section titled “本地状态(默认)”# 状态文件位于项目目录ls -la terraform.tfstatels -la terraform.tfstate.backup远程状态 - S3 后端
Section titled “远程状态 - S3 后端”terraform { backend "s3" { bucket = "my-terraform-state" key = "production/terraform.tfstate" region = "ap-northeast-1" encrypt = true dynamodb_table = "terraform-lock" # 状态锁定 }}远程状态 - 阿里云 OSS 后端
Section titled “远程状态 - 阿里云 OSS 后端”terraform { backend "oss" { bucket = "my-terraform-state" prefix = "production" region = "cn-hangzhou" encrypt = true
tablestore_endpoint = "https://tf-state-lock.cn-hangzhou.ots.aliyuncs.com" tablestore_table = "terraform-lock" }}# 列出状态中的资源terraform state list
# 查看资源详情terraform state show aws_instance.web[0]
# 移动资源(重命名)terraform state mv aws_instance.web aws_instance.webserver
# 从状态中移除资源(不删除实际资源)terraform state rm aws_instance.web[0]
# 导入已有资源到 Terraform 管理terraform import aws_instance.web i-0abc123def456
# 拉取远程状态terraform state pull > state.json
# 推送状态到远端terraform state push state.json模块(Module)用于封装和复用 Terraform 配置。
# 模块目录结构mkdir -p modules/ecs-instancevariable "instance_name" { description = "实例名称" type = string}
variable "instance_type" { description = "实例规格" type = string default = "ecs.t6-c1m1.large"}
variable "image_id" { description = "镜像 ID" type = string}
variable "vswitch_id" { description = "交换机 ID" type = string}
variable "security_group_id" { description = "安全组 ID" type = string}
variable "tags" { description = "资源标签" type = map(string) default = {}}resource "alicloud_instance" "this" { instance_name = var.instance_name instance_type = var.instance_type image_id = var.image_id vswitch_id = var.vswitch_id security_groups = [var.security_group_id] internet_max_bandwidth_out = 10 system_disk_size = 40 tags = var.tags}output "instance_id" { value = alicloud_instance.this.id}
output "public_ip" { value = alicloud_instance.this.public_ip}
output "private_ip" { value = alicloud_instance.this.private_ip}# main.tf - 使用自定义模块module "web_server" { source = "./modules/ecs-instance"
instance_name = "web-server-01" instance_type = "ecs.t6-c1m1.large" image_id = data.alicloud_images.almalinux.images[0].id vswitch_id = alicloud_vswitch.main.id security_group_id = alicloud_security_group.web.id
tags = { Role = "web" Env = "production" }}
module "api_server" { source = "./modules/ecs-instance"
instance_name = "api-server-01" instance_type = "ecs.c6.large" image_id = data.alicloud_images.almalinux.images[0].id vswitch_id = alicloud_vswitch.main.id security_group_id = alicloud_security_group.web.id
tags = { Role = "api" Env = "production" }}
output "web_server_ip" { value = module.web_server.public_ip}
output "api_server_ip" { value = module.api_server.public_ip}使用远程模块
Section titled “使用远程模块”# 使用 Terraform Registry 上的模块module "vpc" { source = "alibaba/vpc/alicloud" version = "1.10.0"
vpc_name = "production-vpc" vpc_cidr = "10.0.0.0/8"}推荐的项目结构
Section titled “推荐的项目结构”terraform-project/├── environments/│ ├── production/│ │ ├── main.tf│ │ ├── variables.tf│ │ ├── outputs.tf│ │ ├── terraform.tfvars│ │ └── backend.tf│ └── staging/│ ├── main.tf│ ├── variables.tf│ ├── outputs.tf│ ├── terraform.tfvars│ └── backend.tf├── modules/│ ├── ecs-instance/│ ├── vpc/│ └── security-group/└── .gitignore为 Terraform 项目创建 .gitignore:
cat > .gitignore << 'EOF'# Terraform.terraform/*.tfstate*.tfstate.backup*.tfplan*.tfvars!example.tfvars
# 敏感文件*.pem*.keyEOFTerraform 是基础设施即代码的核心工具,将云资源的创建和管理纳入版本控制。配合 Cloud-Init 传入 user-data 和 Ansible 进行后续配置,三者共同构建出完整的自动化基础设施交付流水线。