4. 密码改造工具选型:Ansible、SaltStack、Puppet vs 自研脚本
说实话,选工具这事,往往比写代码本身更让人头疼。我见过不少团队,一上来就撸袖子写脚本,到最后维护成本高得吓人。也见过迷信某个自动化框架,结果在改造现场发现水土不服。密码改造这种东西,涉及到的节点多、版本杂、回滚要求严,选错工具的代价可不是多花几天工时那么简单。
我个人习惯把这几个方案放在一张表里看完再定。下面这张表格,把核心的差异点列出来了,你对照着看会更清楚。
| 特性维度 | Ansible | SaltStack | Puppet | 自研脚本 |
|---|---|---|---|---|
| 架构模式 | 无代理 (Agentless),SSH直连 | 主从/无代理混合 (ZeroMQ) | 主从架构 (HTTPS) | 无固定架构,取决于实现 |
| 学习曲线 | 低,YAML+Jinja2 | 中,YAML+状态模块 | 高,自研DSL (Puppet语言) | 高,取决于脚本语言 |
| 批量执行速度 | 中,串行/并行依赖SSH | 快,ZeroMQ消息高吞吐 | 慢,Pull模式有周期延迟 | 取决于实现质量 |
| 幂等性 | 强,模块设计哲学 | 强,状态模式保证 | 强,声明式语言保证 | 弱,需要人工编码保证 |
| 执行依赖 | 需Python + SSH服务 | 需Salt Minion (主从模式) | 需Puppet Agent | 需解释器环境 |
| 回滚原生支持 | 无原生,需编排任务 | 无原生,需自定义state | 无原生,资源回收困难 | 完全自定义 |
| 业界案例 | GitHub, Red Hat生态 | LinkedIn, 各大云厂商 | 大型传统企业 | 各类自运维团队 |
4.1 Ansible:上手最快,但别小看它
我第一次用Ansible做密码改造,那感觉真爽。不用在每台机器上装Agent,一条命令推下去,几百台设备就搞定了。它的Playbook语法非常友好,任何一个懂点运维的人,半小时就能看懂核心逻辑。
但是,它的短板也很明显。SSH通道在并发量大的情况下,性能会急速下降。我记得有一次改造两千台设备,Ansible的并发fork开到50,结果网络都差点被打满。嗯,后来我不得不改用分批策略,但时间就拉长了。
下面是一个简单的Playbook例子,用来批量分发并应用新的密码策略:
---
- name: 密码改造 - 修改SSH密码策略
hosts: all
become: yes
tasks:
- name: 确保口令复杂度策略生效
lineinfile:
path: /etc/security/pwquality.conf
regexp: '^minlen'
line: 'minlen = 14'
state: present
- name: 强制用户下次登录修改密码
shell: "chage -d 0 {{ item }}"
loop: "{{ users }}"
when: item != 'root'
这个例子很简单,但原理是一样的:声明你要的结果,而不是过程。
4.2 SaltStack:大规模环境下的利器
如果你管理的设备数量超过两千,甚至上万台,我建议你试试SaltStack。它底层的ZeroMQ消息队列,天生就是为了高吞吐设计的。我在一个大型政务云项目里用过SaltStack做全量密码改造,8,000台虚拟机,一个命令下去,十几分钟就全部结束了。Ansible在那个量级下一小时都跑不完。
不过,SaltStack的部署和维护成本相对更高。你需要维护Salt Master和Minion之间的连接,还要保证消息队列的稳定性。有一次,我因为Minion的证书过期,导致一批节点失联,排查了半天才发现是时间同步的问题。细节真不能忽视。
# state.sls - 检查并更新/etc/shadow中空密码账户
check_empty_password:
cmd.run:
- name: 'awk -F: ''($2 == "") {print $1}'' /etc/shadow | wc -l'
- unless: 'test "$(awk -F: ''($2 == "") {print $1}'' /etc/shadow | wc -l)" -eq 0'
- failhard: True
这个state用来检测并禁止空密码账户,在改造过程中,扫清那些“历史遗留”的弱口令节点非常实用。
4.3 Puppet:声明式鼻祖,但别在回滚上依赖它
Puppet的声明式语言确实优雅,但它太重了。我曾经在一个金融客户那里见过Puppet管理了上万台设备,配置非常规范,但一旦需要紧急回滚,麻烦就来了。Puppet的设计理念是确保配置收敛,但不会帮你记录“上一次是什么状态”。回滚操作需要你自己去写外部脚本或者依赖版本控制。
4.4 自研脚本:最后的底牌
说实话,不到万不得已,我不建议你直接上自研脚本。很多团队觉得框架太重,自己写个Python脚本多简单。确实,写一个能用的一两百行就够了。但维护呢?异常处理呢?日志记录呢?回滚逻辑呢?
我记得有一次,一个同事用Shell脚本批量替换密码,结果因为一个服务器网络闪断,脚本跳过了一台机器,导致那个节点成了“漏网之鱼”。后来排查发现问题时,已经过了三天。
但自研脚本并非一无是处。当现有框架确实无法满足你的定制化需求时——比如需要对接特定的硬件加密卡接口,或者执行非常规的密码替换逻辑——自研脚本是唯一的选择。
一个相对合格的自研脚本至少应该包含以下模块:
- 连接管理:支持重试、超时、并发控制。
- 幂等检查:执行前检查是否已经符合目标状态。
- 执行日志:记录每一步的输入输出、耗时、异常。
- 回滚快照:修改任何文件前,备份原文件到本地和远端。
# Python 伪代码示例:带回滚的密码修改
def update_password(host, user, new_pass):
try:
# 1. 备份当前shadow
ssh.exec_command(f"cp /etc/shadow /etc/shadow.bak.{timestamp}")
# 2. 执行密码修改
ssh.exec_command(f"echo '{user}:{new_pass}' | chpasswd")
# 3. 验证
result = ssh.exec_command("passwd -S {}".format(user))
if "PS" not in result:
raise Exception("密码状态验证失败")
except Exception as e:
# 回滚
ssh.exec_command(f"cp /etc/shadow.bak.{timestamp} /etc/shadow")
log.error(f"回滚完成: {host} - {e}")
return False
return True
4.5 总结:怎么选?
说白了,工具只是手段,思路才是核心。我个人习惯用一张决策图来定方向:
核心判断逻辑:
- 设备量 < 1000 且团队熟悉SSH:选Ansible,快且稳。
- 设备量 > 1000 或网络复杂:选SaltStack,性能优势无可替代。
- 已有Puppet强管控环境:继续用,但要额外搭建回滚机制。
- 需要对接专有硬件或软件:自研脚本,但一定要写好回滚。
这张流程图你多看几遍,基本上就能把工具选型的思路理清了。记住,没有完美的工具,只有合适的方案。你的目标不是学会所有工具,而是找到能帮你最稳、最快完成密码改造的那一个。