在写这篇blog前,我的心情久久不能平静,虽然明白运维工作如履薄冰,但没有料到这么一个细小的疏漏会带来如此严重的灾难。这是一起其他公司误用puppet参数引发的事故,而且这个参数我也曾被“坑过”。
0. 一个purge参数引发的事故
file {'/var/lib/data_directory': xxxx => xxx, ......
recurse => true, purge => true }
1. 语法检查
puppet parser validate logserver.pp Error: Could not parse for environment production: Syntax error at 'eth0_netmask' at sunfire/manifests/logserver.pp:6:3
route-eth.erb:1: syntax error, unexpected '<' <%= @internal_network %> via <%= @internal_gateway %> ^
2. 代码风格检查
puppet-lint manifests/init.pp WARNING: class inheriting from params class on line 339 WARNING: line has more than 80 characters on line 47 WARNING: line has more than 80 characters on line 167
puppet-lint --no-80chars-check /path/to/my/manifest.pp
3. 模块测试
it { should contain_package('keystone').with( 'ensure' => param_hash['package_ensure'] ) } it { should contain_group('keystone').with( 'ensure' => 'present', 'system' => true ) } it { should contain_user('keystone').with( 'ensure' => 'present', 'gid' => 'keystone', 'system' => true ) }
随后执行rspec来验证这些测试能否通过。
如果希望集成到rake命令中去,我们可以在Rakefile里添加:
require 'puppetlabs_spec_helper/rake_tasks'
随后使用以下命令来完成相应的spec执行模块测试:
rake spec # Run spec tests in a clean fixtures directory rake spec_clean # Clean up the fixtures directory rake spec_prep # Create the fixtures directory rake spec_standalone # Run spec tests on an existing fixtures directory
因此,在使用从github或者puppetforge下载的module时,阅读README和测试用例是非常重要的,如果我当时仔细阅读了apache::init的测试用例,也不会出现所谓被坑的问题,因为人家明明在apache_spec.rb里写有对/etc/apache/sites-enabled目录的测试:
it { should contain_file("/etc/httpd/conf.d").with( 'ensure' => 'directory', 'recurse' => 'true', 'purge' => 'true', 'notify' => 'Class[Apache::Service]', 'require' => 'Package[httpd]' ) }
所以说,其实并不存在坑,只是因为在使用他人编写的模块前没有去阅读其文档和测试,完全可以避免的。
4.开发环境和测试环境的验证
最终部署逻辑能否上线到生产环境,还需要在开发环境和测试环境进行验证。可以使用目前流行的vagrant,Openstack等工具搭建一个测试平台,调用API创建符合生产环境的集群,通过puppet做软件安装和配置,验证部署逻辑是否符合预期。开发环境和测试环境的不同点在于,测试环境的所有变更与线上环境完全一致,不允许有任何的人工干预。
至此,一个通过验证的puppet部署逻辑可以release了,打上tag,可以准备发布到线上了。当然不能少了线上变更流程,写下在此次线上变更的详细操作以及回滚机制。
尾声
故事的尾声,我想告诉大家不幸中的万幸,那个可怜的同学,最终找回了大部分的数据。