Puppet 简明教程
Puppet - Overview
Puppet 是由 Puppet Labs 开发的一个配置管理工具,用于自动化基础设施管理和配置。Puppet 是一个非常强大的工具,有助于实现“基础设施即代码”的概念。该工具是用 Ruby DSL 语言编写的,这有助于将完整的基础设施转换为代码格式,以便于管理和配置。
Puppet is a configuration management tool developed by Puppet Labs in order to automate infrastructure management and configuration. Puppet is a very powerful tool which helps in the concept of Infrastructure as code. This tool is written in Ruby DSL language that helps in converting a complete infrastructure in code format, which can be easily managed and configured.
Puppet 遵循客户端-服务器模型,其中任何集群中的一台机器充当服务器(称为 puppet 主服务器),而另一台则充当客户端(称为节点上的从服务器)。Puppet 有能力从头开始管理任何系统,从初始配置到任何特定机器的生命周期结束。
Puppet follows the client-server model, where one machine in any cluster acts as the server, known as puppet master and the other acts as a client known as a slave on nodes. Puppet has the capability to manage any system from scratch, starting from initial configuration till the end-of-life of any particular machine.
Features of Puppet System
以下是 Puppet 最重要的功能。
Following are the most important features of Puppet.
Idempotency
Puppet 具有使其独一无二的幂等性支持。与 Chef 类似,在 Puppet 中,人们可以在同一台机器上多次安全地运行同一组配置。在此流程中,Puppet 会检查目标机器的当前状态,并且仅在配置中有任何特定更改时才会进行更改。
Puppet supports Idempotency which makes it unique. Similar to Chef, in Puppet, one can safely run the same set of configuration multiple times on the same machine. In this flow, Puppet checks for the current status of the target machine and will only make changes when there is any specific change in the configuration.
幂等性有助于在机器整个生命周期内管理任何特定机器,从创建机器、机器中的配置更改,直至使用寿命结束。当有任何配置更改时,Puppet 幂等性功能非常有助于保持机器更新多年,而不必多次重建同一台机器。
Idempotency helps in managing any particular machine throughout its lifecycle starting from the creation of machine, configurational changes in the machine, till the end-of-life. Puppet Idempotency feature is very helpful in keeping the machine updated for years rather than rebuilding the same machine multiple times, when there is any configurational change.
Cross-platform
在 Puppet 中,借助使用 Puppet 资源的资源抽象层 (RAL),人们可以针对系统的指定配置,而不用担心实现细节和配置命令将在系统内部如何工作,这些细节在基础配置文件中进行了定义。
In Puppet, with the help of Resource Abstraction Layer (RAL) which uses Puppet resources, one can target the specified configuration of system without worrying about the implementation details and how the configuration command will work inside the system, which are defined in the underlying configuration file.
Puppet − Workflow
Puppet 使用以下工作流将配置应用到系统上。
Puppet uses the following workflow to apply configuration on the system.

-
In Puppet, the first thing what the Puppet master does is to collect the details of the target machine. Using the factor which is present on all Puppet nodes (similar to Ohai in Chef) it gets all the machine level configuration details. These details are collected and sent back to the Puppet master.
-
Then the puppet master compares the retrieved configuration with defined configuration details, and with the defined configuration it creates a catalog and sends it to the targeted Puppet agents.
-
The Puppet agent then applies those configurations to get the system into a desired state.
-
Finally, once one has the target node in a desired state, it sends a report back to the Puppet master, which helps the Puppet master in understanding where the current state of the system is, as defined in the catalog.
Puppet − Key Components
以下列出 Puppet 的关键组件。
Following are the key components of Puppet.

Puppet Resources
Puppet 资源是为任何特定机器建模的关键组件。这些资源有各自的实施模型。Puppet 使用相同的模型以所需的某个状态获取任何特定资源。
Puppet resources are the key components for modeling any particular machine. These resources have their own implementation model. Puppet uses the same model to get any particular resource in the desired state.
Providers
提供程序基本上是 Puppet 中使用的任何特定资源的满足者。例如,软件包类型“apt-get”和“yum”都适用于软件包管理。有时候,在特定平台上会提供多个提供程序。虽然每个平台始终都有一个默认提供程序。
Providers are basically fulfillers of any particular resource used in Puppet. For example, the package type ‘apt-get’ and ‘yum’ both are valid for package management. Sometimes, more than one provider would be available on a particular platform. Though each platform always have a default provider.
Manifest
清单是由函数或类内耦合的资源集合,用于配置任何目标系统。它们包含一系列 Ruby 代码,以便配置系统。
Manifest is a collection of resources which are coupled inside the function or classes to configure any target system. They contain a set of Ruby code in order to configure a system.
Modules
模块是 Puppet 的关键构建模块,可以定义为资源、文件、模板等的集合。它们可以轻松地分布在不同类型的操作系统中,因为它们被定义为具有相同性质的。由于它们可以轻松地进行分布,因此可以多次使用具有相同配置的一个模块。
Module is the key building block of Puppet, which can be defined as a collection of resources, files, templates, etc. They can be easily distributed among different kinds of OS being defined that they are of the same flavor. As they can be easily distributed, one module can be used multiple times with the same configuration.
Templates
模板使用 Ruby 表达式来定义自定义内容和变量输入。用于开发自定义内容。模板在清单中进行定义,并复制到系统上的某个位置。例如,如果需要使用自定义端口定义 httpd,那么可以使用以下表达式完成此操作。
Templates use Ruby expressions to define the customized content and variable input. They are used to develop custom content. Templates are defined in manifests and are copied to a location on the system. For example, if one wants to define httpd with a customizable port, then it can be done using the following expression.
Listen <% = @httpd_port %>
在此情形下,httpd_port 变量在引用此模板的清单中进行定义。
The httpd_port variable in this case is defined in the manifest that references this template.
Static Files
静态文件可定义为有时需要执行特定任务的一般文件。可以使用 Puppet 轻松地将它们从一个位置复制到另一个位置。所有静态文件都位于任何模块的 files 目录中。清单中文件的任何操作都使用文件资源来完成。
Static files can be defined as a general file which are sometimes required to perform specific tasks. They can be simply copied from one location to another using Puppet. All static files are located inside the files directory of any module. Any manipulation of the file in a manifest is done using the file resource.
Puppet - Architecture
下列是 Puppet 架构的图表说明。
Following is the diagrammatic representation of Puppet architecture.

Puppet Master
Puppet Master 是处理所有配置相关内容的关键机制。它使用 Puppet 代理对节点应用配置。
Puppet Master is the key mechanism which handles all the configuration related stuff. It applies the configuration to nodes using the Puppet agent.
Puppet Agent
Puppet 代理是实际的工作机器,它们由 Puppet 主机进行管理。它们在内部运行着 Puppet 代理守护程序服务。
Puppet Agents are the actual working machines which are managed by the Puppet master. They have the Puppet agent daemon service running inside them.
Config Repository
这是在需要时,将所有节点和服务器相关配置保存和提取到的存储库。
This is the repo where all nodes and server-related configurations are saved and pulled when required.
Facts
Facts 是与节点或主机器相关的详细信息,这些信息基本上用于分析任何节点的当前状态。在事实的基础上,在任何目标机器上进行变更。在 Puppet 中有预定义事实和自定义事实。
Facts are the details related to the node or the master machine, which are basically used for analyzing the current status of any node. On the basis of facts, changes are done on any target machine. There are pre-defined and custom facts in Puppet.
Puppet - Installation
Puppet 采用客户端-服务器架构,其中我们将服务器称作 Puppet 主服务器,将客户端称作 Puppet 节点。此设置可通过在客户端和所有服务器计算机上安装 Puppet 来实现。
Puppet works on the client server architecture, wherein we call the server as the Puppet master and the client as the Puppet node. This setup is achieved by installing Puppet on both the client and well as on all the server machines.
对于大多数平台,可通过包管理器选择来安装 Puppet。然而,对于少数平台,可通过安装 tarball 或 RubyGems 来操作。
For most of the platforms, Puppet can be installed via the package manager of choice. However, for few platforms it can be done by installing the tarball or RubyGems.
Prerequisites
Factor 是唯一一个与 Ohai 无关的先决条件, Ohai 是 Chef 中的固有要素。
Factor is the only pre-requisite that does not come along with Ohai which is present in Chef.
Standard OS Library
我们需要拥有任何底层操作系统的标准库集。所有剩余的系统都随 Ruby 1.8.2 + 版本一同提供。以下是操作系统应包含的库项目列表。
We need to have standard set of library of any underlying OS. Remaining all the system comes along with Ruby 1.8.2 + versions. Following is the list of library items, which an OS should consist of.
-
base64
-
cgi
-
digest/md5
-
etc
-
fileutils
-
ipaddr
-
openssl
-
strscan
-
syslog
-
uri
-
webrick
-
webrick/https
-
xmlrpc
Facter Installation
如有讨论, facter 不随 Ruby 标准版本一同提供。因此,为了在目标系统中获取 facter,需要从源手动安装它,因为 facter 库是 Puppet 的先决条件。
As discussed, the facter does not come along with the standard edition of Ruby. So, in order to get the facter in the target system one needs to install it manually from the source as the facter library is a pre-requisite of Puppet.
此包面向多个平台提供,但为保险起见,它可使用 tarball 安装,后者有助于获取最新版本。
This package is available for multiple platforms however just to be on the safer side it can be installed using tarball, which helps in getting the latest version.
首先,使用 wget 实用工具从 Puppet 官方网站下载 tarball 。
First, download the tarball from the official site of Puppet using the wget utility.
$ wget http://puppetlabs.com/downloads/facter/facter-latest.tgz ------: 1
下一步,将 tar 文件解压缩。使用 CD 命令进入已解压的目录。最后,使用 facter 目录中现有的 install.rb 文件安装 facter。
Next, un-tar the tar file. Get inside the untarred directory using the CD command. Finally, install the facter using install.rb file present inside the facter directory.
$ gzip -d -c facter-latest.tgz | tar xf - -----: 2
$ cd facter-* ------: 3
$ sudo ruby install.rb # or become root and run install.rb -----:4
Installing Puppet from the Source
首先,使用 wget 从 Puppet 网站安装 Puppet tar 归档。然后,将 tar 归档解压缩到目标位置。使用 CD 命令进入已创建的目录。使用 install.rb 文件,在底层服务器上安装 Puppet。
First, install the Puppet tarball from the Puppet site using wget. Then, extract the tarball to a target location. Move inside the created directory using the CD command. Using install.rb file, install Puppet on the underlying server.
# get the latest tarball
$ wget http://puppetlabs.com/downloads/puppet/puppet-latest.tgz -----: 1
# untar and install it
$ gzip -d -c puppet-latest.tgz | tar xf - ----: 2
$ cd puppet-* ------: 3
$ sudo ruby install.rb # or become root and run install.rb -------: 4
Puppet - Configuration
一旦我们在系统上安装完 Puppet,下一步就是对其进行配置以执行某些初始操作。
Once we have Puppet installed on the system, the next step is to configure it to perform certain initial operations.
Open Firewall Ports on Machines
为了让 Puppet 服务器集中管理客户端服务器,需要在所有机器上打开一个指定端口,即 如果我们在尝试配置的机器上没有使用 8140 ,可以使用它。我们需要在所有机器上启用 TCP 和 UDP 通信。
To make the Puppet server manage the client’s server centrally, one needs to open a specified port on all the machines, i.e. 8140 can be used if it is not in use in any of the machines which we are trying to configure. We need to enable both TCP and UDP communication on all the machines.
Configuration File
Puppet 的主配置文件为 etc/puppet/puppet.conf 。所有配置文件都会在 Puppet 的基于包的配置中创建。在这些文件中保留了配置 Puppet 所需的大部分配置,而且一旦 Puppet 运行开始,它就会自动选取这些配置。但是,对于配置 Web 服务器或外部证书颁发机构 (CA) 等一些特定任务,Puppet 具有用于文件和设置的单独配置。
The main configuration file for Puppet is etc/puppet/puppet.conf. All the configuration files get created in a package-based configuration of Puppet. Most of the configuration which is required to configure Puppet is kept in these files and once the Puppet run takes place, it picks up those configurations automatically. However, for some specific tasks such as configuring a web server or an external Certificate Authority (CA), Puppet has separate configuration for files and settings.
服务器配置文件位于 conf.d 目录中,该目录又称为 Puppet 主控。这些文件默认位于 /etc/puppetlabs/puppetserver/conf.d 路径下。这些配置文件采用 HOCON 格式,该格式保留了 JSON 的基本结构,但更具可读性。当 Puppet 启动时,它会从 conf.d 目录中选取所有 .cong 文件并将它们用于进行任何配置更改。只有在重新启动服务器时,这些文件中的任何更改才会发生。
Server configuration files are located in conf.d directory which is also known as the Puppet master. These files are by default located under /etc/puppetlabs/puppetserver/conf.d path. These config files are in HOCON format, which keeps the basic structure of JSON but it is more readable. When the Puppet startup takes place it picks up all .cong files from conf.d directory and uses them for making any configurational changes. Any changes in these files only takes place when the server is restarted.
List File and Settings File
-
global.conf
-
webserver.conf
-
web-routes.conf
-
puppetserver.conf
-
auth.conf
-
master.conf (deprecated)
-
ca.conf (deprecated)
Puppet 中有不同的配置文件,它们特定于 Puppet 中的每个组件。
There are different configuration files in Puppet which are specific to each component in Puppet.
Puppet.conf
Puppet.conf 文件是 Puppet 的主配置文件。Puppet 使用同一配置文件来配置所有必需的 Puppet 命令和服务。所有 Puppet 相关设置(例如 Puppet 主控、Puppet 代理、Puppet 应用和证书的定义)都在此文件中定义。Puppet 可以根据要求引用它们。
Puppet.conf file is Puppet’s main configuration file. Puppet uses the same configuration file to configure all the required Puppet command and services. All Puppet related settings such as the definition of Puppet master, Puppet agent, Puppet apply and certificates are defined in this file. Puppet can refer them as per requirement.
该配置文件类似于一个标准 ini 文件,其中设置可以进入主部分的特定应用程序部分。
The config file resembles a standard ini file wherein the settings can go into the specific application section of the main section.
Main Config Section
[main]
certname = Test1.vipin.com
server = TestingSrv
environment = production
runinterval = 1h
Puppet Master Config File
[main]
certname = puppetmaster.vipin.com
server = MasterSrv
environment = production
runinterval = 1h
strict_variables = true
[master]
dns_alt_names = MasterSrv,brcleprod01.vipin.com,puppet,puppet.test.com
reports = puppetdb
storeconfigs_backend = puppetdb
storeconfigs = true
environment_timeout = unlimited
Detail Overview
在 Puppet 配置中,要使用的文件有多个配置部分,其中每个部分有多种不同数量的设置。
In Puppet configuration, the file which is going to be used has multiple configuration sections wherein each section has different kinds of multiple number of settings.
Config Section
Puppet 配置文件主要包含以下配置部分。
Puppet configuration file mainly consists of the following config sections.
-
Main − This is known as the global section which is used by all the commands and services in Puppet. One defines the default values in the main section which can be overridden by any section present in puppet.conf file.
-
Master − This section is referred by Puppet master service and Puppet cert command.
-
Agent − This section is referred by Puppet agent service.
-
User − It is mostly used by Puppet apply command as well as many of the less common commands.
[main]
certname = PuppetTestmaster1.example.com
Key Components of Config File
以下是配置文件的主要组件。
Following are the key components of Config file.
Comment Lines
在 Puppet 中,任何注释行都以 ( # ) 符号开头。这可能意指任何数量的空间。我们也可以在同一行中添加部分注释。
In Puppet, any comment line starts with (#) sign. This may intend with any amount of space. We can have a partial comment as well within the same line.
# This is a comment.
Testing = true #this is also a comment in same line
Settings Lines
设置行的语法必须包含:
Settings line must consist of −
-
Any amount of leading space (optional)
-
Name of the settings
-
An equals = to sign, which may be surrounded by any number of space
-
A value for the setting
Setting Variables
在大多数情况下,设置的值是一个单词,但有些特殊情况下,则有几个特殊值。
In most of the cases, the value of settings will be a single word but in some special cases, there are few special values.
Paths
在配置文件设置中,列出目录。定义这些目录时,应该记住用系统路径分隔符分隔,在*nix平台上为“:”,在Windows上为分号“;”。
In configuration file settings, take a list of directories. While defining these directories, one should keep in mind that they should be separated by the system path separator character, which is (:) in *nix platforms and semicolons (;) on Windows.
# *nix version:
environmentpath = $codedir/special_environments:$codedir/environments
# Windows version:
environmentpath = $codedir/environments;C:\ProgramData\PuppetLabs\code\environment
在定义中,首先扫描列出的文件目录,然后再移动到列表中的其他目录,如果没找到一个。
In the definition, the file directory which is listed first is scanned and then later moves to the other directory in the list, if it doesn’t find one.
Files and Directories
所有接受单个文件或目录的设置都可以接受可选的权限哈希。当服务器启动时,Puppet将强制执行列表中的那些文件或目录。
All the settings that take a single file or directory can accept an optional hash of permissions. When the server is starting up, Puppet will enforce those files or directories in the list.
ssldir = $vardir/ssl {owner = service, mode = 0771}
在上面的代码中,允许的hash为所有者、组和模式。所有者和组键只有两个有效值。
In the above code, the allowed hash are owner, group, and mode. There are only two valid values of the owner and group keys.
Puppet - Environment Conf
在 Puppet 中,所有环境都有 environment.conf 文件。每当主服务器为该特定环境分配的任何节点或所有节点提供服务时,此文件可以覆盖多个默认设置。
In Puppet, all environments have the environment.conf file. This file can override several default settings whenever the master is serving any of the nodes or all the nodes assigned to that particular environment.
Location
在 Puppet 中,对于所有定义的环境,environment.conf 文件都位于其主环境的顶层,紧邻清单和模块目录。考虑一个示例,如果您的环境位于默认目录 (Vipin/testing/environment) 中,则测试环境的配置文件位于 Vipin/testing/environments/test/environment.conf 中。
In Puppet, for all the environments which are defined, environment.conf file is located at the top level of its home environment, very next to the manifest and modules directors. Considering an example, if your environment is in default directories (Vipin/testing/environment), then test environment’s config file is located at Vipin/testing/environments/test/environment.conf.
Example
# /etc/testingdir/code/environments/test/environment.conf
# Puppet Enterprise requires $basemodulepath; see note below under modulepath".
modulepath = site:dist:modules:$basemodulepath
# Use our custom script to get a git commit for the current state of the code:
config_version = get_environment_commit.sh
Format
Puppet 中的所有配置文件都以相同的方式使用相同的类似 INI 的格式。 environment.conf 文件遵循与其他文件(如 puppet.conf 文件)相同的类似 INI 的格式。environment.conf 和 puppet.conf 之间的唯一区别是 environment.conf 文件不能包含 [main] 部分。environment.conf 文件中的所有设置都必须位于任何配置部分之外。
All the configuration files in Puppet uses the same INI-like format in the same way. environment.conf file follow the same INI-like format as others do like puppet.conf file. The only difference between environment.conf and puppet.conf is environment.conf file cannot contain the [main] section. All settings in the environment.conf file must be outside any config section.
Relative Path in Values
大多数允许的设置都接受文件路径或路径列表作为值。如果任何路径都是相对路径,则它们不以前导斜杠或驱动器号开头 - 它们大多将相对于该环境的主目录解析。
Most of the allowed settings accept file path or list of path as the value. If any of the paths are relevant path, they start without a leading slash or drive letter – they will be mostly resolved relative to that environment’s main directory.
Interpolation in Values
Environment.conf 设置文件能够将其他设置的值用作变量。有多个有用的变量可以内插到 environment.conf 文件中。以下是几个重要变量的列表 -
Environment.conf settings file is capable of using values of other settings as variable. There are multiple useful variables which could be interpolated into the environment.conf file. Here is a list of few important variables −
-
$basemodulepath − Useful for including directories in the module path settings. Puppet enterprise user should usually include this value of modulepath since the Puppet engine uses module in the basemodulepath.
-
$environment − Useful as a command line argument to your config_version script. You can interpolate this variable only in the config_version setting.
-
$codedir − Useful for locating files.
Allowed Settings
默认情况下,Puppet environment.conf 文件仅允许覆盖配置中列出的四项设置。
By default, Puppet environment.conf file is only allowed to override four settings in the configuration as listed.
-
Modulepath
-
Manifest
-
Config_version
-
Environment_timeout
Modulepath
这是 environment.conf 文件中的一个关键设置。模块路径中定义的所有目录都将默认由 Puppet 加载。这是 Puppet 加载其模块的路径位置。需要显式设置此项。如果未设置此上述设置,则 Puppet 中任何环境的默认模块路径为 -
This is one of the key settings in environment.conf file. All the directors defined in modulepath are by default loaded by Puppet. This is the path location from where Puppet loads its modules. One needs to explicitly set this up. If this above setting is not set, the default modulepath of any environment in Puppet will be −
<MODULES DIRECTORY FROM ENVIRONMENT>:$basemodulepath
Manifest
这用于定义主清单文件,Puppet 主机在启动并根据定义的清单(将用于配置环境)编译编录时将使用该文件。在此,我们可以定义一个文件、一个文件列表,甚至一个包含多个清单文件的目录,需要按定义的字母顺序对其进行评估和编译。
This is used to define the main manifest file, which Puppet master will use while booting up and compiling the catalog out of the defined manifest which is going to be used to configure the environment. In this, we can define a single file, a list of files, or even a directory consisting of multiple manifest files which needs to be evaluated and compiled in a defined alphabetical sequence.
需要在 environment.conf 文件中明确定义此设置。如果没有,则 Puppet 将使用环境默认清单目录作为其主清单。
One needs to explicitly define this setting in the environment.conf file. If not, then Puppet will use environments default manifest directory as its main manifest.
Config_version
config_version 可以定义为用于识别目录和事件的明确版本。当 Puppet 默认编译任何清单文件时,它会向生成的目录以及当 Puppet 主机在 Puppet 节点上应用任何定义的目录时生成的报告添加一个配置版本。Puppet 运行脚本来执行上述所有步骤,并将所有生成的输出用作 Config_version。
Config_version can be defined as a definite version used to identify catalogs and events. When Puppet compiles any manifest file by default, it adds a config version to the generated catalogs as well as to the reports which gets generated when the Puppet master applies any defined catalog on Puppet nodes. Puppet runs a script to perform all the above steps and uses all the generated output as Config_version.
Environment Timeout
它用于获取 Puppet 用于为给定环境加载数据所需时间量的信息。如果在 puppet.conf 文件中定义了该值,则这些值将覆盖默认超时值。
It is used to get the details about the amount of time which Puppet should use to load data for a given environment. If the value is defined in puppet.conf file, then these values will override the default timeout value.
Sample environment.conf File
[master]
manifest = $confdir/environments/$environment/manifests/site.pp
modulepath = $confdir/environments/$environment/modules
在上述代码 $confdir 中是环境配置文件所在的目录的路径。 $environment 是正在对其执行配置的环境的名称。
In the above code $confdir is the path of the directory, where environment configuration files are located. $environment is the name of the environment for which the configuration is being done.
Production Ready environment config File
# The environment configuration file
# The main manifest directory or file where Puppet starts to evaluate code
# This is the default value. Works with just a site.pp file or any other
manifest = manifests/
# The directories added to the module path, looked in first match first used order:
# modules - Directory for external modules, populated by r10k based on Puppetfile
# $basemodulepath - As from: puppet config print basemodulepath
modulepath = site:modules:$basemodulepath
# Set the cache timeout for this environment.
# This overrides what is set directly in puppet.conf for the whole Puppet server
# environment_timeout = unlimited
# With caching you need to flush the cache whenever new Puppet code is deployed
# This can also be done manually running: bin/puppet_flush_environment_cache.sh
# To disable catalog caching:
environment_timeout = 0
# Here we pass to one in the control repo the Puppet environment (and git branch)
# to get title and essential info of the last git commit
config_version = 'bin/config_script.sh $environment'
Puppet - Master
在 Puppet 中,Puppet Master 的客户端服务器架构被认为是整个设置的控制权限。Puppet Master 在设置中充当服务器,并控制所有节点上的所有活动。
In Puppet, the client server architecture of Puppet master is considered as the controlling authority of the entire setup. Puppet master acts as the server in the setup and controls all the activities on all the nodes.
对于任何需要充当 Puppet Master 的服务器,它应运行着 Puppet 服务器软件。此服务器软件是控制节点上所有活动的关键部件。在此设置中,需要记住的一个关键要点是,对想要在设置中使用所有机器拥有超级用户访问权限。以下是设置 Puppet Master 的步骤。
For any server which needs to act as Puppet master, it should have Puppet server software running. This server software is the key component of controlling all the activities on nodes. In this setup, one key point to remember is to have a super user access to all the machines that one is going to use in the setup. Following are the steps to setup Puppet master.
Prerequisites
Private Network DNS − 应配置转发和返回,其中每个服务器应拥有唯一的 Hostname。如果未配置 DNS,则可以使用专用网络与基础设施通信。
Private Network DNS − Forward and backward should be configured, wherein each server should have a unique hostname. If one does not have the DNS configured, then one can use a private network for communication with the infrastructure.
Firewall Open Port − Puppet Master 应在特定端口上打开,以便它可以在特定端口上侦听传入的请求。我们可以使用防火墙上开放的任何端口。
Firewall Open Port − Puppet master should be open on a particular port so that it can listen to the incoming requests on a particular port. We can use any port which is open on the firewall.
Creating Puppet Master Server
我们正在创建的 Puppet 主机将使用 Puppet(作为主机名)置于 CentOS 7 × 64 机器上。创建 Puppet 主机的最低系统配置是两个 CPU 内核和 1GB 内存。配置可能也会更大,具体取决于我们将用此主机管理的节点数。在基础设施中,配置使用 2GB RAM 的更大。
Puppet master that we are creating is going to be on CentOS 7 × 64 machine using Puppet as the host name. The minimum system configuration for the creation of Puppet master is two CPU core and 1GB of memory. Configuration may have bigger size as well depending on the number of nodes we are going to manage with this master. In the infrastructure, is bigger than it is configured using 2 GB RAM.
Host Name |
Role |
Private FQDN |
Brcleprod001 |
Puppet master |
bnrcleprod001.brcl.com |
接下来,需要生成 Puppet 主机 SSL 证书,并且主机机器的名称将复制到所有节点的配置文件中。
Next, one needs to generate Puppet master SSL certificate and the name of the master machine will be copied in the configuration file of all the nodes.
Installing NTP
由于 Puppet 主机是任何给定设置中代理节点的中央授权,因此维护准确的系统时间以避免可能出现的配置问题是 Puppet 主机的一项主要职责,它可以在向节点颁发代理证书时出现。
Since Puppet master is the central authority for agent nodes in any given setup, it is one of the key responsibility of the Puppet master to maintain accurate system time to avoid potential configuration problems, which can arise when it issues agent certificates to nodes.
如果出现时间冲突问题,那么如果主机和节点之间存在时间差异,证书可能会出现过期。网络时间协议是避免此类问题的主要机制之一。
If the time conflict issue arises, then certificates can appear expired if there are time discrepancies between the master and the node. Network time protocol is one of the key mechanisms to avoid such kind of problems.
Listing Available Time Zones
$ timedatectl list-timezones
上述命令将提供可用时区的完整列表。它将提供具有时区可用性的区域。
The above command will provide a whole list of available time zones. It will provide regions with time zone availability.
可以使用以下命令在机器上设置所需时区。
Following command can be used to set the required time zone on the machine.
$ sudo timedatectl set-timezone India/Delhi
使用 CentOS 机器上的 yum 实用程序在 Puppet 服务器机器上安装 NTP。
Install NTP on the Puppet server machine using the yum utility of CentOS machine.
$ sudo yum -y install ntp
使用我们上述命令中设置的系统时间同步 NTP。
Sync NTP with the system time which we have set in the above commands.
$ sudo ntpdate pool.ntp.org
通常,我们将更新 NTP 配置以使用离机器数据中心最近的公共池。为此,我们需要编辑 /etc 下的 ntp.conf 文件。
In common practice, we will update the NTP configuration to use common pools which is available nearer to the machine datacenters. For this, we need to edit ntp.conf file under /etc.
$ sudo vi /etc/ntp.conf
从提供的 NTP 池时区中添加时间服务器。以下是 ntp.conf 文件的外观。
Add the time server from the NTP pool time zones available. Following is how the ntp.conf file looks like.
brcleprod001.brcl.pool.ntp.org
brcleprod002.brcl.pool.ntp.org
brcleprod003.brcl.pool.ntp.org
brcleprod004.brcl.pool.ntp.org
保存配置。启动服务器并启用守护进程。
Save the configuration. Start the server and enable the daemon.
$ sudo systemctl restart ntpd
$ sudo systemctl enable ntpd
Setup Puppet Server Software
Puppet 服务器软件是在 Puppet 主机机器上运行的软件。它是将配置推送到运行 Puppet 代理软件的其他机器上的机器。
Puppet server software is a software which runs on the Puppet master machine. It is the machine which pushes configurations to other machines running the Puppet agent software.
使用以下命令启用官方 Puppet 实验室集合存储库。
Enable official Puppet labs collection repository using the following command.
$ sudo rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el7.noarch.rpm
安装 puppetserver 包。
Install puppetserver package.
$ sudo yum -y install puppetserver
Configure Memory Allocation on the Puppet Server
正如我们已经讨论的,默认情况下,Puppet 服务器在 2GB RAM 机器上进行配置。可以根据机器上可用的空闲内存和服务器将管理的节点数自定义设置。
As we have discussed, by default, the Puppet server gets configured on 2GB RAM machine. One can customize the setup according to the free memory available on the machine and how many nodes the server will manage.
在 vi 模式下编辑 puppet 服务器配置
Edit the puppet server configuration on the vi mode
$ sudo vi /etc/sysconfig/puppetserver
Find the JAVA_ARGS and use the –Xms and –Xms options to set the memory allocation.
We will allocate 3GB of space
JAVA_ARGS="-Xms3g -Xmx3g"
完成后,保存并退出编辑模式。
Once done, save and exit from the edit mode.
在所有上述设置完成后,我们准备使用以下命令在主机机器上启动 Puppet 服务器。
After all the above setup is complete, we are ready to start the Puppet server on the master machine with the following command.
$ sudo systemctl start puppetserver
接下来,我们将进行设置以在主机服务器启动时启动 puppet 服务器。
Next, we will do the setup so that the puppet server starts whenever the master server boots.
$ sudo systemctl enable puppetserver
Puppet.conf Master Section
[master]
autosign = $confdir/autosign.conf { mode = 664 }
reports = foreman
external_nodes = /etc/puppet/node.rb
node_terminus = exec
ca = true
ssldir = /var/lib/puppet/ssl
certname = sat6.example.com
strict_variables = false
manifest =
/etc/puppet/environments/$environment/manifests/site.pp
modulepath = /etc/puppet/environments/$environment/modules
config_version =
Puppet - Agent Setup
Puppet 代理是一个软件应用程序,由 Puppet 实验室提供,它在 Puppet 集群中的任何节点上运行。如果想使用 Puppet 主机管理任何服务器,则需要在该特定服务器上安装 Puppet 代理软件。通常,将在任何给定基础设施上排除 Puppet 主机机器的所有机器上安装 Puppet 代理。Puppet 代理软件能够在大多数 Linux、UNIX 和 Windows 机器上运行。在以下示例中,我们正在使用 CentOS 机器在其上安装 Puppet 代理软件。
Puppet agent is a software application, provided by Puppet labs, which runs on any node in Puppet cluster. If one wants to manage any server using the Puppet master, the Puppet agent software needs to be installed on that particular server. In general, the Puppet agent will be installed on all the machines excluding the Puppet master machine on any given infrastructure. Puppet agent software has the capability to run on most of the Linux, UNIX, and Windows machines. In the following examples, we are using CentOS machine installation Puppet agent software on it.
Step 1 −使用以下命令启用官方 Puppet 实验室收集存储库。
Step 1 − Enable the official Puppet labs collection repository with the following command.
$ sudo rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el7.noarch.rpm
Step 2 −安装 Puppet 代理包。
Step 2 − Install the Puppet agent package.
$ sudo yum -y install puppet-agent
Step 3 −一旦安装了 Puppet 代理,请使用以下命令启用它。
Step 3 − Once the Puppet agent is installed, enable it with the following command.
$ sudo /opt/puppetlabs/bin/puppet resource service puppet ensure=running enable = true
Puppet 代理的一个关键功能是,Puppet 代理在首次开始运行时,它将生成一个 SSL 证书并将其发送给 Puppet 主机,以便由该主机进行签名和批准。一旦 Puppet 主机批准了代理的证书签名请求,它便能够通信并管理代理节点。
One key feature of the Puppet agent is, for the first time when the Puppet agent starts running, it generates a SSL certificate and sends it to the Puppet master which is going to manage it for signing and approval. Once the Puppet master approves the agent’s certificate signature request, it will be able to communicate and manage the agent node.
Note −需要在需要配置和管理任何给定 Puppet 主机的所有节点上重复上述步骤。
Note − One needs to repeat the above steps on all the nodes which needs to be configured and managed any a given Puppet master.
Puppet - SSL Sign Certificate Setup
Puppet 代理软件首次在任何 Puppet 节点上运行时,它将生成一个证书并向 Puppet 主服务器发送证书签名请求。Puppet 服务器在能够通信和控制代理节点之前必须签署该特定代理节点的证书。在以下各部分,我们将描述如何签署和检查签名请求。
When the Puppet agent software runs for the first time on any Puppet node, it generates a certificate and sends the certificate signing request to the Puppet master. Before the Puppet server is able to communicate and control the agent nodes, it must sign that particular agent node’s certificate. In the following sections, we will describe how to sign and check for the signing request.
List Current Certificate Requests
在 Puppet 主服务器上,运行以下命令以查看所有未签名的证书请求。
On the Puppet master, run the following command to see all unsigned certificate requests.
$ sudo /opt/puppetlabs/bin/puppet cert list
由于我们刚刚设置了一个新的代理节点,因此我们将看到一条请求审批。以下将是 output 。
As we have just set up a new agent node, we will see one request for approval. Following will be the output.
"Brcleprod004.brcl.com" (SHA259)
15:90:C2:FB:ED:69:A4:F7:B1:87:0B:BF:F7:ll:
B5:1C:33:F7:76:67:F3:F6:45:AE:07:4B:F 6:E3:ss:04:11:8d
它开头没有包含任何 +(签名),这表明证书仍未签署。
It does not contain any + (sign) in the beginning, which indicates that the certificate is still not signed.
Sign a Request
为了签署在 Puppet 代理在新节点上运行时生成的新的证书请求,将使用 Puppet cert sign 命令,其中包含证书的主机名,该主机名由需要签署的新配置的节点生成。由于我们有 Brcleprod004.brcl.com 的证书,因此我们将使用以下命令。
In order to sign the new certificate request which was generated when the Puppet agent run took place on the new node, the Puppet cert sign command would be used, with the host name of the certificate, which was generated by the newly configured node that needs to be signed. As we have Brcleprod004.brcl.com’s certificate, we will use the following command.
$ sudo /opt/puppetlabs/bin/puppet cert sign Brcleprod004.brcl.com
以下是 output 。
Following will be the output.
Notice: Signed certificate request for Brcle004.brcl.com
Notice: Removing file Puppet::SSL::CertificateRequest Brcle004.brcl.com at
'/etc/puppetlabs/puppet/ssl/ca/requests/Brcle004.brcl.com.pem'
puppet sever 现在可以通信到节点,其中属于签名证书。
The puppet sever can now communicate to the node, where the sign certificate belongs.
$ sudo /opt/puppetlabs/bin/puppet cert sign --all
Revoking the Host from the Puppet Setup
当需要从设置中删除主机并重新添加它时,内核重建的配置存在条件。这些是 Puppet 本身无法管理的条件。它可以使用以下命令来完成。
There are conditions on configuration of kernel rebuild when it needs to removing the host from the setup and adding it again. These are those conditions which cannot be managed by the Puppet itself. It could be done using the following command.
$ sudo /opt/puppetlabs/bin/puppet cert clean hostname
Viewing All Signed Requests
以下命令将生成已签名的证书列表,其中 +(签名)表示已批准请求。
The following command will generate a list of signed certificates with + (sign) which indicates that the request is approved.
$ sudo /opt/puppetlabs/bin/puppet cert list --all
以下是其 output 。
Following will be its output.
+ "puppet" (SHA256) 5A:71:E6:06:D8:0F:44:4D:70:F0:
BE:51:72:15:97:68:D9:67:16:41:B0:38:9A:F2:B2:6C:B
B:33:7E:0F:D4:53 (alt names: "DNS:puppet", "DNS:Brcle004.nyc3.example.com")
+ "Brcle004.brcl.com" (SHA259) F5:DC:68:24:63:E6:F1:9E:C5:FE:F5:
1A:90:93:DF:19:F2:28:8B:D7:BD:D2:6A:83:07:BA:F E:24:11:24:54:6A
+ " Brcle004.brcl.com" (SHA259) CB:CB:CA:48:E0:DF:06:6A:7D:75:E6:CB:22:BE:35:5A:9A:B3
一旦完成以上操作,我们的基础设施便已准备就绪,其中 Puppet 主服务器现在能够管理新添加的节点。
Once the above is done, we have our infrastructure ready in which the Puppet master is now capable of managing newly added nodes.
Puppet - Installing and Configuring r10K
在 Puppet 中,我们有一个已知的代码管理工具叫 r10k,它有助于管理与我们在 Puppet 中配置的不同类型的环境相关的环境配置,例如开发、测试和生产。这有助于在源代码库中存储与环境相关的配置。使用源代码控制库分支,r10k 会在 Puppet 主控机上创建环境安装,并使用库中现有的模块更新环境。
In Puppet, we have a code management tool known as r10k that helps in managing environment configurations related to different kind of environments that we can configure in Puppet such as development, testing, and production. This helps in storing environment-related configuration in the source code repository. Using the source control repo branches, r10k creates environments on Puppet master machine installs and updates environment using modules present in the repo.
Gem 文件可以用来在任何机器上安装 r10k,但为了模块化并获得最新版本,我们将使用 rpm 和 rpm 包管理器。以下是同一个示例。
Gem file can be used to install r10k on any machine but for modularity and in order to get the latest version, we will use rpm and rpm package manager. Following is an example for the same.
$ urlgrabber -o /etc/yum.repos.d/timhughes-r10k-epel-6.repo
https://copr.fedoraproject.org/coprs/timhughes/yum -y install rubygem-r10k
在 /etc/puppet/puppet.conf 中配置环境
Configure environment in /etc/puppet/puppet.conf
[main]
environmentpath = $confdir/environments
Create a Configuration File for r10k Config
cat <<EOF >/etc/r10k.yaml
# The location to use for storing cached Git repos
:cachedir: '/var/cache/r10k'
# A list of git repositories to create
:sources:
# This will clone the git repository and instantiate an environment per
# branch in /etc/puppet/environments
:opstree:
#remote: 'https://github.com/fullstack-puppet/fullstackpuppet-environment.git'
remote: '/var/lib/git/fullstackpuppet-environment.git'
basedir: '/etc/puppet/environments'
EOF
Installing Puppet Manifest and Module
r10k deploy environment -pv
由于我们需要每 15 分钟就持续更新环境,我们将为此创建一个 cron 作业。
As we need to continue updating the environment in every 15 minutes, we will create a cron job for the same.
cat << EOF > /etc/cron.d/r10k.conf
SHELL = /bin/bash
PATH = /sbin:/bin:/usr/sbin:/usr/bin
H/15 * * * * root r10k deploy environment -p
EOF
Testing Installation
为了测试是否一切按照接受的方式工作,你需要为 Puppet 模块编译 Puppet 清单。运行以下命令并获取 YAML 输出作为结果。
In order to test if everything works as accepted, one needs to compile the Puppet manifest for Puppet module. Run the following command and get a YAML output as the result.
curl --cert /etc/puppet/ssl/certs/puppet.corp.guest.pem \
--key /etc/puppet/ssl/private_keys/puppet.corp.guest.pem \
--cacert /etc/puppet/ssl/ca/ca_crt.pem \
-H 'Accept: yaml' \
https://puppet.corp.guest:8140/production/catalog/puppet.corp.guest
Puppet - Validating Puppet Setup
在 Puppet 中,可以本地测试设置。因此,一旦我们设置好 Puppet 主服务器和节点,就可以在本地验证设置了。我们需要在本地安装 Vagrant 和 Vagrant 框,它们有助于在本地测试设置。
In Puppet, the setup can be tested locally. Hence, once we have set up Puppet master and node, it’s time to validate the setup locally. We need to have Vagrant and Vagrant box installed locally, which helps in testing the setup locally.
Setting Up the Virtual Machine
由于我们正在本地测试设置,因此实际上不需要运行 Puppet 主服务器。这意味着无需在服务器上实际运行 Puppet 主服务器,我们可以简单地使用 Puppet 来应用命令以进行 Puppet 设置验证。Puppet apply 命令将根据配置文件中虚拟机的主机名从 local/etc/puppet 中应用更改。
As we are testing the setup locally, we do not actually require a running Puppet master. This means without actually running the Puppet master on the server, we can simply use Puppet to apply command for Puppet setup validation. Puppet apply command will apply changes from local/etc/puppet depending on the virtual machine’s hostname in the configuration file.
为了测试设置,我们需要执行的第一步是构建以下 Vagrantfile 并启动计算机并将 /etc/puppet 文件夹装入适当位置。所需的所有文件都将使用以下结构放置在版本控制系统中。
First step which we need to perform in order to test the setup is to build the following Vagrantfile and start a machine and mount the /etc/puppet folder into place. All the files which are required will be place inside the version control system with the following structure.
Directory Structure
- manifests
\- site.pp
- modules
\- your modules
- test
\- update-puppet.sh
\- Vagrantfile
- puppet.conf
Vagrant File
# -*- mode: ruby -*-
# vi: set ft = ruby :
Vagrant.configure("2") do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
config.vm.provider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--memory", 1028, "--cpus", 2]
end
# Mount our repo onto /etc/puppet
config.vm.synced_folder "../", "/etc/puppet"
# Run our Puppet shell script
config.vm.provision "shell" do |s|
s.path = "update-puppet.sh"
end
config.vm.hostname = "localdev.example.com"
end
在上面的代码中,我们使用了 Shell 配置工具,其中我们尝试运行名为 update-puppet.sh 的 Shell 脚本。此脚本存在于 Vagrant 文件所在的相同目录中,并且脚本的内容如下所示。
In the above code, we have used Shell provisioner in which we are trying to run a Shell script named update-puppet.sh. The script is present in the same directory where the Vagrant file is located and the content of the script are listed below.
!/bin/bash
echo "Puppet version is $(puppet --version)"
if [ $( puppet --version) != "3.4.1" ]; then
echo "Updating puppet"
apt-get install --yes lsb-release
DISTRIB_CODENAME = $(lsb_release --codename --short)
DEB = "puppetlabs-release-${DISTRIB_CODENAME}.deb"
DEB_PROVIDES="/etc/apt/sources.list.d/puppetlabs.list"
if [ ! -e $DEB_PROVIDES ]
then
wget -q http://apt.puppetlabs.com/$DEB
sudo dpkg -i $DEB
fi
sudo apt-get update
sudo apt-get install -o Dpkg::Options:: = "--force-confold"
--force-yes -y puppet
else
echo "Puppet is up to date!"
fi
在进一步处理中,用户需要在 Manifests 目录中创建一个清单文件,其名称为 site.pp ,它将安装一些虚拟机软件。
Further processing, the user needs to create a manifest file inside Manifests directory with the name site.pp which will install some software on VM.
node 'brclelocal03.brcl.com' {
package { ['vim','git'] :
ensure => latest
}
}
echo "Running puppet"
sudo puppet apply /etc/puppet/manifests/site.pp
一旦用户准备好上述脚本以及所需的 Vagrant 文件配置,用户就可以 cd 到测试目录并运行 vagrant up command 。这将启动一个新的虚拟机,稍后安装 Puppet,然后使用 Shell 脚本运行它。
Once the user has the above script ready with the required Vagrant file configuration, the user can cd to the test directory and run the vagrant up command. This will boot a new VM, Later, install Puppet and then run it using the Shell script.
输出将如下所示。
Following will be the output.
Notice: Compiled catalog for localdev.example.com in environment production in 0.09 seconds
Notice: /Stage[main]/Main/Node[brclelocal03.brcl.com]/Package[git]/ensure: created
Notice: /Stage[main]/Main/Node[brcllocal03.brcl.com]/Package[vim]/ensure: ensure changed 'purged' to 'latest'
Validating Multiple Machine Configuration
如果我们需要在本地测试多台计算机的配置,只需更改 Vagrant 配置文件即可轻松完成。
If we need to test the configuration of multiple machines locally, it can be simply done by making a change in Vagrant configuration file.
New Configured Vagrant File
config.vm.define "brclelocal003" do |brclelocal003|
brclelocal03.vm.hostname = "brclelocal003.brcl.com"
end
config.vm.define "production" do |production|
production.vm.hostname = "brcleprod004.brcl.com"
end
我们假设有一台新的生产服务器,需要安装 SSL 实用程序。我们只需要使用以下配置扩展旧清单。
Let’s assume we have a new production server, which needs SSL utility installed. We just need to extend the old manifest with the following configuration.
node 'brcleprod004.brcl.com' inherits 'brcleloacl003.brcl.com' {
package { ['SSL'] :
ensure => latest
}
}
在清单文件中进行配置更改后,我们只需要移动到测试目录并运行基本的 vagrant up 命令,该命令将同时启动 brclelocal003.brcl.com 和 brcleprod004.brcl.com 计算机。在我们的示例中,我们尝试启动生产计算机,可以通过运行 vagrant up production command 来完成。这样将创建一个名称为“production”的新计算机,如 Vagrant 文件中所定义,并且其中将安装 SSL 软件包。
After making configurational changes in the manifest file, we just need to move to the test directory and run the basic vagrant up command which will bring up both brclelocal003.brcl.com and brcleprod004.brcl.com machine. In our case, we are trying to bring up production machine which could be done by running the vagrant up production command. The will create a new machine with the name production as defined in Vagrant file and it will have SSL package installed in it.
Puppet - Coding Style
在 Puppet 中,编码风格定义了在尝试将机器配置上的基础设施转换成代码时需要遵循的所有标准。Puppet 使用资源来执行并完成其所有已定义的任务。
In Puppet, the coding style defines all the standards which one needs to follow while trying to convert the infrastructure on the machine configuration into a code. Puppet works and performs all its defined tasks using resources.
Puppet 的语言定义有助于用结构化的方式指定所有资源,这是管理任何需要管理的目标机器所必需的。Puppet 使用 Ruby 作为其编码语言,其具有多项内置功能,可以很容易地用代码端的简单配置来完成任务。
Puppet’s language definition helps in specifying all the resources in a structured way, which is required to manage any target machine that needs to be managed. Puppet uses Ruby as its encoding language, which has multiple inbuilt features that makes it very easy to get things done with a simple configuration on the code side.
Fundamental Units
Puppet 使用多种容易理解和管理的基本编码风格。以下列出其中几种。
Puppet uses multiple fundamental coding styles which is easy to understand and manage. Following is a list of few.
Resources
在 Puppet 中,资源被称为基本建模单元,用于管理或修改任何目标系统。资源涵盖系统的所有方面,例如文件、服务和包。Puppet 附带一项内置功能,允许用户或开发人员开发自定义资源,这有助于管理机器的任何特定单元。
In Puppet, resources are known as fundamental modeling unit which are used to manage or modify any target system. Resources cover all the aspects of a system such as file, service, and package. Puppet comes with an in-built capability wherein it allows the users or developers to develop custom resources, which help in managing any particular unit of a machine
在 Puppet 中,所有资源都使用 “define” 或 “classes” 聚合在一起。这些聚合功能有助于组织模块。以下是一个示例资源,它由多种类型、一个标题和一个 Puppet 可以支持多个属性的属性列表组成。Puppet 中的每个资源都有自己的默认值,在需要时可以覆盖。
In Puppet, all the resources are aggregated together either by using “define” or “classes”. These aggregation features help in organizing a module. Following is a sample resource which consists of multiple types, a title, and a list of attributes with which Puppet can support multiple attributes. Each resource in Puppet has its own default value, which could be overridden when required.
Sample Puppet Resource for File
在以下命令中,我们尝试为特定文件指定权限。
In the following command, we are trying to specify a permission for a particular file.
file {
'/etc/passwd':
owner => superuser,
group => superuser,
mode => 644,
}
每当上述命令在任何机器上执行时,它将验证系统中的 passwd 文件是否按说明进行配置。冒号之前的文件是资源的标题,可以在 Puppet 配置的其他部分中将其称为资源。
Whenever the above command gets executed on any machine, it will verify that the passwd file in the system is configured as described. The file before: colon is the title of resource, which can be referred as resource in other parts of Puppet configuration.
Specifying Local Name in Addition to the Title
file { 'sshdconfig':
name => $operaSystem ? {
solaris => '/usr/local/etc/ssh/sshd_config',
default => '/etc/ssh/sshd_config',
},
owner => superuser,
group => superuser,
mode => 644,
}
通过使用始终相同的标题,很容易在配置中引用文件资源,而无需重复与操作系统相关的逻辑。
By using the title, which is always the same it is very easy to refer file resource in configuration without having to repeat the OS related logic.
另一个示例可能是使用依赖于文件的服务。
Another example could be using a service that depends on a file.
service { 'sshd':
subscribe => File[sshdconfig],
}
通过此依赖关系, sshd 服务将在 sshdconfig 文件更改后始终重新启动。这里需要记住的是 File[sshdconfig] 是声明作为小写形式的文件,如果我们将其更改为 FILE[sshdconfig] ,那将成为引用。
With this dependency, the sshd service will always restart once the sshdconfig file changes. The point to be remember here is File[sshdconfig] is a declaration as File as in lower case but if we change it to FILE[sshdconfig] then it would have been a reference.
在声明资源时需要牢记的一项基本原则是,每个配置文件只能声明它一次。重复声明同一个资源多次将会导致错误。通过这个基本概念,Puppet 确保配置具有良好的建模。
One fundamental point that one needs to keep in mind while declaring a resource is, it can be declared only once per config file. Repeating declaration of the same resource more than once will cause an error. Through this fundamental concept, Puppet makes sure that the configuration is well modeled.
我们甚至有能力管理资源依赖关系,这有助于管理多种关系。
We even have the capability to manage resource dependency which helps is managing multiple relationships.
service { 'sshd':
require => File['sshdconfig', 'sshconfig', 'authorized_keys']
}
Metaparameters
元参数在 Puppet 中被称为全局参数。元参数的一项关键特性是它可以与 Puppet 中的任何类型的资源配合使用。
Metaparameters are known as global parameters in Puppet. One of the key features of metaparameter is, it works with any type of resource in Puppet.
Resource Default
当人们需要定义默认资源属性值时,Puppet 提供了一组语法来归档它,使用的是没有标题的大写资源规范。
When one needs to define a default resource attribute value, Puppet provides a set of syntax to archive it, using a capitalized resource specification that has no title.
例如,如果我们想设置所有可执行文件的默认路径,可以使用以下命令来完成。
For example, if we want to set the default path of all the executable it can be done with the following command.
Exec { path => '/usr/bin:/bin:/usr/sbin:/sbin' }
exec { 'echo Testing mataparamaters.': }
在上述命令中,第一个语句 Exec 将针对 exec 资源设置默认值。Exec 资源需要一个完全限定的路径或看起来像可执行文件的路径。使用它可以针对整个配置定义一个单独的默认路径。Defaults 可适用于 Puppet 中的任何资源类型。
In the above command, the first statement Exec will set the default value for exec resource. Exec resource requires a fully qualified path or a path which looks like an executable. With this, one can define a single default path for the entire configuration. Defaults work with any resource type in Puppet.
不过,Defaults 不是全局值,它们仅影响定义其内容的范围或其紧邻的变量。如果想要为完整配置定义 default ,那么我们在紧接着的部分中定义 default 和类。
Defaults are not global values, however, they only affect the scope in which they are defined or the very next variable to it. If one wants to define default for a complete configuration, then we define the default and the class in the very next section.
Resource Collections
聚合是将项目收集到一起的方法。Puppet 支持一个功能非常强大的聚合概念。在 Puppet 中,聚合用于对作为 Puppet 的基本单元的资源进行分组。Puppet 中的聚合概念通过使用被称为 classes 和 definition 的两种强大方法实现。
Aggregation is method of collecting things together. Puppet supports a very powerful concept of aggregation. In Puppet, aggregation is used for grouping resource which is the fundamental unit of Puppet together. This concept of aggregation in Puppet is achieved by using two powerful methods known as classes and definition.
Classes and Definition
类的职责是对节点的基本方面进行建模。它们可以说明节点是 Web 服务器,并且此特定节点是其中之一。在 Puppet 中,编程类是单例的,并且它们可以针对每个节点进行一次求值。
Classes are responsible for modeling the fundamental aspects of node. They can say node is a web server and this particular node is one of them. In Puppet, programming classes are singleton and they can get evaluated once per node.
另一方面,定义可以在单个节点上多次使用。它们的运作方式与使用这种语言创建自己的 Puppet 类型类似。创建它们是为了能够在每次使用不同的输入时多次使用它们。这意味着可以将变量值传递到定义中。
Definition on the other hand can be used many times on a single node. They work similarly as one has created his own Puppet type using the language. They are created to be used multiple times with different input each time. This means one can pass variable values into the definition.
Difference between Class and Definition
类和定义之间的唯一关键差别在于,在定义构建结构并分配资源时,类只针对每个节点求值一次,而另一方面,会在同一个单个节点上多次使用一个定义。
The only key difference between a class and definition is while defining the building structure and allocating resources, class gets evaluated only once per node, wherein on the other hand, a definition is used multiple times on the same single node.
Classes
在 Puppet 中使用 class 关键字引入类,并且该特定类的内容会被封装在花括号中,如下面的示例所示。
Classes in Puppet are introduced using the class keyword and the content of that particular class is wrapped inside the curly braces as shown in the following example.
class unix {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
'/etc/shadow':
owner => 'vipin',
group => 'vipin',
mode => 440;
}
}
在下面的示例中,我们使用了类似于上面的一些简写。
In the following example, we have used some short hand which is similar to the above.
class unix {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
}
file {'/etc/shadow':
owner => 'vipin',
group => 'vipin',
mode => 440;
}
}
Inheritance in Puppet Classes
在 Puppet 中,默认情况下支持面向对象编程 (OOP) 的继承概念,其中类可以扩展以前的功能,而不必在新建类中再次复制并粘贴完整代码位。继承允许子类覆盖在父类中定义的资源设置。使用继承时需要记住的一件关键事项是,一个类只能从一个父类继承特性,不能从多个父类继承。
In Puppet, the OOP concept of inheritance is supported by default wherein classes can extend the functionality of previous without copying and pasting the complete code bit again in newly created class. Inheritance allows the subclass to override the resource settings defined in the parent class. One key thing to keep in mind while using inheritance is, a class can only inherit features from only one parent class, not more than one.
class superclass inherits testsubclass {
File['/etc/passwd'] { group => wheel }
File['/etc/shadow'] { group => wheel }
}
如果需要撤消在父类中指定的一些逻辑,我们可以使用 undef command 。
If there is a need to undo some logic specified in a parent class, we can use undef command.
class superclass inherits testsubcalss {
File['/etc/passwd'] { group => undef }
}
Alternative Way of Using Inheritance
class tomcat {
service { 'tomcat': require => Package['httpd'] }
}
class open-ssl inherits tomcat {
Service[tomcat] { require +> File['tomcat.pem'] }
}
Nested Class in Puppet
Puppet 支持将类嵌套的概念,其中它允许使用嵌套类,即一个类位于另一个类中。这有助于实现模块化和范围。
Puppet supports the concept of nesting of classes in which it allows to use nested classes which means one class inside the other. This helps in achieving modularity and scoping.
class testclass {
class nested {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
}
}
}
class anotherclass {
include myclass::nested
}
Parameterized Classes
在 Puppet 中,类可以扩展其功能以允许将参数传递到类中。
In Puppet, classes can extend their functionality to allow the passing of parameters into a class.
要在类中传递参数,可以使用以下结构:
To pass a parameter in a class, one can use the following construct −
class tomcat($version) {
... class contents ...
}
在 Puppet 中需要记住的一个关键点是,使用 include 函数不添加包含参数的类,而是可以将生成的类添加为定义。
One key point to remember in Puppet is, classes with parameters are not added using the include function, rather the resulting class can be added as a definition.
node webserver {
class { tomcat: version => "1.2.12" }
}
Run Stages
Puppet 支持运行阶段的概念,这意味着用户可以根据要求添加任意数量的阶段,以便管理任何特定资源或多个资源。当用户想要开发一个复杂的目录时,此功能非常有用。在一个复杂的目录中,需要编译大量资源,同时要记住不应影响定义的资源之间的依赖关系。
Puppet supports the concept of run stage, which means the user can add multiple number of stages as per the requirement in order to manage any particular resource or multiple resources. This feature is very helpful when the user wants to develop a complex catalog. In a complex catalog, one has large number of resources which needs to be compiled while keeping in mind that the dependencies among the resources defined should not be impacted.
运行阶段对于管理资源依赖关系非常有用。这可以通过在已定义的阶段中添加类来实现,其中特定类包含资源集合。通过运行阶段,Puppet 可以确保定义的阶段将在每次运行目录并将其应用到任何 Puppet 节点时以指定的可预测顺序运行。
Run Stage is very helpful in managing resource dependencies. This can be done by adding classes in defined stages wherein a particular class contains a collection of resources. With run stage, Puppet guarantees that the defined stages will run in a specified predictable order every time the catalog runs and gets applied on any Puppet node.
为了使用这个,需要声明超出已经存在的阶段的其他阶段,然后可以将其配置为使用 require “→” 和 “+>” 之前的相同资源关系语法以指定顺序管理每个阶段。然后,该关系将保证与每个阶段关联的类的顺序。
In order to use this, one needs to declare additional stages beyond the already present stages and then Puppet can be configured to manage each stage in a specified order using the same resource relationship syntax before require “→” and “+>”. The relationship will then guarantee the order of classes associated with each stage.
Declaring Additional Stages with Puppet Declarative Syntax
stage { "first": before => Stage[main] }
stage { "last": require => Stage[main] }
声明阶段后,可以使用 stage 将类与主类以外的阶段关联。
Once the stages have been declared, a class may be associated with the stage other than the main using the stage.
class {
"apt-keys": stage => first;
"sendmail": stage => main;
"apache": stage => last;
}
所有与 apt-key 类关联的资源将首先运行。Sendmail 中的所有资源将作为主类,与 Apache 关联的资源则作为最后一个阶段。
All resources associated with class apt-key will run first. All the resources in Sendmail will be the main class and the resources associated with Apache will be the last stage.
Definitions
在 Puppet 中,任何清单文件中资源的集合是通过类或定义完成的。定义与 Puppet 中的类非常相似,但是它们以 define keyword (not class) 引入,并且支持参数而非继承。它们可以在同一系统上使用不同参数多次运行。
In Puppet, collection of resources in any manifest file is done either by classes or definitions. Definitions are very much similar to a class in Puppet however they are introduced with a define keyword (not class) and they support argument not inheritance. They can run on the same system multiple times with different parameters.
例如,如果某人想要创建一个控制源代码存储库(打算在同一系统上创建多个存储库)的定义,那么某人可以使用定义而不是类。
For example, if one wants to create a definition that controls the source code repositories where one is trying to create multiple repositories on the same system, then one can use the definition not class.
define perforce_repo($path) {
exec {
"/usr/bin/svnadmin create $path/$title":
unless => "/bin/test -d $path",
}
}
svn_repo { puppet_repo: path => '/var/svn_puppet' }
svn_repo { other_repo: path => '/var/svn_other' }
此处需要注意的关键点是如何将变量与定义一起使用。我们使用 ( $ ) 美元符号变量。在上文中,我们使用了 $title。定义可以同时有 $title 名称和 $name 名称,可以使用这些名称和标题进行表示。默认情况下,$title 和 $name 设置为相同的值,但某人可以设置 title 属性并传递不同的名称作为参数。$title 和 $name 仅在定义中有效,在类或其他资源中无效。
The key point to be noted here is how a variable can be used with a definition. We use ($) dollar sign variable. In the above, we have used $title. Definitions can have both a $title and $name with which the name and the title can be represented. By default, $title and $name are set to the same value, but one can set a title attribute and pass different name as a parameter. $title and $name only works in definition, not in class or other resource.
Modules
可以将模块定义为由 Puppet 主机使用的所有配置的集合,以针对任何特定 Puppet 节点(代理)应用配置更改。它们也被称为各种不同配置的可移植集合,而这些配置是执行特定任务所必需的。例如,模块可能包含配置 Postfix 和 Apache 所需的所有资源。
A module can be defined as a collection of all the configurations which would be used by the Puppet master to apply configurational changes on any particular Puppet node (agent). They are also known as portable collection of different kind of configurations, which are required to perform a specific task. For example, a module might contain all the resources required to configure Postfix and Apache.
Nodes
节点非常简单,剩下的一步是如何将我们定义的内容(“这看起来像是 Web 服务器”)与选择来执行这些指令的机器相匹配。
Nodes are very simple remaining step which is how we match what we defined (“this is what a webserver looks like”) to what machines are chosen to fulfill those instructions.
节点定义看起来完全像类,包括支持继承,但是它们很特殊,因为当节点(运行 Puppet 客户端的受管计算机)连接到 Puppet 主机守护程序时,其名称将在定义的节点列表中查找。将为节点评估已定义的信息,然后节点将发送该配置。
Node definition exactly looks like classes, including the supporting inheritance, however they are special such that when a node (a managed computer running a puppet client) connects to the Puppet master daemon, its name will be looked in the defined list of nodes. The information defined will be evaluated for node, and then the node will send that configuration.
节点名称可以是短主机名或完全合格的域名 (FQDN)。
Node name can be a short host name or the fully qualified domain name (FQDN).
node 'www.vipin.com' {
include common
include apache, squid
}
以上定义创建了一个名为 www.vipin.com 的节点,其中包括 common、Apache 和 Squid 类。
The above definition creates a node called www.vipin.com and includes the common, Apache and Squid classe
我们可以通过用逗号分隔的方式将相同的配置发送到不同的节点。
We can send the same configuration to different nodes by separating each with comma.
node 'www.testing.com', 'www.testing2.com', 'www3.testing.com' {
include testing
include tomcat, squid
}
Node Inheritance
节点支持一种受限的继承模型。与类一样,节点只能从一个其他节点继承。
Node supports a limited inheritance model. Like classes, nodes can only inherit from one other node.
node 'www.testing2.com' inherits 'www.testing.com' {
include loadbalancer
}
在上述代码中,www.testing2.com 继承了 www.testing.com 的所有功能,此外还继承了一个额外的 loadbalancer 类。
In the above code, www.testing2.com inherits all the functionalities from www.testing.com in addition to an additional loadbalancer class.
Advanced Supported Features
Quoting − 在大多数情况下,我们不需要在 Puppet 中引用字符串。任何以字母开头的字母数字字符串都应在不加引号的情况下保留。但是,对于任何非负值,始终采用对字符串加引号的最佳做法。
Quoting − In most of the cases, we don’t need to quote a string in Puppet. Any alpha numeric string starting with a letter is to be left without quoting. However, it is always a best practice to quote a string for any non-negative values.
Variable Interpolation with Quotes
到目前为止,我们已经从定义的角度提到了变量。如果某人需要将这些变量与字符串一起使用,请使用双引号,而不是单引号。单引号字符串不会执行任何变量内插,双引号字符串会执行此操作。变量可以用括号括起来 {} 中,这使得它们更容易一起使用且更容易理解。
So far we have mentioned variable in terms of definition. If one needs to use those variables with a string, use double quotes, not single quotes. Single quotes string will not do any variable interpolation, double quotes string will do. The variable can be bracketed in {} which makes them easier to use together and easier to understand.
$value = "${one}${two}"
作为最佳做法,某人应为所有不需要字符串内插的字符串使用单引号。
As a best practice, one should use single quotes for all the strings that do not require string interpolation.
Capitalization
大写是用于引用、继承和设置特定资源的默认属性的过程。它基本上有两种基本用法。
Capitalization is a process which is used for referencing, inheritance, and setting default attributes of a particular resource. There are basically two fundamental ways of using it.
-
Referencing − It is the way of referencing an already created resource. It is mainly used for dependency purposes, one has to capitalize the name of the resource. Example, require ⇒ file [sshdconfig]
-
Inheritance − When overriding the setting for parent class from subclass, use the upper case version of the resource name. Using the lower case version will result in an error.
-
Setting Default Attribute Value − Using the capitalized resource with no title works to set the default of the resource.
Arrays
Puppet 在多个区域允许使用数组 [One, two, three]。
Puppet allows the use of arrays in multiple areas [One, two, three].
如主机定义中的别名,几个类型成员接受在其值中的数组。具有多个别名的主机资源看起来应像如下。
Several type members, such as alias in the host definition accepts arrays in their values. A host resource with multiple aliases will look like something as follows.
host { 'one.vipin.com':
alias => [ 'satu', 'dua', 'tiga' ],
ip => '192.168.100.1',
ensure => present,
}
上述代码会使用三个别名 ‘satu’ ‘dua’ ‘tiga’ 向主机列表添加一个主机 ‘one.brcletest.com’ 。如果希望向一个资源添加多个资源,可以像以下示例所示操作。
The above code will add a host ‘one.brcletest.com’ to the host list with three aliases ‘satu’ ‘dua’ ‘tiga’. If one wants to add multiple resources to one resource, it can be done as shown in the following example.
resource { 'baz':
require => [ Package['rpm'], File['testfile'] ],
}
Variables
Puppet 支持多个变量,就像大多数其他编程语言一样。Puppet 变量用 $ 表示。
Puppet supports multiple variables like most of the other programming languages. Puppet variables are denoted with $.
$content = 'some content\n'
file { '/tmp/testing': content => $content }
如之前所述,Puppet 是一种声明式语言,这意味着其范围和分配规则不同于命令式语言。主要的差异是,因为它们依赖于文件中确定一个变量的顺序,所以不能在单个范围内中更改该变量。顺序在声明式语言中没有意义。
As stated earlier Puppet is a declarative language, which means that its scope and assignment rules are different than the imperative language. The primary difference is that one cannot change the variable within a single scope, because they rely on order in the file to determine the value of a variable. Order does not matter in the declarative language.
$user = root
file {
'/etc/passwd':
owner => $user,
}
$user = bin
file {
'/bin':
owner => $user,
recurse => true,
}
Variable Scope
变量范围定义所有已定义的变量是否有效。与最新特征一样,Puppet 当前是动态范围的,这在 Puppet 中表示所有已定义的变量都会在其范围内而不是已定义的位置进行评估。
Variable scope defines if all the variables which are defined are valid. As with the latest features, Puppet is currently dynamically scoped which in Puppet terms means that all the variables which are defined gets evaluated on their scope rather than the location which they are defined.
$test = 'top'
class Testclass {
exec { "/bin/echo $test": logoutput => true }
}
class Secondtestclass {
$test = 'other'
include myclass
}
include Secondtestclass
Qualified Variable
Puppet 支持在类别或定义中使用限定变量。当用户希望在其他类别中使用同一变量时,这非常有用,用户已定义或将定义该变量。
Puppet supports the use of qualified variables inside a class or a definition. This is very helpful when the user wishes to use the same variable in other classes, which he has defined or is going to define.
class testclass {
$test = 'content'
}
class secondtestclass {
$other = $myclass::test
}
在上述代码中,$other 变量的值评估内容。
In the above code, the value of $other variable evaluates the content.
Conditionals
条件是指当已定义条件或所需条件得到满足时,用户希望执行一套的语句或代码。Puppet 支持两种类型的条件。
Conditions are situations when the user wishes to execute a set of statement or code when the defined condition or the required condition is satisfied. Puppet supports two types of conditions.
选择器条件仅能够在已定义的资源中使用,以挑选机器的正确值。
The selector condition which can only be used within the defined resources to pick the correct value of the machine.
语句条件在清单中是使用更广泛的条件,这有助于包括用户希望包括在同一清单文件中的附加类别。在类别中定义一组不同的资源,或做出其他结构决策。
Statement conditions are more widely used conditions in manifest which helps in including additional classes which the user wishes to include in the same manifest file. Define a distinct set of resources within a class, or make other structural decisions.
Selectors
当用户希望指定资源属性和根据事实或其他变量而不同于默认值的变量时,选择器是有用的。在 Puppet 中,选择器索引像多值三元运算符一样工作。选择器也有能力在清单中未定义且匹配条件的 no 值中定义自定义的默认值。
Selectors are useful when the user wishes to specify a resource attribute and variables which are different from the default values based on the facts or other variables. In Puppet, the selector index works like a multivalued three-way operator. Selectors are also capable of defining the custom default values in no values, which are defined in manifest and matches the condition.
$owner = $Sysoperenv ? {
sunos => 'adm',
redhat => 'bin',
default => undef,
}
在 Puppet 0.25.0 的后续版本中,选择器可用作正则表达式。
In later versions of Puppet 0.25.0 selectors can be used as regular expressions.
$owner = $Sysoperenv ? {
/(Linux|Ubuntu)/ => 'bin',
default => undef,
}
在上述示例中,选择器 $Sysoperenv 的值匹配 Linux 或 Ubuntu,则 bin 为选定的结果,否则用户将设置为未定义。
In the above example, the selector $Sysoperenv value matches either Linux or Ubuntu, then the bin will be the selected result, otherwise the user will be set as undefined.
Statement Condition
语句条件是 Puppet 中的另一种类型条件语句,这与 Shell 脚本中的 switch case 语句非常相似。在此中,定义了一组多重 case 语句,并且给定的输入值与每个条件进行匹配。
Statement condition is other type of conditional statement in Puppet which is very much similar to switch case condition in Shell script. In this, a multiple set of case statements are defined and the given input values are matched against each condition.
匹配给定的输入条件的 case 语句得到执行。此 case 语句条件没有任何返回值。在 Puppet 中,条件语句的非常常见的用例是在基础操作系统上运行一组代码位。
The case statement which matches the given input condition gets executed. This case statement condition does not have any return value. In Puppet, a very common use case for condition statement is running a set of code bit based on the underlying operating system.
case $ Sysoperenv {
sunos: { include solaris }
redhat: { include redhat }
default: { include generic}
}
Case 语句还可以通过用逗号分隔条件来指定多个条件。
Case Statement can also specify multiple conditions by separating them with a comma.
case $Sysoperenv {
development,testing: { include development } testing,production: { include production }
default: { include generic }
}
If-Else Statement
Puppet 支持基于条件的操作概念。为了实现它,If/else 语句基于条件的返回值提供分支选项。如下示例所示:-
Puppet supports the concept of condition-based operation. In order to achieve it, If/else statement provides branching options based on the return value of the condition. As shown in the following example −
if $Filename {
file { '/some/file': ensure => present }
} else {
file { '/some/other/file': ensure => present }
}
最新版本的 Puppet 支持变量表达式,其中 if 语句还可基于表达式的值进行分支。
The latest version of Puppet supports variable expression in which the if statement can also branch based on the value of an expression.
if $machine == 'production' {
include ssl
} else {
include nginx
}
为了在代码中实现更多样性并执行复杂的条件操作,Puppet 支持嵌套 if/else 语句,如下面的代码所示。
In order to achieve more diversity in code and perform complex conditional operations, Puppet supports nested if/else statement as shown in the following code.
if $ machine == 'production' {
include ssl
} elsif $ machine == 'testing' {
include nginx
} else {
include openssl
}
Virtual Resource
虚拟资源是那些在未实现时不会发送到客户端的资源。
Virtual resources are those that are not sent to the client unless realized.
下面是 Puppet 中使用虚拟资源的语法。
Following is the syntax of using virtual resource in Puppet.
@user { vipin: ensure => present }
在上例中,用户 vipin 被虚拟定义,以实现可在集中使用该定义。
In the above example, the user vipin is defined virtually to realize the definition one can use in the collection.
User <| title == vipin |>
Comments
注释被用于代码段中,以便对一系列代码行及其功能做出说明。在 Puppet 中,目前支持两种类型的注释。
Comments are used in any code bit to make an additional node about a set of lines of code and its functionality. In Puppet, there are currently two types of supported comments.
-
Unix shell style comments. They can be on their own line or the next line.
-
Multi-line c-style comments.
下面是一个 shell 样式注释示例。
Following is an example of shell style comment.
# this is a comment
下面是一个多行注释示例。
Following is an example of multiline comment.
/*
This is a comment
*/
Operator Precedence
Puppet 运算符优先级符合大多数系统中的标准优先级,从最高到最低。
The Puppet operator precedence conforms to the standard precedence in most systems, from the highest to the lowest.
以下是表达式列表
Following is the list of expressions
-
! = not
-
/ = times and divide
-
- + = minus, plus
-
<< >> = left shift and right shift
-
== != = not equal, equal
-
>= ⇐ > < = greater equal, less or equal, greater than, less than
Comparison Expression
当用户希望在满足给定条件时执行一系列语句时,会使用比较表达式。比较表达式包括使用 == 表达式的相等性测试。
Comparison expression are used when the user wants to execute a set of statements when the given condition is satisfied. Comparison expressions include tests for equality using the == expression.
if $environment == 'development' {
include openssl
} else {
include ssl
}
Not Equal Example
if $environment != 'development' {
$otherenvironment = 'testing'
} else {
$otherenvironment = 'production'
}
Arithmetic Expression
$one = 1
$one_thirty = 1.30
$two = 2.034e-2 $result = ((( $two + 2) / $one_thirty) + 4 * 5.45) -
(6 << ($two + 4)) + (0×800 + -9)
Boolean Expression
可以使用 or、and、& not 来形成布尔表达式。
Boolean expressions are possible using or, and, & not.
$one = 1
$two = 2
$var = ( $one < $two ) and ( $one + 1 == $two )
Regular Expression
Puppet 支持使用 =~(匹配)和 !~(不匹配)进行正则表达式匹配。
Puppet supports regular expression matching using =~ (match) and !~ (not-match).
if $website =~ /^www(\d+)\./ {
notice('Welcome web server #$1')
}
与 case 和 selector 类似,regex match 为每个 regex 创建了一个限定范围的变量。
Like case and selector regex match creates limited scope variable for each regex.
exec { "Test":
command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt",
unless => "/bin/which php"
}
同样,我们可以使用 unless,除非始终执行命令,但除非下的命令成功退出。
Similarly, we can use unless, unless execute the command all the time, except the command under unless exits successfully.
exec { "Test":
command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt",
unless => "/bin/which php"
}
Working with Templates
当希望在木偶的多个模块中使用预定义结构并将在多个机器上分发这些模块时,将使用模板。使用模版的第一个步骤是创建一个使用模版方法呈现模版内容的模版。
Templates are used when one wishes to have a pre-defined structure which is going be used across multiple modules in Puppet and those modules are going to be distributed on multiple machines. The first step in order to use template is to create one that renders the template content with template methods.
file { "/etc/tomcat/sites-available/default.conf":
ensure => "present",
content => template("tomcat/vhost.erb")
}
木偶在处理本地文件时做出了一些假设,以确保组织和模块化。木偶在模块目录中的 apache/templates 文件夹中查找 vhost.erb 模板。
Puppet makes few assumptions when dealing with local files in order to enforce organization and modularity. Puppet looks for vhost.erb template inside the folder apache/templates, inside the modules directory.
Defining and Triggering Services
在木偶中,它有一个称为服务的资源,该资源能够管理在任何特定机器或环境上运行的所有服务的生命周期。服务资源用于确保服务已初始化并启用。它们也用于服务重启。
In Puppet, it has a resource called service which is capable of managing the life cycle of all the services running on any particular machine or environment. Service resources are used to make sure services are initialized and enabled. They are also used for service restart.
例如,在我们设置 apache 虚拟主机的前一个 tomcat 模板中。如果想要确保在虚拟主机更改后重新启动 apache,则需要使用以下命令为 apache 服务创建服务资源。
For example, in the previous template of tomcat that we have where we set the apache virtual host. If one wants to make sure apache is restarted after a virtual host change, we need to create a service resource for the apache service using the following command.
service { 'tomcat':
ensure => running,
enable => true
}
在定义资源时,我们需要包括 notify 选项以触发重新启动。
When defining the resources, we need to include the notify option in order to trigger the restart.
file { "/etc/tomcat/sites-available/default.conf":
ensure => "present",
content => template("vhost.erb"),
notify => Service['tomcat']
}
Puppet - Manifest Files
在Puppet中,使用Ruby编程语言编写的并以 .pp 扩展名保存的所有程序都称为 Puppet代码。一般来说,所有旨在创建或管理任何目标主机机器的Puppet程序都称为清单。所有用Puppet编写的程序都遵循Puppet编码风格。
In Puppet, all the programs which are written using Ruby programming language and saved with an extension of .pp are called manifests. In general terms, all Puppet programs which are built with an intension of creating or managing any target host machine is called a manifest. All the programs written in Puppet follow Puppet coding style.
Puppet的核心是声明资源的方式以及这些资源如何表示其状态。在任何清单中,用户都可以拥有一组不同类型的资源,这些资源使用类和定义分组在一起。
The core of Puppet is the way resources are declared and how these resources are representing their state. In any manifest, the user can have a collection of different kind of resources which are grouped together using class and definition.
在某些情况下,Puppet清单甚至可以包含条件语句,以便实现所需的状态。但是,最终这一切都归结为确保所有资源都得到正确的定义和使用,并且在转换为目录后应用时,定义的清单能够执行其设计任务。
In some cases, Puppet manifest can even have a conditional statement in order to achieve a desired state. However, ultimately it all comes down to make sure that all the resources are defined and used in the right way and the defined manifest when applied after getting converted to a catalog is capable of performing the task for which it was designed.
Manifest File Workflow
Puppet清单由以下组件组成:
Puppet manifest consists of the following components −
-
Files (these are plain files where Puppet has nothing to do with them, just to pick them up and place them in the target location)
-
Resources
-
Templates (these can be used to construct configuration files on the node).
-
Nodes (all the definition related to a client node is defined here)
-
Classes
Points to Note
-
In Puppet, all manifest files use Ruby as their encoding language and get saved with .pp extension.
-
"Import" statement in many manifest are used for loading files when Puppet starts.
-
In order to import all files contained in a directory, you can use the import statement in another way like import 'clients/'. This will import all *.pp files inside that directory.

Writing Manifests
Working with Variables
在编写清单时,用户可以在清单中的任何点定义新变量或使用现有变量。Puppet支持不同类型的变量,但其中几个经常使用,例如字符串和字符串数组。除了它们之外,还支持其他格式。
While writing a manifest, the user can define a new variable or use an existing variable at any point in a manifest. Puppet supports different kind of variables but few of them are frequently used such as strings and array of string. Apart from them, other formats are also supported.
Using Loops
循环用于当满足已定义条件时要对同一组代码执行多次迭代。它们还用于对不同的值集执行重复性任务。为10种不同的东西创建10项任务。可以创建一个单一任务,并使用循环重复想要安装的不同包的任务。
Loops are used when one wishes to go through multiple iterations on a same set of code till a defined condition is met. They are also used to do repetitive tasks with different set of values. Creating 10 tasks for 10 different things. One can create a single task and use a loop to repeat the task with different packages one wants to install.
最常使用数组用不同的值重复测试。
Most commonly an array is used to repeat a test with different values.
$packages = ['vim', 'git', 'curl']
package { $packages:
ensure => "installed"
}
Using Conditionals
Puppet 支持大多数传统编程语言中的条件结构。可以使用条件来动态定义是否执行特定任务或应执行一组代码。例如 if/else 和 case 语句。此外,execute 这样的条件还将支持像条件一样工作的属性,但仅接受命令输出作为条件。
Puppet supports most of the conditional structure which can be found in traditional programming languages. Condition can be used to dynamically define whether to perform a particular task or a set of code should get executed. Like if/else and case statements. Additionally, conditions like execute will also support attributes that works like condition, but only accepts a command output as a condition.
if $OperatingSystem != 'Linux' {
warning('This manifest is not supported on this other OS apart from linux.')
} else {
notify { 'the OS is Linux. We are good to go!': }
}
Puppet - Module
在 Puppet 中,模块可以定义为资源、类、文件、定义和模板的集合。Puppet 支持对模块进行轻松重新分配,这对于代码模块化非常有用,因为人们可以编写一个特定的通用模块,并通过非常简单的代码更改多次使用它。例如,这将在 /etc/puppet 下启用默认的站点配置,在 /etc/share/puppet 下使用 Puppet 自带的模块。
In Puppet, a module can be defined as a collection of resources, classes, files, definition, and templates. Puppet supports easy re-distribution of modules, which is very helpful in modularity of code as one can write a specified generic module and can use it multiple times with very few simple code changes. For example, this will enable default site configuration under /etc/puppet, with modules shipped by Puppet proper in /etc/share/puppet.
Module Configuration
在任何 Puppet 模块中,都有两个分区,有助于定义代码的结构和控制标记。
In any Puppet module, we have two partitions which help in defining the structure of code and controlling the denominates.
-
The search path of modules is configured using colon-separated list of directories in the puppetmasterd or masterd, the later section of Puppet’s master configuration file with the modulepath parameter.
[puppetmasterd]
...
modulepath = /var/lib/puppet/modules:/data/puppet/modules
-
Access control settings for the file server modules in fileserver.conf, the path configuration for that module is always ignored, and specifying a path will produce a warning.
Modules Source
Puppet 支持存储模块的不同位置。任何模块都可以存储在任何特定计算机的不同文件系统中。但是,必须在称为 modulepath 的配置变量中指定存储模块的所有路径,它通常是 Puppet 扫描所有模块目录并在启动时加载它们的路径变量。
Puppet supports a different location for storing modules. Any module can be stored in different file system of any particular machine. However, all the paths where modules are stored must be specified in configuration variable known as modulepath which is in general, a path variable where Puppet scans for all module directories and loads them up when it is booting up.
可以将合理默认路径配置为 -
A reasonable default path can be configured as −
/etc/puppet/modules:/usr/share/puppet:/var/lib/modules.
或者,可以将 /etc/puppet 目录建立为特殊匿名模块,该模块总是首先被搜索。
Alternatively, the /etc/puppet directory could be established as a special anonymous module, which is always searched first.
Module Naming
Puppet 遵循特定模块的相同命名标准,其中模块名称必须是匹配 [-\\w+](字母、单词、数字、下划线和连字符)的正常单词,并且不包含命名空间分隔符:: 或 /。虽然它可能允许关于模块层次结构,但对于新模块,它不能被嵌套。
Puppet follows the same naming standards of a particular module wherein the module name must be normal words, matching [-\\w+] (letter, word, number, underscore and dashes) and not containing the namespace separator: : or /. While it might be allowed regarding module hierarchies, for new modules it cannot be nested.
Module Internal Organization
当用户在 Puppet 中创建新模块时,它遵循相同的结构,并且包含以特定目录结构排列的清单、分配的文件、插件和模板,如下面的代码所示。
When the user creates a new module in Puppet, it follows the same structure and contains manifest, distributed file, plugins, and templates arranged in a specific directory structure as shown in the following code.
MODULE_PATH/
downcased_module_name/
files/
manifests/
init.pp
lib/
puppet/
parser/
functions
provider/
type/
facter/
templates/
README
每当创建一个模块时,它都包含 manifests 目录中的指定修复位置的 init.pp 清单文件。此清单文件是一个默认文件,它在任何特定模块中首先执行并包含与该特定模块相关的所有类的集合。可以将其他 .pp 文件直接添加到 manifests 文件夹下。如果我们正在添加其他 .pp 文件,则应以类命名。
Whenever a module is created, it contains init.pp manifest file at the specified fix location inside manifests directory. This manifest file is a default file which executes first in any particular module and contains a collection of all the classes associated with that particular module. Additional .pp file can be added directly under the manifests folder. If we are adding additional .pp files, they should be named after the class.
使用模块实现的关键功能之一是代码共享。模块本质上应该是自包含的,这意味着应该能够随时随地包含任何模块并将其放到模块路径中,该模块路径会在 Puppet 启动时加载。在模块的帮助下,人们可以在 Puppet 基础设施编码中获得模块化。
One of the key feature achieved by using modules is code sharing. A module by nature should be self-contained which means one should be able to include any module from anywhere and drop it onto the module path, which gets loaded when Puppet boots up. With the help of modules, one gets modularity in Puppet infrastructure coding.

Example
考虑一个 autofs 模块,它安装一个固定的 auto.homes 映射并从模板生成 auto.master。
Consider an autofs module that installs a fixed auto.homes map and generates the auto.master from templates.
class autofs {
package { autofs: ensure => latest }
service { autofs: ensure => running }
file { "/etc/auto.homes":
source => "puppet://$servername/modules/autofs/auto.homes"
}
file { "/etc/auto.master":
content => template("autofs/auto.master.erb")
}
}
文件系统将具有以下文件。
The file system will have the following files.
MODULE_PATH/
autofs/
manifests/
init.pp
files/
auto.homes
templates/
auto.master.erb
Module Lookup
Puppet 遵循预定义的结构,其中按照定义的结构包含多个目录和子目录。这些目录包含不同类型的文件,模块执行某些操作需要这些文件。幕后的少量魔术确保正确的文件与正确的上下文相关联。所有模块搜索都在模块路径中,它是目录的冒号分隔列表。
Puppet follows a pre-defined structure wherein it contains multiple directories and subdirectories in a defined structure. These directories contain different kind of files which are required by a module to perform certain actions. A little behind-the-scenes magic makes sure that the right file is associated with the right context. All module searches are within the modulepath, a colon-separated list of directories.
对于文件服务器上的文件引用,使用类似的引用,以便对 puppet 的引用://$servername/modules/autofs/auto.homes 解析为模块路径中的 autofs/files/auto.homes。
For file references on the fileserver, a similar reference is used so that a reference to puppet: //$servername/modules/autofs/auto.homes resolves to the file autofs/files/auto.homes in the module’s path.
要使模块同时与命令行客户端和 Puppet 主机可用,人们可以使用 puppet:///path 的 URL。即,没有显式服务器名称的 URL。此类 URL 的处理方式稍有不同 Puppet 和 puppetd 。Puppet 在本地文件系统中搜索无服务器 URL。
To make a module usable with both the command line client and a puppet master, one can use a URL of the from puppet:///path. i.e. a URL without an explicit server name. Such URL is treated slightly different by Puppet and puppetd. Puppet searches for serverless URL in the local file system.
模板文件的搜索方式与清单文件和文件类似:提及模板(“autofs/auto.master.erb”)将使 puppetmaster 先在 $templatedir/autofs/auto.master.erb ,然后在模块路径上的 autofs/templates/auto.master.erb 查找文件。使用 Puppet 时,可以利用 Puppet 下所有内容的 Puppet 版本。这称为模块自动加载。Puppet 将尝试从模块自动加载类和定义。
Template files are searched in a manner similar to manifest and files: a mention of template (“autofs/auto.master.erb”) will make the puppetmaster first look for a file in $templatedir/autofs/auto.master.erb and then autofs/templates/auto.master.erb on the module path. With Puppet versions of everything under the Puppet, it is available to use. This is called module auto loading. Puppet will attempt to auto-load classes and definitions from the module.
Puppet - File Server
Puppet 遵循客户端和服务器的概念,其中设置中的一台计算机作为服务器计算机运行 Puppet 服务器软件,而其他计算机作为客户端运行 Puppet 代理软件。文件服务器的此功能有助于在多台计算机之间复制文件。Puppet 中的文件服务功能的此功能是作为中央 Puppet daemon 的一部分提供的。Puppetmasterd 和客户端功能在作为文件对象采购文件属性时扮演着关键角色。
Puppet follows the concept of client and server where one machine in a setup works as the server machine with Puppet server software running on it and the remaining works as the client with Puppet agent software running on it. This feature of the file server helps in copying the files around multiple machines. This feature of file serving function in Puppet comes as a part of central Puppet daemon. Puppetmasterd and the client function plays a key role in sourcing file attributes as the file object.
class { 'java':
package => 'jdk-8u25-linux-x64',
java_alternative => 'jdk1.8.0_25',
java_alternative_path => '/usr/java/jdk1.8.0_25/jre/bin/java'
}
在上面的代码片段中,Puppet 的文件服务函数通过支持文件服务模块抽象了本地文件系统拓扑。我们将以以下方式指定文件服务模块。
As in the above code snippet, Puppet’s file serving functions abstracts the local filesystem topology by supporting the file service module. We will specify the file serving module in the following manner.
“puppet://server/modules/module_name/sudoers”
File Format
在 Puppet 目录结构中,默认情况下文件服务器配置位于 /etc/puppet/fileserver.config 目录下,如果用户希望更改此默认配置文件路径,可以使用 new config 标志 puppetmasterd 来完成。配置文件类似于 INI 文件,但并不完全相同。
In Puppet directory structure, by default the file server configuration is located under /etc/puppet/fileserver.config directory, if the user wishes to change this default configuration file path, it can be done using the new config flag to puppetmasterd. The configuration file resembles INI files but is not exactly the same.
[module]
path /path/to/files
allow *.domain.com
deny *.wireless.domain.com
如上所示的代码片段中,所有三个选项在配置文件中表示。模块名称以某种方式位于括号中。路径是唯一必需的选项。默认安全选项是拒绝所有访问,因此如果没有指定允许行,则将配置的模块可供任何人使用。
As shown in the above code snippet, all the three options are represented in the configuration file. The module name somewhat goes in the brackets. The path is the only required option. Default security option is to deny all the access, so if no allow lines are specified, the module which will be configured will be available to anyone.
路径可以包含任意或全部 %d、%h 和 %H,这些内容会动态替换为其域名、其主机名和完全限定的主机名。所有内容都取自客户端的 SSL 证书(因此,如果主机名与证书名称不匹配,请小心)。当在模块中创建每个客户端的文件完全分开时,这非常有用。例如,用于私有主机密钥。
The path can contain any or all of the %d, %h and %H which are dynamically replaced by its domain name, its host name, and fully qualified host name. All are taken from the client’s SSL certificate (so be careful if one has a mismatch in hostname and certificate name). This is useful is creating modules where the files of each client are kept completely separately. Example, for private host keys.
[private]
path /data/private/%h
allow *
在上面的代码片段中,代码尝试从客户端 client1.vipin.com 中搜索文件/private/file.txt。它将在 /data/private/client1/file.txt 中查找它,而对 client2.vipin.com 的相同请求将尝试在文件服务器上检索文件 /data/private/client2/file.txt。
In the above code snippet, the code is trying to search for file /private/file.txt from the client client1.vipin.com. It will look for it in /data/private/client1/file.txt, while the same request for client2.vipin.com will try to retrieve the file /data/private/client2/file.txt on the file server.
Security
Puppet 支持两种保护 Puppet 文件服务器上文件的基本概念。通过允许访问特定文件并拒绝访问不需要的文件来实现此目的。默认情况下,Puppet 不允许访问任何文件。需要显式定义。可以在文件中使用允许或拒绝访问的格式通过使用 IP 地址、名称或全局允许来定义。
Puppet supports the two basic concepts of securing file on the Puppet file server. This is achieved by allowing access to specific files and denying access to the ones which are not required. By default, Puppet does not allow access to any of the files. It needs to be defined explicitly. The format which can be used in the files to allow or deny access is by using IP address, name, or global allow.
如果客户端没有直接连接到 Puppet 文件服务器,例如使用反向代理和 Mongrel,那么文件服务器将看到所有连接都来自代理服务器,而不是 Puppet 客户端。在上述情况下,根据主机名限制主机名是最佳做法。
If the client is not connected to the Puppet file server directly, for example using a reverse proxy and Mongrel, then the file server will see all the connections as coming from the proxy server and not the Puppet client. In the above cases, restricting the host name on the base of hostname is the best practice.
定义文件结构时需要注意的一个关键点是,所有拒绝声明都在允许声明之前被解析。因此,如果任何拒绝声明与主机匹配,则该主机将被拒绝,并且如果在即将到来的文件中没有写入允许声明,则该主机将被拒绝。此功能有助于设置任何特定网站的优先级。
One key point to be noted while defining the file structure is, all the deny statements are parsed before the allow statement. Hence, if any deny statement matches a host, then that host will be denied and if no allow statement is written in the upcoming files, then the host will be denied. This feature helps in setting priority of any particular site.
Host Name
在任何文件服务器配置中,文件主机名可以通过两种方式指定,一种是使用完整主机名,另一种是使用 * 通配符指定整个域名,如下例所示。
In any file server configuration, file hostname can be specified in two ways either by using a complete hostname or specifying an entire domain name using the * wildcard as shown in the following example.
[export]
path /usr
allow brcleprod001.brcl.com
allow *.brcl.com
deny brcleprod002.brcl.com
IP Address
在任何文件服务器配置中,文件地址都可以指定为类似于主机名,使用完整的 IP 地址或通配符地址。还可以使用 CIDR 系统表示法。
In any file server configuration, the file address can be specified as similar to the host names, using either complete IP address or wildcard address. One can also use CIDR system notation.
[export]
path /usr
allow 127.0.0.1
allow 172.223.30.*
allow 172.223.30.0/24
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 −
-
Core Facts
-
Custom Facts
-
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 −
-
Using the “export FACTER … Syntax”
-
Using the $LOAD_PATH settings
-
FACTERLIB
-
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.
Puppet - Resource
资源是 Puppet 用于设计和构建任何特定基础设施或机器的关键基本单元之一。它们主要用于建模和维护系统配置。Puppet 具有多种类型的资源,可用于定义系统架构或用户具有构建和定义新资源的杠杆。
Resources are one of the key fundamental units of Puppet used to design and build any particular infrastructure or a machine. They are mainly used for modeling and maintaining system configurations. Puppet has multiple type of resources, which can be used to define the system architecture or the user has the leverage to build and define a new resource.
清单文件或任何其他文件中的 Puppet 代码块称为资源声明。该代码块是用一种称为声明建模语言 (DML) 的语言编写的。以下是如何介绍它的示例。
The block of Puppet code in manifest file or any other file is called a resource declaration. The block of code is written in a language called Declarative Modelling Language (DML). Following is an example of how it looks like.
user { 'vipin':
ensure => present,
uid => '552',
shell => '/bin/bash',
home => '/home/vipin',
}
在 Puppet 中,对任何特定资源类型的资源声明都在代码块中完成。在下面的示例中,用户主要由四个预定义的参数组成。
In Puppet, resource declaration for any particular resource type is done in code block. In the following example, the user is made up of mainly four pre-defined parameters.
-
Resource Type − In the above code snippet, it is the user.
-
Resource Parameter − In the above code snippet, it is Vipin.
-
Attributes − In the above code snippet, it is ensure, uid, shell, home.
-
Values − These are the values that correspond to each property.
每种资源类型都有它自己定义定义和参数的一种方式,并且用户享有选择他希望其资源看起来像哪种方式的权利。
Each resource type has its own way of defining definitions and parameters, and the user has the privilege to pick and choose the way he wants his resource to look like.
Resource Type
Puppet 中有不同类型的可用资源,这些资源有它们自己可供使用的功能的方式。这些资源类型可以使用 “描述” 命令与 “-list” 选项一起被查看。
There are different types of resources available in Puppet which have their own way of functionality. These resource types can be viewed using the “describe” command along with the “-list” option.
[root@puppetmaster ~]# puppet describe --list
These are the types known to puppet:
augeas - Apply a change or an array of changes to the ...
computer - Computer object management using DirectorySer ...
cron - Installs and manages cron jobs
exec - Executes external commands
file - Manages files, including their content, owner ...
filebucket - A repository for storing and retrieving file ...
group - Manage groups
host - Installs and manages host entries
interface - This represents a router or switch interface
k5login - Manage the ‘.k5login’ file for a user
macauthorization - Manage the Mac OS X authorization database
mailalias - .. no documentation ..
maillist - Manage email lists
mcx - MCX object management using DirectoryService ...
mount - Manages mounted filesystems, including puttin ...
nagios_command - The Nagios type command
nagios_contact - The Nagios type contact
nagios_contactgroup - The Nagios type contactgroup
nagios_host - The Nagios type host
nagios_hostdependency - The Nagios type hostdependency
nagios_hostescalation - The Nagios type hostescalation
nagios_hostextinfo - The Nagios type hostextinfo
nagios_hostgroup - The Nagios type hostgroup
nagios_service - The Nagios type service
nagios_servicedependency - The Nagios type servicedependency
nagios_serviceescalation - The Nagios type serviceescalation
nagios_serviceextinfo - The Nagios type serviceextinfo
nagios_servicegroup - The Nagios type servicegroup
nagios_timeperiod - The Nagios type timeperiod
notify - .. no documentation ..
package - Manage packages
resources - This is a metatype that can manage other reso ...
router - .. no documentation ..
schedule - Define schedules for Puppet
scheduled_task - Installs and manages Windows Scheduled Tasks
selboolean - Manages SELinux booleans on systems with SELi ...
service - Manage running services
ssh_authorized_key - Manages SSH authorized keys
sshkey - Installs and manages ssh host keys
stage - A resource type for creating new run stages
tidy - Remove unwanted files based on specific crite ...
user - Manage users
vlan - .. no documentation ..
whit - Whits are internal artifacts of Puppet's curr ...
yumrepo - The client-side description of a yum reposito ...
zfs - Manage zfs
zone - Manages Solaris zones
zpool - Manage zpools
Resource Title
在以上代码片段中,我们有唯一资源标题,它在代码的相同文件中用于每个资源,该标题是唯一的。这对于此用户资源类型来说是唯一标题。我们无法拥有一个名称相同资源,因为它会引起冲突。
In the above code snippet, we have resource title as vipin which is unique for each resource used in the same file of the code. This is a unique title for this user resource type. We cannot have a resource with the same name because it will cause conflicts.
可以将资源命令用于查看所有资源的列表,其中包括类型用户。
Resource command can be used to view the list of all the resources using type user.
[root@puppetmaster ~]# puppet resource user
user { 'abrt':
ensure => 'present',
gid => '173',
home => '/etc/abrt',
password => '!!',
password_max_age => '-1',
password_min_age => '-1',
shell => '/sbin/nologin',
uid => '173',
}
user { 'admin':
ensure => 'present',
comment => 'admin',
gid => '444',
groups => ['sys', 'admin'],
home => '/var/admin',
password => '*',
password_max_age => '99999',
password_min_age => '0',
shell => '/sbin/nologin',
uid => '55',
}
user { 'tomcat':
ensure => 'present',
comment => 'tomcat',
gid => '100',
home => '/var/www',
password => '!!',
password_max_age => '-1',
password_min_age => '-1',
shell => '/sbin/nologin',
uid => '100',
}
Listing the Resources of a Particular User
[root@puppetmaster ~]# puppet resource user tomcat
user { 'apache':
ensure => 'present',
comment => 'tomcat',
gid => '100',
home => '/var/www',
password => '!!',
password_max_age => '-1',
password_min_age => '-1',
shell => '/sbin/nologin',
uid => '100’,
}
Attributes & Values
任何资源的主体是由一系列的属性-值对组成的。这里可以指定一个给定资源属性的值。每个资源类型都有它自己的一组属性,这些属性可以由键值对来配置。
The main body of any resource is made up of a collection of attribute-value pairs. Here one can specify the values for a given resource’s property. Each resource type has its own set of attributes that can be configured with the key-value pairs.
描述子命令可以用来获取关于特定资源属性的更多细节。在以下示例中,我们有关用户资源的详细信息及其所有可配置属性。
Describe the sub-command that can be used to get more details about a particular resources attribute. In the following example, we have the details about the user resource along with all its configurable attributes.
[root@puppetmaster ~]# puppet describe user
user
====
Manage users. This type is mostly built to manage system users,
so it is lacking some features useful for managing normal users.
This resource type uses the prescribed native tools for creating groups
and generally uses POSIX APIs for retrieving information about them.
It does not directly modify ‘/etc/passwd’ or anything.
**Autorequires:** If Puppet is managing the user's primary group
(as provided in the ‘gid’ attribute),
the user resource will autorequire that group.
If Puppet is managing any role accounts corresponding to the user's roles,
the user resource will autorequire those role accounts.
Parameters
----------
- **allowdupe**
Whether to allow duplicate UIDs. Defaults to ‘false’.
Valid values are ‘true’, ‘false’, ‘yes’, ‘no’.
- **attribute_membership**
Whether specified attribute value pairs should be treated as the
**complete list** (‘inclusive’) or the **minimum list** (‘minimum’) of
attribute/value pairs for the user. Defaults to ‘minimum’.
Valid values are ‘inclusive’, ‘minimum’.
- **auths**
The auths the user has. Multiple auths should be
specified as an array.
Requires features manages_solaris_rbac.
- **comment**
A description of the user. Generally the user's full name.
- **ensure**
The basic state that the object should be in.
Valid values are ‘present’, ‘absent’, ‘role’.
- **expiry**
The expiry date for this user. Must be provided in
a zero-padded YYYY-MM-DD format --- e.g. 2010-02-19.
If you want to make sure the user account does never
expire, you can pass the special value ‘absent’.
Valid values are ‘absent’. Values can match ‘/^\d{4}-\d{2}-\d{2}$/’.
Requires features manages_expiry.
- **forcelocal**
Forces the mangement of local accounts when accounts are also
being managed by some other NSS
- **gid**
The user's primary group. Can be specified numerically or by name.
This attribute is not supported on Windows systems; use the ‘groups’
attribute instead. (On Windows, designating a primary group is only
meaningful for domain accounts, which Puppet does not currently manage.)
- **groups**
The groups to which the user belongs. The primary group should
not be listed, and groups should be identified by name rather than by
GID. Multiple groups should be specified as an array.
- **home**
The home directory of the user. The directory must be created
separately and is not currently checked for existence.
- **ia_load_module**
The name of the I&A module to use to manage this user.
Requires features manages_aix_lam.
- **iterations**
This is the number of iterations of a chained computation of the
password hash (http://en.wikipedia.org/wiki/PBKDF2). This parameter
is used in OS X. This field is required for managing passwords on OS X
>= 10.8.
Requires features manages_password_salt.
- **key_membership**
- **managehome**
Whether to manage the home directory when managing the user.
This will create the home directory when ‘ensure => present’, and
delete the home directory when ‘ensure => absent’. Defaults to ‘false’.
Valid values are ‘true’, ‘false’, ‘yes’, ‘no’.
- **membership**
Whether specified groups should be considered the **complete list**
(‘inclusive’) or the **minimum list** (‘minimum’) of groups to which
the user belongs. Defaults to ‘minimum’.
Valid values are ‘inclusive’, ‘minimum’.
- **name**
The user name. While naming limitations vary by operating system,
it is advisable to restrict names to the lowest common denominator,
which is a maximum of 8 characters beginning with a letter.
Note that Puppet considers user names to be case-sensitive, regardless
of the platform's own rules; be sure to always use the same case when
referring to a given user.
- **password**
The user's password, in whatever encrypted format the local
system requires.
* Most modern Unix-like systems use salted SHA1 password hashes. You can use
Puppet's built-in ‘sha1’ function to generate a hash from a password.
* Mac OS X 10.5 and 10.6 also use salted SHA1 hashes.
Windows API
for setting the password hash.
[stdlib]: https://github.com/puppetlabs/puppetlabs-stdlib/
Be sure to enclose any value that includes a dollar sign ($) in single
quotes (') to avoid accidental variable interpolation.
Requires features manages_passwords.
- **password_max_age**
The maximum number of days a password may be used before it must be changed.
Requires features manages_password_age.
- **password_min_age**
The minimum number of days a password must be used before it may be changed.
Requires features manages_password_age.
- **profile_membership**
Whether specified roles should be treated as the **complete list**
(‘inclusive’) or the **minimum list** (‘minimum’) of roles
of which the user is a member. Defaults to ‘minimum’.
Valid values are ‘inclusive’, ‘minimum’.
- **profiles**
The profiles the user has. Multiple profiles should be
specified as an array.
Requires features manages_solaris_rbac.
- **project**
The name of the project associated with a user.
Requires features manages_solaris_rbac.
- **uid**
The user ID; must be specified numerically. If no user ID is
specified when creating a new user, then one will be chosen
automatically. This will likely result in the same user having
different UIDs on different systems, which is not recommended. This is
especially noteworthy when managing the same user on both Darwin and
other platforms, since Puppet does UID generation on Darwin, but
the underlying tools do so on other platforms.
On Windows, this property is read-only and will return the user's
security identifier (SID).
Puppet - Resource Abstraction Layer
在木偶中,资源抽象层 (RAL) 可以被视为整个基础设施和木偶设置工作的核心概念化模型。在 RAL 中,每个字母都有自己重要的含义,定义如下。
In Puppet, Resource Abstraction Layer (RAL) can be considered as the core conceptualized model on which the whole infrastructure and Puppet setup works. In RAL, each alphabet has its own significant meaning which is defined as follows.
Resource [R]
资源可以被视为在木偶中用于对任何配置进行建模的所有资源。它们基本上是内置资源,默认情况下存在于木偶中。它们可以被认为属于预定义资源类型的资源集。它们类似于任何其他编程语言中的 OOP 概念,其中对象是类的实例。在木偶中,它的资源是资源类型的实例。
A resource can be considered as all the resources which are used to model any configuration in Puppet. They are basically in-built resources which are by default present in Puppet. They can be considered as a set of resources belonging to a pre-defined resource type. They are similar to OOP concept in any other programming language wherein the object is an instance of class. In Puppet, its resource is an instance of a resource type.
Abstraction [A]
抽象可以被视为一个关键特性,其中资源独立于目标操作系统定义。换句话说,在编写任何清单文件时,用户不必担心目标机器或 OS,这是存在于该特定机器上的。在抽象中,资源提供有关木偶代理上需要存在什么内容的足够信息。
Abstraction can be considered as a key feature where the resources are defined independently from the target OS. In other words, while writing any manifest file the user need not worry about the target machine or the OS, which is present on that particular machine. In abstraction, resources give enough information about what needs to exist on the Puppet agent.
木偶将负责所有在幕后发生的功能或魔术。无论资源和 OS 如何,木偶都将负责在目标机器上实现配置,其中用户不必担心木偶在幕后如何操作。
Puppet will take care of all the functionalities or magic happening behind the scene. Regardless of the resources and OS, Puppet will take care of implementing the configuration on the target machine, wherein the user need not worry how Puppet does behind the scenes.
在抽象中,木偶将资源与其实现分开。这种特定于平台的配置存在于提供程序中。我们可以使用其提供程序与多个子命令。
In abstraction, Puppet separates out the resources from its implementation. This platformspecific configuration exists from providers. We can use multiple subcommands along with its providers.
Layer [L]
有可能根据资源集合定义整个机器设置和配置,并且可以通过木偶的 CLI 界面查看和管理它。
It is possible that one defines an entire machine setup and configuration in terms of collection of resources, and it can be viewed and managed via Puppet’s CLI interface.
Example for User Resource Type
[root@puppetmaster ~]# puppet describe user --providers
user
====
Manage users.
This type is mostly built to manage systemusers,
so it is lacking some features useful for managing normalusers.
This resource type uses the prescribed native tools for
creating groups and generally uses POSIX APIs for retrieving informationabout them.
It does not directly modify '/etc/passwd' or anything.
- **comment**
A description of the user. Generally the user's full name.
- **ensure**
The basic state that the object should be in.
Valid values are 'present', 'absent', 'role'.
- **expiry**
The expiry date for this user.
Must be provided in a zero-padded YYYY-MM-DD format --- e.g. 2010-02-19.
If you want to make sure the user account does never expire,
you can pass the special value 'absent'.
Valid values are 'absent'.
Values can match '/^\d{4}-\d{2}-\d{2}$/'.
Requires features manages_expiry.
- **forcelocal**
Forces the management of local accounts when accounts are also
being managed by some other NSS
Valid values are 'true', 'false', 'yes', 'no'.
Requires features libuser.
- **gid**
The user's primary group. Can be specified numerically or by name.
This attribute is not supported on Windows systems; use the ‘groups’
attribute instead. (On Windows, designating a primary group is only
meaningful for domain accounts, which Puppet does not currently manage.)
- **groups**
The groups to which the user belongs. The primary group should
not be listed, and groups should be identified by name rather than by
GID. Multiple groups should be specified as an array.
- **home**
The home directory of the user. The directory must be created
separately and is not currently checked for existence.
- **ia_load_module**
The name of the I&A module to use to manage this user.
Requires features manages_aix_lam.
- **iterations**
This is the number of iterations of a chained computation of the
password hash (http://en.wikipedia.org/wiki/PBKDF2).
This parameter is used in OS X.
This field is required for managing passwords on OS X >= 10.8.
- **key_membership**
Whether specified key/value pairs should be considered the
**complete list** ('inclusive') or the **minimum list** ('minimum') of
the user's attributes. Defaults to 'minimum'.
Valid values are 'inclusive', 'minimum'.
- **keys**
Specify user attributes in an array of key = value pairs.
Requires features manages_solaris_rbac.
- **managehome**
Whether to manage the home directory when managing the user.
This will create the home directory when 'ensure => present', and
delete the home directory when ‘ensure => absent’. Defaults to ‘false’.
Valid values are ‘true’, ‘false’, ‘yes’, ‘no’.
- **membership**
Whether specified groups should be considered the **complete list**
(‘inclusive’) or the **minimum list** (‘minimum’) of groups to which
the user belongs. Defaults to ‘minimum’.
Valid values are ‘inclusive’, ‘minimum’.
- **name**
The user name. While naming limitations vary by operating system,
it is advisable to restrict names to the lowest common denominator.
- **password**
The user's password, in whatever encrypted format the local system requires.
* Most modern Unix-like systems use salted SHA1 password hashes. You can use
Puppet's built-in ‘sha1’ function to generate a hash from a password.
* Mac OS X 10.5 and 10.6 also use salted SHA1 hashes.
* Mac OS X 10.7 (Lion) uses salted SHA512 hashes.
The Puppet Labs [stdlib][] module contains a ‘str2saltedsha512’
function which can generate password hashes for Lion.
* Mac OS X 10.8 and higher use salted SHA512 PBKDF2 hashes.
When managing passwords on these systems the salt and iterations properties
need to be specified as well as the password.
[stdlib]: https://github.com/puppetlabs/puppetlabs-stdlib/
Be sure to enclose any value that includes a dollar sign ($) in single
quotes (') to avoid accidental variable interpolation.
Requires features manages_passwords.
- **password_max_age**
The maximum number of days a password may be used before it must be changed.
Requires features manages_password_age.
- **password_min_age**
The minimum number of days a password must be used before it may be changed.
Requires features manages_password_age.
- **profile_membership**
Whether specified roles should be treated as the **complete list**
(‘inclusive’) or the **minimum list** (‘minimum’) of roles
of which the user is a member. Defaults to ‘minimum’.
Valid values are ‘inclusive’, ‘minimum’.
- **profiles**
The profiles the user has. Multiple profiles should be
specified as an array.
Requires features manages_solaris_rbac.
- **project**
The name of the project associated with a user.
Requires features manages_solaris_rbac.
- **purge_ssh_keys**
Purge ssh keys authorized for the user
if they are not managed via ssh_authorized_keys.
When true, looks for keys in .ssh/authorized_keys in the user's home directory.
Possible values are true, false, or an array of
paths to file to search for authorized keys.
If a path starts with ~ or %h, this token is replaced with the user's home directory.
Valid values are ‘true’, ‘false’.
- **role_membership**
Whether specified roles should be considered the **complete list**
(‘inclusive’) or the **minimum list** (‘minimum’) of roles the user has.
Defaults to ‘minimum’.
Valid values are ‘inclusive’, ‘minimum’.
- **roles**
The roles the user has. Multiple roles should be
specified as an array.
Requires features manages_solaris_rbac.
- **salt**
This is the 32 byte salt used to generate the PBKDF2 password used in
OS X. This field is required for managing passwords on OS X >= 10.8.
Requires features manages_password_salt.
- **shell**
The user's login shell. The shell must exist and be
executable.
This attribute cannot be managed on Windows systems.
Requires features manages_shell.
- **system**
Whether the user is a system user, according to the OS's criteria;
on most platforms, a UID less than or equal to 500 indicates a system
user. Defaults to ‘false’.
Valid values are ‘true’, ‘false’, ‘yes’, ‘no’.
- **uid**
The user ID; must be specified numerically. If no user ID is
specified when creating a new user, then one will be chosen
automatically. This will likely result in the same user having
different UIDs on different systems, which is not recommended.
This is especially noteworthy when managing the same user on both Darwin and
other platforms, since Puppet does UID generation on Darwin, but
the underlying tools do so on other platforms.
On Windows, this property is read-only and will return the user's
security identifier (SID).
Providers
---------
- **aix**
User management for AIX.
* Required binaries: '/bin/chpasswd', '/usr/bin/chuser',
'/usr/bin/mkuser', '/usr/sbin/lsgroup', '/usr/sbin/lsuser',
'/usr/sbin/rmuser'.
* Default for ‘operatingsystem’ == ‘aix’.
* Supported features: ‘manages_aix_lam’, ‘manages_expiry’,
‘manages_homedir’, ‘manages_password_age’, ‘manages_passwords’,
‘manages_shell’.
- **directoryservice**
User management on OS X.
* Required binaries: ‘/usr/bin/dscacheutil’, ‘/usr/bin/dscl’,
‘/usr/bin/dsimport’, ‘/usr/bin/plutil’, ‘/usr/bin/uuidgen’.
* Default for ‘operatingsystem’ == ‘darwin’.
* Supported features: ‘manages_password_salt’, ‘manages_passwords’,
‘manages_shell’.
- **hpuxuseradd**
User management for HP-UX. This provider uses the undocumented ‘-F’
switch to HP-UX's special ‘usermod’ binary to work around the fact that
its standard ‘usermod’ cannot make changes while the user is logged in.
* Required binaries: ‘/usr/sam/lbin/useradd.sam’,
‘/usr/sam/lbin/userdel.sam’, ‘/usr/sam/lbin/usermod.sam’.
* Default for ‘operatingsystem’ == ‘hp-ux’.
* Supported features: ‘allows_duplicates’, ‘manages_homedir’,
‘manages_passwords’.
- **ldap**
User management via LDAP.
This provider requires that you have valid values for all of the
LDAP-related settings in ‘puppet.conf’, including ‘ldapbase’.
You will almost definitely need settings for ‘ldapuser’ and ‘ldappassword’ in order
for your clients to write to LDAP.
* Supported features: ‘manages_passwords’, ‘manages_shell’.
- **pw**
User management via ‘pw’ on FreeBSD and DragonFly BSD.
* Required binaries: ‘pw’.
* Default for ‘operatingsystem’ == ‘freebsd, dragonfly’.
* Supported features: ‘allows_duplicates’, ‘manages_expiry’,
‘manages_homedir’, ‘manages_passwords’, ‘manages_shell’.
- **user_role_add**
User and role management on Solaris, via ‘useradd’ and ‘roleadd’.
* Required binaries: ‘passwd’, ‘roleadd’, ‘roledel’, ‘rolemod’,
‘useradd’, ‘userdel’, ‘usermod’.
* Default for ‘osfamily’ == ‘solaris’.
* Supported features: ‘allows_duplicates’, ‘manages_homedir’,
‘manages_password_age’, ‘manages_passwords’, ‘manages_solaris_rbac’.
- **useradd**
User management via ‘useradd’ and its ilk. Note that you will need to
install Ruby's shadow password library (often known as ‘ruby-libshadow’)
if you wish to manage user passwords.
* Required binaries: ‘chage’, ‘luseradd’, ‘useradd’, ‘userdel’, ‘usermod’.
* Supported features: ‘allows_duplicates’, ‘libuser’, ‘manages_expiry’,
‘manages_homedir’, ‘manages_password_age’, ‘manages_passwords’,
‘manages_shell’, ‘system_users’.
- **windows_adsi**
Local user management for Windows.
* Default for 'operatingsystem' == 'windows'.
* Supported features: 'manages_homedir', 'manages_passwords'.
Testing Resource
在木偶中,直接测试资源表示需要首先应用要用于配置目标节点的资源,以便机器状态相应地发生变化。
In Puppet, testing a resource directly indicates that one needs to first apply resources which one wants to use to configures a target node, so that the state of the machine changes accordingly.
对于测试,我们将在本地应用资源。由于我们上面预定义了一个资源 user = vipin 。应用资源的一种方法是使用 CLI。可以通过将完整资源重写为单个命令,然后将其传递给资源子命令来完成此操作。
For testing we are going to apply the resource locally. As we have a resource predefined above with user = vipin. One way of applying a resource is by CLI. This can be done by re-writing the complete resource into a single command and then passing it to a resource sub command.
puppet resource user vipin ensure = present uid = '505'
shell = '/bin/bash' home = '/home/vipin'
测试已应用的资源。
Test the applied resource.
[root@puppetmaster ~]# cat /etc/passwd | grep "vipin"
vipin:x:505:501::/home/vipin:/bin/bash
以上输出显示该资源已应用到系统,并且我们创建了一个名为 Vipin 的新用户。建议您自行测试此问题,因为上述所有代码均已测试并且正在使用代码。
The above output shows that the resource is applied to the system and we have a new user created with the name of Vipin. It is advisable that you test this on your own as all the above codes are tested and are working codes.
Puppet - Template
Templating 是一种以标准格式获取内容的方法,该格式可以用于多个位置。在 Puppet 中,使用作为标准 Ruby 库一部分的 erb 支持模板和模板,除了 Ruby 项目(例如在 Ruby on Rails 项目中)之外,还可以用于其他项目。作为标准做法,需要对 Ruby 有基本的了解。当用户尝试管理模板文件的内容时,模板化非常有用。当配置无法通过内置 Puppet 类型管理时,模板发挥着关键作用。
Templating is a method of getting things in a standard format, which can be used in multiple locations. In Puppet, templating and templates are supported using erb which comes as a part of standard Ruby library, which can be used on other projects apart from Ruby like in Ruby on Rails projects. As a standard practice, one needs to have a basic understanding of Ruby. Templating is very helpful when the user is trying to manage content of a template file. Templates plays a key role when configurations cannot be managed by a built-in Puppet type.
Evaluating Templates
使用简单函数评估模板。
Templates are evaluated using simple functions.
$value = template ("testtemplate.erb")
可以指定模板的完整路径,也可以在 Puppet 的 template 中提取所有模板,该模板通常位于 /var/puppet/templates。可以通过运行 puppet –-configprint templatedir 来查找目录位置。
One can specify the full path of a template or one can pull all templates in Puppet’s templatedir, which is usually located at /var/puppet/templates. One can find the directory location by running the puppet –-configprint templatedir.
模板始终由解析器评估,而不是客户端,这意味着如果使用 puppetmasterd,则模板只需在服务器上,而无需将其下载到客户端。客户端在使用模板和将文件的所有内容指定为字符串之间的区别上没有区别。这清楚地表明,在 puppet 启动阶段,puppetmasterd 首先学习客户端特定的变量。
Templates are always evaluated by the parser, not the client which means that if one is using puppetmasterd, then the template only needs to be on the server and one never needs to download them to the client. There’s no difference on how the client sees between using a template and specifying all the content of a file as a string. This clearly indicates that client-specific variables are learned first by puppetmasterd during the puppet startup phase.
Using Templates
以下是为测试站点生成 Tomcat 配置的示例。
Following is an example of generating the tomcat configuration for testing sites.
define testingsite($cgidir, $tracdir) {
file { "testing-$name":
path => "/etc/tomcat/testing/$name.conf",
owner => superuser,
group => superuser,
mode => 644,
require => File[tomcatconf],
content => template("testsite.erb"),
notify => Service[tomcat]
}
symlink { "testsym-$name":
path => "$cgidir/$name.cgi",
ensure => "/usr/share/test/cgi-bin/test.cgi"
}
}
以下是模板定义。
Following is the template definition.
<Location "/cgi-bin/ <%= name %>.cgi">
SetEnv TEST_ENV "/export/svn/test/<%= name %>"
</Location>
# You need something like this to authenticate users
<Location "/cgi-bin/<%= name %>.cgi/login">
AuthType Basic
AuthName "Test"
AuthUserFile /etc/tomcat/auth/svn
Require valid-user
</Location>
这会将每个模板文件推入一个单独的文件,然后只需告诉 Apache 加载这些配置文件。
This pushes each template file into a separate file and then one needs to just tell Apache to load these configuration files.
Include /etc/apache2/trac/[^.#]*
Combining Templates
可以使用以下命令轻松组合两个模板。
Two templates can be easily combined using the following command.
template('/path/to/template1','/path/to/template2')
Iteration in Templates
Puppet 模板还支持数组迭代。如果变量访问的是一个数组,那么可以在其上进行迭代。
Puppet template also supports array iteration. If the variable one is accessing is an array, then one can iterate over it.
$values = [val1, val2, otherval]
我们可以创建如下模板。
We can have templates like the following.
<% values.each do |val| -%>
Some stuff with <%= val %>
<% end -%>
上述命令将产生以下结果。
The above command will produce the following result.
Some stuff with val1
Some stuff with val2
Some stuff with otherval
Conditions in Templates
erb 模板化支持条件。以下结构是一种快速简便的方法,可以有条件地将内容放入文件中。
The erb templating supports conditionals. The following construct is a quick and easy way to conditionally put a content in a file.
<% if broadcast != "NONE" %> broadcast <%= broadcast %> <% end %>
Templates and Variables
除了填充文件内容外,还可以使用模板来填充变量。
One can use templates to fill in variables in addition to filling out the file content.
testvariable = template('/var/puppet/template/testvar')
Undefined Variable
如果需要在使用变量之前检查变量是否已定义,则可以使用以下命令。
If one needs to check if the variable is defined before using it, the following command works.
<% if has_variable?("myvar") then %>
myvar has <%= myvar %> value
<% end %>
Out of Scope Variable
可以使用 lookupvar 函数明确查找范围外的变量。
One can look for out of scope variable explicitly with the lookupvar function.
<%= scope.lookupvar('apache::user') %>
Sample Project Template
<#Autogenerated by puppet. Do not edit.
[default]
#Default priority (lower value means higher priority)
priority = <%= @priority %>
#Different types of backup. Will be done in the same order as specified here.
#Valid options: rdiff-backup, mysql, command
backups = <% if @backup_rdiff %>rdiff-backup,
<% end %><% if @backup_mysql %>mysql,
<% end %><% if @backup_command %>command<% end %>
<% if @backup_rdiff -%>
[rdiff-backup]
<% if @rdiff_global_exclude_file -%>
global-exclude-file = <%= @rdiff_global_exclude_file %>
<% end -%>
<% if @rdiff_user -%>
user = <%= @rdiff_user %>
<% end -%>
<% if @rdiff_path -%>
path = <%= @rdiff_path %>
<% end -%>
#Optional extra parameters for rdiff-backup
extra-parameters = <%= @rdiff_extra_parameters %>
#How long backups are going to be kept
keep = <%= @rdiff_keep %>
<% end -%>
<% if @backup_mysql -%>%= scope.lookupvar('apache::user') %>
[mysql]
#ssh user to connect for running the backup
sshuser = <%= @mysql_sshuser %>
#ssh private key to be used
sshkey = <%= @backup_home %>/<%= @mysql_sshkey %>
<% end -%>
<% if @backup_command -%>
[command]
#Run a specific command on the backup server after the backup has finished
command = <%= @command_to_execute %>
<% end -%>
Puppet - Classes
Puppet 类定义为资源的集合,这些资源被分组在一起,以便使目标节点或机器处于所需状态。这些类在位于 Puppet 模块中的 Puppet 清单文件中定义。使用类的主要目的是减少任何清单文件或任何其他 Puppet 代码中的相同代码重复。
Puppet classes are defined as a collection of resources, which are grouped together in order to get a target node or machine in a desired state. These classes are defined inside Puppet manifest files which is located inside Puppet modules. The main purpose of using a class is to reduce the same code repetition inside any manifest file or any other Puppet code.
以下是 Puppet 类的示例。
Following is an example of Puppet class.
[root@puppetmaster manifests]# cat site.pp
class f3backup (
$backup_home = '/backup',
$backup_server = 'default',
$myname = $::fqdn,
$ensure = 'directory',
) {
include '::f3backup::common'
if ( $myname == '' or $myname == undef ) {
fail('myname must not be empty')
}
@@file { "${backup_home}/f3backup/${myname}":
# To support 'absent', though force will be needed
ensure => $ensure,
owner => 'backup',
group => 'backup',
mode => '0644',
tag => "f3backup-${backup_server}",
}
}
在上面的示例中,我们有两个用户需要存在的客户端。如可以注意到的,我们重复了相同资源两次。一种不执行相同任务的方法是组合两个节点。
In the above example, we have two clients where the user needs to exist. As can be noticed we have repeated the same resource twice. One way of not doing the same task in combining the two nodes.
[root@puppetmaster manifests]# cat site.pp
node 'Brcleprod001','Brcleprod002' {
user { 'vipin':
ensure => present,
uid => '101',
shell => '/bin/bash',
home => '/home/homer',
}
}
以这种方式合并节点来执行配置不是一个好习惯。这可以通过创建一个类,并将创建的类包含在节点中来轻松实现,如下所示。
Merging nodes in this fashion to perform the configuration is not a good practice. This can be simply achieved by creating a class and including the created class in nodes which is shown as follows.
class vipin_g01063908 {
user { 'g01063908':
ensure => present,
uid => '101',
shell => '/bin/bash',
home => '/home/g01063908',
}
}
node 'Brcleprod001' {
class {vipin_g01063908:}
}
node 'Brcleprod002' {
class {vipin_g01063908:}
}
需要注意的是类结构的外观,以及我们如何使用 class 关键字添加新资源。Puppet 中的每个语法都有其自己的特征。因此,选择哪种语法取决于条件。
The point to be noticed is how the class structure looks like and how we added a new resource using the class keyword. Each syntax in Puppet has its own feature. Hence, the syntax one picks depend on the conditions.
Parameterized Class
如上面的示例中所示,我们已经了解了如何创建类并将其包含在节点中。现在,有时我们需要在每个节点上具有不同的配置,例如当需要使用同一类在每个节点上具有不同用户时。此功能在 Puppet 中使用参数化类提供。新类的配置将如下面的示例所示。
As in the above example, we have seen how to create a class and include it in a node. Now there are situations when we need to have different configurations on each node such as when one needs to have different users on each node using the same class. This feature is provided in Puppet using parameterized class. The configuration for a new class will look as shown in the following example.
[root@puppetmaster ~]# cat /etc/puppet/manifests/site.pp
class user_account ($username){
user { $username:
ensure => present,
uid => '101',
shell => '/bin/bash',
home => "/home/$username",
}
}
node 'Brcleprod002' {
class { user_account:
username => "G01063908",
}
}
node 'Brcleprod002' {
class {user_account:
username => "G01063909",
}
}
当我们对节点应用上述 site.pp 清单时,每个节点的输出将如下所示。
When we apply the above site.pp manifest on nodes, then the output for each node will look like the following.
Brcleprod001
[root@puppetagent1 ~]# puppet agent --test
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for puppetagent1.testing.dyndns.org
Info: Applying configuration version '1419452655'
Notice: /Stage[main]/User_account/User[homer]/ensure: created
Notice: Finished catalog run in 0.15 seconds
[root@brcleprod001 ~]# cat /etc/passwd | grep "vipin"
G01063908:x:101:501::/home/G01063909:/bin/bash
Brcleprod002
[root@Brcleprod002 ~]# puppet agent --test
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for puppetagent2.testing.dyndns.org
Info: Applying configuration version '1419452725'
Notice: /Stage[main]/User_account/User[bart]/ensure: created
Notice: Finished catalog run in 0.19 seconds
[root@puppetagent2 ~]# cat /etc/passwd | grep "varsha"
G01063909:x:101:501::/home/G01063909:/bin/bash
还可以设置类参数的默认值,如以下代码所示。
One can also set the default value of a class parameter as shown in the following code.
[root@puppetmaster ~]# cat /etc/puppet/manifests/site.pp
class user_account ($username = ‘g01063908'){
user { $username:
ensure => present,
uid => '101',
shell => '/bin/bash',
home => "/home/$username",
}
}
node 'Brcleprod001' {
class {user_account:}
}
node 'Brcleprod002' {
class {user_account:
username => "g01063909",
}
}
Puppet - Function
自 Puppet 的基本开发语言是 Ruby 以来,Puppet 提供支持函数,就像其他任何编程语言一样。它支持两种类型的函数,即 statement 和 rvalue 函数。
Puppet supports functions as any other programming language since the base development language of Puppet is Ruby. It supports two types of functions known with the name of statement and rvalue functions.
-
Statements stand on their own and they do not have any return type. They are used for performing standalone tasks like importing other Puppet modules in the new manifest file.
-
Rvalue returns values and can only be used when the statement requires a value, such as an assignment or a case statement.
在 Puppet 中执行函数的关键在于,它只在 Puppet 主服务器上执行,而不会在客户端或 Puppet 代理上执行。因此,它们只能访问 Puppet 主服务器上可用的命令和数据。已有不同种类的函数,甚至用户有权根据要求创建自定义函数。下面列举了一些内置函数。
The key behind the execution of function in Puppet is, it only executes on Puppet master and they do not execute on the client or the Puppet agent. Therefore, they only have access to the commands and data available on the Puppet master. There are different kind of functions which are already present and even the user has the privilege to create custom functions as per requirement. Few inbuilt functions are listed below.
File Function
文件资源的文件函数是加载 Puppet 模块并以字符串形式返回所需输出。它查找的参数是 <module name>/<file> 引用,有助于从 Puppet 模块的文件目录加载模块。
File function of the file resource is to load a module in Puppet and return the desired output in the form of a string. The arguments that it looks for is, the <module name>/<file> reference, which helps in loading the module from Puppet module’s file directory.
例如 script/tesingscript.sh 将从 <module name>/script/files/testingscript.sh 加载文件。该函数能够读取和接受绝对路径,有助于在磁盘上的任何位置加载该文件。
Like script/tesingscript.sh will load the files from <module name>/script/files/testingscript.sh. Function has the capability to read and accept an absolute path, which helps in loading the file from anywhere on the disk.
Include Function
在 Puppet 中,include 函数与任何其他编程语言中的 include 函数非常相似。它用于声明一个或多个类,从而评估这些类中存在的所有资源,并最终将它们添加到目录中。它的工作方式是,include 函数接受类名称、类列表或用逗号分隔的类名称列表。
In Puppet, the include function is very much similar to the include function in any other programming language. It is used for declaration of one or more classes, which results in evaluating all the resources present inside those classes and finally add them to a catalog. The way it works is, include function accepts a class name, list of classes or a comma separated list of class names.
使用 include 语句时,需要注意的一件事是,它可以在一个类中多次使用,但仅限于一次包含一个类。如果包含的类接受参数,则 include 函数将自动使用 <类名称>::<参数名称> 作为查找键为其查找值。
One thing to keep in mind while using an include statement is, it can be used multiple times in a class but has the limitation of including a single class only once. If the included class accepts a parameter, the include function will automatically look up values for them using <class name>::<parameter name> as the lookup key.
include 函数不会在声明类时导致类包含在该类中,为此,我们需要使用 contained 函数。它甚至不会在声明的类及其周围类中创建依赖关系。
Include function does not cause a class to be contained in the class when they are declared, for that we need to use a contained function. It even does not create a dependency in the declared class and classes surrounding it.
在 include 函数中,仅允许使用类的全名,不允许相对名称。
In include function, only the full name of a class is allowed, relative names are not allowed.
Defined Function
在 Puppet 中,defined 函数有助于确定给定的类或资源类型在哪里被定义,并返回一个布尔值或非布尔值。还可以使用 define 来确定是否定义了特定资源,或者定义的变量是否有值。在使用 defined 函数时要记住的关键点是,此函数至少接受一个字符串参数,该参数可以是类名、类型名、资源引用或形式为“$name”的变量引用。
In Puppet, the defined function helps in determining where a given class or resource type is defined and returns a Boolean value or not. One can also use define to determine whether a specific resource is defined or the variable defined has a value. Key point to keep in mind while using the defined function is, this function takes at least one string argument, which can be a class name, type name, resource reference, or variable reference of the form “$name”.
defined 函数检查本机和定义的函数类型,包括模块提供的类型。类型和类通过其名称匹配。该函数使用资源引用匹配资源声明。
Define function checks for both native and defined function type, including types provided by modules. Type and class are matched by their names. The function matches the resource deceleration by using the resource reference.
Puppet - Custom Functions
正如前一章所述,函数为用户提供了开发自定义函数的权限。Puppet 可以通过使用自定义函数来扩展其解释能力。自定义函数有助于增强和扩展 Puppet 模块和清单文件的能力。
As described in the previous chapter, function provides the user with a privilege of developing custom functions. Puppet can extend its interpretation power by using custom functions. Custom function helps in increasing and extending the power of Puppet modules and manifest files.
Writing Custom Function
在编写函数之前,有一些事项需要牢记。
There are few things which one needs to keep in mind before writing a function.
-
In Puppet, functions are executed by compilers which means all the functions run on Puppet master and they don’t need to deal with any of the Puppet client for the same. Functions can only interact with agents, provided information is in the form of facts.
-
The Puppet master catches custom functions which means that one needs to restart the Puppet master, if one does some changes in Puppet function.
-
Function will be executed on the server which means any file that the function needs should be present on the server, and one can’t do anything if the function requires direct access to the client machine.
-
There are completely two different type of functions available, one is the Rvalue function which returns the value and the statement function which does not return anything.
-
The name of the file containing function should be the same as the name of the function in the file. Otherwise, it will not get loaded automatically.
Location to Put Custom Function
所有自定义函数都作为单独的 .rb 文件实现,并分布在模块中。需要将自定义函数放入 lib/puppet/parser/function 中。可以从以下位置从 .rb 文件加载函数。
All the custom functions are implemented as separate .rb files and are distributed among modules. One needs to put custom functions in lib/puppet/parser/function. Functions can be loaded from .rb file from the following locations.
-
$libdir/puppet/parser/functions
-
puppet/parser/functions sub-directories in your Ruby $LOAD_PATH
Creating a New Function
使用 newfunction 方法在 puppet::parser::Functions 模块中创建或定义新函数。需要将函数名称作为符号传递给 newfunction 方法,并作为块传递要运行的代码。以下示例是一个函数,它用于将一个字符串写入 /user 目录中的文件。
New functions are created or defined using the newfunction method inside the puppet::parser::Functions module. One needs to pass the function name as a symbol to newfunction method and the code to run as a block. The following example is a function, which is used to write a string to the file inside the /user directory.
module Puppet::Parser::Functions
newfunction(:write_line_to_file) do |args|
filename = args[0]
str = args[1]
File.open(filename, 'a') {|fd| fd.puts str }
end
end
一旦用户声明了该函数,就可以在清单文件中使用,如下所示。
Once the user has the function declared, it can be used in the manifest file as shown below.
write_line_to_file('/user/vipin.txt, "Hello vipin!")
Puppet - Environment
在软件开发和交付模型中,有不同类型的测试环境,用于测试特定产品或服务。作为标准实践,主要有三种类型的环境,如开发、测试和生产,其中每一种都有自己的配置集。
In software development and delivery model, there are different kind of testing environments which are used for testing a particular product or a service. As a standard practice, there are mainly three kind of environments as development, testing and production, wherein each of them have their own set configuration.
Puppet 支持管理与 Ruby on Rails 相同的多个环境。创建这些环境的关键因素是为管理不同级别的 SLA 协议提供一种轻松的机制。在某些情况下,机器始终需要保持启用状态,且没有任何容忍度和旧软件的使用。其他环境则为最新状态,并用于测试目的。它们用于更重要机器的升级。
Puppet supports the management of multiple environment along the same line as Ruby on Rails. The key factor behind the creation of these environments is providing an easy mechanism for managing at different levels of SLA agreement. In some cases, the machine always needs to be up without any tolerance and use of old software. Wherein other environments are up-to-date and are used for testing purposes. They are used for upgrades for more important machines.
Puppet 建议坚持使用标准的生产、测试和开发环境配置,但是,它甚至还为用户提供了根据要求创建自定义环境的杠杆。
Puppet recommends to stick with the standard production, testing, and development environment configuration, however, here it even provides the user with a leverage of creating custom environments as per requirement.
Environment Goal
按环境拆分设置的主要目标是:Puppet 可以为模块和清单使用不同的源。然后可以在测试环境中测试配置中的更改,而不会影响生产节点。这些环境还可用于在不同网络源上部署基础设施。
The main goal of setup split by an environment, is that Puppet can have different sources for modules and manifests. One can then test the changes in configuration in the testing environment without impacting the production nodes. These environments can also be used to deploy infrastructure on different sources of network.
Using the Environment on Puppet Master
环境的重点是测试需要发送给客户端的文件清单、模块和模板。因此,必须配置 Puppet 以提供针对这些信息的特定于环境的源。
The point of an environment is to test which manifest, module, template of the file needs to be send to the client. Thus, Puppet must be configured to provide environment-specific source for these information.
Puppet 环境的实现方式非常简单,只需将 pre-environment 部分添加到服务器的 puppet.conf,并为每个环境选择不同的配置源即可实现。然后将优先使用这些 pre-environment 部分,而不是主部分。
Puppet environments are implemented simply by adding the pre-environment sections to the server’s puppet.conf and choosing different configuration source for each environment. These pre-environment sections are then used in preference to the main section.
[main]
manifest = /usr/testing/puppet/site.pp
modulepath = /usr/testing/puppet/modules
[development]
manifest = /usr/testing/puppet/development/site.pp
modulepath = /usr/testing/puppet/development/modules
在上述代码中,开发环境中的任何客户端都将使用 /usr/share/puppet/development 目录中位于 site.pp 清单文件,而 Puppet 将在 /usr/share/puppet/development/modules directory 中搜索任何模块。
In the above code, any client in the development environment will use the site.pp manifest file located in the directory /usr/share/puppet/development and Puppet will search for any module in /usr/share/puppet/development/modules directory.
使用或不使用任何环境运行 Puppet 都将默认使用 site.pp 文件和在主配置部分中的清单和 modulepath 值中指定目录。
Running Puppet with or without any environment would default to site.pp file and the directory specified in the manifest and modulepath values in the main configuration section.
实际上只有几个配置才适合在环境前进行配置,而且这些参数都围绕指定使用哪些文件来编译客户端的配置。
There are only few configurations which actually makes sense to be configured preenvironment, and all of those parameters revolve around specifying what files to use to compile a client’s configuration.
以下是这些参数。
Following are the parameters.
-
Modulepath − In Puppet, as a basic standard mode it’s best to have a standard module directory that all environment share and then a pre-environment directory where the custom module can be stored. Module path is the location where Puppet looks for all the environment related configuration files.
-
Templatedir − Template directory is the location where all the versions of related templates are saved. The module should be preferred to these settings, however it allows one to have different versions of a given template in each environment.
-
Manifest − This defines which configuration to use as entrypoint script.
对于多个模块,Puppets 帮助获取配置模块性。如果你主要依赖模块,你可以在 Puppet 中使用多个环境,效果会非常好。通过对模块中的更改进行封装,更容易将更改迁移到环境。文件服务器使用特定于环境的模块路径;如果你从模块提供文件服务,而不是独立的装载目录,这个环境将能够获取特定于环境的文件,最后,当前环境也会在清单文件中 $environment 变量中显示。
With multiple modules, Puppets help in getting the modularity for configurations. One can use multiple environments in Puppet which works much better if one relies largely on modules. It is easier to migrate changes to environments by encapsulating changes in the module. File server uses an environment specific module path; if one does file serving from modules, instead of separate mounted directories, this environment will be able to get environment-specific files and finally the current environment will also be available in $environment variable within the manifest file.
Setting the Clients Environment
与环境配置相关的所有配置都将在 puppet.conf 文件中完成。若要指定 Puppet 客户端应该使用哪个环境,你可以在客户端的 puppet.conf 文件中为 environment 配置变量指定一个值。
All the configurations related to environment configuration are done on puppet.conf file. To specify which environment the Puppet client should use, one can specify a value for the environment configuration variable in client’s puppet.conf file.
[puppetd]
environment = Testing
配置文件中的以上定义定义了配置文件所在的哪个环境,在本例中为 testing。
The above definition in configuration file defines which environment the configuration file is in our case it is testing.
你还可以使用 - 在命令行中指定此内容:
One can also specify this on the command line using −
#puppetd -–environment = testing
此外,Puppet 还支持在环境配置中使用动态值。开发人员可以创建自定义事实,而不是定义静态值,这些事实基于其他客户端属性或外部数据源创建客户端环境。这样做的方式是使用自定义工具。这些工具能够指定节点的环境,并且通常更擅长指定节点信息。
Alternatively, Puppet also supports the use of dynamic values in environment configuration. Rather than defining the static values, the developer has a leverage to create custom facts that creates client environment based upon some other client attributes or an external data source. The preferred way of doing it is using a custom tool. These tools are capable of specifying a node’s environment and are generally much better at specifying node information.
Puppet Search Path
Puppet 使用一个简单的搜索路径来确定需要在目标机器上应用哪些配置。同样,当 Puppet 尝试选取需要应用的适当值时,Puppet 中的搜索路径非常有用。Puppet 搜索需要应用的值时有如下多个位置。
Puppet uses a simple search path to determine which configuration needs to be applied on the target machine. In the same way, search path in Puppet is very useful when it is trying to pick up appropriate values which needs to be applied. There are multiple locations as listed below where Puppet searches for the values which needs to be applied.
-
Value specified in the command line
-
Values specified in an environment-specific section
-
Values specified in an executable-specific section
-
Values specified in the main section
Puppet - Type and Provider
Puppet 类型用于单个配置管理。Puppet 有不同的类型,如服务类型、程序包类型、提供程序类型等。其中,每一种类型都有提供程序。提供程序处理不同平台或工具上的配置。例如,package 类型具有 aptitude、yum、rpm 和 DGM 提供程序。有许多类型,Puppet 涵盖了需要管理的良好频谱配置管理项。
Puppet types are used for individual configuration management. Puppet has different types like a service type, package type, provider type, etc. Wherein each type has providers. The provider handles the configuration on different platforms or tools. For example, the package type has aptitude, yum, rpm, and DGM providers. There are a lot of types and Puppet covers a good spectrum configuration management item that needs to be managed.
Puppet 使用 Ruby 作为其基本语言。所有现有的 Puppet 类型和提供程序都是使用 Ruby 语言编写的。因为它遵循标准编码格式,所以可以简单地创建它们,如仓库中管理存储库的示例所示。在这里,我们将创建类型 repo 和提供程序 svn 和 git。repo 类型的第一个部分是类型本身。这些类型通常存储在 lib/puppet/type 中。为此,我们将创建一个名为 repo.rb 文件。
Puppet uses Ruby as its base language. All Puppet types and providers present are written in Ruby language. As it follows the standard encoding format, one can simply create them as shown in the example for repo which manages repositories. Here, we will create type repo and providers’ svn and git. The first part of the repo type is type itself. The types are usually stored in lib/puppet/type. For this, we will create a file called repo.rb.
$ touch repo.rb
在文件中添加以下内容。
Add the following content in the file.
Puppet::Type.newtype(:repo) do
@doc = "Manage repos"
Ensurable
newparam(:source) do
desc "The repo source"
validate do |value|
if value =~ /^git/
resource[:provider] = :git
else
resource[:provider] = :svn
end
end
isnamevar
end
newparam(:path) do
desc "Destination path"
validate do |value|
unless value =~ /^\/[a-z0-9]+/
raise ArgumentError , "%s is not a valid file path" % value
end
end
end
end
在上面的脚本中,我们创建了一个块“ Puppet::Type.newtype(:repo) do ”,它创建了一个名称为 repo 的新类型。然后,我们有 @doc,它有助于添加想要添加的任何级别的详细信息。下一个语句是 Ensurable;它创建了一个基本的 ensure 属性。Puppet 类型使用 ensure 属性来确定配置项的状态。
In the above script, we have created a block "Puppet::Type.newtype(:repo) do" which creates a new type with the name repo. Then, we have @doc which helps in adding whatever level of details one wants to add. The next statement is Ensurable; it creates a basic ensure property. Puppet type uses ensure property to determine the state of configuration item.
Example
service { "sshd":
ensure => present,
}
ensure 语句告诉 Puppet 除了在提供程序中创建、销毁和存在。这些方法提供以下功能 −
The ensure statement tells Puppet to except three method: create, destroy, and exist in the provider. These methods provide the following features −
-
A command to create a resource
-
A command to delete a resource
-
A command to check the existence of a resource
我们随后需要做的,就是指定这些方法及其内容。Puppet 会在其周围创建支持性的基础设施。
All we then need to do is specify these methods and their contents. Puppet creates the supporting infrastructure around them.
接下来,我们定义一个名为源(source)的新参数。
Next, we define a new parameter called source.
newparam(:source) do
desc "The repo source"
validate do |value|
if value =~ /^git/
resource[:provider] = :git
else
resource[:provider] = :svn
end
end
isnamevar
end
源将告诉存储库类型从何处检索/克隆/检出源存储库。在此,我们还使用了名为验证(validate)的挂钩。在提供程序部分中,我们已经定义了 git 和 svn,它们用于检查我们已经定义的存储库的有效性。
The source will tell the repo type where to retrieve/clone/checkout the source repository. In this, we are also using a hook called validate. In the provider section, we have defined git and svn which check for the validity of the repository we have defined.
最后,在代码中我们已经定义了另一个称为路径(path)的参数。
Finally, in the code we have defined one more parameter called path.
newparam(:path) do
desc "Destination path"
validate do |value|
unless value =~ /^\/[a-z0-9]+/
raise ArgumentError , "%s is not a valid file path" % value
end
这是值类型,它指定将检索到的新代码放置在何处。在这里,再次使用验证(validate)挂钩来创建一个检查适用性的值块。
This is the value type which specifies where to put the new code that is retrieved. Here, again use the validate hook to create a block that checks the value of appropriateness.
Subversion Provider Use Case
我们使用上面创建的类型从 subversion 提供程序开始。
Let’s start with the subversion provider using the above created type.
require 'fileutils'
Puppet::Type.type(:repo).provide(:svn) do
desc "SVN Support"
commands :svncmd => "svn"
commands :svnadmin => "svnadmin"
def create
svncmd "checkout", resource[:name], resource[:path]
end
def destroy
FileUtils.rm_rf resource[:path]
end
def exists?
File.directory? resource[:path]
end
end
在上面的代码中,我们已经预先定义了我们需要库 fileutils ,需要方法 'fileutils' 。
In the above code, we have upfront defined that we need fileutils library, require 'fileutils' which we are going to use method from.
接下来,我们已经将提供程序定义为块 Puppet::Type.type(:repo).provide(:svn) do,它告诉 Puppet 这是称为 repo 的类型的提供程序。
Next, we have defined the provider as block Puppet::Type.type(:repo).provide(:svn) do which tells Puppet that this is the provider for type called repo.
然后,我们已经添加了 desc ,它允许向提供程序添加一些文档。我们还已经定义了该提供程序将使用哪些命令。在下一行中,我们正在检查资源的功能,例如创建、删除和是否存在。
Then, we have added desc which allows to add some documentation to the provider. We have also defined the command that this provider will use. In the next line, we are checking the features of resource like create, delete, and exist.
Creating a Resource
一旦完成了上述所有操作,我们将创建一个将在我们的类和清单文件中(如下面的代码所示)使用的资源。
Once all the above is done, we will create a resource which will be used in our classes and manifest files as shown in the following code.
repo { "wp":
source => "http://g01063908.git.brcl.org/trunk/",
path => "/var/www/wp",
ensure => present,
}
Puppet - RESTful API
Puppet 使用 RESTful API 作为 Puppet 主机和 Puppet 代理之间的通信通道。以下是访问此 RESTful API 的基本 URL。
Puppet uses RESTful API’s as the communication channel between both Puppet master and Puppet agents. Following is the basic URL to access this RESTful API.
https://brcleprod001:8140/{environment}/{resource}/{key}
https://brcleprod001:8139/{environment}/{resource}/{key}
REST API Security
Puppet 通常负责安全和 SSL 证书管理。但是,如果希望在群集外部使用 RESTful API,则在尝试连接到计算机时需要自行管理证书。可以通过 rest authconfig 文件配置 Puppet 的安全策略。
Puppet usually takes care of security and SSL certificate management. However, if one wishes to use the RESTful API outside the cluster one needs to manage the certificate on their own, when trying to connect to a machine. The security policy for Puppet can be configured through the rest authconfig file.
Testing REST API
Curl 实用程序可用作基本实用程序来建立 RESTful API 连接。以下是使用 REST API curl 命令检索节点目录的示例。
Curl utility can be used as a basic utility to rest RESTful API connectivity. Following is an example of how we can retrieve the catalog of node using REST API curl command.
curl --cert /etc/puppet/ssl/certs/brcleprod001.pem --key
/etc/puppet/ssl/private_keys/brcleprod001.pem
在以下命令集中,我们只是设置 SSL 证书,该证书会因 SSL 目录位置和正在使用的节点名称的不同而不同。例如,我们来看一下以下命令。
In the following set of commands we are just setting the SSL certificate, which will be different depending on where the SSL directory is and the name of the node being used. For example, let’s look at the following command.
curl --insecure -H 'Accept: yaml'
https://brcleprod002:8140/production/catalog/brcleprod001
在上一个命令中,我们只是发送一个标题,指定我们希望返回的格式或格式和一个 RESTful URL,用于生成 brcleprod001 在生产环境中的目录,将生成以下输出。
In the above command, we just send a header specifying the format or formats we want back and a RESTful URL for generating a catalog of brcleprod001 in production environment, will generate a the following output.
--- &id001 !ruby/object:Puppet::Resource::Catalog
aliases: {}
applying: false
classes: []
...
让我们假设另一个示例,我们希望从 Puppet 主机获取 CA 证书。它不需要使用自己签名的 SSL 证书进行身份验证,因为这是在认证之前需要的东西。
Let’s assume another example, where we want to get the CA certificate back from Puppet master. It doesn’t require to be authenticated with own signed SSL certificate since that is something which is required before being authenticated.
curl --insecure -H 'Accept: s' https://brcleprod001:8140/production/certificate/ca
-----BEGIN CERTIFICATE-----
MIICHTCCAYagAwIBAgIBATANBgkqhkiG9w0BAQUFADAXMRUwEwYDVQQDDAxwdXBw
Puppet Master API Reference
经过身份验证的资源(有效的已签名证书是必需的)。
Authenticated Resources (Valid, signed certificate required).
Catalogs
GET /{environment}/catalog/{node certificate name}
curl -k -H "Accept: pson" https://brcelprod001:8140/production/catalog/myclient
Certificate Revocation List
GET /certificate_revocation_list/ca
curl -k -H "Accept: s" https://brcleprod001:8140/production/certificate/ca
Certificate Request
GET /{environment}/certificate_requests/{anything} GET
/{environment}/certificate_request/{node certificate name}
curl -k -H "Accept: yaml" https://brcelprod001:8140/production/certificate_requests/all
curl -k -H "Accept: yaml" https://brcleprod001:8140/production/certificate_request/puppetclient
Reports Submit a Report
PUT /{environment}/report/{node certificate name}
curl -k -X PUT -H "Content-Type: text/yaml" -d "{key:value}" https://brcleprod002:8139/production
Puppet Agent API Reference
当在任何计算机上设置一个新代理时,默认情况下,Puppet 代理不会侦听 HTTP 请求。需要在 Puppet 中通过在 puppet.conf 文件中添加“listen=true”来启用它。这样可以在启动 Puppet 代理时启用 Puppet 代理侦听 HTTP 请求。
When a new agent is set up on any machine, by default Puppet agent does not listen to HTTP request. It needs to be enabled in Puppet by adding “listen=true” in puppet.conf file. This will enable Puppet agents to listen to HTTP request when the Puppet agent is starting up.
Facts
GET /{environment}/facts/{anything}
curl -k -H "Accept: yaml" https://brcelprod002:8139/production/facts/{anything}
Run − 使客户机像 puppetturn 或 puppet kick 一样进行更新。
Run − Causes the client to update like puppetturn or puppet kick.
PUT /{environment}/run/{node certificate name}
curl -k -X PUT -H "Content-Type: text/pson" -d "{}"
https://brcleprod002:8139/production/run/{anything}
Puppet - Live Project
为了执行有关在 Puppet 节点上应用配置和清单的现场测试,我们将使用一个现场操作演示。这可以直接复制并粘贴,以测试配置的运行方式。如果用户希望使用相同的代码集,则需要遵循代码段中所示的相同命名约定,如下所示。
In order to perform the live testing of applying configuration and manifests on Puppet node, we will use a live working demo. This can be directly copied and pasted to test how the configuration works. If the user wishes to use the same set of code, he needs to have the same naming convention as shown in code snippets as follows.
我们先从创建一个新模块开始。
Let’s start with the creation of a new module.
Creating a New Module
测试和应用 httpd 配置的第一步是创建一个模块。为此,用户需要将其工作目录更改为 Puppet 模块目录,并创建一个基本模块结构。可以手动创建结构,或使用 Puppet 为模块创建样板文件。
The first step in testing and applying the httpd configuration is by creating a module. In order to do this, the user needs to change his working directory to Puppet module directory and create a basic module structure. The structure creation can be done manually or by using Puppet to create boilerplate for the module.
# cd /etc/puppet/modules
# puppet module generate Live-module
Note - Puppet 模块生成命令要求模块名称采用 [用户名]-[模块] 格式以符合 Puppet forge 规范。
Note − Puppet module generate command requires that the module-name takes the format of [username]-[module] to comply with Puppet forge specifications.
新模块包含一些基本文件,包括 manifest 目录。该目录中已包含一个名为 init.pp 的 manifest,这是模块的主 manifest 文件。这是对模块进行的空类声明。
The new module contains some basic files, including a manifest directory. The directory already contains a manifest named init.pp, which is modules main manifest file. This is an empty class declaration for the module.
class live-module {
}
该模块中还有一个 test 目录,其中包含一个名为 init.pp 的 manifest。该 test manifest 包含对 manifest/init.pp 中 live-module 类的引用:
The module also contains a test directory containing a manifest called init.pp. This test manifest contains reference to the live-module class within manifest/init.pp:
include live-module
Puppet 将使用该 test 模块对 manifest 进行测试。现在我们可以为模块添加配置。
Puppet will use this test module to test the manifest. Now we are ready to add the configuration to the module.
Installing a HTTP Server
Puppet 模块将安装运行 http 服务器所需的软件包。这需要一个资源定义,用于定义 httpd 软件包的配置。
Puppet module will install the necessary packages to run http server. This requires a resource definition that defines the configuration of httpd packages.
在模块的 manifest 目录中,创建一个名为 httpd.pp 的新 manifest 文件。
In the module’s manifest directory, create a new manifest file called httpd.pp
# touch test-module/manifests/httpd.pp
该 manifest 将包含我们模块的所有 HTTP 配置。为了分离起见,我们将会把 httpd.pp 文件与 init.pp manifest 文件分开。
This manifest will contain all HTTP configuration for our module. For separation purpose, we will keep the httpd.pp file separate from init.pp manifest file
我们需要将以下代码放到 httpd.pp manifest 文件中。
We need to put the following code in httpd.pp manifest file.
class test-module::httpd {
package { 'httpd':
ensure => installed,
}
}
该代码定义了 test-module 的一个子类,称为 httpd,然后为 httpd 软件包定义了一个软件包资源声明。ensure ⇒ installed 属性将检查所需的软件包是否已安装。如果未安装,则 Puppet 将使用 yum 实用程序对其进行安装。接下来,需要将该子类包含在我们主 manifest 文件中。我们需要编辑 init.pp manifest。
This code defines a subclass of test-module called httpd, then defines a package resource declaration for the httpd package. The ensure ⇒ installed attribute checks if the required package is installed. If not installed, Puppet uses yum utility to install it. Next, is to include this subclass in our main manifest file. We need to edit init.pp manifest.
class test-module {
include test-module::httpd
}
现在,是时候测试该模块了,如下所示:
Now, it’s the time to test the module which could be done as follows
# puppet apply test-module/tests/init.pp --noop
puppet apply 命令应用 manifest 文件中存在的配置到目标系统。此处,我们使用 test init.pp,它引用主 init.pp。–noop 执行配置的空运行,这只会显示输出,但实际上并不执行任何操作。
The puppet apply command applies the configuration present in manifest file on the target system. Here, we are using test init.pp which refers to main init.pp. The –noop performs the dry run of the configuration, which only shows the output but actually does not do anything.
以下是输出。
Following is the output.
Notice: Compiled catalog for puppet.example.com in environment
production in 0.59 seconds
Notice: /Stage[main]/test-module::Httpd/Package[httpd]/ensure:
current_value absent, should be present (noop)
Notice: Class[test-module::Httpd]: Would have triggered 'refresh' from 1
events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Finished catalog run in 0.67 seconds
高亮行是 ensure ⇒ installed 属性的结果。current_value 不存在表示 Puppet 已经检测到已安装 httpd 软件包。如果没有 –noop 选项,Puppet 将安装 httpd 软件包。
The highlight line is the result of the ensure ⇒ installed attribute. The current_value absent means that Puppet has detected the httpd package is installed. Without the –noop option, Puppet will install the httpd package.
Running the httpd Server
在安装了 httpd 服务器后,我们需要使用其他资源减速:Service 来启动服务。
After installing the httpd servers, we need to start the service using other resource deceleration: Service
我们需要编辑 httpd.pp manifest 文件,并编辑以下内容。
We need to edit the httpd.pp manifest file and edit the following content.
class test-module::httpd {
package { 'httpd':
ensure => installed,
}
service { 'httpd':
ensure => running,
enable => true,
require => Package["httpd"],
}
}
以下是我们从上述代码中获得的目标列表。
Following is the list of targets that we have achieved from the above code.
-
The ensure ⇒ running status checks if the service is running, if not then it enables it.
-
The enable ⇒ true attribute sets the service to run when the system boots up.
-
The require ⇒ Package["httpd"] attribute defines an ordering relationship between one resource deceleration and other. In the above case, it ensures that the httpd service starts after the http package is installed. This creates a dependency between the service and the respective package.
再次运行 puppet apply 命令以测试该变更。
Run the puppet apply command to test the changes again.
# puppet apply test-module/tests/init.pp --noop
Notice: Compiled catalog for puppet.example.com in environment
production in 0.56 seconds
Notice: /Stage[main]/test-module::Httpd/Package[httpd]/ensure:
current_value absent, should be present (noop)
Notice: /Stage[main]/test-module::Httpd/Service[httpd]/ensure:
current_value stopped, should be running (noop)
Notice: Class[test-module::Httpd]: Would have triggered 'refresh' from 2
events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Finished catalog run in 0.41 seconds
Configuring httpd Server
在完成上方步骤后,我们已安装并启用了 HTTP 服务器。下一步是向服务器提供一些配置。默认情况下,httpd 在 /etc/httpd/conf/httpd.conf 中提供一些默认配置,它提供了一个 80 端口的 Web 主机。我们将添加一些附加主机,为 Web 主机提供一些特定于用户的工具。
Once the above steps are completed, we will have HTTP server installed and enabled. The next step is to provide some configuration to the server. By default, httpd provides some default configurations in /etc/httpd/conf/httpd.conf which provides a webhost port 80. We will add some additional host to provide some user-specific facilities to the web-host.
将使用模板提供附加端口,因为它需要一个可变输入。我们将创建一个名为 template 的目录,并在新目录中添加一个名为 test-server.config.erb 的文件,并添加以下内容。
A template will be used to provide additional port as it requires a variable input. We will create a directory called template and add a file called test-server.config.erb in the new director and add the following content.
Listen <%= @httpd_port %>
NameVirtualHost *:<% = @httpd_port %>
<VirtualHost *:<% = @httpd_port %>>
DocumentRoot /var/www/testserver/
ServerName <% = @fqdn %>
<Directory "/var/www/testserver/">
Options All Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
上面的模板遵循标准的 apache-tomcat 服务器配置格式。唯一的区别是使用了 Ruby 转义字符来注入模块中的变量。我们有 FQDN,它存储系统完全限定的域名。这被称为 system fact 。
The above template follows the standard apache-tomcat server configuration format. The only difference is the use of Ruby escape character to inject variables from the module. We have FQDN which stores fully qualified domain name of the system. This is known as the system fact.
在生成每个相应系统的 puppet 目录之前,会从每个系统收集系统事实。Puppet 使用 facter 命令来获取此信息,而且人们可以使用 facter 来获取有关系统的其他详情。我们需要在 httpd.pp 清单文件中添加高亮行。
System facts are collected from each system prior to generating each respective system’s puppet catalog. Puppet uses the facter command to get this information and one can use facter to get other details regarding the system. We need to add the highlight lines in httpd.pp manifest file.
class test-module::httpd {
package { 'httpd':
ensure => installed,
}
service { 'httpd':
ensure => running,
enable => true,
require => Package["httpd"],
}
file {'/etc/httpd/conf.d/testserver.conf':
notify => Service["httpd"],
ensure => file,
require => Package["httpd"],
content => template("test-module/testserver.conf.erb"),
}
file { "/var/www/myserver":
ensure => "directory",
}
}
这有助于实现以下内容:
This helps in achieving the following things −
-
This adds a file resource declaration for the server configuration file (/etc/httpd/conf.d/test-server.conf). The content of this file is the test-serverconf.erb template that was created earlier. We also check the httpd package installed before adding this file.
-
This adds the second file resource declaration which creates a directory (/var/www/test-server) for the web server.
-
Next, we add the relationship between the configuration file and the https service using the notify ⇒ Service["httpd"]attribute. This checks if there are any configuration file changes. If there is, then Puppet restarts the service.
下一步是在主清单文件中包含 httpd_port。为此,我们需要结束主 init.pp 清单文件并包括以下内容。
Next is to include the httpd_port in the main manifest file. For this, we need to end the main init.pp manifest file and include the following content.
class test-module (
$http_port = 80
) {
include test-module::httpd
}
这将将 httpd 端口设置为默认值 80。接下来运行 Puppet apply 命令。
This sets the httpd port to the default value of 80. Next is to run the Puppet apply command.
输出将如下所示。
Following will be the output.
# puppet apply test-module/tests/init.pp --noop
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera
defaults
Notice: Compiled catalog for puppet.example.com in environment
production in 0.84 seconds
Notice: /Stage[main]/test-module::Httpd/File[/var/www/myserver]/ensure:
current_value absent, should be directory (noop)
Notice: /Stage[main]/test-module::Httpd/Package[httpd]/ensure:
current_value absent, should be present (noop)
Notice:
/Stage[main]/test-module::Httpd/File[/etc/httpd/conf.d/myserver.conf]/ensure:
current_value absent, should be file (noop)
Notice: /Stage[main]/test-module::Httpd/Service[httpd]/ensure:
current_value stopped, should be running (noop)
Notice: Class[test-module::Httpd]: Would have triggered 'refresh' from 4
events
Notice: Stage[main]: Would have triggered 'refresh' from 1 events
Notice: Finished catalog run in 0.51 seconds
Configuring the Firewall
为了与服务器通信,需要开放端口。这里的问题是不同类型的操作系统使用不同的方法来控制防火墙。对于 Linux,6 以下的版本使用 iptables,而 7 版使用 firewalld。
In order to communicate with the server one requires an open port. The problem here is that different kind of operating systems use different methods of controlling the firewall. In case of Linux, versions below 6 use iptables and version 7 use firewalld.
Puppet 使用系统事实及其逻辑在某种程度上处理了使用适当服务的决策。为此,我们需要首先检查操作系统,然后运行适当的防火墙命令。
This decision of using an appropriate service is somewhat handled by Puppet using the system facts and its logic. For this, we need to first check the OS and then run the appropriate firewall command.
为了实现此目的,我们需要在 testmodule::http 类中添加以下代码片段。
In order to achieve this, we need to add the following code snippet inside testmodule::http class.
if $operatingsystemmajrelease <= 6 {
exec { 'iptables':
command => "iptables -I INPUT 1 -p tcp -m multiport --ports
${httpd_port} -m comment --comment 'Custom HTTP Web Host' -j ACCEPT &&
iptables-save > /etc/sysconfig/iptables",
path => "/sbin",
refreshonly => true,
subscribe => Package['httpd'],
}
service { 'iptables':
ensure => running,
enable => true,
hasrestart => true,
subscribe => Exec['iptables'],
}
} elsif $operatingsystemmajrelease == 7 {
exec { 'firewall-cmd':
command => "firewall-cmd --zone=public --addport = $ {
httpd_port}/tcp --permanent",
path => "/usr/bin/",
refreshonly => true,
subscribe => Package['httpd'],
}
service { 'firewalld':
ensure => running,
enable => true,
hasrestart => true,
subscribe => Exec['firewall-cmd'],
}
}
以上代码执行以下操作:
The above code performs the following −
-
Using the operatingsystemmajrelease determines whether the OS which is used is version 6 or 7.
-
If the version is 6, then it runs all the required configuration commands to configure Linux 6 version.
-
If OS version is 7, then it runs all the required commands required to configure the firewall.
-
The code snippet for both the OS contains a logic which ensures that the configuration runs only after the http package is installed.
最后,运行 Puppet apply 命令。
Finally, run the Puppet apply command.
# puppet apply test-module/tests/init.pp --noop
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera
defaults
Notice: Compiled catalog for puppet.example.com in environment
production in 0.82 seconds
Notice: /Stage[main]/test-module::Httpd/Exec[iptables]/returns:
current_value notrun, should be 0 (noop)
Notice: /Stage[main]/test-module::Httpd/Service[iptables]: Would have
triggered 'refresh' from 1 events
Configuring the SELinux
由于我们在第 7 版及以上版本的 Linux 机器上工作,因此我们需要配置它来进行 http 通信。SELinux 默认会限制对 HTTP 服务器的非标准访问。如果我们定义了一个自定义端口,则我们需要配置 SELinux 以提供对该端口的访问权限。
As we are working on a Linux machine which is version 7 and above, hence we need to configure it to make a http communication. SELinux restricts non-standard access to the HTTP server by default. If we define a custom port, then we need to configure the SELinux to provide access to that port.
Puppet 包含一些管理 SELinux 函数的资源类型,如布尔值和模块。这里,我们需要执行 semanage 命令来管理端口设置。此工具是 policycoreutils-python 包的一部分,默认情况下未安装在 red-hat 服务器上。为了实现上述目的,我们需要在 test-module::http 类中添加以下代码。
Puppet contains some resource type to manage SELinux functions, such as Booleans and modules. Here, we need to execute semanage command to manage port settings. This tools is a part of policycoreutils-python package, which is not installed on red-hat servers by default. In order to achieve the above, we need to add the following code inside the test-module::http class.
exec { 'semanage-port':
command => "semanage port -a -t http_port_t -p tcp ${httpd_port}",
path => "/usr/sbin",
require => Package['policycoreutils-python'],
before => Service ['httpd'],
subscribe => Package['httpd'],
refreshonly => true,
}
package { 'policycoreutils-python':
ensure => installed,
}
以上代码执行以下操作:
The above code performs the following −
-
The require ⇒ Package['policycoreutils-python'] ensures that we have the required python module installed.
-
Puppet uses semanage to open the port using the httpd_port as a veriable.
-
The before ⇒ service ensures to execute this command before httpd service starts. If HTTPD starts before SELinux command, then SELinux the service request and the service request fails.
最后,运行 Puppet apply 命令
Finally, run the Puppet apply command
# puppet apply test-module/tests/init.pp --noop
...
Notice: /Stage[main]/test-module::Httpd/Package[policycoreutilspython]/
ensure: current_value absent, should be present (noop)
...
Notice: /Stage[main]/test-module::Httpd/Exec[semanage-port]/returns:
current_value notrun, should be 0 (noop)
...
Notice: /Stage[main]/test-module::Httpd/Service[httpd]/ensure:
current_value stopped, should be running (noop)
Puppet 先安装 Python 模块,然后配置端口访问,最后启动 httpd 服务。
Puppet installs the python module first and then configures the port access and finally starts the httpd service.
Copying HTML Files in the Web Host
通过上述步骤,我们完成了 http 服务器配置。现在,我们有一个可以安装基于 Web 的应用程序的平台,Puppet 也可以配置它。为了进行测试,我们将复制一些示例 html index 网页到服务器。
With the above steps we have completed the http server configuration. Now, we have a platform ready to install a web-based application, which Puppet can also configure. To test, we will copy some sample html index web pages to the server.
在 files 目录中创建 index.html 文件。
Create an index.html file inside the files directory.
<html>
<head>
<title>Congratulations</title>
<head>
<body>
<h1>Congratulations</h1>
<p>Your puppet module has correctly applied your configuration.</p>
</body>
</html>
在 manifest 目录中创建清单 app.pp 并添加以下内容。
Create a manifest app.pp inside the manifest directory and add the following content.
class test-module::app {
file { "/var/www/test-server/index.html":
ensure => file,
mode => 755,
owner => root,
group => root,
source => "puppet:///modules/test-module/index.html",
require => Class["test-module::httpd"],
}
}
此新类包含一个单个资源声明。它将文件从模块的文件目录复制到 Web 服务器并设置其权限。required 属性确保在应用 test-module::app 之前 test-module::http 类成功完成配置。
This new class contains a single resource deceleration. This copies a file from the module’s file directory to the web server and sets its permissions. The required attribute ensures the test-module::http class completes the configuration successfully before one applies test-module::app.
最后,我们需要在我们的 main init.pp 清单中包含一个新清单。
Finally, we need to include a new manifest in our main init.pp manifest.
class test-module (
$http_port = 80
) {
include test-module::httpd
include test-module::app
}
现在,运行 apply 命令来实际测试正在发生的事情。以下是输出。
Now, run the apply command to actually test what is happening. Following will be the output.
# puppet apply test-module/tests/init.pp --noop
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera
defaults
Notice: Compiled catalog for brcelprod001.brcle.com in environment
production in 0.66 seconds
Notice: /Stage[main]/Test-module::Httpd/Exec[iptables]/returns:
current_value notrun, should be 0 (noop)
Notice: /Stage[main]/Test-module::Httpd/Package[policycoreutilspython]/
ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Test-module::Httpd/Service[iptables]: Would have
triggered 'refresh' from 1 events
Notice: /Stage[main]/Test-module::Httpd/File[/var/www/myserver]/ensure:
current_value absent, should be directory (noop)
Notice: /Stage[main]/Test-module::Httpd/Package[httpd]/ensure:
current_value absent, should be present (noop)
Notice:
/Stage[main]/Test-module::Httpd/File[/etc/httpd/conf.d/myserver.conf]/ensur
e: current_value absent, should be file (noop)
Notice: /Stage[main]/Test-module::Httpd/Exec[semanage-port]/returns:
current_value notrun, should be 0 (noop)
Notice: /Stage[main]/Test-module::Httpd/Service[httpd]/ensure:
current_value stopped, should be running (noop)
Notice: Class[test-module::Httpd]: Would have triggered 'refresh' from 8
Notice:
/Stage[main]/test-module::App/File[/var/www/myserver/index.html]/ensur:
current_value absent, should be file (noop)
Notice: Class[test-module::App]: Would have triggered 'refresh' from 1
Notice: Stage[main]: Would have triggered 'refresh' from 2 events Notice:
Finished catalog run in 0.74 seconds
高亮显示的行显示 index.html 文件被复制到 Web 主机中的结果。
The highlighted line shows the result of index.html file being copied to the web-host.