跳转至

第08章 配置管理

配置管理图

📚 章节概述

本章将深入讲解配置管理,包括Ansible自动化运维、Terraform基础设施即代码等工具的使用。通过本章学习,你将能够实现配置的自动化管理和基础设施的代码化。

🎯 学习目标

完成本章后,你将能够:

  1. 理解配置管理的核心概念
  2. 掌握Ansible的使用
  3. 了解Terraform的IaC实践
  4. 掌握配置版本控制
  5. 能够搭建生产级的配置管理系统

8.1 配置管理概述

8.1.1 什么是配置管理

配置管理是对系统、应用、网络等配置进行自动化管理和控制的过程。

配置管理的价值

  1. 一致性
  2. 统一的配置标准
  3. 减少配置漂移
  4. 确保环境一致

  5. 自动化

  6. 自动化配置部署
  7. 减少人为错误
  8. 提高效率

  9. 可追溯

  10. 配置版本控制
  11. 变更历史记录
  12. 审计追踪

  13. 可重复

  14. 配置即代码
  15. 环境可重建
  16. 灾难恢复

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架构。

核心特性

  1. 无Agent
  2. 基于SSH
  3. 无需安装客户端
  4. 简单部署

  5. 简单易用

  6. YAML配置
  7. 模块化设计
  8. 学习曲线平缓

  9. 幂等性

  10. 多次执行结果一致
  11. 安全可靠
  12. 适合自动化

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)工具,支持多云管理。

核心特性

  1. 多云支持
  2. AWS、Azure、GCP
  3. 阿里云、腾讯云
  4. 200+提供商

  5. 声明式配置

  6. 描述期望状态
  7. 自动计算变更
  8. 幂等性

  9. 状态管理

  10. 状态文件
  11. 变更追踪
  12. 依赖管理

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 练习题

基础题

  1. 选择题
  2. Ansible采用什么架构?

    • A. Agent-based
    • B. Agentless
    • C. Hybrid
    • D. Distributed
  3. 简答题

  4. 解释Ansible的幂等性。
  5. 说明Terraform的声明式配置。

进阶题

  1. 实践题
  2. 编写一个Ansible Playbook。
  3. 使用Terraform创建AWS基础设施。
  4. 实现配置的版本控制。

  5. 设计题

  6. 设计一个生产级的配置管理架构。
  7. 设计一个多环境配置方案。

答案

1. 选择题答案

  1. B(Ansible采用Agentless架构)

2. 简答题答案

Ansible的幂等性: - 多次执行结果一致 - 不会重复创建资源 - 适合自动化

Terraform的声明式配置: - 描述期望状态 - 自动计算变更 - 幂等性

3. 实践题答案

参见8.2-8.3节的示例。

4. 设计题答案

参见8.1-8.3节的架构设计。

8.5 面试准备

大厂面试题

字节跳动

  1. 解释配置管理的价值。
  2. Ansible和Puppet的区别是什么?
  3. Terraform的状态管理机制是什么?
  4. 如何实现配置的版本控制?

腾讯

  1. Ansible的模块有哪些?
  2. 如何实现配置的自动化部署?
  3. Terraform的变量如何管理?
  4. 如何处理配置冲突?

阿里云

  1. IaC的最佳实践是什么?
  2. 如何实现配置的审计?
  3. 如何设计配置管理策略?
  4. 如何处理配置漂移?

📚 参考资料

🎯 本章小结

本章深入讲解了配置管理,包括:

  1. 配置管理的核心概念
  2. Ansible自动化运维
  3. Terraform基础设施即代码
  4. 配置版本控制
  5. 完整的实战案例

通过本章学习,你掌握了配置管理的核心技术,能够搭建生产级的配置管理系统。下一章将深入学习服务网格。