本文有感于《精通Puppet配置管理工具》在豆瓣上的某些差评而顺手写的书评。

半路出家

   
  故事要从12年初说起。 
  某天,部门老大让我所在team的老大调研一下当下业界的配置管理工具。于是我的老大给我分配了一个棘手的任务,要求我转型去做devops,并尝试在本季度内使用Puppet来管理现有的IAAS内部平台上的所有业务,工作成果计入KPI。 
   
  于是,我半路出家从dev转成了ops。 
   
  我花了几天的时间把learning Puppet动手练习了一遍,在会使用几个基础的resource type对系统资源进行管理之后,我自觉已经入门了,于是开始找书看,兴奋地发现京东上只有这一本书:精通Puppet配置管理工具。那看来puppet比较简单呀,看完一本书就能精通了。 
   
  起初拿到这本书的时候很兴奋,哟呵,原来这么薄,看完这本书就能成为一名精通puppet的运维人员了。 
   
  前几章比较容易,边看边动手一下就到了第三章。 
  看到第四章就有点瞌睡了,扩展?为什么要做扩展?一台puppet master难道不够吗? 
  第五章更是纳闷,什么是ENC?用site.pp不就可以管理节点了吗? 
  第六章让我困惑不已:什么是配置的导出和存储? 
  第七章是说Puppet的面板,我安装完Puppet dashboard却不知道它由什么用,还有foreman,又是什么? 
  Report是干嘛的,看日志不就行了嘛? 
  ... 
  后面还有一个Marionette Collective? 编排器?这是什么玩意? 
   
  这书搞得我一头雾水,很快就把它丢到了一旁。

实践出真知 

我当时的第一个任务是在青岛IDC部署一套小规模的Openstack集群用于支持内部的开发环境。 
  虽然我从11年开始接触Openstack,但一直围绕对象存储系统(Swift)做研发工作,对于nova和glance了解的不多,好在有大牛的指导和帮助下,我花了一周的时间把每个服务都详细地了解一遍并手动配置成功后,使用puppet对openstack的包,服务,静态配置文件经行了管理。在这个阶段中,我熟悉了puppet 常见的resource的用法,以及C/S架构puppet的配置,但还是属于初级阶段。 
   
  下一个任务仍是与openstack集群部署相关,我发现之前写的puppet代码并不合理: 
  1. 首先配置文件中许多参数是需要配置的,于是我开始研究使用template来替换原先的静态文件。 
  2. 其次其他服务都是手动安装和配置的,比如mysql和rabbitmq,每台机器上还需要安装ntp服务等等。于是我又添加上了管理相关服务的代码。 
  3. 然后我发现把所有的类放到一个module里实在是不太合理,于是开始进行初步的分离,把每个服务都抽象成一个单独的模块,例如puppet-mysql,puppet-openstack等等。 
  在这个阶段,我掌握了如何根据实际情况将逻辑抽象为class,define和module。 
   
  随后,我发现github的puppetlabs project已经有许多比较成熟的module,于是开始使用upstream的代码来替代原先旧有的代码。阅读这些代码使得我掌握了一些新知识,通过阅读这些有经验的puppet程序员编写的代码,我掌握了如何使用逻辑判断,选择器,链式语法,各种数据类型,函数的用法。 
   
 

参与社区

   
  在这个时候,Puppetlabs的Dan Bode在社区发起了一个项目叫做puppet-openstack,目的是使用puppet来完成openstack的部署,最初这个项目大约由8个相关的module组成,参与人员有cisco,red hat等公司的工程师。这个过程中,我学会了如何使用这些模块来管理现有的集群,掌握了如何使用收集器,配置的存储和导出等等一些高级用法。 
   
  在此同时,我又发现其实这些模块并不完美,存在很多的bug,于是我对代码进行了修改,并在本地进行验证后,发送pull request到了puppet社区。社区的人很快就给我回复了,态度很nice,但指出了我非常低级的错误,老外很严谨,小到多一个多行,少一个空格都会在那标记。 
  我在此过程中,逐渐熟悉了puppet的代码风格,学习了在提交代码前如何对puppet代码和erb模板做语法检查,使用puppet-lint对代码风格进行检查。时至今日,我每看到新人写的代码明显带有其他语言引入的奇怪风格时,都会严格地纠正,即使只是一个空格。 
   
  因为openstack是一个迭代频繁的项目,因此配置文件的管理一直是让我们头疼的地方。从最初的模板到后来的concat方式来拼接配置文件,一直没有找到一个可以灵活管理配置文件的方法。后来iweb的magne提了一个patch,使用了自定义resource可以做到对每个选项灵活地管理。在这个过程中,我开始学习如何编写自定义resource,自定义function,自定义facter。 
   
  当时又来了一个新任务,部署一个multi region的openstack集群(6个IDC)。我当时兴冲冲地使用site.pp开始定义每个机房的每台服务器的角色。当我写到第2个机房的时候,site.pp已经突破500行了。于是我开始对site.pp进行分割,使用import函数将每个机房节点的配置划分到一个文件中去。但我很快发现这仍然不适合做大规模的管理,于是我开始拿起这本书研究起ENC来,我编写了一个python脚本使用yaml格式的文件来管理节点的配置。现在仍然存在一个问题,那就是节点的配置和数据都存在一起,并不方便管理,并且好多参数的值其实是相同的,何必要重复定义呢?于是我又开始研究了hiera。 
   
  那时,我是通过中心的一台puppet master节点来管理所有机房,有时会因为cpu跑满,导致complie catalog失败的情况,于是我又拿起了这本开始研究如何做HA。多台puppet master前面加个LB+KeepAlived解决了这个问题。在这个过程中,我掌握了如何解决多master节点的证书配置和证书同步。 
   
  在此过程中,我把对于puppet-openstack的bug修复反馈到了社区,并且开始积极参与社区的ML和IRC中的讨论,涉及puppet的技术细节和openstack业务逻辑的抽象,这对我后来在开发内部项目puppet模块的影响很大。 
  

业务需求

  后来公司开始做一个私有云的项目,有我来负责部署逻辑的实现。 
  私有云部署的要求一是对用户简单,二是速度要快。我开始阅读书上的第七章,使用foreman来做provision,配合puppet来部署。这个阶段,我掌握了运用facter,resource collect and export,将许多变量变为自动设置的。 
   
  当时有一个痛苦的地方是,每次部署的耗时非常久,令老大不满,部署一台all-in-one的节点大约要半小时。我发现造成这个问题的原因是因为使用了storeconfig这一特性,我使用了mysql + mysql2 adapter作为后端存储。在我查阅了资料后发现原来activerecord在3.x已经弃用了,我当时使用的puppet版本是2.7.x,同时,3.x带来的性能提升大约有40%。 
  于是我开始了两个计划: 
  1. 把puppet升级到3.x 
  2. 使用PuppetDB来代替旧有的ActiveRecord 
   
  这个过程中,我掌握了必须要及时了解社区项目的最新进展,去比较版本的新增特性,puppetdb的安装和配置。 
  

核心开发者 

  在这段时间里,我参与了大量的社区开发和代码审查,深入参与每个项目的开发。 
  也许是因为我在社区的良好表现,在13年的5月,我被推选进入了openstack社区puppet-manager-core team,成为了一名core developer。 
   
  我在使用puppet的过程中,开始对puppet的作者Luke Kanies开始感到好奇,为什么他能写成这么NB的CMS呢?于是我花了一周的业余时间,开始阅读相关的资料,博文,采访以及推特,写下了一篇博文: 
  关于puppet不得不说的故事     同时刊登在《码农》第7期 
  
  接着我就更加好奇了,我想了解puppet背后的架构细节和设计哲学,我开始阅读puppet的源码,并在公司内部分享了两篇文章。 
   
  好奇是没有止境的,我开始对CMS背后的原理感到好奇了,开始阅读Cfengine作者的著作以及DSOM等国际会议上相关的论文,同时温习了读研时候学的自动机理论,这时候对于CMS的认识豁然开朗。 
   
  11月的时候,在HK openstack Icehouse summit的puppet-openstack design summit上和社区的core dev碰了面,我见到了team leader Dan Bode, 我的好基友magne,法国小哥EmilienM, PuppetLabs的Chris, packstack的作者dvorak,RH大名鼎鼎的Dan Prince,Cisco的ChamP... 
   
  我们讨论了在 Icehouse release的milestone和各自的分工,很难想象在一年前的我对于Puppet一无所知。 
  

性能优化

  随着模块和节点的增加,Puppet性能成为诟病,常常被站在背后的老大盯到发毛,于是性能优化提上日程。

最初我们使用的版本是2.7.x系列,当时Puppet发布3.2.x,通过测试,我发现在处理catalog的时候,性能提升了近50%,然而当时使用的诸多模块并没有升级到Puppet3,于是花费数天修复所有不兼容的代码。

然而,整体速度并没有很高的提升,原因是在于代码中使用了一些高级特性,这些特性依赖于storeconfig。最初选择ActiveRecord + MySQL的方式来做storeconfigs严重拖了后腿,随后我开始调研PuppetDB+PostgreSQL,性能提升非常明显。

每次Puppetmaster在处理agent的请求时,cpu负载非常高,为了缓解压力,我将消耗CPU运算的ssl证书验证迁移到了负载均衡节点上,使用传统的Web横向扩展将后端扩展到多台Puppetmaster。

  在管理多个机房的时候,我对于使用ssh登陆服务器批量操作puppet运行的方式渐渐不满起来,而puppet kick的主动触发方式在puppet 3.x轰轰烈烈的大讨论中正式被弃用了。

  最初我使用python写了一个叫dispatcher的小工具,后来使用cluster替换了它。ssh在单个机房内的执行时间还算理想,但是跨多个机房的时候,就可能会出现连接超时的情况,另外还有安全隐患。

于是,我发现一个叫Marionette Collective的工具,号称可以做并发执行任务的框架。它使用MQ作为middleware,通过C/S架构实现并发地异步执行多作业,而且支持各种filter,可以自定义plugin等等,在几番测试后,mco替换了原先的ssh工具,大大提高了执行效率。 
   
  

代码重构

  14年春季过后,我开始对以前编写的代码进行重构,理由是不够抽象,参数冗余,不够智能。 
   
  我对于主要业务的逻辑经行了抽象与合并,举例来说:mysql模块负责mysql的安装和配置,galera类负责主主模式的配置,但是它涉及galera包的安装以及大量参数的配置和一些exec类的操作,应该单独划分成一个模块,而主从模式只是my.cnf中部分参数的配置,抽象为一个类更为合理,线上业务的数据库初始化全部抽取称为一个独立的类。 
   
  削减冗余参数是我重构的最大动力,直到今天下班,我把目前线上业务划分成27种角色,大约1200多个参数,实际需要配置的参数只有40个,但仍没有达到我的预期。 
   
  智能化就更有趣了: 
  整个集群的各种角色根据facter自动配置IP,netmask和gateway,如果绑有公网IP,自动配置高级路由。 
  通道机每增加一个用户,他的ssh publickey就会添加到他有权限访问的服务器上。 
  负载均衡每加一个新节点,其他机器会自动更新自己的配置文件。 
  Gaelra集群每添加一台机器会按照正确的顺序启动。 
  在虚拟机上以qemu形式启动虚拟机,在物理机上以kvm启动虚拟机。 
  如果起了网桥,就把绑定网卡的IP去掉。 
   
      

结尾

   
  截止今天晚上12点,我通过git submodule的方式管理着67个puppet module,43698行puppet代码,59868行ruby代码,这还是DSL的代码行数,如果换成python,估计破百万不是问题,看看Canoical的juju就明白了(那玩意真是太扯了)。 
  通过一年多的努力,我实现了自动化地管理开发,测试,线上环境所有物理服务器和虚拟机上的所有业务,即使细小到vim的配置,.bashrc中的环境变量也纳入管理之中。

有人觉得精通puppet配置管理这本书很烂,有人觉得配置管理没有技术含量shell脚本都可以做,又有人... 
   
  我觉得书是死的,人是活的,技术的更迭很快,如果你觊觎靠一本纸质书精通一门技术的话,那就有点滑稽了。这本书的最大优点是在每一个重要领域都给了你一个指引,告诉你puppet能做这件事,至于怎么做,书上蜻蜓点水,怎么做得更好,那就要靠你自己的摸索了。
  
  在我看来, 
  当你带着偏见看待一件事情的时候,或许你还没有了解它。 
  

从入门到精通Puppet的实践之路的更多相关文章

  1. <程序员从入门到精通> -- How

    定位 自己才是职业生涯的管理者,想清楚自己的发展路径: 远期的理想是什么?近期的规划是什么?今日的任务和功课又是什么? 今日之任务或功课哪些有助于近期之规划的实现,而近期之规划是否有利于远期之理想? ...

  2. 从入门到精通C++需要学的10本书

    学习C++从入门到精通的的十本最经典书籍  文章来源中国IT实验室收集整理作者佚名更新时间2009-5-16 12:27:05 保存本文保存本文推荐给好友推荐给好友收藏本页收藏本页 欢迎进入C/C++ ...

  3. Android开发书籍推荐:从入门到精通系列学习路线书籍介绍

    Android开发书籍推荐:从入门到精通系列学习路线书籍介绍 很多时候我们都会不断收到新手的提问"Android开发的经典入门教材和学习路线?"."Android 开发入 ...

  4. Jenkins pipeline 入门到精通系列文章

    Jenkins2 入门到精通系列文章. Jenkins2 下载与启动jenkins2 插件安装jenkins2 hellopipelinejenkins2 pipeline介绍jenkins2 jav ...

  5. Azure Blob Storage从入门到精通

    今天推荐的是一个系列文章,让读者阅读完成后可以对Azure Blob Storage的开发有一个全面的了解,可谓是从入门到精通. Azure在最初的版本里面就提供了非结构化数据的存储服务,也即Blob ...

  6. 学java入门到精通,不得不看的15本书

    学java入门到精通,不得不看的15本书 一.Java编程入门类1.<Java编程思想>2.<Agile Java>中文版 二.Java编程进阶类1.<重构 改善既有代码 ...

  7. Java入门-浅析Java学习从入门到精通【转】

    一. JDK (Java Development Kit)  JDK是整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具和Java基础的类库 ...

  8. 【转载】google搜索从入门到精通

    原文地址:http://www.cnblogs.com/helloIT/articles/5095668.html /***************************************** ...

  9. 2017最新技术java高级架构、千万高并发、分布式集群、架构师入门到精通视频教程

    * { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩展. ...

随机推荐

  1. HTML5教程之html 5 本地数据库(Web Sql Database)

    HTML5的Web SQL Databases(html5 本地数据库)的确很诱惑人,当你发现可以用与mysql查询一样的查询语句来操作本地数据库时,你会发现这东西挺有趣的.今天,我们一起来了解HTM ...

  2. C# 用原生JS进行文件的上传

    1.此文章是用原生JS来进行文件的上传,有两个版本,一个不用ajax,一个用ajax. 1)非AJAX <!DOCTYPE html> <html> <head> ...

  3. 深入浅出React Native 3: 从零开始写一个Hello World

    这是深入浅出React Native的第三篇文章. 1. 环境配置 2. 我的第一个应用 将index.ios.js中的代码全部删掉,为什么要删掉呢?因为我们准备从零开始写一个应用~学习技术最好的方式 ...

  4. 用Ant来做一键部署

    部署Java Web项目到远程服务器上,以前经常用的操作方式: 1.在eclipse上导出项目war包 2.把war包通过ftp方式传到服务器上,比如Tomcat的webapps目录下 3.启动tom ...

  5. 常用SQL Server日期格式化

    Select CONVERT(varchar(100), GETDATE(), 8): 10:57:46 Select CONVERT(varchar(100), GETDATE(), 24): 10 ...

  6. 强大的UML建模工具——StarUML

    用例图: usecase          生成时序图,协作图,活动图等            生成的时序图:           反向工程以及生成代码:          类图:           ...

  7. 克隆机器后eth1变为eth0问题

    1. 清空该文件 2.进入网络配置文件把HADDR 和UUID注释掉,并重启 3.成功修改eth0 4. 4.可以结合这篇帖子来看   http://www.cnblogs.com/zydev/p/4 ...

  8. AngularJs练习Demo6

    @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport&quo ...

  9. Linux使用快捷键,who命令,rm命令,ps命令,cd,命令kill命令,find命令,grep命令,tar命令(gz、tar、bz2),用户管理,vim配置的一部分,相关命令

    1.进入Ubuntu开场后的终端窗口的快捷键是:           ctrl + alt+t:通过这个命令能够打开终端. ctrl + alt+t:通过这个命令能够打开终端. 再开一个tab选项卡式 ...

  10. HashMap分析之红黑树树化过程

    概述 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型.随着JDK(Java Developmet Kit)版本的更新,JDK1.8对HashMap底层的实现进行了优化,例 ...