引言
在现代云原生时代,基础设施即代码(Infrastructure as Code,IaC)已成为运维工程师的核心技能。面对复杂的多云环境和日益增长的基础设施需求,传统的手动配置方式已无法满足快速、可靠、可重复的部署要求。本文将深入探讨 Terraform 和 Ansible 这两大运维利器的核心差异,明确它们在配置管理和资源编排领域的分工边界,为运维工程师提供清晰的技术选型指导。
Terraform 基础介绍
Terraform 是 HashiCorp 公司开发的一款开源基础设施即代码工具,采用声明式语法,通过 HCL(HashiCorp Configuration Language)语言描述基础设施资源。它的核心优势在于跨云平台的资源编排能力,支持 AWS、Azure、Google Cloud、阿里云等主流云服务商。
Terraform 的核心特性
1. 声明式语法
Terraform 使用声明式语法,用户只需描述最终状态,而非实现过程。这种方式使得基础设施配置更加直观和易于维护。
2. 状态管理
Terraform 通过状态文件(terraform.tfstate)追踪基础设施资源的当前状态,确保实际环境与配置文件的一致性。
3. 计划与应用
在实际部署前,Terraform 会生成执行计划,展示将要进行的变更,提供了安全的变更预览机制。
Ansible 与 Terraform 的分工边界
技术定位差异
Terraform:资源编排专家
• 专注于基础设施资源的创建、修改和删除
• 管理云服务商的各种资源:虚拟机、网络、存储、数据库等
• 维护资源间的依赖关系和生命周期
Ansible:配置管理专家
• 专注于服务器内部的配置管理
• 软件安装、配置文件管理、服务启动等
• 应用程序部署和运行时配置
工作流程对比
典型的云基础设施部署流程中,两者的协作模式如下:
1. Terraform 阶段:创建云资源(VPC、子网、安全组、EC2实例等)
2. Ansible 阶段:配置服务器(安装软件、部署应用、配置服务等)
配置管理 vs 资源编排
资源编排(Infrastructure Orchestration)
资源编排关注的是基础设施资源的生命周期管理,包括:
• 资源创建的顺序和依赖关系
• 资源属性的定义和修改
• 资源的销毁和回收
• 跨云平台的资源统一管理
配置管理(Configuration Management)
配置管理专注于系统内部的状态管理,包括:
• 操作系统级别的配置
• 应用程序的安装和配置
• 服务的启动和运行状态管理
• 配置文件的模板化和动态生成
实际应用案例
案例一:使用 Terraform 创建 AWS 基础设施
# main.tf - AWS 基础设施资源编排
# 定义 Terraform 提供商和版本要求
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# 配置 AWS 提供商
provider "aws" {
region = var.aws_region
}
# 定义变量
variable "aws_region" {
description = "AWS 部署区域"
type = string
default = "us-west-2"
}
variable "environment" {
description = "环境标识"
type = string
default = "production"
}
# 创建 VPC 网络
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
Environment = var.environment
}
}
# 创建公共子网
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 1}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
# 公共子网自动分配公网IP
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-subnet-${count.index + 1}"
Type = "public"
}
}
# 创建私有子网
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index + 10}.0/24"
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${var.environment}-private-subnet-${count.index + 1}"
Type = "private"
}
}
# 获取可用区信息
data "aws_availability_zones" "available" {
state = "available"
}
# 创建互联网网关
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.environment}-igw"
}
}
# 创建路由表
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${var.environment}-public-rt"
}
}
# 关联公共子网到路由表
resource "aws_route_table_association" "public" {
count = length(aws_subnet.public)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
# 创建安全组
resource "aws_security_group" "web" {
name = "${var.environment}-web-sg"
description = "Web 服务器安全组"
vpc_id = aws_vpc.main.id
# 允许 HTTP 入站流量
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# 允许 HTTPS 入站流量
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# 允许 SSH 入站流量
ingress {
from_port = 22
to_port = 22
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.environment}-web-sg"
}
}
# 创建密钥对
resource "aws_key_pair" "main" {
key_name = "${var.environment}-key"
public_key = file("~/.ssh/id_rsa.pub")
}
# 创建 EC2 实例
resource "aws_instance" "web" {
count = 2
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
key_name = aws_key_pair.main.key_name
vpc_security_group_ids = [aws_security_group.web.id]
subnet_id = aws_subnet.public[count.index].id
# 实例启动时执行的脚本
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y python3 python3-pip
pip3 install ansible
EOF
tags = {
Name = "${var.environment}-web-${count.index + 1}"
Role = "web-server"
}
}
# 获取 Ubuntu AMI 信息
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# 输出关键信息
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "公共子网 ID 列表"
value = aws_subnet.public[*].id
}
output "web_server_ips" {
description = "Web 服务器公网 IP"
value = aws_instance.web[*].public_ip
}
案例二:使用 Ansible 进行服务器配置管理
# nginx-playbook.yml - Nginx 配置管理
---
- name: 配置 Nginx Web 服务器
hosts: web_servers
become: yes
gather_facts: yes
vars:
nginx_user: "www-data"
nginx_worker_processes: "auto"
nginx_worker_connections: 1024
nginx_keepalive_timeout: 65
nginx_server_name: "{{ ansible_default_ipv4.address }}"
tasks:
# 更新软件包缓存
- name: 更新 apt 软件包缓存
apt:
update_cache: yes
cache_valid_time: 3600
tags: [packages]
# 安装 Nginx
- name: 安装 Nginx
apt:
name: nginx
state: present
notify: restart nginx
tags: [packages]
# 创建网站目录
- name: 创建网站根目录
file:
path: /var/www/html
state: directory
owner: "{{ nginx_user }}"
group: "{{ nginx_user }}"
mode: '0755'
tags: [directories]
# 配置 Nginx 主配置文件
- name: 配置 Nginx 主配置文件
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: yes
notify: reload nginx
tags: [config]
# 配置虚拟主机
- name: 配置默认虚拟主机
template:
src: default.conf.j2
dest: /etc/nginx/sites-available/default
owner: root
group: root
mode: '0644'
backup: yes
notify: reload nginx
tags: [config]
# 创建自定义网页
- name: 创建自定义首页
template:
src: index.html.j2
dest: /var/www/html/index.html
owner: "{{ nginx_user }}"
group: "{{ nginx_user }}"
mode: '0644'
tags: [content]
# 启动并启用 Nginx 服务
- name: 启动并启用 Nginx 服务
systemd:
name: nginx
state: started
enabled: yes
tags: [service]
# 配置防火墙规则
- name: 配置 UFW 防火墙规则
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- '80'
- '443'
tags: [firewall]
# 安装 SSL 证书工具
- name: 安装 Certbot
apt:
name:
- certbot
- python3-certbot-nginx
state: present
tags: [ssl]
handlers:
# 重启 Nginx 服务
- name: restart nginx
systemd:
name: nginx
state: restarted
# 重新加载 Nginx 配置
- name: reload nginx
systemd:
name: nginx
state: reloaded
{# templates/nginx.conf.j2 - Nginx 主配置模板 #}
# Nginx 主配置文件
# 由 Ansible 自动生成,请勿手动修改
user {{ nginx_user }};
worker_processes {{ nginx_worker_processes }};
pid /run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
use epoll;
multi_accept on;
}
http {
# 基础设置
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout {{ nginx_keepalive_timeout }};
types_hash_max_size 2048;
server_tokens off;
# MIME 类型
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 访问日志
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# 包含虚拟主机配置
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
案例三:集成 Terraform 和 Ansible 的自动化部署
# inventory/hosts.yml - 动态主机清单
---
all:
children:
web_servers:
hosts:
# 这些IP将从 Terraform 输出中动态获取
web-1:
ansible_host: "{{ terraform_outputs.web_server_ips[0] }}"
web-2:
ansible_host: "{{ terraform_outputs.web_server_ips[1] }}"
vars:
ansible_user: ubuntu
ansible_ssh_private_key_file: ~/.ssh/id_rsa
ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
#!/bin/bash
# deploy.sh - 完整部署脚本
# 集成 Terraform 和 Ansible 的自动化部署流程
set -e
# 颜色定义
RED='�33[0;31m'
GREEN='�33[0;32m'
YELLOW='�33[1;33m'
NC='�33[0m' # No Color
# 日志函数
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查依赖工具
check_dependencies() {
log_info "检查依赖工具..."
if ! command -v terraform &> /dev/null; then
log_error "Terraform 未安装"
exit 1
fi
if ! command -v ansible &> /dev/null; then
log_error "Ansible 未安装"
exit 1
fi
log_info "依赖工具检查完成"
}
# Terraform 部署
terraform_deploy() {
log_info "开始 Terraform 基础设施部署..."
# 初始化 Terraform
terraform init
# 生成执行计划
terraform plan -out=tfplan
# 应用配置
terraform apply tfplan
# 获取输出信息
terraform output -json > terraform_outputs.json
log_info "Terraform 部署完成"
}
# 等待实例就绪
wait_for_instances() {
log_info "等待 EC2 实例就绪..."
# 从 Terraform 输出获取 IP 地址
IPS=$(terraform output -json | jq -r '.web_server_ips.value[]')
for ip in $IPS; do
log_info "等待 $ip 就绪..."
while ! ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no ubuntu@$ip 'echo "ready"' &>/dev/null; do
log_warn "等待 $ip 响应..."
sleep 10
done
log_info "$ip 已就绪"
done
}
# Ansible 配置
ansible_configure() {
log_info "开始 Ansible 配置管理..."
# 生成动态主机清单
python3 generate_inventory.py
# 测试连接
ansible all -i inventory/hosts.yml -m ping
# 执行配置
ansible-playbook -i inventory/hosts.yml nginx-playbook.yml
log_info "Ansible 配置完成"
}
# 验证部署
verify_deployment() {
log_info "验证部署结果..."
IPS=$(terraform output -json | jq -r '.web_server_ips.value[]')
for ip in $IPS; do
log_info "测试 $ip 的 Web 服务..."
if curl -s -o /dev/null -w "%{http_code}" http://$ip | grep -q "200"; then
log_info "$ip Web 服务正常"
else
log_error "$ip Web 服务异常"
fi
done
}
# 主函数
main() {
log_info "开始自动化部署流程..."
check_dependencies
terraform_deploy
wait_for_instances
ansible_configure
verify_deployment
log_info "部署完成!"
log_info "访问地址:"
terraform output web_server_ips
}
# 清理资源
cleanup() {
log_warn "清理 Terraform 资源..."
terraform destroy -auto-approve
rm -f terraform_outputs.json
rm -f tfplan
log_info "资源清理完成"
}
# 参数处理
case "${1:-deploy}" in
"deploy")
main
;;
"cleanup")
cleanup
;;
*)
echo "使用方法: $0 [deploy|cleanup]"
exit 1
;;
esac
最佳实践与建议
1. 技术选型原则
使用 Terraform 的场景:
• 需要创建和管理云资源
• 跨云平台的资源编排
• 基础设施版本控制和协作
• 资源依赖关系复杂的场景
使用 Ansible 的场景:
• 服务器配置管理
• 应用程序部署
• 运行时配置更新
• 批量运维操作
2. 协作模式
串行协作模式:先用 Terraform 创建基础设施,再用 Ansible 配置服务器。这是最常见的模式,适用于大多数场景。
并行协作模式:在某些场景下,可以同时使用两个工具管理不同层面的资源,但需要做好状态同步。
3. 状态管理
Terraform 状态管理:
• 使用远程状态存储(如 S3、Azure Blob)
• 启用状态锁定机制
• 定期备份状态文件
Ansible 状态管理:
• 使用幂等性任务设计
• 合理使用 handlers 和 tags
• 建立回滚机制
4. 安全考虑
凭证管理:
• 使用 IAM 角色而非硬编码密钥
• 利用 HashiCorp Vault 或 AWS Secrets Manager
• 实施最小权限原则
网络安全:
• 合理配置安全组规则
• 使用 VPN 或堡垒机访问内网资源
• 启用日志审计
总结
Terraform 和 Ansible 在现代运维体系中扮演着不同但互补的角色。Terraform 专注于基础设施资源的声明式编排,提供了强大的跨云平台能力和状态管理机制;Ansible 则专注于配置管理和应用部署,提供了灵活的任务执行和丰富的模块生态。
理解两者的分工边界,合理地将资源编排和配置管理分离,能够构建更加健壮、可维护的基础设施自动化体系。在实际应用中,建议采用 Terraform 负责基础设施层面的资源管理,Ansible 负责应用层面的配置管理,通过标准化的接口和流程实现两者的无缝协作。
随着云原生技术的发展,运维工程师需要不断学习和实践这些工具,构建适合自己组织需求的自动化运维体系。通过合理的技术选型和最佳实践,能够显著提升运维效率,降低运维风险,为业务发展提供坚实的基础设施保障。
全部0条评论
快来发表一下你的评论吧 !