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,结果网络都差点被打满。嗯,后来我不得不改用分批策略,但时间就拉长了。

我的建议:如果你的设备在500台以内,而且网络环境稳定,Ansible是首选。对于密码改造这种需要频繁验证和回滚的场景,它的幂等性帮你省了不少心。你只需要定义好“最终状态”,它就会确保每次执行都一样。

下面是一个简单的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的设计理念是确保配置收敛,但不会帮你记录“上一次是什么状态”。回滚操作需要你自己去写外部脚本或者依赖版本控制。

避坑指南:我曾经在一次密码改造项目中,用了Puppet来修改sshd_config,结果发现因为agent的runinterval默认30分钟,导致密码策略生效滞后了半小时。如果你需要即时生效的场景,请务必调整runinterval或者直接手动触发一次性运行。

4.4 自研脚本:最后的底牌

说实话,不到万不得已,我不建议你直接上自研脚本。很多团队觉得框架太重,自己写个Python脚本多简单。确实,写一个能用的一两百行就够了。但维护呢?异常处理呢?日志记录呢?回滚逻辑呢?

我记得有一次,一个同事用Shell脚本批量替换密码,结果因为一个服务器网络闪断,脚本跳过了一台机器,导致那个节点成了“漏网之鱼”。后来排查发现问题时,已经过了三天。

但自研脚本并非一无是处。当现有框架确实无法满足你的定制化需求时——比如需要对接特定的硬件加密卡接口,或者执行非常规的密码替换逻辑——自研脚本是唯一的选择。

一个相对合格的自研脚本至少应该包含以下模块:

  1. 连接管理:支持重试、超时、并发控制。
  2. 幂等检查:执行前检查是否已经符合目标状态。
  3. 执行日志:记录每一步的输入输出、耗时、异常。
  4. 回滚快照:修改任何文件前,备份原文件到本地和远端。
# 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强管控环境:继续用,但要额外搭建回滚机制。
  • 需要对接专有硬件或软件:自研脚本,但一定要写好回滚。
密码改造工具选型决策流程图 密码改造任务启动 设备数量 > 2000? 推荐:SaltStack 团队熟悉自研? 推荐:Ansible 有回滚/幂等实现能力? 推荐:自研脚本 现有Puppet管控? Puppet + 外部回滚编排 推荐:Ansible 核心原则:先评估规模与能力,再做选择;无论选哪种工具,必须提前编写回滚方案。

这张流程图你多看几遍,基本上就能把工具选型的思路理清了。记住,没有完美的工具,只有合适的方案。你的目标不是学会所有工具,而是找到能帮你最稳、最快完成密码改造的那一个。