Puppet 简明教程

Puppet - Facter & Facts

Puppet 支持将多个值作为环境变量保存。此功能在 Puppet 中使用 facter 提供支持。在 Puppet 中,facter 是一个独立工具,用于保存环境级别变量。In 可以将其视为 Bash 或 Linux 的 env 变量类似。有时,存储在事实和机器环境变量中的信息之间可能存在重叠。在 Puppet 中,键值对称为“事实”。每个资源都有其自己的事实,并且在 Puppet 中,用户有权构建自己的自定义事实。

Puppet supports holding multiple values as an environment variable. This feature is supported in Puppet by using facter. In Puppet, facter is a standalone tool that holds the environment level variable. In can be considered similar to env variable of Bash or Linux. Sometimes there can be an overlap between the information stored in facts and environment variable of the machine. In Puppet, the key-value pair is known as “fact”. Each resource has its own facts and in Puppet the user has the leverage to build their own custom facts.

# facter

Facter command 可用于列出所有不同的环境变量及其关联值。这些事实集合随 facter 即用型提供,并称为核心事实。可以向集合中添加自定义事实。

Facter command can be used to list all the different environment variables and its associated values. These collection of facts comes with facter out-of-the-box and are referred to as core facts. One can add custom facts to the collection.

如果只想查看一个变量。可以使用以下命令完成。

If one wants to view only one variable. It can be done using the following command.

# facter {Variable Name}

Example
[root@puppetmaster ~]# facter virtual
virtualbox

facter 对 Puppet 很重要的原因是 facter 和事实作为 “global variable” 在整个 Puppet 代码中可用,这意味着它可以在任何时间在代码中使用,而无需任何其他引用。

The reason why facter is important for Puppet is that facter and facts are available throughout Puppet code as “global variable”, which means it can be used in the code at any point of time without any other reference.

Example to Test

[root@puppetmaster modules]# tree brcle_account
brcle_account
└── manifests  └── init.pp [root@puppetmaster modules]# cat brcle_account/manifests/init.pp
class brcle_account {
   user { 'G01063908':
      ensure => 'present',
      uid => '121',
      shell => '/bin/bash',
      home => '/home/G01063908',
   }

   file {'/tmp/userfile.txt':
      ensure => file,
      content => "the value for the 'OperatingSystem' fact is: $OperatingSystem \n",
   }
}

Testing It

[root@puppetmaster modules]# puppet agent --test
Notice: /Stage[main]/Activemq::Service/Service[activemq]/ensure:
ensure changed 'stopped' to 'running'
Info: /Stage[main]/Activemq::Service/Service[activemq]:
Unscheduling refresh on Service[activemq]

Notice: Finished catalog run in 4.09 seconds
[root@puppetmaster modules]# cat /tmp/testfile.txt
the value for the 'OperatingSystem' fact is: Linux

[root@puppetmaster modules]# facter OperatingSystem
Linux

正如我们可以在上面的代码片段中注意到的,我们没有定义 OperatingSystem 。我们刚刚用 $OperatingSystem 作为普通变量替换了具有软编码值的值。

As we can notice in the above code snippet, we haven’t defined the OperatingSystem. We have just replaced the value with soft coded value $OperatingSystem as normal variable.

在 Puppet 中,可以使用和定义三种类型的 facts -

In Puppet, there are three types of fact that can be used and defined −

  1. Core Facts

  2. Custom Facts

  3. External Facts

核心事实是在顶层定义的,并且可以在代码中的任何点供所有人访问。

Core facts are defined at the top level and accessible to all at any point in the code.

Puppet Facts

就在代理从主服务器请求编目之前,代理首先以键值对的形式编译一个自身中可用信息的完整列表。有关代理的信息由称为 facter 的工具收集,并且每个键值对被称为事实。以下是代理上事实的常见输出。

Just before an agent requests for a catalog from the master, the agent first compiles a complete list of information available in itself in the form of a key value pair. The information on the agent is gathered by a tool called facter and each key-value pair is referred as a fact. Following is a common output of facts on an agent.

[root@puppetagent1 ~]# facter
architecture => x86_64
augeasversion => 1.0.0
bios_release_date => 13/09/2012
bios_vendor => innotek GmbH
bios_version => VirtualBox
blockdevice_sda_model => VBOX HARDDISK
blockdevice_sda_size => 22020587520
blockdevice_sda_vendor => ATA
blockdevice_sr0_model => CD-ROM
blockdevice_sr0_size => 1073741312
blockdevice_sr0_vendor => VBOX
blockdevices => sda,sr0
boardmanufacturer => Oracle Corporation
boardproductname => VirtualBox
boardserialnumber => 0

domain => codingbee.dyndns.org
facterversion => 2.1.0
filesystems => ext4,iso9660
fqdn => puppetagent1.codingbee.dyndns.org
hardwareisa => x86_64
hardwaremodel => x86_64
hostname => puppetagent1
id => root
interfaces => eth0,lo
ipaddress => 172.228.24.01
ipaddress_eth0 => 172.228.24.01
ipaddress_lo => 127.0.0.1
is_virtual => true
kernel => Linux
kernelmajversion => 2.6
kernelrelease => 2.6.32-431.23.3.el6.x86_64
kernelversion => 2.6.32
lsbdistcodename => Final
lsbdistdescription => CentOS release 6.5 (Final)
lsbdistid => CentOS
lsbdistrelease => 6.5
lsbmajdistrelease => 6
lsbrelease => :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0noarch:graphics-4.0-amd64:
graphics-4.0-noarch:printing-4.0-amd64:printing-4.0noarch
macaddress => 05:00:22:47:H9:77
macaddress_eth0 => 05:00:22:47:H9:77
manufacturer => innotek GmbH
memoryfree => 125.86 GB
memoryfree_mb => 805.86
memorysize => 500 GB
memorysize_mb => 996.14
mtu_eth0 => 1500
mtu_lo => 16436
netmask => 255.255.255.0
netmask_eth0 => 255.255.255.0

network_lo => 127.0.0.0
operatingsystem => CentOS
operatingsystemmajrelease => 6
operatingsystemrelease => 6.5
osfamily => RedHat
partitions => {"sda1"=>{
"uuid"=>"d74a4fa8-0883-4873-8db0-b09d91e2ee8d", "size" =>"1024000",
"mount" => "/boot", "filesystem" => "ext4"}, "sda2"=>{"size" => "41981952",
"filesystem" => "LVM2_member"}
}
path => /usr/lib64/qt3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
physicalprocessorcount => 1
processor0 => Intel(R) Core(TM) i7 CPU         920  @ 2.67GHz
processor1 => Intel(R) Core(TM) i7 CPU         920  @ 2.67GHz
processor2 => Intel(R) Core(TM) i7 CPU         920  @ 2.67GHz
processorcount => 3
productname => VirtualBox
ps => ps -ef
puppetversion => 3.6.2
rubysitedir => /usr/lib/ruby/site_ruby/1.8
rubyversion => 1.8.7
selinux => true
selinux_config_mode => enforcing
selinux_config_policy => targeted
selinux_current_mode => enforcing
selinux_enforced => true
selinux_policyversion => 24
serialnumber => 0
sshdsakey => AAAAB3NzaC1kc3MAAACBAK5fYwRM3UtOs8zBCtRTjuHLw56p94X/E0UZBZwFR3q7
WH0x5+MNsjfmdCxKvpY/WlIIUcFJzvlfjXm4qDaTYalbzSZJMT266njNbw5WwLJcJ74KdW92ds76pjgm
CsjAh+R9YnyKCEE35GsYjGH7whw0gl/rZVrjvWYKQDOmJA2dAAAAFQCoYABgjpv3EkTWgjLIMnxA0Gfud
QAAAIBM4U6/nerfn6Qvt43FC2iybvwVo8ufixJl5YSEhs92uzsW6jiw68aaZ32q095/gEqYzeF7a2knr
OpASgO9xXqStYKg8ExWQVaVGFTR1NwqhZvz0oRSbrN3h3tHgknoKETRAg/imZQ2P6tppAoQZ8wpuLrXU
CyhgJGZ04Phv8hinAAAAIBN4xaycuK0mdH/YdcgcLiSn8cjgtiETVzDYa+jF
swapfree => 3.55 GB
swapfree_mb => 2015.99
swapsize => 3.55 GB
swapsize_mb => 2015.99
timezone => GMT
type => Other
uniqueid => a8c0af01
uptime => 45:012 hours
uptime_days => 0
uptime_hours => 6
uptime_seconds => 21865
uuid => BD8B9D85-1BFD-4015-A633-BF71D9A6A741
virtual => virtualbox

在上面的代码中,我们可以看到一些数据与 bash“env”变量中可用的一些信息重叠。Puppet 直接不使用数据,而是使用 facter 数据,Facter 数据被视为全局变量。

In the above code, we can see some of the data overlap with few of the information available in bash “env” variable. Puppet directly does not use the data, instead it makes use of facter data, Facter data is treated as global variable.

然后事实可用作顶层变量,并且 Puppet 主服务器可以使用它们为请求代理编译 Puppet 编目。Facter 在清单中作为带 $ 前缀的普通变量调用。

The facts are then available as top level variable and the Puppet master can use them to compile the Puppet catalog for the requesting agent. Facters are called in manifest as normal variable with $ prefix.

Example

if ($OperatingSystem == "Linux") {
   $message = "This machine OS is of the type $OperatingSystem \n"
} else {
   $message = "This machine is unknown \n"
}

file { "/tmp/machineOperatingSystem.txt":
   ensure => file,
   content => "$message"
}

上述清单文件只涉及一个名为 machineOperatingSystem.txt 的文件,其中此文件的内容由 OperatingSystem 事实隐含。

The above manifest file only bothers about a single file called machineOperatingSystem.txt, where the content of this file is deducted by the fact called OperatingSystem.

[root@puppetagent1 /]# facter OperatingSystem
Linux

[root@puppetagent1 /]# puppet apply /tmp/ostype.pp
Notice: Compiled catalog for puppetagent1.codingbee.dyndns.org
in environment production in 0.07 seconds
Notice: /Stage[main]/Main/File[/tmp/machineOperatingSystem.txt]/ensure:
defined content as '{md5}f59dc5797d5402b1122c28c6da54d073'
Notice: Finished catalog run in 0.04 seconds

[root@puppetagent1 /]# cat /tmp/machinetype.txt
This machine OS is of the type Linux

Custom Facts

我们所看到的上述所有事实是机器的核心事实。可以通过以下途径向节点添加此自定义事实:

All the above facts that we have seen are the core facts of the machine. One can add this custom facts to the node in the following ways −

  1. Using the “export FACTER … Syntax”

  2. Using the $LOAD_PATH settings

  3. FACTERLIB

  4. Pluginsync

Using the “export FACTER” Syntax

可以使用 export FACTER_{fact 的名称} 语法手动添加事实。

One can manually add the facts using the export FACTER_{fact’s name} syntax.

Example

[root@puppetagent1 facter]# export FACTER_tallest_mountain="Everest"
[root@puppetagent1 facter]# facter tallest_mountain Everest

Using the $LOAD_PATH Settings

在 Ruby 中,$LOAD_PATH 等同于 Bash 特殊参数。虽然它类似于 bash $PATH 变量,但实际上 $LOAD_PATH 不是一个环境变量,而是一个预定义变量。

In Ruby, $LOAD_PATH is equivalent to Bash special parameter. Although it is similar to bash $PATH variable, in real facts $LOAD_PATH is not an environment variable, instead it is a pre-defined variable.

$LOAD_PATH 有一个同义词“$:”。此变量是一个查找并加载值 的数组。

$LOAD_PATH has a synonym “$:”. This variable is an array to search and load the values.

[root@puppetagent1 ~]# ruby -e 'puts $LOAD_PATH'
# note you have to use single quotes.
/usr/lib/ruby/site_ruby/1.6
/usr/lib64/ruby/site_ruby/1.6
/usr/lib64/ruby/site_ruby/1.6/x86_64-linux
/usr/lib/ruby/site_ruby
/usr/lib64/ruby/site_ruby
/usr/lib64/site_ruby/1.6
/usr/lib64/site_ruby/1.6/x86_64-linux
/usr/lib64/site_ruby
/usr/lib/ruby/1.6
/usr/lib64/ruby/1.6
/usr/lib64/ruby/1.6/x86_64-linux

我们举一个创建 facter 目录并为其添加 .pp 文件及为其添加内容的示例。

Let’s take an example of creating a directory facter and adding a .pp file and appending a content to it.

[root@puppetagent1 ~]# cd /usr/lib/ruby/site_ruby/
[root@puppetagent1 site_ruby]# mkdir facter
[root@puppetagent1 site_ruby]# cd facter/
[root@puppetagent1 facter]# ls
[root@puppetagent1 facter]# touch newadded_facts.rb

将以下内容添加到 custom_facts.rb 文件。

Add the following content to the custom_facts.rb file.

[root@puppetagent1 facter]# cat newadded_facts.rb
Facter.add('tallest_mountain') do
   setcode "echo Everest"
end

Facter 使用扫描 $LOAD_PATH 中列出的所有文件夹的方式工作,并查找名为 facter 的目录。一旦它找到该特定文件夹,它将加载文件夹结构中的任何位置。如果它找到此文件夹,则在该 facter 文件夹中查找任何 Ruby 文件并加载关于内存中特定配置的所有已定义事实。

Facter works in the method of scanning through all the folder listed in $LOAD_PATH, and looks for a director called facter. Once it finds that particular folder, it will load them anywhere in the folder structure. If it finds this folder then it looks for any Ruby file in that facter folder and loads all the defined facts about any particular configuration in the memory.

Using FACTERLIB

在 Puppet 中,FACTERLIB 的工作方式与 $LOAD_PATH 非常相似,但只有一个关键区别,即它是一个操作系统级别的环境参数,而不是一个 Ruby 特殊变量。默认情况下,可能未设置环境变量。

In Puppet, FACTERLIB works very much similar to $LOAD_PATH but with only one key difference that, it is a OS level environment parameter rather than a Ruby special variable. By default, the environment variable may not be set.

[root@puppetagent1 facter]# env | grep "FACTERLIB"
[root@puppetagent1 facter]#

要测试 FACTERLIB,我们需要执行以下步骤。

To test FACTERLIB, we need to perform the following steps.

在以下结构中创建一个名为 test_facts 的文件夹。

Create a folder called test_facts in the following structure.

[root@puppetagent1 tmp]# tree /tmp/test_facts/
/tmp/some_facts/
├── vipin
│   └── longest_river.rb
└── testing
   └── longest_wall.rb

将以下内容添加到 .rb 文件。

Add the following contents to the .rb files.

[root@puppetagent1 vipin]# cat longest_river.rb
Facter.add('longest_river') do
   setcode "echo Nile"
end

[root@puppetagent1 testing]# cat longest_wall.rb
Facter.add('longest_wall') do
   setcode "echo 'China Wall'"
end

使用导出语句。

Use the export statement.

[root@puppetagent1 /]# export
FACTERLIB = "/tmp/some_facts/river:/tmp/some_facts/wall"
[root@puppetagent1 /]# env | grep "FACTERLIB"
FACTERLIB = /tmp/some_facts/river:/tmp/some_facts/wall

测试新的 facter。

Test the new facter.

[root@puppetagent1 /]# facter longest_river
Nile
[root@puppetagent1 /]# facter longest_wall
China Wall

External Facts

当用户想要应用在供应时间创建的一些新事实时,外部事实非常有用。外部事实是应用元数据到虚拟机供应阶段的一种主要方式(例如使用 vSphere、OpenStack、AWS 等)。

External facts are very useful when the user wishes to apply some new facts created at the provisioning time. External facts are one of the key ways of applying metadata to a VM at its provisioning stage (e.g. using vSphere, OpenStack, AWS, etc.)

Puppet 可以使用创建的所有元数据及其详细信息来确定目录中应包含哪些信息,而这将被应用。

All the metadata and its details created can be used by Puppet to determine what details should be present in the catalog, which is going to be applied.

Creating an External Fact

在代理机器上,我们需要创建一个目录,如下所述。

On the agent machine, we need to create a directory as mentioned below.

$ mkdir -p /etc/facter/facts.d

带着以下内容在目录中创建一个 Shell 脚本。

Create a Shell script in the directory with the following content.

$ ls -l /etc/facter/facts.d
total 4
-rwxrwxrwx. 1 root root 65 Sep 18 13:11 external-factstest.sh
$ cat /etc/facter/facts.d/external-factstest.sh
#!/bin/bash
echo "hostgroup = dev"
echo "environment = development"

更改脚本文件权限。

Change the permission of the script file.

$ chmod u+x /etc/facter/facts.d/external-facts.sh

完成后,我们现在可以看到存在带有键/值对的变量。

Once done, we can now see the variable present with the key/value pair.

$ facter hostgroup
dev
$ facter environment
development

人们可以在 Puppet 中编写自定义事实。作为参考,请从 Puppet 网站使用以下链接。

One can write custom facts in Puppet. As a reference, use the following link from the Puppet site.