使用Terraform管理云服务器基础设施

本文详解使用Terraform实现基础设施即代码(IaC),实现云服务器的自动化部署与版本管理。

为什么需要Terraform

方式 问题 Terraform优势
手动控制台 不可复现、易出错 声明式、幂等
云厂商CLI 命令不统一 统一语法、多云支持
自定义脚本 无状态管理 状态文件追踪变更

安装Terraform

# Ubuntu/Debian
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt update && sudo apt install terraform

# macOS
brew tap hashicorp/tap
brew install hashicorp/tap/terraform

# Windows (Chocolatey)
choco install terraform

# 验证
terraform version

基础目录结构

wordpress-infra/
├── main.tf
├── variables.tf
├── outputs.tf
├── terraform.tfvars
├── modules/
   ├── vpc/
   ├── ec2/
   ├── rds/
   └── cloudflare/
└── environments/
    ├── staging.tfvars
    └── production.tfvars

第一个Terraform配置(AWS EC2)

main.tf

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

  # 后端存储状态文件(S3 + DynamoDB锁)
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "wordpress/terraform.tfstate"
    region         = "ap-southeast-1"
    dynamodb_table = "terraform-lock"
    encrypt        = true
  }
}

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = {
      Project     = "WordPress"
      Environment = var.environment
      ManagedBy   = "Terraform"
    }
  }
}

# 数据来源:获取最新Ubuntu AMI
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical

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

# EC2实例
resource "aws_instance" "wordpress" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = var.instance_type
  key_name               = aws_key_pair.wordpress.key_name
  vpc_security_group_ids = [aws_security_group.wordpress.id]
  subnet_id              = aws_subnet.public.id

  root_block_device {
    volume_size = 50
    volume_type = "gp3"
    encrypted   = true
  }

  user_data = templatefile("${path.module}/userdata.sh", {
    wp_db_password = var.db_password
  })

  tags = {
    Name = "WordPress-${var.environment}"
  }
}

# 安全组
resource "aws_security_group" "wordpress" {
  name        = "wordpress-${var.environment}"
  description = "Allow HTTP/HTTPS/SSH"
  vpc_id      = aws_vpc.main.id

  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"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = [var.admin_ip]
  }

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

# Elastic IP
resource "aws_eip" "wordpress" {
  instance = aws_instance.wordpress.id
  domain   = "vpc"

  tags = {
    Name = "WordPress-EIP-${var.environment}"
  }
}

# 输出
output "wordpress_public_ip" {
  value = aws_eip.wordpress.public_ip
}

output "wordpress_dns" {
  value = aws_instance.wordpress.public_dns
}

variables.tf

variable "aws_region" {
  description = "AWS region"
  type        = string
  default     = "ap-southeast-1"
}

variable "environment" {
  description = "Environment name"
  type        = string
  default     = "staging"
}

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t3.medium"
}

variable "db_password" {
  description = "WordPress database password"
  type        = string
  sensitive   = true
}

variable "admin_ip" {
  description = "Admin SSH access IP"
  type        = string
  default     = "0.0.0.0/0"  # 生产环境请限制具体IP
}

terraform.tfvars

aws_region    = "ap-southeast-1"
environment   = "production"
instance_type = "t3.large"
db_password   = "YourSecurePassword123!"
admin_ip      = "1.2.3.4/32"

初始化和应用

# 初始化(下载Provider插件)
terraform init

# 检查配置格式
terraform fmt

# 验证配置
terraform validate

# 预览变更
terraform plan

# 应用变更(需要确认)
terraform apply

# 自动确认(CI/CD中使用)
terraform apply -auto-approve

# 销毁资源
terraform destroy

模块化设计

创建VPC模块

# modules/vpc/main.tf
resource "aws_vpc" "main" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "vpc-${var.environment}"
  }
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "igw-${var.environment}"
  }
}

resource "aws_subnet" "public" {
  count                   = length(var.public_subnets)
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnets[count.index]
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "public-subnet-${count.index + 1}"
  }
}

# modules/vpc/variables.tf
variable "cidr_block" {
  default = "10.0.0.0/16"
}

variable "public_subnets" {
  type    = list(string)
  default = ["10.0.1.0/24", "10.0.2.0/24"]
}

variable "environment" {}

使用模块

# main.tf
module "vpc" {
  source = "./modules/vpc"

  cidr_block     = "10.0.0.0/16"
  public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  environment    = var.environment
}

多环境管理

使用工作区(Workspace)

# 创建staging工作区
terraform workspace new staging

# 创建production工作区
terraform workspace new production

# 切换到staging
terraform workspace select staging

# 查看当前工作区
terraform workspace show

# 列出所有工作区
terraform workspace list

根据工作区配置变量

# variables.tf
variable "instance_type" {
  type = map(string)
  default = {
    default    = "t3.medium"
    staging    = "t3.small"
    production = "t3.large"
  }
}

# main.tf
resource "aws_instance" "wordpress" {
  instance_type = var.instance_type[terraform.workspace]
  # ...
}

状态管理

远程状态(S3 + DynamoDB)

# backend.tf
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "wordpress/terraform.tfstate"
    region         = "ap-southeast-1"
    dynamodb_table = "terraform-lock"
    encrypt        = true
  }
}
# 初始化后端
terraform init

# 状态文件迁移(本地 → S3)
terraform init -migrate-state

# 查看当前状态
terraform show

# 查看状态列表
terraform state list

# 移除状态中的资源(不删除实际资源)
terraform state rm aws_instance.wordpress

CI/CD集成(GitLab CI示例)

# .gitlab-ci.yml
stages:
  - validate
  - plan
  - apply

variables:
  TF_ROOT: ${CI_PROJECT_DIR}
  TF_STATE_NAME: ${CI_ENVIRONMENT_NAME}

cache:
  paths:
    - .terraform/*

before_script:
  - cd ${TF_ROOT}
  - terraform init -backend-config="bucket=${TF_STATE_BUCKET}"

validate:
  stage: validate
  script:
    - terraform validate
    - terraform fmt -check

plan:
  stage: plan
  script:
    - terraform plan -out=tfplan
  artifacts:
    paths:
      - tfplan
  environment:
    name: ${CI_COMMIT_REF_NAME}

apply:
  stage: apply
  script:
    - terraform apply -auto-approve tfplan
  dependencies:
    - plan
  environment:
    name: ${CI_COMMIT_REF_NAME}
  when: manual  # 需要手动点击确认

敏感数据管理

使用AWS Secrets Manager

resource "aws_secretsmanager_secret" "db_password" {
  name = "wordpress-db-password"
}

resource "aws_secretsmanager_secret_version" "db_password" {
  secret_id     = aws_secretsmanager_secret.db_password.id
  secret_string = var.db_password
}

# EC2实例中读取
data "aws_secretsmanager_secret_version" "db_password" {
  secret_id = aws_secretsmanager_secret.db_password.id
}

常用命令速查

命令 用途
terraform init 初始化工作目录
terraform plan 预览变更
terraform apply 应用变更
terraform destroy 销毁资源
terraform fmt 格式化配置
terraform validate 验证配置
terraform show 显示状态
terraform state list 列出状态中的资源

通过Terraform,可以将云基础设施版本化、自动化,实现一键部署多台服务器。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。