如你所见,这基本上是我们最初的file配置块,但是它现在被包在一个class块内,而且helloworld.txt的路径改变了。在Puppet清单中,class块可以用来定义配置块的地方,这样后期可以在其他地方使用这些配置块。file 块并不是 node 定义的一部分,虽然我们把它定义成 node 的一部分,但它还是在那里估算的。类本身并不是做任何事情,只有它在其它地方被声明时,才会有意义。我们可以通过including语句来在node块中声明我们新定义的类:
/etc/puppet/manifests/site.pp on puppetserver
1
2
3
4
5
node "puppetclient" {
include helloworld
}
我们的节点定义现在不直接执行配置块,而只需要引用我们在helloworld类中定义的配置块,这样我们的节点也是新的helloworld模块中的一部分。将helloworld相关的配置都放到一个模块中,给我们带来了非常大的灵活性。设想一下我们有一个包含了成百上千个节点的集群,这些节点都需要接收helloworld配置块,我们可以通过复制-粘贴配置块的方式来实现,但这样在扩展方面不是特别好。然而,helloworld模块是可重用的,任意多数目的节点都可以使用它。
现在我们已经重新组织了现有的配置设置结构,它没有改变实际的配置目录,但是,当我们在puppetclient虚拟机上再次运行代理的话,可以看到:
On the puppetclient VM
第一个真实的模块:apache2
关于那些枯燥的Hello World示例,我已经谈了足够多的内容了,现在让我们在puppetclient客户端建立一个真实的web服务器吧。
我们首先来重命名helloworld模块, 因为我们已经不再需要它了。我们将会使用apache2 Ubuntu包来安装web服务器,这样我们也可以来调用新的apache2模块:
On the puppetserver VM
这看上去和我们之前遇到的file块有点儿像,但还是有一些明显的区别的。它包括了两个新内容:变量和模板(我们后面还会有模板中的变量)。
变量是一个强大的工具,我们可以用它来编写更加智能的清单。如你所见,文件路径通过hostname变量被参数化了,这个变量用来解析目标节点的完全限定域名字(full qualified domain name),对于我们的puppetclient虚拟机来说,主机名字当然就是puppetclient。
On the puppetclient VM
1
2
3
~# hostname
puppetclient
这以为这当我们在目标节点上运行清单文件时,它会创建一个名为/etc/apache2/sites-available/puppetclient.conf文件。
Puppet自己可以决定很多变量的值,hostname只是其中一个,稍后我们会在这个系列中看到如何定义我们自己的变量。
在file块中另外一个区别是content语句,它和我们之前遇到的source语句的不同之处在于,它不会指向一个静态文件,而是一个内嵌的ruby模板。对于静态文件,它只是从puppet master传输到客户端,而对于模板文件来说,它是动态的,可以包含变量和语句,这些变量会被替换成对应的值,而语句则会被执行。
我们可以在puppetserver虚拟机上查看一下/etc/puppet/modules/apache2/templates/etc/apache2/sites-available/vhost.conf.erb文件,以便了解模板文件的结构:
/etc/puppet/modules/apache2/templates/etc/apache2/sites-available/vhost.conf.erb on puppetserver
我们可以在清单中向Puppet解释清单块之间的依赖关系。为了说明针对虚拟机文件的file模块依赖于apache2-mpm-prefork安装结束,我们可以向file块中添加require语句:
/etc/puppet/modules/apache2/manifests/config.pp on puppetserver
info: Caching catalog for puppetclient
info: Applying configuration version '1396980729'
notice: /Stage[main]/Apache2::Install/Package[apache2-utils]/ensure: ensure changed 'purged' to 'present'
notice: /Stage[main]/Apache2::Install/Package[apache2-mpm-prefork]/ensure: ensure changed 'purged' to 'present'
notice: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-available/puppetclient.conf]/ensure: defined content as '{md5}c55c5bd945cea21c817bca1a465b7dd3'
notice: Finished catalog run in 16.62 seconds
好吧,现在可以工作了,但我们现在还没有实现目标。puppetclient虚拟机需要被激活。为了实现这一点,只需要需要一个从 /etc/apache2/sites-enabled/puppetclient.conf 到 /etc/apache2/sites-available/puppetclient.conf的符号链接,我们可以创建另外一个file类型块:
/etc/puppet/modules/apache2/manifests/config.pp on puppetserver
info: Caching catalog for puppetclient
info: Applying configuration version '1396983687'
notice: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-enabled/puppetclient.conf]/ensure: created
notice: Finished catalog run in 0.07 seconds
这样我们就做完了,对吗?好吧,从某种程度上说,是的。我们安装了Apache,配置了虚拟主机。但是,如果使用Puppet,我们可以做得更好。如果手动管理puppetclient,我们会如何做呢?在修改了Apache配置后,我们会测试改动是否有任何错误(使用apachectl configtest),如果没有错误,我们会重启apache2服务。事实证明,Puppet也可以做到这一点。 改进模型
首先,我们需要让Puppet学习apache2服务。为此,我们需要在puppetserver虚拟机上创建另外一个清单文件,这个文件位于/etc/puppet/modules/apache2/manifests/service.pp:
/etc/puppet/modules/apache2/manifests/service.pp on puppetserver
如你所见,Puppet包括了service类型,可以用来处理守护(daemon)应用程序。在这个清单中,我们让Puppet来控制apache2服务。无论何时Puppet代理在目标系统运行,它都会确保这个服务是在运行。同时,Puppet还可以重启服务。在这种情况下,我们甚至可以教会Puppet只有在apachectl configtest运行没有错误时才会重启apache2服务。这样,我们就可以实现自动化的服务管理,而且没有放弃手动管理过程中的安全性检查。
当然,我们需要在主清单文件中声明一个新类:
/etc/puppet/modules/apache2/manifests/init.pp on puppetserver
1
2
3
4
5
6
class apache2 {
include apache2::install
include apache2::config
include apache2::service
}
最后,因为无论何时修改虚拟主机的配置,我们都想触发Apache重启动作,所以我们需要将config清单和service清单连在一起,为此实现这一点,我们可以添加一个notify语句:
/etc/puppet/modules/apache2/manifests/config.pp on puppetserver
现在我们看一下是否可以按照我们期望的那样工作。可以简单的修改一下位于/etc/puppet/modules/apache2/templates/etc/apache2/sites-available/vhost.conf.erb的虚拟主机模板文件(添加一个空格或者空行就可以了),然后在puppetclient虚拟机上重新运行代理,我已经高亮显示了其中值得注意的地方:
On the puppetclient VM
info: Caching catalog for puppetclient
info: Applying configuration version '1396998784'
info: FileBucket adding {md5}c55c5bd945cea21c817bca1a465b7dd3
info: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-available/puppetclient.conf]: Filebucketed /etc/apache2/sites-available/puppetclient.conf to puppet with sum c55c5bd945cea21c817bca1a465b7dd3
notice: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-available/puppetclient.conf]/content: content changed '{md5}c55c5bd945cea21c817bca1a465b7dd3' to '{md5}afafea12b21e61c5e18879ce3fe475d2'
info: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-available/puppetclient.conf]: Scheduling refresh of Service[apache2]
notice: /Stage[main]/Apache2::Service/Service[apache2]: Triggered 'refresh' from 1 events
notice: Finished catalog run in 0.32 seconds
我们也可以检查试下安全机制是否正常工作。再一次编辑虚拟机模板文件,让它变得不正确,例如,可以删掉一个标签的结束符>。
代理会像我们期望的那样处理:
On the puppetclient VM
info: Caching catalog for puppetclient
info: Applying configuration version '1396998943'
info: FileBucket adding {md5}d15f727106b64c29d1c188efc9e6c97d
info: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-available/puppetclient.conf]: Filebucketed /etc/apache2/sites-available/puppetclient.conf to puppet with sum d15f727106b64c29d1c188efc9e6c97d
notice: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-available/puppetclient.conf]/content: content changed '{md5}d15f727106b64c29d1c188efc9e6c97d' to '{md5}7c86c7ba3cd4d7522d36b9d9fdcd46e2'
info: /Stage[main]/Apache2::Config/File[/etc/apache2/sites-available/puppetclient.conf]: Scheduling refresh of Service[apache2]
err: /Stage[main]/Apache2::Service/Service[apache2]: Failed to call refresh: Could not restart Service[apache2]: Execution of '/usr/sbin/apachectl configtest && /usr/sbin/service apache2 reload' returned 1: at /etc/puppet/modules/apache2/manifests/service.pp:10
notice: Finished catalog run in 0.19 seconds