Puppet:维护运行环境一致性的利器

配置管理工具的定位

每次我提到配置管理工具,有些同学就会问类似的问题:容器化时代和Serverless时代,还需要配置管理工具吗?我们先不去讨论容器化之后是否需要配置管理工具,那什么时候容器能够在全球范围达到100%的普及?什么时候AWS仅提供容器而不再提供虚拟机呢?

之所以会有如上的问题,根源还在于配置管理工具的定位,到底要解决什么问题?配置管理工具的厂商当然希望你什么事情都通过它来实现,在很长时间内,因为市面上没有针对运维各类场景的细分产品,因此配置管理工具就承担了多面手的角色,而随着各类细分产品的逐渐成熟,那些本不适合配置管理工具解决的场景,必然会被逐步替换。举个例子,你可以搜索到很多早期用配置管理工具进行服务部署的教程,但现在讲服务部署,恐怕很少会有人建议你使用配置管理工具了。

那配置管理工具的定位到底是什么呢?个人认为是持续保证运行环境的一致性,主要针对符合幂等性的变更操作,具体解释如下:

  • 持续保证,是要在机器的整个生命周期中始终确保最终结果符合预期,不论是何种原因导致的不同,都能够修正或者至少推送不一致信息出来。如果只是一次性的操作,那直接批量下去即可,哪里需要配置管理工具。
  • 一致性,主要是规模问题,如果只有一台机器,那这台机器就是标准,也就不会用到配置管理工具,因此配置管理工具主要是支持超大规模集群的一致性管理。
  • 符合幂等性的变更操作,也就是无论这些配置在该客户机上执行多少遍,每次的结果都是相同的。举例来说,维护JVM的版本为x.x.x,这类操作,无论执行多少次,结果都是相同的。
  • 运行环境,通俗点就是安装完操作系统之后到部署服务之前这段环节的准备工作,比方说对系统参数进行优化,调整DNS/NTP等的配置,安装一些常用的工具,部署通用的客户端等等。大致的分类可以参考下图。类似于JVM这种和服务强关联的软件,在有些公司会将其定位为程序的一部分放在发布包中,而有的公司则会视其为运行环境的一部分,分类不同而已,起码大家不会把NTP的配置归入到程序包中进行管理而是交由运行环境保障。

市面上,配置管理工具的选择有很多,号称CAPS( Chef 、 Ansible 、 Puppet 、 SaltStack ),我使用Puppet较多,通过在单机上的客户端,可以做到”持续保证运行环境的一致性“。对于工具的选型,如果有几个候选相差不大,那么更适合你的或者说你更容易搞定的,选他就对了。

配置管理工具的解决方案

全球范围内,笔者了解到的一些使用信息:

那为什么还会有公司使用Puppet呢(接下来,我将把配置管理工具替换为Puppet),其实刚刚的定位就可以回答这个问题,持续保证运行环境的一致性。在系统安装阶段,各大公司都会将一些定制化的内容置于安装镜像内,例如常用的软件和工具,客户端,一些调优参数,内核模块等等,从而达到开机即用的要求。但存量问题,如何对已经装机完毕的机器,新增/修改/删除部分配置内容(例如新装各种工具如iotop、iftop),以及说服务器存在安全漏洞,需要紧急修复,这个时候,其实镜像模式都不能很好的解决问题,大部分情况下,还得找运维团队通过Ansible这类批量操作的方式进行处理。

有同学会说,镜像有问题,重新上线镜像就好了,分分钟就能搞定,但是下面的问题大家是否考虑了:

  • 全量更新公司的上百万个容器需要多久时间(这类场景数据一般都不需要移动)
  • 运行容器的宿主机如果全量重装就意味着其上的虚拟机要迁移数据
  • 变更入口无法收敛时,服务器运行时间越久,不一致状态的可能性越高
  • 对于一致性状态的收集和统计

综合上述的原因看,不可变基础设施对于全量上云的公司来讲,或许可以一试,也许有可能实现,但对于云厂商本身或者大厂来讲,追求所谓的不可变基础设施,投入产出可能不成比例。退而求其次,零接触配置(ZTP,Zero Touch Provisioning)其实也挺好的。

基于此,我提出的折中方案是镜像+Puppet+Grafana的组合:

  • 持续将Puppet维护的内容定期推送到镜像当中,尽量减少Puppet的操作场景
  • Puppet的重点从配置管理转变为一致性检查并辅助进行临时性的配置变更
  • 将一致性检查的结果通过Grafana进行展示和监控
  • 对运行环境的变更只能通过镜像和Puppet方式进行

一些可落地的实践

  • 通过Puppet,我们能够确保如下信息持续的一致性
  • 定期收集服务器上的各类基础信息用于一致性监控
  • 各类Agent被成功部署并能正常运行且版本符合预期
  • 系统服务版本、配置和运行状态的统一维护(系统服务如NTP/DNS/YUM)
  • 系统内核参数的统一维护
  • 各类工具和软件均被正确安装且版本符合预期
  • 信任关系的统一维护(避免违规的信任关系建立)
  • UID和GID的统一维护(避免不同机器同一账号的UID不同)
  • 密码和密码强度要求统一维护(提升安全性)
  • 主机名的统一维护
  • /etc/hosts的统一维护,禁止添加任何记录
  • 定期清空Iptables策略
  • 关闭SWAP分区

上述策略的具体配置,可以参考我们开源的内容:

https://github.com/cloud-op/puppet-public

而Puppet官方也给出了一些高频场景(Top 5 Things to Automate Right Now with Puppet,详见参考文档的链接)

  • Task 1: Standardize service accounts
  • Task 2: Cron jobs and scheduled tasks
  • Task 3: Standardize NTP
  • Task 4: Disable Windows shutdown event tracker on non‑production systems
  • Task 5: Standardize MySQL deployments

对于各类信息的一致性监控,两个页面以供参考:

下面的截图是全量服务器的硬件信息的统计

下面的截图是全量服务器的内核参数配置的统计

从以上的截图内容也可以看出,这类信息,不管是服务器还是Docker,随着运行时间的推移,都有可能发生各种变化,在变更入口无法完全收敛的情况下,通过Puppet来维护和统计状态,就变得极为重要了。

最后,对于超大规模集群,也可以参考Puppet官方提供的解决方案,后期我们也会提供国内互联网厂商的解决方案的相关文章。

不一致的影响

问题定位耗时长

很多人都玩过”大家来找茬“,就是在两张相似的图片中将所有的不同点找出来。在工作中,大家来找茬的场景变成了在一万台机器中找出一个不同的机器来,难度和耗时可想而知。如果不巧遇到这类问题,加上支撑工具不完善,想要找出来这种小概率异常的问题,真的是要剥层皮。

缺少权威源

手表定律是指拥有两块以上手表,并不能帮人更准确的判断时间,反而会制造混乱,让看表的人失去对时间的判断。

笔者几年前参加的一个case study(故障复盘)大致情况如下,运维人员长期进行手工上线,有一次误操作,将线上所有服务器的Nginx配置全部删除,相关的配置也没有版本管理,导致服务故障。只能从测试环境为数不多的几台机器上找配置了,但测试环境的配置,每台机器都不一样,也无法判断哪个配置是最新的完整的配置,只能一个个试试碰运气,即使这样,最后也只是勉强恢复服务,依然有很多二级和三级路径的转发规则丢失了。

广义的不一致

除去文中已经提到的运行环境的各种配置可能导致的不一致外,还有一些广义上的不一致的问题,可能会影响服务的可用性,同样需要进行一致性检查:

  • 硬件规格和批次不一致导致的性能不一致,如CPU型号不同,硬盘类型不同,阵列卡/网卡厂商不同
  • 容器规格不同导致的性能不同,如2C4G和4C8G
  • 同一个服务在多个AZ的实例数量不同
  • 底层硬件的配置不同,如BIOS的设置,Raid卡的设置等
  • 服务器所处的网络设备型号不同,带宽不同,延时不同,拥塞程度不同
  • 两个AZ的业务特点不同,如某AZ是下载类业务居多,某AZ是离线计算任务居多,在该AZ的业务都可能会受到不同的影响
  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/eO3dfscjaWQEp5qi70em

扫码关注云+社区

领取腾讯云代金券