使用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,可以将云基础设施版本化、自动化,实现一键部署多台服务器。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)