UNIX/Linux系统管理技术手册-读书笔记-第二十三章
《UNIX/Linux系统管理技术手册-读书笔记-第二十三章
配置管理
1. 配置管理概述
1.1 什么是配置管理
| 概念 | 说明 | 能做什么 |
|---|---|---|
| 配置管理(CM) | 以代码形式描述系统期望状态,自动化实现服务器配置 | 替代“雪花服务器”,实现可重现、可审计、可版本控制的基础设施 |
| 声明式 vs 过程式 | 声明式:描述“要达到什么状态”;过程式:描述“要执行哪些步骤” | 声明式更简洁,CM系统自动处理执行细节 |
| 幂等性(Idempotence) | 重复执行同一操作,系统状态不变 | 可安全反复运行CM代码,无需担心副作用 |
| 基础设施即代码 | 基础设施配置存储在版本控制系统中 | 可追溯变更历史,支持代码审查和回滚 |
CM系统的核心操作:
- 创建/删除用户账户
- 安装/卸载软件包
- 同步配置文件(模板化)
- 重启服务
- 执行任意shell命令
- 创建云服务器实例
- 管理数据库账户
1.2 配置管理的危险(重要)
| 风险 | 说明 |
|---|---|
| 禁止手动修改 | 一旦CM托管,手动修改即退化为雪花服务器,造成状态漂移 |
| 陡峭学习曲线 | 所有CM系统都有学习成本,建议先在虚拟实验室练习 |
| 基础设施开销 | 大规模站点需专用服务器运行CM工作负载 |
| 系统间术语差异 | 不同CM系统概念相同但命名不同(见表23.2),知识迁移需重新学习 |
2. 配置管理核心要素
| 概念 | 说明 |
|---|---|
| 操作(Operation) | 最小配置单元(如package install nginx、service start nginx) |
| 参数(Parameter) | 操作的输入值(如软件包名、服务名) |
| 变量(Variable) | 命名过的值,用于参数化和模板填充 |
| 事实数据(Fact) | CM系统自动收集的目标主机信息(OS类型、IP地址、内存等) |
| 处理程序(Handler) | 响应特定事件的操作(如配置文件变更后重启服务) |
| 绑定(Binding) | 将操作集合与特定主机/主机组关联 |
| 操作集(Bundle) | 完成特定功能的操作集合(如“安装并配置Web服务器”) |
| 环境(Environment) | 隔离的配置世界(开发/测试/生产),支持分阶段部署 |
2.1 各CM系统术语对照表(表23.2)
| 通用概念 | Ansible | Salt | Puppet | Chef |
|---|---|---|---|---|
| 操作 | task | state | resource | resource |
| 操作类型 | module | function | resource type, provider | provider |
| 操作列表 | tasks | states | class, manifest | recipe |
| 绑定 | playbook | top file | classification | run list |
| 控制主机 | control | master | master | server |
| 客户机 | host | minion | agent, node | node |
| 客户组 | group | nodegroup | role | — |
| 变量 | variable | variable | parameter, variable | attribute |
| 事实数据 | fact | grain | fact | automatic attribute |
| 处理程序 | handler | requisite | notify | notifies |
| 操作集 | role | formula | module | cookbook |
| 操作集仓库 | Galaxy | GitHub | Forge | Supermarket |
3. 主流CM系统对比
3.1 一览表(表23.1扩展)
| 系统 | 实现语言 | 配置格式 | 模板引擎 | 守护进程(服务器/客户端) | 首次发布 |
|---|---|---|---|---|---|
| Ansible | Python | YAML | Jinja2 | ❌ 无(仅SSH) | 2012 |
| Salt | Python | YAML | Jinja2 | ✅ 可选/可选 | 2011 |
| Puppet | Ruby | 自定义DSL | ERB | ✅ 可选/可选 | 2005 |
| Chef | Ruby | Ruby DSL | ERB | ✅ 有/有 | 2009 |
市场份额:Puppet最老(2005)→ 用户量最大;Ansible和Salt增长最快;Chef在企业级场景受青睐。
3.2 架构差异(关键决策点)
| 对比维度 | Ansible | Salt | Puppet | Chef |
|---|---|---|---|---|
| 无服务器模式 | ✅ 默认(仅需SSH) | ✅ 支持(SSH模式) | ❌ 需master | ✅ 支持(chef-solo) |
| 性能 | 较慢(SSH往返) | 快速(ZeroMQ/消息总线) | 中等 | 中等 |
| 配置语言 | YAML + Jinja | YAML + Jinja | 自定义Ruby DSL | Ruby DSL |
| 学习曲线 | 低 | 中 | 中 | 高(需熟悉Ruby) |
| 大规模扩展 | 需调优 | ✅ 原生支持 | 有瓶颈(已知Lyft等迁移案例) | ✅ 分层架构支持 |
| 加密配置 | ✅ ansible-vault(内建) | ❌ 无内建 | ❌ 无内建 | ❌ 无内建 |
| Windows支持 | ✅ | ✅ | ✅ | ✅ |
| 模块/操作集仓库 | Ansible Galaxy | GitHub Formulas | Puppet Forge | Chef Supermarket |
3.3 各系统点评
Ansible(推荐小型到中型环境):
- ✅ 最大优势:无服务器守护进程,仅需SSH+Python,配置简洁
- ✅ ansible-vault提供内建加密
- ❌ 大规模部署时速度明显慢于Salt
- ❌ 手动管理客户端清单(无自动注册)
Salt(推荐大规模、云原生环境):
- ✅ 速度快(消息总线架构),原生支持云集成
- ✅ minion自动注册,配置语法一致性强
- ✅ 可无服务器运行(SSH模式)
- ❌ 依赖Jinja较重,文档组织较差
- ❌ 无内建加密方案(需外部工具)
Puppet(市场份额最大但呈下降趋势):
- ✅ 用户基数大,模块丰富,有免费WebGUI
- ❌ 历史包袱重,配置语言不直观
- ❌ 大规模场景存在master瓶颈
Chef(适合已有Ruby经验的企业):
- ✅ 功能完备,强健,可扩展,支持AIX
- ❌ 学习曲线最陡,企业级复杂度高
- ❌ “非Chef场景”慎选——若<100台服务器,其他系统更轻量
4. YAML(配置语言基础)
| 特性 | 说明 |
|---|---|
| 本质 | JSON的另一种语法(人类可读性更好) |
| 列表 | - item1(破折号+空格) |
| 散列 | key: value |
| 多行字符串 | ` |
| 变量插值 | {{ variable }}(Ansible/Salt的Jinja扩展) |
YAML陷阱:
- 缩进必须用空格(不能用Tab)
- 布尔值(
yes/no、true/false)自动转换 - 以
{{开头的值需加引号(某些情况下)
5. Ansible核心知识
5.1 架构与安装
| 组件 | 说明 |
|---|---|
| 控制主机 | 运行Ansible的机器(无需在受管节点安装agent) |
| 受管节点要求 | ✅ SSH访问 + ✅ Python 2/3 + ✅ sudo权限 |
| 配置文件 | /etc/ansible/ansible.cfg(系统级)或~/.ansible.cfg(用户级) |
| 清单(Inventory) | /etc/ansible/hosts(默认),列出受管主机 |
安装:
性能优化(ansible.cfg):
5.2 清单(Inventory)与分组
静态清单示例(/etc/ansible/hosts):
|
|
动态清单:可执行脚本输出JSON → 从云API动态获取主机列表(如ec2.py自动根据AWS标签分组)。
5.3 模块与任务
常用模块:
| 模块 | 功能 | 示例 |
|---|---|---|
package |
软件包管理 | package: name=nginx state=present |
service |
服务管理 | service: name=nginx state=started enabled=yes |
copy |
复制文件 | copy: src=file dest=/path/file mode=0644 |
template |
模板渲染(Jinja2) | template: src=file.j2 dest=/path/file |
user / group |
用户/组管理 | user: name=john groups=sudo append=yes |
file |
文件/目录属性 | file: path=/dir state=directory mode=0755 |
lineinfile |
文件行管理 | lineinfile: path=/etc/hosts line="127.0.0.1 localhost" |
shell / command |
执行命令 | shell: "df -h" |
setup |
收集事实数据 | ansible new-client -m setup |
group_by |
动态分组 | group_by: key={{ ansible_os_family }} |
任务示例:
5.4 变量与事实数据
| 变量类型 | 定义位置 | 优先级 |
|---|---|---|
| 主机变量 | host_vars/hostname.yml |
最高 |
| 组变量 | group_vars/groupname.yml |
中 |
| 全局变量 | group_vars/all.yml |
低 |
| 剧本内变量 | vars: 或 vars_files: |
覆盖默认 |
事实数据(自动收集):
|
|
常用事实:ansible_os_family、ansible_distribution、ansible_default_ipv4.address
变量引用:{{ variable_name }}
5.5 循环与条件
循环(with_items) :
条件(when) :
5.6 剧本(Playbook)—— 绑定
剧本结构:
|
|
执行:
5.7 角色(Role)—— 操作集
角色目录结构:
roles/
webserver/
defaults/main.yml # 最低优先级变量
vars/main.yml # 固定变量
tasks/main.yml # 主要任务列表
handlers/main.yml # 处理程序
files/ # 静态文件
templates/ # Jinja2模板
meta/main.yml # 依赖关系
使用角色:
安装公共角色(Ansible Galaxy):
|
|
5.8 加密配置(ansible-vault)
5.9 Ansible安全最佳实践(23.5.14节)
| 实践 | 说明 |
|---|---|
| 专用账户 | 每个客户端使用同名专用账户(如ansible) |
| 分离凭证 | SSH私钥口令 ≠ vault口令,单个凭证受损不暴露全部 |
| 禁用密码SSH | PasswordAuthentication no |
| ssh-agent | 管理私钥访问,会话期间只输入一次口令 |
| 避免私钥落地客户端 | 使用ForwardAgent临时转发,不复制私钥 |
6. Salt核心知识
6.1 架构与安装
| 组件 | 说明 |
|---|---|
| Master | 中央配置服务器,TCP端口4505(消息总线)+ 4506(文件服务) |
| Minion | 受管节点,主动连接master拉取配置 |
| 密钥管理 | minion首次连接需master用salt-key批准 |
安装(Master + Minion) :
配置文件:
- Master:
/etc/salt/master - Minion:
/etc/salt/minion(设置master: salt.example.com)
密钥管理:
6.2 核心概念:Pillar(变量) vs State(操作)
| 概念 | 位置 | 求值 | 用途 |
|---|---|---|---|
| Pillar | /srv/pillar/ |
Master端 | 存储变量、密码、配置数据(每个minion看到不同内容) |
| State | /srv/salt/ |
Minion端 | 定义期望状态(操作列表) |
Pillar/State根目录配置(/etc/salt/master):
6.3 绑定(top.sls)
State绑定(/srv/salt/top.sls):
Pillar绑定(/srv/pillar/top.sls):
6.4 Minion匹配类型(表23.5)
| 类型 | 语法 | 示例 |
|---|---|---|
| 扩展匹配(默认) | glob |
'*.example.com' |
| 正则表达式 | E@ |
E@web-\d+\.example\.com |
| Grain匹配 | G@ |
G@os:Ubuntu |
| Pillar匹配 | I@ |
I@role:database |
| 列表 | L@ |
L@host1,host2,host3 |
| 复合匹配 | compound |
not G@os_family:RedHat |
查看grain/pillar:
6.5 State文件(.sls)语法
示例(安装sudo并配置sudoers):
|
|
依赖关系:require(前驱必须成功)、watch(变更时触发重启)
名称简化:状态ID可同时作为操作名:
6.6 Jinja模板与循环
Salt + Jinja原则:尽可能将逻辑放在pillar数据中,而非Jinja代码中。用pillar替代条件判断(见23.6.5节示例)。
6.7 Highstate(执行配置)
6.8 Salt Formulas(操作集)
- 位于
/srv/salt/子目录中的操作集 - 社区仓库:GitHub
salt-formulas组织 - 与Ansible角色不同:Salt formula不可多次实例化(通过pillar数据迭代模拟)
6.9 环境(Environment)与限定(Pinning)
Salt环境(开发/测试/生产)配置在file_roots中定义,minion通过environment设置限定。
| 模式 | 说明 |
|---|---|
| 默认(多环境混合) | minion可接收多个环境的状态(有弗兰肯服务器风险) |
| 限定(Pinned) | minion硬编码到单一环境(更安全,需复制通用配置) |
调试命令:
7. 最佳实践(23.8节)
| 实践 | 说明 |
|---|---|
| 版本控制 | 配置基础库必须置于Git等版本控制之下(CM健全性基本要求) |
| 单一集成仓库 | 避免分散目录/仓库,统一管理简化日常操作 |
| 加密敏感数据 | 密码/密钥禁止明文进入Git(Ansible用vault,Salt用外部工具) |
| 配置服务器加固 | CM服务器拥有root访问权 → 最高安全级别的专用服务器 |
| 幂等性检查 | 确保CM运行时无虚假变更报告(脚本和shell命令是常见问题源) |
| 测试环境隔离 | 用Vagrant/云沙箱测试,绝不在生产环境测试 |
| 细分配置 | 每个文件职责单一清晰 |
| 完全托管状态 | 禁用手动修改/临时禁用CM(避免状态漂移) |
| 与CM集成数据源 | 从LDAP/CMDB等权威来源接入数据,避免信息重复 |
| 弹性环境优化 | 新节点引导时间控制在60s内:预先构建含软件包的镜像,CM只做最后配置 |
8. 本章核心命令速查表
| 命令 | 功能 | 系统 |
|---|---|---|
ansible -m setup host |
查看主机事实数据 | Ansible |
ansible-playbook playbook.yml |
执行剧本 | Ansible |
ansible-playbook playbook.yml -l host |
限制执行主机 | Ansible |
ansible-playbook playbook.yml -t tag |
仅执行特定标签 | Ansible |
ansible-galaxy install role |
安装公共角色 | Ansible |
ansible-vault create/edit/file |
管理加密文件 | Ansible |
salt '*' test.ping |
测试minion连通性 | Salt |
salt-key -l unaccepted |
查看待批准minion | Salt |
salt-key -yA |
批准所有minion | Salt |
salt '*' state.apply |
应用highstate | Salt |
salt 'host' grains.items |
查看grain | Salt |
salt 'host' pillar.items |
查看pillar | Salt |
puppet agent -t |
手动触发Puppet运行 | Puppet |
chef-client |
手动运行Chef | Chef |
knife node list |
列出Chef节点 | Chef |
DBA视角补充:
- CM是DBA运维的“工业化升级”:传统DBA用脚本管理数十台数据库服务器 → CM可管理数百台,且配置可版本控制、可审计、可复用。为不同环境(开发/测试/生产)定义差异化的数据库配置。
- 数据库配置模板化:
my.cnf/postgresql.conf通过模板(Jinja/ERB)根据主机角色(主库/从库、内存大小)动态生成,避免每台手动调优。- Ansible实战价值:因无agent要求,适合快速为现有数据库服务器建立CM(只需SSH+Python)。典型用例:部署
pt-query-digest等监控工具、批量修改数据库参数、自动化备份脚本分发。- 敏感数据管理:数据库密码、SSL证书私钥应通过CM的加密机制(ansible-vault)存储,绝不以明文放入Git。
- 幂等性核心价值:重复运行CM不会破坏已有数据库(如
mysql_user模块检查用户是否存在,不存在才创建),适合CI/CD流水线中的数据库变更管理。- 环境隔离:开发、测试、生产数据库的CM配置使用不同环境(变量不同,如连接字符串、缓冲池大小),确保开发环境误操作不影响生产。
- 迁移现有数据库:将现有“雪花”数据库迁移到CM时,先“捕获”当前配置(如
SHOW VARIABLES),再编写CM代码复现,在测试环境验证后逐步推广。
文章作者 会写代码的小郎中
上次更新 2011-07-04
许可协议 CC BY-NC-ND 4.0