第08章 配置管理¶
📚 章节概述¶
本章将深入讲解配置管理,包括Ansible自动化运维、Terraform基础设施即代码等工具的使用。通过本章学习,你将能够实现配置的自动化管理和基础设施的代码化。
🎯 学习目标¶
完成本章后,你将能够:
- 理解配置管理的核心概念
- 掌握Ansible的使用
- 了解Terraform的IaC实践
- 掌握配置版本控制
- 能够搭建生产级的配置管理系统
8.1 配置管理概述¶
8.1.1 什么是配置管理¶
配置管理是对系统、应用、网络等配置进行自动化管理和控制的过程。
配置管理的价值¶
- 一致性
- 统一的配置标准
- 减少配置漂移
-
确保环境一致
-
自动化
- 自动化配置部署
- 减少人为错误
-
提高效率
-
可追溯
- 配置版本控制
- 变更历史记录
-
审计追踪
-
可重复
- 配置即代码
- 环境可重建
- 灾难恢复
8.1.2 配置管理工具对比¶
| 工具 | 类型 | 语言 | 特点 |
|---|---|---|---|
| Ansible | Agentless | Python | 无需Agent,简单易用 |
| Puppet | Agent-based | Ruby | 强大的DSL,成熟稳定 |
| Chef | Agent-based | Ruby | 灵活,适合大型环境 |
| SaltStack | Agent-based | Python | 高性能,实时执行 |
| Terraform | IaC | Go | 多云支持,声明式 |
8.2 Ansible¶
8.2.1 Ansible概述¶
Ansible是一个开源的自动化配置管理工具,采用无Agent架构。
核心特性¶
- 无Agent
- 基于SSH
- 无需安装客户端
-
简单部署
-
简单易用
- YAML配置
- 模块化设计
-
学习曲线平缓
-
幂等性
- 多次执行结果一致
- 安全可靠
- 适合自动化
8.2.2 Ansible安装¶
Bash
# 安装Ansible
pip install ansible
# 验证安装
ansible --version
# 配置SSH密钥
ssh-keygen -t rsa -b 4096
ssh-copy-id user@server
8.2.3 Ansible Playbook¶
基本Playbook¶
YAML
---
# Playbook:配置Web服务器集群
- name: Configure web servers
hosts: webservers # 目标主机组,在inventory中定义
become: yes # 使用sudo提权执行
vars: # 定义Playbook级别变量
http_port: 80
max_clients: 200
tasks:
# 任务1:安装Apache(apt模块管理Debian/Ubuntu软件包)
- name: Install Apache
apt:
name: apache2
state: present # 确保已安装(幂等操作)
update_cache: yes # 安装前刷新apt缓存
# 任务2:启动并设置Apache开机自启
- name: Start Apache service
service:
name: apache2
state: started # 确保服务处于运行状态
enabled: yes # 设置开机自启动
# 任务3:将本地应用文件复制到远程服务器
- name: Deploy web application
copy:
src: /path/to/app/
dest: /var/www/html/
owner: www-data # 设置文件属主为Web服务用户
group: www-data
mode: '0644' # 设置文件权限(只读)
# 任务4:使用Jinja2模板渲染配置文件
- name: Configure Apache
template:
src: apache.conf.j2 # 本地Jinja2模板
dest: /etc/apache2/sites-available/000-default.conf # 远程目标路径
notify:
- Restart Apache # 配置变更时触发handler重启服务
# handlers:被notify触发时才执行,用于服务重启等操作
handlers:
- name: Restart Apache
service:
name: apache2
state: restarted
高级Playbook¶
YAML
---
# 高级Playbook:部署完整应用技术栈
- name: Deploy application stack
hosts: all
become: yes
vars_files:
- vars/main.yml # 从外部文件加载变量,便于环境隔离
# pre_tasks:在roles和tasks之前执行的预处理任务
pre_tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600 # 缓存有效期3600秒,避免频繁刷新
# roles:引用Ansible Galaxy社区角色,自动安装基础设施组件
roles:
- geerlingguy.docker # 安装Docker容器运行时
- geerlingguy.nginx # 安装Nginx反向代理
- geerlingguy.mysql # 安装MySQL数据库
- geerlingguy.redis # 安装Redis缓存
tasks:
# 创建应用目录,使用变量实现多环境配置
- name: Create application directory
file:
path: "{{ app_dir }}"
state: directory
owner: "{{ app_user }}"
group: "{{ app_user }}"
mode: '0755'
# 从Git仓库拉取应用代码,指定版本(标签/分支/commit)
- name: Deploy application
git:
repo: "{{ app_repo }}"
dest: "{{ app_dir }}"
version: "{{ app_version }}" # 指定部署的版本号
force: yes # 强制覆盖本地修改
notify:
- Restart application # 代码更新后重启应用
# 在虚拟环境中安装Python依赖,隔离系统Python
- name: Install Python dependencies
pip:
requirements: "{{ app_dir }}/requirements.txt"
virtualenv: "{{ app_dir }}/venv"
# 使用模板生成systemd服务单元文件
- name: Configure systemd service
template:
src: app.service.j2
dest: /etc/systemd/system/{{ app_name }}.service
notify:
- Reload systemd # 服务文件变更后需重载systemd
# 启动应用服务并设置开机自启
- name: Start application service
systemd:
name: "{{ app_name }}"
state: started
enabled: yes
handlers:
# 重启应用服务(代码更新时触发)
- name: Restart application
systemd:
name: "{{ app_name }}"
state: restarted
# 重载systemd守护进程(服务文件变更时触发)
- name: Reload systemd
systemd:
daemon_reload: yes
8.2.4 Ansible Roles¶
Role结构¶
Text Only
myrole/
├── defaults/
│ └── main.yml
├── files/
│ └── config.conf
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
│ └── config.j2
├── tests/
│ ├── inventory
│ └── test.yml
└── vars/
└── main.yml
Role示例¶
YAML
# tasks/main.yml — Role的主任务文件
--- # YAML文档分隔符
# 使用loop循环安装多个依赖包(package模块自动适配包管理器)
- name: Install required packages
package:
name: "{{ item }}"
state: present
loop:
- nginx
- python3-pip
# 创建系统用户用于运行应用(system: yes表示系统账户,不可登录)
- name: Create application user
user:
name: "{{ app_user }}"
system: yes
shell: /bin/bash
home: "{{ app_home }}"
create_home: yes
# 创建应用部署目录并设置权限
- name: Create application directory
file:
path: "{{ app_dir }}"
state: directory
owner: "{{ app_user }}"
group: "{{ app_user }}"
mode: '0755'
# 从Git仓库克隆/更新应用代码
- name: Deploy application
git:
repo: "{{ app_repo }}"
dest: "{{ app_dir }}"
version: "{{ app_version }}"
# 在Python虚拟环境中安装项目依赖
- name: Install Python dependencies
pip:
requirements: "{{ app_dir }}/requirements.txt"
virtualenv: "{{ app_dir }}/venv"
# 使用Jinja2模板生成Nginx站点配置
- name: Configure Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/{{ app_name }}
notify:
- Restart Nginx
# 创建符号链接启用站点配置(Nginx的sites-enabled机制)
- name: Enable site
file:
src: /etc/nginx/sites-available/{{ app_name }}
dest: /etc/nginx/sites-enabled/{{ app_name }}
state: link
notify:
- Restart Nginx
# 删除Nginx默认站点,避免端口冲突
- name: Remove default site
file:
path: /etc/nginx/sites-enabled/default
state: absent
notify:
- Restart Nginx
# 启动Nginx并设置开机自启
- name: Start Nginx
service:
name: nginx
state: started
enabled: yes
8.3 Terraform¶
8.3.1 Terraform概述¶
Terraform是一个基础设施即代码(IaC)工具,支持多云管理。
核心特性¶
- 多云支持
- AWS、Azure、GCP
- 阿里云、腾讯云
-
200+提供商
-
声明式配置
- 描述期望状态
- 自动计算变更
-
幂等性
-
状态管理
- 状态文件
- 变更追踪
- 依赖管理
8.3.2 Terraform安装¶
Bash
# 下载Terraform
wget https://releases.hashicorp.com/terraform/1.5.0/terraform_1.5.0_linux_amd64.zip
# 解压
unzip terraform_1.5.0_linux_amd64.zip
# 安装
sudo mv terraform /usr/local/bin/
# 验证安装
terraform version
8.3.3 Terraform配置¶
AWS基础设施¶
Terraform
# provider.tf — 定义云服务提供商及认证方式
provider "aws" {
region = var.aws_region
# 推荐使用环境变量 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
# 或 AWS CLI 配置文件(~/.aws/credentials),避免在代码中硬编码凭证
}
# vpc.tf — 创建VPC虚拟私有网络(所有资源的网络基础)
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr # VPC的IP地址范围
enable_dns_support = true # 启用DNS解析
enable_dns_hostnames = true # 启用DNS主机名
tags = {
Name = "${var.project_name}-vpc" # 使用字符串插值生成资源名称
Environment = var.environment
}
}
# subnet.tf — 创建公有/私有子网(按可用区分布,实现高可用)
# 注意:下方示例使用 count 仅为简化演示。
# 生产环境推荐使用 for_each + 命名映射,避免删除/插入元素时索引偏移导致资源不必要的重建。
resource "aws_subnet" "public" {
count = length(var.availability_zones) # 每个可用区创建一个子网
vpc_id = aws_vpc.main.id # 引用上面创建的VPC
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index) # 自动计算子网CIDR
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true # 公有子网:自动分配公网IP
tags = {
Name = "${var.project_name}-public-subnet-${count.index}"
Environment = var.environment
}
}
# 私有子网:不分配公网IP,通过NAT网关访问外网
resource "aws_subnet" "private" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + 3) # CIDR偏移3,避免与公有子网冲突
availability_zone = var.availability_zones[count.index]
tags = {
Name = "${var.project_name}-private-subnet-${count.index}"
Environment = var.environment
}
}
# ec2.tf — 创建EC2 Web服务器实例
resource "aws_instance" "web" {
count = var.instance_count # 创建的实例数量
ami = var.ami_id # Amazon Machine Image(操作系统镜像)
instance_type = var.instance_type # 实例规格(CPU/内存)
subnet_id = aws_subnet.public[count.index % length(var.availability_zones)].id # 轮询分配到不同可用区
vpc_security_group_ids = [aws_security_group.web.id] # 关联安全组
# user_data:实例首次启动时执行的初始化脚本
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y docker
service docker start
usermod -aG docker ec2-user
EOF
tags = {
Name = "${var.project_name}-web-${count.index}"
Environment = var.environment
}
}
# security_group.tf — 定义安全组规则(相当于云上防火墙)
resource "aws_security_group" "web" {
name = "${var.project_name}-web-sg"
description = "Security group for web servers"
vpc_id = aws_vpc.main.id
# 入站规则:允许HTTP(80端口)访问
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # 对所有IP开放
}
# 入站规则:允许HTTPS(443端口)访问
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# 入站规则:限制SSH(22端口)访问来源
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = var.ssh_allowed_cidr # 仅允许指定CIDR范围访问
}
# 出站规则:允许所有出站流量(protocol="-1" 表示全协议)
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.project_name}-web-sg"
Environment = var.environment
}
}
# variables.tf — 定义所有可配置变量(支持多环境复用)
variable "aws_region" {
description = "AWS region" # AWS部署区域
type = string
default = "us-east-1"
}
variable "project_name" {
description = "Project name" # 项目名称,用于资源命名前缀
type = string
default = "myapp"
}
variable "environment" {
description = "Environment name" # 环境标识(production/staging/dev)
type = string
default = "production"
}
variable "vpc_cidr" {
description = "VPC CIDR block" # VPC网段,/16提供65536个IP
type = string
default = "10.0.0.0/16"
}
variable "availability_zones" {
description = "Availability zones" # 可用区列表,跨AZ部署实现高可用
type = list(string)
default = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
variable "ami_id" {
description = "AMI ID" # 操作系统镜像ID
type = string
default = "ami-0c55b159cbfafe1f0"
}
variable "instance_type" {
description = "Instance type" # 实例规格(t3.micro适合测试)
type = string
default = "t3.micro"
}
variable "instance_count" {
description = "Number of instances" # Web服务器实例数量
type = number
default = 3
}
variable "ssh_allowed_cidr" {
description = "CIDR blocks allowed for SSH" # SSH访问白名单(生产环境应限制具体IP)
type = list(string)
default = ["0.0.0.0/0"]
}
# outputs.tf — 定义输出值(用于跨模块引用或部署后查看关键信息)
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "Public subnet IDs"
value = aws_subnet.public[*].id # [*] 展开列表获取所有子网ID
}
output "private_subnet_ids" {
description = "Private subnet IDs"
value = aws_subnet.private[*].id
}
output "instance_ids" {
description = "Instance IDs"
value = aws_instance.web[*].id
}
output "instance_public_ips" {
description = "Instance public IPs" # 输出所有实例的公网IP,便于访问
value = aws_instance.web[*].public_ip
}
8.4 练习题¶
基础题¶
- 选择题
-
Ansible采用什么架构?
- A. Agent-based
- B. Agentless
- C. Hybrid
- D. Distributed
-
简答题
- 解释Ansible的幂等性。
- 说明Terraform的声明式配置。
进阶题¶
- 实践题
- 编写一个Ansible Playbook。
- 使用Terraform创建AWS基础设施。
-
实现配置的版本控制。
-
设计题
- 设计一个生产级的配置管理架构。
- 设计一个多环境配置方案。
答案¶
1. 选择题答案¶
- B(Ansible采用Agentless架构)
2. 简答题答案¶
Ansible的幂等性: - 多次执行结果一致 - 不会重复创建资源 - 适合自动化
Terraform的声明式配置: - 描述期望状态 - 自动计算变更 - 幂等性
3. 实践题答案¶
参见8.2-8.3节的示例。
4. 设计题答案¶
参见8.1-8.3节的架构设计。
8.5 面试准备¶
大厂面试题¶
字节跳动¶
- 解释配置管理的价值。
- Ansible和Puppet的区别是什么?
- Terraform的状态管理机制是什么?
- 如何实现配置的版本控制?
腾讯¶
- Ansible的模块有哪些?
- 如何实现配置的自动化部署?
- Terraform的变量如何管理?
- 如何处理配置冲突?
阿里云¶
- IaC的最佳实践是什么?
- 如何实现配置的审计?
- 如何设计配置管理策略?
- 如何处理配置漂移?
📚 参考资料¶
- Ansible官方文档:https://docs.ansible.com/
- Terraform官方文档:https://www.terraform.io/docs
- 《Ansible实战》
- 《Terraform Up & Running》
🎯 本章小结¶
本章深入讲解了配置管理,包括:
- 配置管理的核心概念
- Ansible自动化运维
- Terraform基础设施即代码
- 配置版本控制
- 完整的实战案例
通过本章学习,你掌握了配置管理的核心技术,能够搭建生产级的配置管理系统。下一章将深入学习服务网格。