随机
Enter 搜索 ↑↓ 切换 Esc 清空

terraform

命令

基础设施即代码工具

terraform

基础设施即代码工具

补充说明

terraform 是 HashiCorp 开发的开源基础设施即代码 (IaC) 工具,通过声明式配置文件管理云资源。支持 AWS、Azure、GCP、Kubernetes 等多种 provider。

基本语法

# main.tf 示例

# 指定 provider
provider "aws" {
  region = "us-east-1"
}

# 指定 terraform 版本要求
terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

# 远程状态配置
terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "us-east-1"
  }
}

# 创建资源
resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  tags = {
    Name = "example-instance"
  }
}

# 变量定义
variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t2.micro"
}

# 输出值
output "instance_ip" {
  value       = aws_instance.example.public_ip
  description = "The public IP of the instance"
}

变量

# 字符串变量
variable "ami" {
  type        = string
  description = "AMI ID"
  default     = "ami-0c55b159cbfafe1f0"
}

# 数字变量
variable "count" {
  type        = number
  default     = 3
}

# 布尔变量
variable "enable_monitoring" {
  type        = bool
  default     = true
}

# 列表变量
variable "azs" {
  type    = list(string)
  default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}

# Map 变量
variable "tags" {
  type = map(string)
  default = {
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

# 对象变量
variable "server" {
  type = object({
    name = string
    port = number
  })
  default = {
    name = "web"
    port = 8080
  }
}

# 使用变量
resource "aws_instance" "example" {
  ami           = var.ami
  instance_type = var.instance_type
}

资源

# EC2 实例
resource "aws_instance" "web" {
  ami                    = "ami-0c55b159cbfafe1f0"
  instance_type          = "t2.micro"
  subnet_id              = aws_subnet.main.id
  vpc_security_group_ids = [aws_security_group.web.id]

  user_data = <<-EOF
              #!/bin/bash
              yum install -y nginx
              systemctl start nginx
              EOF

  tags = {
    Name = "web-server"
  }
}

# 安全组
resource "aws_security_group" "web" {
  name = "web-sg"
  
  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"]
  }
}

# S3 桶
resource "aws_s3_bucket" "data" {
  bucket = "my-unique-bucket-name"

  tags = {
    Name = "data-bucket"
  }
}

# RDS 实例
resource "aws_db_instance" "default" {
  identifier           = "mydb"
  engine               = "mysql"
  engine_version       = "8.0"
  instance_class       = "db.t2.micro"
  allocated_storage    = 20
  username             = "admin"
  password             = "password"
  skip_final_snapshot  = true
}

数据源

# 获取 AMI
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}

# 获取 VPC
data "aws_vpc" "default" {
  default = true
}

# 获取可用区
data "aws_availability_zones" "available" {
  state = "available"
}

# 使用数据源
resource "aws_instance" "web" {
  ami = data.aws_ami.ubuntu.id
}

# 获取 SSM 参数
data "aws_ssm_parameter" "ami" {
  name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}

模块

# 模块目录结构
# modules/
# └── ec2-instance/
#     ├── main.tf
#     ├── variables.tf
#     └── outputs.tf

# main.tf
resource "aws_instance" "this" {
  ami           = var.ami
  instance_type = var.instance_type
  subnet_id     = var.subnet_id

  tags = {
    Name = var.name
  }
}

# variables.tf
variable "ami" {
  type = string
}

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

variable "subnet_id" {
  type = string
}

variable "name" {
  type = string
}

# outputs.tf
output "instance_id" {
  value = aws_instance.this.id
}

# 调用模块
module "web_servers" {
  source = "./modules/ec2-instance"

  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.main.id
  name          = "web-server"
}

# 远程模块
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.0.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"
}

状态管理

# 本地状态
terraform {
  backend "local" {
    path = "terraform.tfstate"
  }
}

# S3 后端
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

# Azure Blob 存储后端
terraform {
  backend "azurerm" {
    resource_group_name  = "terraform"
    storage_account_name  = "tfstate123"
    container_name        = "tfstate"
    key                   = "prod.terraform.tfstate"
  }
}

# GCS 后端
terraform {
  backend "gcs" {
    bucket = "my-terraform-state"
    prefix = "prod"
  }
}

工作流命令

# 初始化
terraform init
terraform init -upgrade    # 升级模块

# 格式化
terraform fmt

# 验证
terraform validate

# 规划
terraform plan
terraform plan -out=plan.tfplan    # 保存计划
terraform plan -var-file=prod.tfvars

# 应用
terraform apply
terraform apply plan.tfplan
terraform apply -auto-approve      # 自动确认

# 销毁
terraform destroy
terraform destroy -target=aws_instance.web  # 指定资源
terraform destroy -auto-approve

# 显示状态
terraform show
terraform show -json

# 状态操作
terraform state list                # 列出资源
terraform state show aws_instance.web  # 显示资源详情
terraform state mv aws_instance.web aws_instance.web_new  # 重命名
terraform state rm aws_instance.web  # 从状态移除
terraform state pull                # 拉取远程状态
terraform state push                # 推送本地状态

条件与循环

# 条件表达式
resource "aws_instance" "example" {
  ami           = var.use_large_ami ? "ami-large" : "ami-small"
  instance_type = var.use_large_ami ? "t2.large" : "t2.micro"
}

# count 循环
resource "aws_instance" "server" {
  count = 3

  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  tags = {
    Name = "server-${count.index}"
  }
}

# for_each 循环
resource "aws_security_group_rule" "http" {
  for_each = toset(["80", "443"])

  type              = "ingress"
  from_port         = each.value
  to_port           = each.value
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.example.id
}

# for 表达式
locals {
  names = ["web", "api", "db"]
  tags = [for name in local.names : {
    name = name
    env = "prod"
  }]
}

# 动态块
resource "aws_security_group" "example" {
  name = "example"

  dynamic "ingress" {
    for_each = var.ingress_rules
    content {
      from_port   = ingress.value.from_port
      to_port     = ingress.value.to_port
      protocol    = ingress.value.protocol
      cidr_blocks = ingress.value.cidr_blocks
    }
  }
}

函数

# 字符串函数
locals {
  name = lower("MY-SERVER")           # "my-server"
  name = replace("web-server", "-", "_")  # "web_server"
  name = format("server-%03d", 1)    # "server-001"
}

# 集合函数
locals {
  combined = concat(var.list1, var.list2)
  filtered = toset([for s in var.list : upper(s)])
  joined   = join(",", var.list)
}

# 文件函数
locals {
  user_data = file("${path.module}/scripts/init.sh")
  policy    = templatefile("${path.module}/templates/policy.json", {
    name = var.name
  })
}

# 查找函数
locals {
  region = try(var.override_region, data.aws_region.current.name)
}

输出与敏感数据

# 普通输出
output "instance_ip" {
  value = aws_instance.web.public_ip
}

# 敏感输出(会隐藏值但仍显示)
output "password" {
  value     = aws_instance.web.password
  sensitive = true
}

# 条件输出
output "bucket_arn" {
  value = var.create_bucket ? aws_s3_bucket.example[0].arn : ""
}

# 多值输出
output "instance_ips" {
  value = aws_instance.web[*].public_ip
}

workspace

# 列出 workspace
terraform workspace list

# 创建 workspace
terraform workspace new production

# 选择 workspace
terraform workspace select production

# 当前 workspace
terraform workspace show

# 删除 workspace(需要先切换走)
terraform workspace delete staging

Import

# 导入已有资源
terraform import aws_instance.existing i-1234567890abcdef0

# 导入到模块
terraform import module.vpc.aws_vpc.this vpc-12345678