• Puppet扩展篇1-自定义fact结合ENC(hirea)的应用实践
  • 一、先来解决节点与类勾连的问题
  • 1、在Master端安装hiera工具
  • 2、编辑hiera主配置文件hiera.yaml
    • 2.1、创建软连接
    • 2.2、编辑hiera.yaml
    • 2.3、创建变量common对应的文件
    • 2.4、创建变量osfamily对应的文件
    • 2.5、创建变量hostname对应的所有节点文件
  • 3、应用hiera变量于Puppetmaster
    • 3.1、将hiera变量应用于site.pp文件中
    • 3.2、将hiera变量应用于模块puppet中
  • 4、测试
    • 4.1、测试classes
    • 4.2、测试hiera变量certname和puppetserver
    • 二、集中管理自定义fact变量
    • 1、在现有facts模块中直接添加
    • 2、添加管理file资源的pp文件
    • 3、创建file资源对应的下载文件
    • 4、应用模块facts至hiera中
    • 5、节点测试

    Puppet扩展篇1-自定义fact结合ENC(hirea)的应用实践

    在大量节点加入Puppet之后,你至少会面临两个比较大的问题:

    1、由于节点数的增多,site.pp文件必然会编写更多的节点条目,以及节点包含的类。假设你用Puppet管理500个节点,存在三种情况:1、所有节点有共同的类,也可以理解为模块;2、所有节点分成了50组,每组节点有不同的应用,每组应用编写一个模块;3、每个节点也应该有一个自己的模块,在这种环境下,可想而知,site.pp文件是多么的复杂,多么的难以维护。

    2、在使用MCO推送更新的时候,后面可以跟上fact变量用于过滤一组节点。而官方给的facter只能满足普遍存在的fact变量,可是,你要对一组节点进行归类怎么办呢,比如有10个节点的应用是Apache,15个节点属于Nginx等,那么就要自定义fact变量。现在面临的问题是,所有节点都要自定义fact变量,又如何做到集中管理呢?

    一、先来解决节点与类勾连的问题

    其实、节点与类之间的勾连,更多时候是要借助ENC(外部节点分类器)来完成,因为puppet软件本身并不具备此类功能。Puppet-dashboard企业版和Foreman已经具备了这方面的功能,而且是图形界面操作,还是很方便的。众所周知,Puppet-dashboard社区版目前最新版本为1.2.23,到目前为止已经有一年多未更新了,可见Puppetlabs的意图很明确,逼着你用企业版。而Foreman部署和使用略复杂些,其次Foreman很重,它的内部并不仅仅是包含puppet还包含了很多其它管理工具,非常庞大,可以酌情考虑使用。接下来要介绍的是官方推荐的hiera软件,一个很强大的ENC,编写的文件只要遵循yaml格式即可,使用非常方便,可惜的是没有图形界面。但这并不代表你不会开发图形界面哦。

    1、在Master端安装hiera工具

    hiera工具和Puppetmaster结合需要通过hiera-puppet工具完成,在puppet-server 3.0.*版本后,这个工具已经集成到了puppet-server安装包中。而我们现在使用的环境仍然是puppet2.7版本,所以需要安装hiera-puppet工具。

    1. [root@puppetmaster RHEL6U4]# yum install hiera hiera-puppet #注意依赖关系
    2. ...
    3. Dependencies Resolved
    4. ===========================================================================
    5. Package Arch Version Repository Size
    6. ===========================================================================
    7. Installing:
    8. hiera noarch 1.3.2-1.el6 rhel-puppet 23 k
    9. hiera-puppet noarch 1.0.0-1.el6 rhel-puppet 14 k
    10. Installing for dependencies:
    11. ruby-irb x86_64 1.8.7.352-7.el6_2 rhel-base 311 k
    12. ruby-rdoc x86_64 1.8.7.352-7.el6_2 rhel-base 375 k
    13. rubygem-json x86_64 1.5.5-1.el6 rhel-puppet 763 k
    14. rubygems noarch 1.3.7-1.el6 rhel-puppet 206 k
    15. Transaction Summary
    16. ===========================================================================
    17. ...

    2、编辑hiera主配置文件hiera.yaml

    2.1、创建软连接

    默认hiera.yaml主配置文件在/etc目录下,为了结合后期版本控制系统集中管理,建议将此文件copy到/etc/puppet目录下,然后创建软连接指向/etc/hiera.yaml即可。

    1. [root@puppetmaster ~]# mv /etc/hiera.yaml /etc/puppet/
    2. [root@puppetmaster ~]# ln -s /etc/puppet/hiera.yaml /etc/hiera.yaml
    3. [root@puppetmaster ~]# ll /etc/hiera.yaml
    4. lrwxrwxrwx 1 root root 22 Apr 20 20:05 /etc/hiera.yaml -> /etc/puppet/hiera.yaml

    2.2、编辑hiera.yaml

    • 添加全局变量common,注释掉defaults、global和clientcert。
    • 添加系统类型变量osfamily
    • 添加主机名变量hostname
    • 添加datadir路径位置,中间用了puppet环境变量,这里的环境变量和puppet应用的环境变量是一致的。如果你只有一种环境,只需要将其中变量去掉即可。

    备注: 以上变量其实就是fact变量。

    1. [root@puppetmaster ~]# vim /etc/puppet/hiera.yaml
    2. ---
    3. :backends:
    4. - yaml
    5. :hierarchy:
    6. # - defaults
    7. # - "%{clientcert}"
    8. - common
    9. - "%{environment}"
    10. - "%{osfamily}"
    11. - "%{hostname}"
    12. # - global
    13. :yaml:
    14. :datadir:"/etc/puppet/environments/%{environment}/hiera"

    hiera主配置文件编写完成之后,需要重启puppetmaster后方可生效。

    1. [root@puppetmaster hiera]# /etc/init.d/puppetmaster restart
    2. Stopping puppetmaster: [ OK ]
    3. Starting puppetmaster: [ OK ]

    2.3、创建变量common对应的文件

    1. [root@puppetmaster hiera]# vim common.yaml
    2. ---
    3. puppetserver:
    4. - 'puppetmaster.kisspuppet.com'

    通过hiera命令测试

    1. [root@puppetmaster ~]# hiera puppetserver environment=kissprd
    2. ["puppetmaster.kisspuppet.com"]
    3. [root@puppetmaster ~]# hiera puppetserver environment=kissdev
    4. nil

    通过以上命令可以得知在环境为kissprd的情况下,puppetserver的变量为puppetmaster.kisspuppet.com,值为nil的意思是不存在。

    2.4、创建变量osfamily对应的文件

    1. [root@agent1 ~]# facter osfamily
    2. RedHat
    3. [root@puppetmaster hiera]# vim RedHat.yaml
    4. ---
    5. classes:
    6. - 'puppet'
    7. - 'yum'

    通过hiera命令测试

    1. [root@puppetmaster hiera]# hiera classes environment=kissprd
    2. nil
    3. [root@puppetmaster hiera]# hiera classes environment=kissprd osfamily=RedHat
    4. ["motd", "puppet", "yum"]
    5. [root@puppetmaster hiera]# hiera classes environment=kissprd osfamily=SLES
    6. nil

    通过以上命令可以得在环境为kissprd,系统为RedHat的情况下,classes的变量为三个值(puppet、yum)。

    2.5、创建变量hostname对应的所有节点文件

    1. [root@agent1 ~]# facter hostname
    2. agent1
    3. [root@puppetmaster hiera]# vim agent1.yaml
    4. ---
    5. classes:
    6. - 'motd'
    7. certname:
    8. - 'agent1_cert.kisspuppet.com'
    9. [root@puppetmaster hiera]# vim agent2.yaml
    10. ---
    11. classes:
    12. - 'motd'
    13. certname:
    14. - 'agent2_cert.kisspuppet.com'
    15. [root@puppetmaster hiera]# vim agent3.yaml
    16. ---
    17. certname:
    18. - 'agent3_cert.kisspuppet.com'

    通过hiera命令测试

    1. [root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent
    2. 1
    3. ["motd"]
    4. [root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent
    5. 2
    6. ["motd"]
    7. [root@puppetmaster hiera]# hiera classes environment=kissprd hostname=agent
    8. 3
    9. nil
    10. [root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent1
    11. ["agent1_cert.kisspuppet.com"]
    12. [root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent2
    13. ["agent2_cert.kisspuppet.com"]
    14. [root@puppetmaster hiera]# hiera certname environment=kissprd hostname=agent3
    15. ["agent3_cert.kisspuppet.com"]

    通过以上命令测试可以得知,系统fact变量hostname为agent1和agent2的情况下,hiera变量classes为motd。certname变量为各自的certname变量。

    3、应用hiera变量于Puppetmaster

    3.1、将hiera变量应用于site.pp文件中

    以前的写法:

    1. [root@puppetmaster ~]# vim /etc/puppet/environments/kissprd/manifests/site.pp
    2. $puppetserver = 'puppetmaster.kisspuppet.com'
    3. class environments{
    4. include puppet,yum
    5. }
    6. node 'puppetmaster_cert.kisspuppet.com'{
    7. include environments
    8. }
    9. node 'agent1_cert.kisspuppet.com'{
    10. include environments,motd
    11. }
    12. node 'agent2_cert.kisspuppet.com'{
    13. include environments,motd
    14. }
    15. node 'agent3_cert.kisspuppet.com'{
    16. include environments
    17. }

    应用了hiera之后的写法:

    1. [root@puppetmaster ~]# vim /etc/puppet/environments/kissprd/manifests/site.pp
    2. $puppetserver = hiera('puppetserver') #引用了hiera中common.yaml中的全局变量puppetserver
    3. node default {
    4. hiera_include('classes') #引用了hiera中osfamily和hostname变量
    5. }

    备注:以后添加节点,只需要编写yaml文件即可,而site.pp文件无需在进行修改。

    3.2、将hiera变量应用于模块puppet中

    未使用hiera之前的编写方式

    1. [root@puppetmaster hiera]# vim /etc/puppet/environments/kissprd/environment/modules/puppet/manifests/params.pp
    2. class puppet::params {
    3. $puppetserver = 'puppetmaster.kisspuppet.com'
    4. $certname = "${::hostname}_cert.kisspuppet.com"
    5. case $operatingsystemmajrelease{
    6. 5: {
    7. $puppet_release = '2.7.23-1.el5'
    8. $facter_release = '1.7.3-1.el5'
    9. }
    10. 6: {
    11. $puppet_release = '2.7.23-1.el6'
    12. $facter_release = '1.7.3-1.el6'
    13. }
    14. default: {
    15. fail("Module puppet is not supported on ${::operatingsystem}")
    16. }
    17. }
    18. }

    应用了hiera变量之后的编写方式

    1. [root@puppetmaster hiera]# vim /etc/puppet/environments/kissprd/environment/modules/puppet/manifests/params.pp
    2. class puppet::params {
    3. $puppetserver = hiera('puppetserver') #应用了hiera全局文件common.yaml中的puppetserver变量
    4. $certname = hiera('certname') #应用了hiera中变量hostname对应的节点文件$hostname.yaml中的certname变量
    5. case $operatingsystemmajrelease{
    6. 5: {
    7. $puppet_release = '2.7.23-1.el5'
    8. $facter_release = '1.7.3-1.el5'
    9. }
    10. 6: {
    11. $puppet_release = '2.7.23-1.el6'
    12. $facter_release = '1.7.3-1.el6'
    13. }
    14. default: {
    15. fail("Module puppet is not supported on ${::operatingsystem}")
    16. }
    17. }
    18. }

    4、测试

    4.1、测试classes

    1. [root@agent1 ~]# puppet agent -t --environment=kissprd
    2. info: Retrieving plugin
    3. info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
    4. info: Caching catalog for agent1_cert.kisspuppet.com
    5. info: Applying configuration version '1398007834'
    6. notice: Hardware-Clock: Sun 20 Apr 2014 11:30:35 PM CST -0.059676 seconds
    7. notice: /Stage[main]/Motd/Notify[ Hardware-Clock: Sun 20 Apr 2014 11:30:35 PM CST -0.059676 seconds]/message: defined 'message' as ' Hardware-Clock: Sun 20 Apr 2014 11:30:35 PM CST -0.059676 seconds'
    8. notice: /Stage[main]/Motd/File[/etc/motd]/content:
    9. --- /etc/motd 2014-04-20 23:30:26.000000000 +0800
    10. +++ /tmp/puppet-file20140420-9781-fm0gig-0 2014-04-20 23:30:37.000000000 +0800
    11. @@ -0,0 +1,3 @@
    12. +-- --
    13. +--------puppet test---------
    14. +-- --
    15. info: FileBucket got a duplicate file {md5}d41d8cd98f00b204e9800998ecf8427e
    16. info: /Stage[main]/Motd/File[/etc/motd]: Filebucketed /etc/motd to puppet with sum d41d8cd98f00b204e9800998ecf8427e
    17. notice: /Stage[main]/Motd/File[/etc/motd]/content: content changed '{md5}d41d8cd98f00b204e9800998ecf8427e' to '{md5}87ea3a1af8650395038472457cc7f2b1'
    18. notice: Finished catalog run in 0.76 seconds
    19. [root@agent1 ~]# cat /etc/motd
    20. -- --
    21. --------puppet test---------
    22. -- --
    23. [root@agent3 ~]# >/etc/motd
    24. [root@agent3 ~]# puppet agent -t --environment=kissprd
    25. info: Retrieving plugin
    26. notice: /File[/var/lib/puppet/lib/facter]/ensure: created
    27. notice: /File[/var/lib/puppet/lib/facter/hwclock.rb]/ensure: defined content as '{md5}d8cc9fe2b349a06f087692763c878e28'
    28. info: Loading downloaded plugin /var/lib/puppet/lib/facter/hwclock.rb
    29. info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
    30. info: Caching catalog for agent3_cert.kisspuppet.com
    31. info: Applying configuration version '1398007834'
    32. notice: Finished catalog run in 0.67 seconds
    33. [root@agent3 ~]# cat /etc/motd
    34. [root@agent3 ~]#

    从以上测试可以得知类motd应用到了agent1并未应用到agent3,说明hiera传输变量正确。

    4.2、测试hiera变量certname和puppetserver

    1. [root@agent3 ~]# vim /etc/puppet/puppet.conf
    2. ### config by puppet ###
    3. [main]
    4. logdir = /var/log/puppet
    5. rundir = /var/run/puppet
    6. ssldir = $vardir/ssl
    7. pluginsync = true
    8. [agent]
    9. classfile = $vardir/classes.txt
    10. localconfig = $vardir/localconfig
    11. # server = puppetmaster.kisspuppet.com #注释掉进行测试
    12. # certname = agent3_cert.kisspuppet.com
    13. runinterval = 10
    14. [root@agent3 ~]# puppet agent -t --environment=kissprd --server=puppetmaster.kisspuppet.com --certname=agent3_cert.kisspuppet.com
    15. info: Retrieving plugin
    16. info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
    17. info: Caching catalog for agent3_cert.kisspuppet.com
    18. info: Applying configuration version '1398008880'
    19. notice: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]/content:
    20. --- /etc/puppet/puppet.conf 2014-04-20 23:46:05.839948111 +0800
    21. +++ /tmp/puppet-file20140420-5618-45rytg-0 2014-04-20 23:48:01.653944253 +0800
    22. @@ -7,6 +7,6 @@
    23. [agent]
    24. classfile = $vardir/classes.txt
    25. localconfig = $vardir/localconfig
    26. -# server = puppetmaster.kisspuppet.com
    27. -# certname = agent3_cert.kisspuppet.com
    28. + server = puppetmaster.kisspuppet.com
    29. + certname = agent3_cert.kisspuppet.com
    30. runinterval = 10
    31. info: FileBucket adding {md5}13430e5962e7584c9422e5adc1f3ba43
    32. info: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]: Filebucketed /etc/puppet/puppet.conf to puppet with sum 13430e5962e7584c9422e5adc1f3ba43
    33. notice: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]/content: content changed '{md5}13430e5962e7584c9422e5adc1f3ba43' to '{md5}23545b7afd09af671920f122a20db952'
    34. info: /Stage[main]/Puppet::Config/File[/etc/puppet/puppet.conf]: Scheduling refresh of Class[Puppet::Service]
    35. info: Class[Puppet::Service]: Scheduling refresh of Service[puppet]
    36. notice: /Service[puppet]: Triggered 'refresh' from 1 events
    37. notice: Finished catalog run in 0.54 seconds
    38. [root@agent3 ~]# cat /etc/puppet/puppet.conf
    39. ### config by puppet ###
    40. [main]
    41. logdir = /var/log/puppet
    42. rundir = /var/run/puppet
    43. ssldir = $vardir/ssl
    44. pluginsync = true
    45. [agent]
    46. classfile = $vardir/classes.txt
    47. localconfig = $vardir/localconfig
    48. server = puppetmaster.kisspuppet.com
    49. certname = agent3_cert.kisspuppet.com
    50. runinterval = 10

    通过以上测试可以得知hiera变量certname和puppetserver传输正常。

    特别说明: 由于hiera定义的变量需要通过转换才能变为puppet能够使用的变量,而这个转换是需要耗费CPU资源的,笔者曾经测试过一组节点(50个)同时传输hiera的变量数超过2000个,出现CPU负载过高的性能瓶颈问题需要特别注意。其次hiera数据除了用yaml格式保存外还可以存放在redis数据库中,这样查询起来性能会高很多,具体可参考官网,《pro puppet 》第二版也有这方面的介绍,可参阅。

    通过以上测试至少解决了两个问题:

    • site.pp编写繁琐复杂的问题。
    • certname名定义问题(可以不适用其他fact变量进行定义,比如不再使用hostname变量,这样做的好处是即使节点hostname名变化也不会影响puppet通信)

    二、集中管理自定义fact变量

    思路: 参考Puppet基础篇10-自定义fact实现的四种方式介绍
    在puppetmaster端编写一个facts模块,传输一个变量文件至节点对应的目录里面,变量文件名可以通过主机名进行定义。

    1、在现有facts模块中直接添加

    之前facts模块中的结构

    1. [root@puppetmaster modules]# tree facts/
    2. facts/
    3. ├── files
    4. ├── lib
    5. └── facter
    6. └── hwclock.rb #通过pluginsync模式发布的自定义fact变量,无需修改
    7. ├── manifests
    8. └── templates
    9. 5 directories, 1 file

    2、添加管理file资源的pp文件

    1. [root@puppetmaster manifests]# vim config.pp #定义file资源
    2. class facts::config{
    3. file{ "/etc/facter/facts.d/$hostname.txt": #文件名称通过变量hostname获取
    4. owner => "root",
    5. group => "root",
    6. mode => 0400,
    7. source => "puppet:///modules/facts/facts.d/$hostname.txt", #文件名称通过节点变量hostname获取
    8. require => Class['facts::exec'],
    9. }
    10. }
    11. [root@puppetmaster manifests]# vim exec.pp #定义可执行资源保证目录 /etc/facter/facts.d 存在
    12. class facts::exec{
    13. exec {"create fact external":
    14. command => "mkdir -p /etc/facter/facts.d ",
    15. path => ["/usr/bin","/usr/sbin","/bin","/sbin"],
    16. creates => "/etc/facter/facts.d",
    17. }
    18. }
    19. [root@puppetmaster manifests]# vim init.pp
    20. class facts{
    21. include facts::config,facts::exec
    22. }

    3、创建file资源对应的下载文件

    1. [root@puppetmaster facts.d]# pwd
    2. /etc/puppet/environments/kissprd/environment/modules/facts/files/facts.d
    3. [root@puppetmaster facts.d]# vim agent1.txt
    4. env=prd
    5. app=weblogic
    6. [root@puppetmaster facts.d]# vim agent2.txt
    7. env=qa
    8. app=db2
    9. [root@puppetmaster facts.d]# vim agent3.txt
    10. env=prd
    11. app=nginx

    4、应用模块facts至hiera中

    由于模块facts属于全局的,应用于common.ymal或者RedHat.ymal中即可。

    1. [root@puppetmaster hiera]# vim RedHat.yaml
    2. ---
    3. classes:
    4. - 'puppet'
    5. - 'yum'
    6. - 'facts'

    5、节点测试

    1. [root@agent3 ~]# ll /etc/facter/facts.d
    2. ls: cannot access /etc/facter/facts.d: No such file or directory
    3. [root@agent3 ~]# puppet agent -t --environment=kissprd
    4. info: Retrieving plugin
    5. info: Loading facts in /var/lib/puppet/lib/facter/hwclock.rb
    6. info: Caching catalog for agent3_cert.kisspuppet.com
    7. info: Applying configuration version '1398010573'
    8. notice: /Stage[main]/Facts::Exec/Exec[create fact external]/returns: executed successfully
    9. notice: /Stage[main]/Facts::Config/File[/etc/facter/facts.d/agent3.txt]/ensure: defined content as '{md5}3330b8efe95f6747de47a9eca3a5411e'
    10. notice: Finished catalog run in 0.66 seconds
    11. [root@agent3 ~]# cat /etc/facter/facts.d/agent3.txt
    12. env=prd
    13. app=nginx
    14. [root@agent3 ~]# facter env
    15. prd
    16. [root@agent3 ~]# facter app
    17. nginx

    其它节点测试略

    注意:以上方法只是提供给你一种集中管理自定义fact的思路,并不是最好的解决方案,只不过这种方法目前笔者用于上产环境中感觉还不错,特此分享。