人偶 – 快速指南
人偶 – 快速指南
人偶 – 概述
Puppet 是由 Puppet Labs 开发的配置管理工具,用于自动化基础设施管理和配置。Puppet 是一个非常强大的工具,它有助于实现基础设施即代码的概念。这个工具是用 Ruby DSL 语言编写的,有助于将完整的基础设施转换为代码格式,可以轻松管理和配置。
Puppet 遵循客户端-服务器模型,其中任何集群中的一台机器充当服务器,称为 puppet master,另一台充当客户端,称为节点上的从属。Puppet 能够从头开始管理任何系统,从初始配置开始,直到任何特定机器的生命周期结束。
人偶系统特点
以下是 Puppet 最重要的功能。
幂等性
Puppet 支持幂等性,这使得它独一无二。与 Chef 类似,在 Puppet 中,可以安全地在同一台机器上多次运行同一组配置。在这个流程中,Puppet 检查目标机器的当前状态,并且只有在配置有任何特定更改时才会进行更改。
幂等性有助于管理任何特定机器的整个生命周期,从机器的创建、机器中的配置更改到生命周期结束。Puppet 幂等特性非常有助于保持机器更新多年,而不是在发生任何配置更改时多次重建同一台机器。
跨平台
在 Puppet 中,借助使用 Puppet 资源的资源抽象层 (RAL),可以针对系统的指定配置,而无需担心实现细节以及配置命令在系统内部如何工作,这些都是在底层配置中定义的文件。
木偶 – 工作流程
Puppet 使用以下工作流程在系统上应用配置。
-
在 Puppet 中,Puppet master 做的第一件事就是收集目标机器的详细信息。使用存在于所有 Puppet 节点上的因素(类似于 Chef 中的 Ohai),它可以获得所有机器级别的配置详细信息。收集这些详细信息并将其发送回 Puppet 主人。
-
然后 Puppet Master 将检索到的配置与定义的配置细节进行比较,并与定义的配置创建一个目录并将其发送到目标 Puppet 代理。
-
Puppet 代理然后应用这些配置以使系统进入所需状态。
-
最后,一旦目标节点处于所需状态,它就会向 Puppet master 发送一份报告,这有助于 Puppet master 了解系统的当前状态,如目录中所定义。
Puppet – 关键组件
以下是 Puppet 的关键组件。
傀儡资源
Puppet 资源是对任何特定机器进行建模的关键组件。这些资源有自己的实现模型。Puppet 使用相同的模型来获取处于所需状态的任何特定资源。
供应商
提供者基本上是 Puppet 中使用的任何特定资源的履行者。例如,包类型“apt-get”和“yum”都对包管理有效。有时,在特定平台上会提供多个提供商。尽管每个平台总是有一个默认的提供者。
显现
清单是资源的集合,这些资源在函数或类中耦合以配置任何目标系统。它们包含一组用于配置系统的 Ruby 代码。
模块
模块是 Puppet 的关键构建块,可以定义为资源、文件、模板等的集合。它们可以很容易地分布在被定义为相同风格的不同类型的操作系统中。由于它们易于分布,因此一个模块可以以相同的配置多次使用。
模板
模板使用 Ruby 表达式来定义自定义内容和变量输入。它们用于开发自定义内容。模板在清单中定义并复制到系统上的某个位置。例如,如果要使用可自定义的端口定义 httpd,则可以使用以下表达式来完成。
Listen <% = @httpd_port %>
这种情况下的 httpd_port 变量在引用此模板的清单中定义。
静态文件
静态文件可以定义为有时需要执行特定任务的通用文件。可以使用 Puppet 简单地将它们从一个位置复制到另一个位置。所有静态文件都位于任何模块的 files 目录中。清单中文件的任何操作都是使用文件资源完成的。
木偶 – 建筑
以下是 Puppet 架构的图示。
木偶大师
Puppet Master 是处理所有配置相关内容的关键机制。它使用 Puppet 代理将配置应用到节点。
傀儡特工
Puppet Agents 是由 Puppet master 管理的实际工作机器。它们内部运行着 Puppet 代理守护程序服务。
配置库
这是所有节点和服务器相关配置在需要时保存和拉取的存储库。
事实
Facts是与节点或主机相关的细节,主要用于分析任何节点的当前状态。根据事实,在任何目标机器上进行更改。Puppet 中有预定义和自定义的事实。
目录
用 Puppet 编写的所有清单文件或配置首先转换为称为目录的编译格式,然后将这些目录应用到目标机器上。
木偶 – 安装
Puppet 工作在客户端服务器架构上,其中我们将服务器称为 Puppet master,将客户端称为 Puppet 节点。这个设置是通过在客户端和所有服务器机器上安装 Puppet 来实现的。
对于大多数平台,可以通过选择的包管理器安装 Puppet。但是,对于少数平台,可以通过安装tarball或RubyGems来完成。
先决条件
Factor 是Chef 中唯一不随Ohai一起出现的先决条件。
标准操作系统库
我们需要有任何底层操作系统的标准库集。剩下的所有系统都带有 Ruby 1.8.2 + 版本。以下是操作系统应包含的库项目列表。
- base64
- 计算机图形学
- 摘要/md5
- 等等
- 文件工具
- ipaddr
- openssl
- 扫描
- 系统日志
- uri
- 韦瑞克
- webrick/https
- xmlrpc
因子安装
随着讨论的,facter不使用Ruby的标准版一起走。因此,为了在目标系统中获取因子,需要从源手动安装它,因为因子库是 Puppet 的先决条件。
该软件包可用于多个平台,但为了更安全,它可以使用tarball安装,这有助于获取最新版本。
首先,使用wget实用程序从 Puppet 的官方站点下载tarball。
$ wget http://puppetlabs.com/downloads/facter/facter-latest.tgz ------: 1
接下来,解压 tar 文件。使用 CD 命令进入解压缩的目录。最后,使用facter目录中的install.rb文件安装facter。
$ gzip -d -c facter-latest.tgz | tar xf - -----: 2 $ cd facter-* ------: 3 $ sudo ruby install.rb # or become root and run install.rb -----:4
从源代码安装 Puppet
首先,使用wget从 Puppet 站点安装 Puppet tarball 。然后,将 tarball 提取到目标位置。使用CD命令在创建的目录中移动。使用install.rb文件,在底层服务器上安装 Puppet。
# 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
使用 Ruby Gem 安装 Puppet 和 Factor
# Installing Facter $ wget http://puppetlabs.com/downloads/gems/facter-1.5.7.gem $ sudo gem install facter-1.5.7.gem # Installing Puppet $ wget http://puppetlabs.com/downloads/gems/puppet-0.25.1.gem $ sudo gem install puppet-0.25.1.gem
人偶 – 配置
一旦我们在系统上安装了 Puppet,下一步就是配置它以执行某些初始操作。
在机器上打开防火墙端口
为了让Puppet服务器集中管理客户端的服务器,需要在所有机器上打开一个指定的端口,即8140如果在我们尝试配置的任何机器上都没有使用,则可以使用它。我们需要在所有机器上启用 TCP 和 UDP 通信。
配置文件
Puppet 的主要配置文件是etc/puppet/puppet.conf。所有配置文件都是在 Puppet 的基于包的配置中创建的。配置 Puppet 所需的大部分配置都保存在这些文件中,一旦 Puppet 运行发生,它就会自动获取这些配置。但是,对于某些特定任务,例如配置 Web 服务器或外部证书颁发机构 (CA),Puppet 具有单独的文件和设置配置。
服务器配置文件位于conf.d目录中,该目录也称为 Puppet master。这些文件默认位于/etc/puppetlabs/puppetserver/conf.d路径下。这些配置文件采用 HOCON 格式,保留了 JSON 的基本结构,但更具可读性。当 Puppet 启动时,它会从 conf.d 目录中提取所有 .cong 文件并使用它们进行任何配置更改。这些文件中的任何更改仅在服务器重新启动时发生。
列表文件和设置文件
- 全局配置文件
- 网络服务器配置文件
- web-routes.conf
- puppetserver.conf
- 配置文件
- master.conf(已弃用)
- ca.conf(已弃用)
Puppet 中有不同的配置文件,这些文件特定于 Puppet 中的每个组件。
人偶配置文件
Puppet.conf 文件是 Puppet 的主要配置文件。Puppet 使用相同的配置文件来配置所有必需的 Puppet 命令和服务。所有与 Puppet 相关的设置,如 Puppet master、Puppet 代理、Puppet 应用和证书的定义都在这个文件中定义。Puppet 可以根据需要引用它们。
配置文件类似于标准的 ini 文件,其中设置可以进入主部分的特定应用程序部分。
主要配置部分
[main] certname = Test1.vipin.com server = TestingSrv environment = production runinterval = 1h
Puppet 主配置文件
[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
详细概述
在 Puppet 配置中,将要使用的文件有多个配置节,其中每个节都有不同种类的多种设置。
配置部分
Puppet 配置文件主要由以下配置部分组成。
-
Main – 这被称为全局部分,由 Puppet 中的所有命令和服务使用。一个定义主要部分中的默认值,可以被 puppet.conf 文件中的任何部分覆盖。
-
Master – 此部分由 Puppet 主服务和 Puppet cert 命令引用。
-
Agent – 此部分由 Puppet 代理服务引用。
-
用户– 它主要由 Puppet apply 命令以及许多不太常见的命令使用。
[main] certname = PuppetTestmaster1.example.com
配置文件的关键组件
以下是配置文件的关键组件。
评论行
在 Puppet 中,任何注释行都以 ( # ) 符号开头。这可能意味着任何空间量。我们也可以在同一行中添加部分注释。
# This is a comment. Testing = true #this is also a comment in same line
设置行
设置行必须包括 –
- 任意数量的前导空间(可选)
- 设置名称
- 一个等于 = 符号,可以被任意数量的空格包围
- 设置值
设置变量
在大多数情况下,settings 的值将是一个单词,但在某些特殊情况下,很少有特殊值。
路径
在配置文件设置中,获取目录列表。在定义这些目录时,应该记住它们应该由系统路径分隔符分隔,在 *nix 平台上是 (:),在 Windows 上是分号 (;)。
# *nix version: environmentpath = $codedir/special_environments:$codedir/environments # Windows version: environmentpath = $codedir/environments;C:\ProgramData\PuppetLabs\code\environment
在定义中,首先扫描列出的文件目录,如果没有找到,则随后移动到列表中的另一个目录。
文件和目录
采用单个文件或目录的所有设置都可以接受可选的权限散列。当服务器启动时,Puppet 将强制执行列表中的那些文件或目录。
ssldir = $vardir/ssl {owner = service, mode = 0771}
在上面的代码中,允许的哈希是所有者、组和模式。所有者和组密钥只有两个有效值。
Puppet – 环境会议
在 Puppet 中,所有环境都有environment.conf文件。每当主服务器为任何节点或分配给该特定环境的所有节点提供服务时,此文件可以覆盖多个默认设置。
地点
在 Puppet 中,对于所有定义的环境,environment.conf 文件位于其主环境的顶层,非常靠近清单和模块控制器。举个例子,如果您的环境位于默认目录(Vipin/testing/environment) 中,则测试环境的配置文件位于Vipin/testing/environments/test/environment.conf。
例子
# /etc/testingdir/code/environments/test/environment.conf # Puppet Enterprise 需要 $basemodulepath; 请参阅下面的“模块路径”下的注释。 模块路径 = 站点:dist:modules:$basemodulepath # 使用我们的自定义脚本获取代码当前状态的 git commit: config_version = get_environment_commit.sh
格式
Puppet 中的所有配置文件都以相同的方式使用相同的类似 INI 的格式。environment.conf文件遵循与其他人一样的类似 INI 的格式,如 puppet.conf 文件。environment.conf 和puppet.conf之间的唯一区别是 environment.conf 文件不能包含 [main] 部分。environment.conf 文件中的所有设置都必须在任何配置部分之外。
值中的相对路径
大多数允许的设置都接受文件路径或路径列表作为值。如果任何路径是相关路径,它们开始时没有前导斜杠或驱动器号——它们将主要相对于该环境的主目录进行解析。
值的插值
Environment.conf 设置文件能够使用其他设置的值作为变量。有多个有用的变量可以插入到 environment.conf 文件中。以下是一些重要变量的列表 –
-
$basemodulepath – 用于在模块路径设置中包含目录。Puppet 企业用户通常应该包含modulepath 的这个值,因为 Puppet 引擎在basemodulepath 中使用 module 。
-
$environment – 作为 config_version 脚本的命令行参数很有用。您只能在 config_version 设置中插入此变量。
-
$codedir – 用于定位文件。
允许的设置
默认情况下,Puppet environment.conf 文件只允许覆盖列出的配置中的四个设置。
- 模块路径
- 显现
- 配置版本
- 环境超时
模块路径
这是 environment.conf 文件中的关键设置之一。modulepath 中定义的所有导演默认由 Puppet 加载。这是 Puppet 加载其模块的路径位置。需要明确设置这一点。如果未设置上述设置,则 Puppet 中任何环境的默认模块路径将为 –
<来自环境的模块目录>:$basemodulepath
显现
这用于定义主清单文件,Puppet master 将在启动和编译用于配置环境的定义清单之外的目录时使用该文件。在这里,我们可以定义单个文件、文件列表,甚至是由多个清单文件组成的目录,这些文件需要按定义的字母顺序进行评估和编译。
需要在 environment.conf 文件中明确定义此设置。如果没有,则 Puppet 将使用环境默认清单目录作为其主要清单。
配置版本
Config_version 可以定义为用于标识目录和事件的明确版本。默认情况下,当 Puppet 编译任何清单文件时,它会将配置版本添加到生成的目录以及当 Puppet master 在 Puppet 节点上应用任何定义的目录时生成的报告。Puppet 运行一个脚本来执行上述所有步骤,并将所有生成的输出用作 Config_version。
环境超时
它用于获取有关 Puppet 应该用于为给定环境加载数据的时间量的详细信息。如果该值在 puppet.conf 文件中定义,则这些值将覆盖默认超时值。
示例 environment.conf 文件
[掌握] 清单 = $confdir/environments/$environment/manifests/site.pp 模块路径 = $confdir/environments/$environment/modules
上面代码中$confdir是目录的路径,环境配置文件所在的目录。$environment是正在为其完成配置的环境的名称。
生产就绪环境配置文件
#环境配置文件 # Puppet 开始评估代码的主清单目录或文件 # 这是默认值。仅适用于 site.pp 文件或任何其他文件 清单 = 清单/ # 添加到模块路径中的目录,按照先匹配先使用的顺序查找: # modules - 外部模块的目录,由基于 Puppetfile 的 r10k 填充 # $basemodulepath - 来自:puppet config print basemodulepath 模块路径 = 站点:模块:$basemodulepath # 设置此环境的缓存超时时间。 # 这会覆盖在 puppet.conf 中为整个 Puppet 服务器直接设置的内容 # environment_timeout = 无限制 # 使用缓存你需要在部署新的 Puppet 代码时刷新缓存 # 这也可以手动完成运行:bin/puppet_flush_environment_cache.sh # 禁用目录缓存: 环境超时 = 0 # 这里我们将控制仓库中的一个 Puppet 环境(和 git 分支)传递给一个 # 获取上次 git 提交的标题和基本信息 config_version = 'bin/config_script.sh $environment'
木偶大师
在 Puppet 中,Puppet master 的客户端服务器架构被视为整个设置的控制权限。Puppet Master 在设置中充当服务器并控制所有节点上的所有活动。
对于任何需要充当 Puppet master 的服务器,它都应该运行 Puppet 服务器软件。该服务器软件是控制节点上所有活动的关键组件。在此设置中,要记住的一个关键点是让超级用户访问将在设置中使用的所有机器。以下是设置 Puppet master 的步骤。
先决条件
专用网络 DNS – 应配置前向和后向,其中每个服务器应具有唯一的主机名。如果没有配置 DNS,则可以使用专用网络与基础设施进行通信。
防火墙开放端口– Puppet master 应该在特定端口上打开,以便它可以侦听特定端口上的传入请求。我们可以使用防火墙上打开的任何端口。
创建 Puppet 主服务器
我们正在创建的 Puppet master 将在 CentOS 7 × 64 机器上使用 Puppet 作为主机名。创建 Puppet master 的最低系统配置是两个 CPU 内核和 1GB 内存。根据我们将使用此主节点管理的节点数量,配置也可能具有更大的大小。在基础设施中,比使用 2 GB RAM 配置的要大。
Host Name | 角色 | 私有 FQDN |
---|---|---|
Brcleprod001 | 木偶大师 | bnrcleprod001.brcl.com |
接下来需要生成Puppet master SSL证书,master的名字会复制到所有节点的配置文件中。
安装 NTP
由于 Puppet master 是任何给定设置中代理节点的中央权威,因此 Puppet master 的主要职责之一是维护准确的系统时间以避免潜在的配置问题,当它向节点颁发代理证书时可能会出现这种问题。
如果出现时间冲突问题,则如果主节点和节点之间存在时间差异,则证书可能会显示已过期。网络时间协议是避免此类问题的关键机制之一。
列出可用时区
$ timedatectl list-timezones
上述命令将提供可用时区的完整列表。它将为区域提供时区可用性。
以下命令可用于在机器上设置所需的时区。
$ sudo timedatectl set-timezone India/Delhi
使用 CentOS 机器的 yum 实用程序在 Puppet 服务器机器上安装 NTP。
$ sudo yum -y install ntp
将 NTP 与我们在上述命令中设置的系统时间同步。
$ sudo ntpdate pool.ntp.org
在通常的实践中,我们将更新 NTP 配置以使用更靠近机器数据中心的公共池。为此,我们需要编辑/etc下的 ntp.conf 文件。
$ sudo vi /etc/ntp.conf
从可用的 NTP 池时区添加时间服务器。以下是 ntp.conf 文件的样子。
brcleprod001.brcl.pool.ntp.org brcleprod002.brcl.pool.ntp.org brcleprod003.brcl.pool.ntp.org brcleprod004.brcl.pool.ntp.org
保存配置。启动服务器并启用守护进程。
$ sudo systemctl restart ntpd $ sudo systemctl enable ntpd
设置 Puppet 服务器软件
Puppet 服务器软件是运行在 Puppet 主机上的软件。它是将配置推送到其他运行 Puppet 代理软件的机器的机器。
使用以下命令启用官方 Puppet 实验室集合存储库。
$ sudo rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el7.noarch.rpm
安装 puppetserver 包。
$ sudo yum -y install puppetserver
在 Puppet 服务器上配置内存分配
正如我们所讨论的,默认情况下,Puppet 服务器配置在 2GB RAM 的机器上。可以根据机器上可用的可用内存以及服务器将管理的节点数量来自定义设置。
vi模式下编辑puppet服务器配置
$ 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"
完成后,保存并退出编辑模式。
完成上述所有设置后,我们就可以使用以下命令在 master 机器上启动 Puppet 服务器了。
$ sudo systemctl start puppetserver
接下来,我们将进行设置,以便在主服务器启动时启动 Puppet 服务器。
$ sudo systemctl enable puppetserver
Puppet.conf 主分区
[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 – 代理设置
Puppet 代理是一个软件应用程序,由 Puppet labs 提供,它运行在 Puppet 集群中的任何节点上。如果您想使用 Puppet master 管理任何服务器,则需要在该特定服务器上安装 Puppet 代理软件。通常,Puppet 代理将安装在任何给定基础架构上的所有机器上,但不包括 Puppet 主机。Puppet 代理软件能够在大多数 Linux、UNIX 和 Windows 机器上运行。在下面的例子中,我们使用 CentOS 机器安装 Puppet 代理软件就可以了。
步骤 1 – 使用以下命令启用官方 Puppet 实验室集合存储库。
$ sudo rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-pc1-el7.noarch.rpm
步骤 2 – 安装 Puppet 代理包。
$ sudo yum -y install puppet-agent
步骤 3 – 安装 Puppet 代理后,使用以下命令启用它。
$ sudo /opt/puppetlabs/bin/puppet resource service puppet ensure=running enable = true
Puppet 代理的一个关键特性是,当 Puppet 代理第一次开始运行时,它会生成一个 SSL 证书并将其发送给 Puppet 主控,后者将对其进行管理以进行签名和批准。一旦 Puppet Master 批准了代理的证书签名请求,它将能够与代理节点进行通信和管理。
注意– 需要在需要配置和管理任何给定 Puppet master 的所有节点上重复上述步骤。
Puppet – SSL 签名证书设置
当 Puppet 代理软件在任何 Puppet 节点上第一次运行时,它会生成一个证书并将证书签名请求发送给 Puppet 主控器。在 Puppet 服务器能够通信和控制代理节点之前,它必须签署该特定代理节点的证书。在以下部分中,我们将描述如何签名和检查签名请求。
列出当前证书请求
在 Puppet 主机上,运行以下命令以查看所有未签名的证书请求。
$ sudo /opt/puppetlabs/bin/puppet cert list
由于我们刚刚设置了一个新的代理节点,我们将看到一个批准请求。以下将是输出。
"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
它的开头不包含任何+(符号),这表示证书仍未签名。
签署请求
为了对在新节点上运行 Puppet 代理时生成的新证书请求进行签名,将使用 Puppet cert sign 命令以及证书的主机名,该证书是由需要新配置的节点生成的待签署。由于我们有 Brcleprod004.brcl.com 的证书,我们将使用以下命令。
$ sudo /opt/puppetlabs/bin/puppet cert sign Brcleprod004.brcl.com
以下将是输出。
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 服务器现在可以与签名证书所属的节点通信。
$ sudo /opt/puppetlabs/bin/puppet cert sign --all
从 Puppet Setup 中撤销 Host
当需要从设置中删除主机并重新添加它时,内核重建的配置有条件。这些是偶人本身无法管理的情况。可以使用以下命令来完成。
$ sudo /opt/puppetlabs/bin/puppet cert clean hostname
查看所有签名的请求
以下命令将生成带有 +(符号)的签名证书列表,表示请求已获批准。
$ sudo /opt/puppetlabs/bin/puppet cert list --all
以下将是它的输出。
+ "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 主控现在可以在其中管理新添加的节点。
Puppet – 安装和配置 r10K
在 Puppet 中,我们有一个名为 r10k 的代码管理工具,它有助于管理与我们可以在 Puppet 中配置的不同类型环境相关的环境配置,例如开发、测试和生产。这有助于在源代码存储库中存储与环境相关的配置。使用源代码控制 repo 分支,r10k 在 Puppet 主机上创建环境,使用 repo 中存在的模块安装和更新环境。
Gem 文件可用于在任何机器上安装 r10k,但为了模块化,为了获得最新版本,我们将使用 rpm 和 rpm 包管理器。以下是相同的示例。
$ 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 中配置环境
[main] environmentpath = $confdir/environments
为 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
安装 Puppet 清单和模块
r10k deploy environment -pv
由于我们需要每 15 分钟继续更新环境,因此我们将为此创建一个 cron 作业。
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
测试安装
为了测试一切是否按可接受的方式工作,需要为 Puppet 模块编译 Puppet 清单。运行以下命令并获得 YAML 输出作为结果。
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 – 验证 Puppet 设置
在 Puppet 中,可以在本地测试设置。因此,一旦我们设置了 Puppet 主节点和节点,就该在本地验证设置了。我们需要在本地安装 Vagrant 和 Vagrant box,这有助于在本地测试设置。
设置虚拟机
当我们在本地测试设置时,我们实际上并不需要一个正在运行的 Puppet master。这意味着无需在服务器上实际运行 Puppet master,我们可以简单地使用 Puppet 应用命令进行 Puppet 设置验证。Puppet apply 命令将根据配置文件中虚拟机的主机名应用来自local/etc/puppet 的更改。
为了测试设置,我们需要执行的第一步是构建以下Vagrantfile并启动机器并将/etc/puppet文件夹安装到位。所需的所有文件都将放置在具有以下结构的版本控制系统中。
目录结构
- manifests \- site.pp - modules \- your modules - test \- update-puppet.sh \- Vagrantfile - puppet.conf
流浪文件
# -*- 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 文件所在的同一目录中,脚本内容如下所示。
!/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的清单文件,该文件将在 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 命令。这将启动一个新的 VM,稍后,安装 Puppet,然后使用 Shell 脚本运行它。
以下将是输出。
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'
验证多机配置
如果我们需要在本地测试多台机器的配置,只需在 Vagrant 配置文件中进行更改即可。
新配置的流浪文件
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 实用程序。我们只需要使用以下配置扩展旧清单。
node 'brcleprod004.brcl.com' inherits 'brcleloacl003.brcl.com' { package { ['SSL'] : ensure => latest } }
在清单文件中进行配置更改后,我们只需要移动到 test 目录并运行基本的 vagrant up 命令,它将同时启动 brclelocal003.brcl.com和brcleprod004.brcl.com机器。在我们的例子中,我们正在尝试启动生产机器,这可以通过运行vagrant up production 命令来完成。这将创建一个名为 production 的新机器,如 Vagrant 文件中定义的那样,它将安装 SSL 包。
Puppet – 编码风格
在 Puppet 中,编码风格定义了在尝试将机器配置上的基础设施转换为代码时需要遵循的所有标准。Puppet 使用资源工作并执行其所有定义的任务。
Puppet 的语言定义有助于以结构化的方式指定所有资源,这是管理任何需要管理的目标机器所必需的。Puppet 使用 Ruby 作为其编码语言,它具有多种内置功能,可以通过代码端的简单配置轻松完成工作。
基本单元
Puppet 使用了多种易于理解和管理的基本编码风格。以下是少数人的名单。
资源
在 Puppet 中,资源被称为基本建模单元,用于管理或修改任何目标系统。资源涵盖了系统的所有方面,例如文件、服务和包。Puppet 具有内置功能,允许用户或开发人员开发自定义资源,这有助于管理机器的任何特定单元
在 Puppet 中,所有资源都通过使用“定义”或“类”聚合在一起。这些聚合功能有助于组织模块。以下是一个示例资源,它由多种类型、一个标题和一个属性列表组成,Puppet 可以使用这些属性来支持多个属性。Puppet 中的每个资源都有自己的默认值,可以在需要时覆盖。
文件的示例木偶资源
在以下命令中,我们尝试为特定文件指定权限。
file { '/etc/passwd': owner => superuser, group => superuser, mode => 644, }
每当在任何机器上执行上述命令时,它都会验证系统中的 passwd 文件是否按描述配置。冒号之前的文件是资源的标题,在Puppet配置的其他部分可以称为资源。
除标题外还指定本地名称
file { 'sshdconfig': name => $operaSystem ? { solaris => '/usr/local/etc/ssh/sshd_config', default => '/etc/ssh/sshd_config', }, owner => superuser, group => superuser, mode => 644, }
通过使用始终相同的标题,可以很容易地在配置中引用文件资源,而无需重复操作系统相关逻辑。
另一个示例可能是使用依赖于文件的服务。
service { 'sshd': subscribe => File[sshdconfig], }
有了这种依赖性,一旦sshdconfig文件发生更改,sshd服务将始终重新启动。这里要记住的一点是File[sshdconfig]是小写形式的 File 声明,但如果我们将其更改为FILE[sshdconfig] ,那么它将成为一个参考。
在声明资源时需要牢记的一个基本点是,每个配置文件只能声明一次。多次重复声明相同的资源会导致错误。通过这个基本概念,Puppet 确保对配置进行良好建模。
我们甚至有能力管理资源依赖,这有助于管理多个关系。
service { 'sshd': require => File['sshdconfig', 'sshconfig', 'authorized_keys'] }
元参数
元参数在 Puppet 中被称为全局参数。元参数的关键特性之一是,它适用于 Puppet 中的任何类型的资源。
资源默认
当需要定义默认资源属性值时,Puppet 提供了一组语法来归档它,使用没有标题的大写资源规范。
例如,如果我们想设置所有可执行文件的默认路径,可以使用以下命令完成。
Exec { path => '/usr/bin:/bin:/usr/sbin:/sbin' } exec { 'echo Testing mataparamaters.': }
在上面的命令中,第一条语句 Exec 将为 exec 资源设置默认值。Exec 资源需要一个完全限定的路径或一个看起来像可执行文件的路径。有了这个,我们可以为整个配置定义一个默认路径。默认值适用于 Puppet 中的任何资源类型。
默认值不是全局值,然而,它们只影响定义它们的范围或它的下一个变量。如果要为完整配置定义默认值,那么我们将在下一节中定义默认值和类。
资源集合
聚合是将事物收集在一起的方法。Puppet 支持一个非常强大的聚合概念。在 Puppet 中,聚合用于将资源分组,这是 Puppet 的基本单位。Puppet 中的这种聚合概念是通过使用两个强大的方法(称为类和定义)来实现的。
类和定义
类负责对节点的基本方面进行建模。他们可以说节点是一个网络服务器,而这个特定的节点就是其中之一。在 Puppet 中,编程类是单例的,每个节点可以评估一次。
另一方面,定义可以在单个节点上多次使用。它们的工作方式类似于使用该语言创建自己的 Puppet 类型。它们被创建为多次使用,每次使用不同的输入。这意味着可以将变量值传递到定义中。
类和定义之间的区别
类和定义之间唯一的主要区别是在定义构建结构和分配资源时,类每个节点仅评估一次,而另一方面,定义在同一单个节点上多次使用。
班级
Puppet 中的类是使用 class 关键字引入的,该特定类的内容包含在花括号内,如下例所示。
class unix { file { '/etc/passwd': owner => 'superuser', group => 'superuser', mode => 644; '/etc/shadow': owner => 'vipin', group => 'vipin', mode => 440; } }
在下面的例子中,我们使用了一些类似于上面的简写。
class unix { file { '/etc/passwd': owner => 'superuser', group => 'superuser', mode => 644; } file {'/etc/shadow': owner => 'vipin', group => 'vipin', mode => 440; } }
Puppet 类中的继承
在 Puppet 中,默认支持继承的 OOP 概念,其中类可以扩展以前的功能,而无需在新创建的类中再次复制和粘贴完整的代码位。继承允许子类覆盖父类中定义的资源设置。使用继承时要记住的一件关键事情是,一个类只能从一个父类继承特性,不能超过一个。
class superclass inherits testsubclass { File['/etc/passwd'] { group => wheel } File['/etc/shadow'] { group => wheel } }
如果需要撤销父类中指定的某些逻辑,我们可以使用undef 命令。
class superclass inherits testsubcalss { File['/etc/passwd'] { group => undef } }
使用继承的替代方法
class tomcat { service { 'tomcat': require => Package['httpd'] } } class open-ssl inherits tomcat { Service[tomcat] { require +> File['tomcat.pem'] } }
Puppet 中的嵌套类
Puppet 支持类嵌套的概念,它允许使用嵌套类,这意味着一个类在另一个类中。这有助于实现模块化和范围界定。
class testclass { class nested { file { '/etc/passwd': owner => 'superuser', group => 'superuser', mode => 644; } } } class anotherclass { include myclass::nested }
参数化类
在 Puppet 中,类可以扩展它们的功能以允许将参数传递到类中。
要在类中传递参数,可以使用以下构造 –
class tomcat($version) { ... class contents ... }
在 Puppet 中要记住的一个关键点是,使用 include 函数不会添加带参数的类,而是可以将生成的类作为定义添加。
node webserver { class { tomcat: version => "1.2.12" } }
默认值作为类中的参数
class tomcat($version = "1.2.12",$home = "/var/www") { ... class contents ... }
运行阶段
Puppet 支持运行阶段的概念,这意味着用户可以根据需要添加多个阶段,以管理任何特定资源或多个资源。当用户想要开发复杂的目录时,此功能非常有用。在复杂的目录中,需要编译大量资源,同时牢记定义的资源之间的依赖关系不应受到影响。
Run Stage 在管理资源依赖方面非常有帮助。这可以通过在定义的阶段添加类来完成,其中特定的类包含资源集合。使用运行阶段,Puppet 保证定义的阶段将在每次目录运行并应用于任何 Puppet 节点时以指定的可预测顺序运行。
为了使用它,需要在已经存在的阶段之外声明额外的阶段,然后可以将 Puppet 配置为使用 require “->”和“+>”之前的相同资源关系语法以指定的顺序管理每个阶段。然后,该关系将保证与每个阶段关联的类的顺序。
使用 Puppet 声明式语法声明额外的阶段
stage { "first": before => Stage[main] } stage { "last": require => Stage[main] }
一旦声明了阶段,一个类就可以与使用阶段的主要阶段以外的阶段相关联。
class { "apt-keys": stage => first; "sendmail": stage => main; "apache": stage => last; }
与 apt-key 类关联的所有资源将首先运行。Sendmail 中的所有资源将是主类,与 Apache 关联的资源将是最后一个阶段。
定义
在 Puppet 中,任何清单文件中的资源收集都是由类或定义完成的。定义与 Puppet 中的类非常相似,但是它们是通过定义关键字(不是类)引入的,并且它们支持参数而不是继承。它们可以使用不同的参数在同一系统上多次运行。
例如,如果想要创建一个定义来控制源代码存储库,其中一个人试图在同一系统上创建多个存储库,则可以使用定义而不是类。
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 和 $name 仅适用于定义,不适用于类或其他资源。
模块
一个模块可以定义为所有配置的集合,Puppet master 将使用这些配置在任何特定的 Puppet 节点(代理)上应用配置更改。它们也被称为执行特定任务所需的不同类型配置的便携式集合。例如,一个模块可能包含配置 Postfix 和 Apache 所需的所有资源。
节点
节点是非常简单的剩余步骤,这就是我们如何将我们定义的内容(“这就是网络服务器的样子”)与选择哪些机器来完成这些指令进行匹配。
节点定义看起来很像类,包括支持的继承,但是它们很特殊,当一个节点(运行 Puppet 客户端的受管计算机)连接到 Puppet 主守护进程时,它的名称将出现在定义的节点列表中。将为节点评估定义的信息,然后节点将发送该配置。
节点名称可以是短主机名或完全限定域名 (FQDN)。
node 'www.vipin.com' { include common include apache, squid }
上面的定义创建了一个名为 www.vipin.com 的节点,并包含了 common、Apache 和 Squid 类
我们可以通过用逗号分隔每个节点来将相同的配置发送到不同的节点。
node 'www.testing.com', 'www.testing2.com', 'www3.testing.com' { include testing include tomcat, squid }
匹配节点的正则表达式
node /^www\d+$/ { include testing }
节点继承
Node 支持有限的继承模型。像类一样,节点只能从另一个节点继承。
node 'www.testing2.com' inherits 'www.testing.com' { include loadbalancer }
在上面的代码中,www.testing2.com 除了额外的负载均衡器类之外,还继承了 www.testing.com 的所有功能。
高级支持功能
Quoting – 在大多数情况下,我们不需要在 Puppet 中引用字符串。任何以字母开头的字母数字字符串都应保留而不加引号。但是,为任何非负值引用字符串始终是最佳实践。
带引号的变量插值
到目前为止,我们已经在定义方面提到了变量。如果需要将这些变量与字符串一起使用,请使用双引号,而不是单引号。单引号字符串不会做任何变量插值,双引号字符串会做。变量可以用{}括起来,这使它们更易于一起使用且更易于理解。
$value = "${one}${two}"
作为最佳实践,应该对所有不需要字符串插值的字符串使用单引号。
大写
大写是用于引用、继承和设置特定资源的默认属性的过程。基本上有两种基本的使用方法。
-
引用– 这是引用已创建资源的方式。它主要用于依赖目的,必须将资源的名称大写。例如,需要 => 文件 [sshdconfig]
-
继承– 从子类覆盖父类的设置时,使用资源名称的大写版本。使用小写版本会导致错误。
-
设置默认属性值– 使用没有标题的大写资源可以设置资源的默认值。
数组
Puppet 允许在多个区域使用数组[一、二、三]。
几个类型成员,例如主机定义中的别名,在它们的值中接受数组。具有多个别名的主机资源将如下所示。
host { 'one.vipin.com': alias => [ 'satu', 'dua', 'tiga' ], ip => '192.168.100.1', ensure => present, }
上面的代码将一个主机‘one.brcletest.com’添加到主机列表中,三个别名为‘satu’ ‘dua’ ‘tiga’。如果想将多个资源添加到一个资源中,可以按照以下示例进行操作。
resource { 'baz': require => [ Package['rpm'], File['testfile'] ], }
变量
Puppet 像大多数其他编程语言一样支持多个变量。Puppet 变量用$表示。
$content = 'some content\n' file { '/tmp/testing': content => $content }
如前所述,Puppet 是一种声明式语言,这意味着它的范围和赋值规则与命令式语言不同。主要区别在于不能在单个范围内更改变量,因为它们依赖文件中的顺序来确定变量的值。顺序在声明性语言中无关紧要。
$user = root file { '/etc/passwd': owner => $user, } $user = bin file { '/bin': owner => $user, recurse => true, }
变量范围
变量作用域定义了所有定义的变量是否有效。与最新功能一样,Puppet 目前是动态范围的,在 Puppet 术语中,这意味着所有定义的变量都在其范围内进行评估,而不是在定义它们的位置。
$test = 'top' class Testclass { exec { "/bin/echo $test": logoutput => true } } class Secondtestclass { $test = 'other' include myclass } include Secondtestclass
限定变量
Puppet 支持在类或定义中使用限定变量。当用户希望在他已经定义或将要定义的其他类中使用相同的变量时,这非常有用。
class testclass { $test = 'content' } class secondtestclass { $other = $myclass::test }
在上面的代码中, $other 变量的值评估内容。
条件句
条件是用户希望在满足定义的条件或所需条件时执行一组语句或代码的情况。Puppet 支持两种类型的条件。
只能在定义的资源内使用的选择器条件来选择机器的正确值。
语句条件是清单中使用更广泛的条件,它有助于包含用户希望包含在同一清单文件中的其他类。在一个类中定义一组不同的资源,或做出其他结构性决策。
选择器
当用户希望基于事实或其他变量指定不同于默认值的资源属性和变量时,选择器很有用。在 Puppet 中,选择器索引的工作方式类似于多值三向运算符。选择器还能够在无值中定义自定义默认值,这些值在清单中定义并与条件匹配。
$owner = $Sysoperenv ? { sunos => 'adm', redhat => 'bin', default => undef, }
在 Puppet 0.25.0 的更高版本中,选择器可以用作正则表达式。
$owner = $Sysoperenv ? { /(Linux|Ubuntu)/ => 'bin', default => undef, }
在上面的例子中,选择器$Sysoperenv值匹配 Linux 或 Ubuntu,那么 bin 将是选择的结果,否则用户将被设置为 undefined。
语句条件
语句条件是 Puppet 中的另一种条件语句,与 Shell 脚本中的 switch case 条件非常相似。在这里,定义了多组 case 语句,并根据每个条件匹配给定的输入值。
执行与给定输入条件匹配的 case 语句。这个case语句条件没有任何返回值。在 Puppet 中,条件语句的一个非常常见的用例是运行一组基于底层操作系统的代码位。
case $ Sysoperenv { sunos: { include solaris } redhat: { include redhat } default: { include generic} }
Case Statement 还可以通过用逗号分隔来指定多个条件。
case $Sysoperenv { development,testing: { include development } testing,production: { include production } default: { include generic } }
If-Else 语句
Puppet 支持基于条件的操作的概念。为了实现它,If/else 语句提供了基于条件返回值的分支选项。如以下示例所示 –
if $Filename { file { '/some/file': ensure => present } } else { file { '/some/other/file': ensure => present } }
最新版本的 Puppet 支持变量表达式,其中 if 语句也可以根据表达式的值进行分支。
if $machine == 'production' { include ssl } else { include nginx }
为了实现更多的代码多样性和执行复杂的条件操作,Puppet 支持嵌套的 if/else 语句,如下代码所示。
if $ machine == 'production' { include ssl } elsif $ machine == 'testing' { include nginx } else { include openssl }
虚拟资源
虚拟资源是那些除非实现否则不会发送到客户端的资源。
以下是在 Puppet 中使用虚拟资源的语法。
@user { vipin: ensure => present }
在上面的例子中,用户vipin是虚拟定义的,以实现可以在集合中使用的定义。
User <| title == vipin |>
注释
在任何代码位中使用注释来创建关于一组代码行及其功能的附加节点。在 Puppet 中,目前支持两种类型的注释。
- Unix shell 风格的注释。他们可以在自己的行上,也可以在下一行。
- 多行 C 风格注释。
以下是 shell 样式注释的示例。
# this is a comment
以下是多行注释的示例。
/* This is a comment */
运算符优先级
Puppet 运算符优先级符合大多数系统中的标准优先级,从最高到最低。
以下是表达式列表
- != 不是
- / = 乘以除法
- – + = 减号,加号
- << >> = 左移和右移
- == !== 不等于,等于
- >= <= > < = 大于等于、小于或等于、大于、小于
比较表达式
当用户想要在满足给定条件时执行一组语句时使用比较表达式。比较表达式包括使用 == 表达式的相等性测试。
if $environment == 'development' { include openssl } else { include ssl }
不相等的例子
if $environment != 'development' { $otherenvironment = 'testing' } else { $otherenvironment = 'production' }
算术表达式
$one = 1 $one_thirty = 1.30 $two = 2.034e-2 $result = ((( $two + 2) / $one_thirty) + 4 * 5.45) - (6 << ($two + 4)) + (0×800 + -9)
布尔表达式
布尔表达式可以使用 or、and、& not。
$one = 1 $two = 2 $var = ( $one < $two ) and ( $one + 1 == $two )
正则表达式
Puppet 支持使用 =~(匹配)和 !~(不匹配)进行正则表达式匹配。
if $website =~ /^www(\d+)\./ { notice('Welcome web server #$1') }
像 case 和 selector regex match 为每个 regex 创建有限范围的变量。
exec { "Test": command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt", unless => "/bin/which php" }
同样,我们可以使用unless、unless一直执行命令,除非unless下的命令成功退出。
exec { "Test": command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt", unless => "/bin/which php" }
使用模板
当一个人希望有一个预定义的结构时使用模板,该结构将在 Puppet 中的多个模块中使用,并且这些模块将分布在多台机器上。使用模板的第一步是创建一个使用模板方法呈现模板内容的模板。
file { "/etc/tomcat/sites-available/default.conf": ensure => "present", content => template("tomcat/vhost.erb") }
为了加强组织和模块化,Puppet 在处理本地文件时几乎没有做任何假设。Puppet 在 apache/templates 文件夹中的 modules 目录中查找 vhost.erb 模板。
定义和触发服务
在 Puppet 中,它有一个称为服务的资源,它能够管理在任何特定机器或环境上运行的所有服务的生命周期。服务资源用于确保服务被初始化和启用。它们也用于服务重启。
例如,在之前的 tomcat 模板中,我们设置了 apache 虚拟主机。如果要确保在虚拟主机更改后重新启动 apache,我们需要使用以下命令为 apache 服务创建服务资源。
service { 'tomcat': ensure => running, enable => true }
在定义资源时,我们需要包含通知选项以触发重启。
file { "/etc/tomcat/sites-available/default.conf": ensure => "present", content => template("vhost.erb"), notify => Service['tomcat'] }
Puppet – 清单文件
在 Puppet 中,所有使用 Ruby 编程语言编写并以.pp扩展名保存的程序都称为manifests。一般而言,所有旨在创建或管理任何目标主机的 Puppet 程序都称为清单。所有用 Puppet 编写的程序都遵循 Puppet 编码风格。
Puppet 的核心是资源的声明方式以及这些资源如何表示它们的状态。在任何清单中,用户都可以拥有一组不同类型的资源,这些资源使用类和定义组合在一起。
在某些情况下,Puppet manifest 甚至可以有一个条件语句以达到所需的状态。但是,最终归根结底是要确保以正确的方式定义和使用所有资源,并且在转换为目录后应用定义的清单能够执行其设计任务。
清单文件工作流
傀儡清单由以下组件组成 –
-
文件(这些是普通文件,Puppet 与它们无关,只是为了捡起它们并将它们放置在目标位置)
-
资源
-
模板(这些可用于在节点上构建配置文件)。
-
节点(所有与客户端节点相关的定义都在这里定义)
-
班级
注意事项
-
在 Puppet 中,所有清单文件都使用 Ruby 作为其编码语言,并以.pp扩展名保存。
-
许多清单中的“导入”语句用于在 Puppet 启动时加载文件。
-
为了导入目录中包含的所有文件,您可以以另一种方式使用 import 语句,例如 import ‘clients/*’。这将导入该目录中的所有.pp文件。
编写清单
使用变量
在编写清单时,用户可以在清单中的任何点定义新变量或使用现有变量。Puppet 支持不同类型的变量,但很少有经常使用的变量,例如字符串和字符串数组。除此之外,还支持其他格式。
字符串变量示例
$package = "vim" package { $package: ensure => "installed" }
使用循环
当一个人希望对同一组代码进行多次迭代直到满足定义的条件时,就会使用循环。它们还用于执行具有不同值集的重复性任务。为 10 个不同的事物创建 10 个任务。可以创建单个任务并使用循环来使用想要安装的不同软件包重复该任务。
最常见的是使用数组来重复具有不同值的测试。
$packages = ['vim', 'git', 'curl'] package { $packages: ensure => "installed" }
使用条件
Puppet 支持大多数可以在传统编程语言中找到的条件结构。条件可用于动态定义是执行特定任务还是执行一组代码。像 if/else 和 case 语句。此外,像 execute 这样的条件也将支持像条件一样工作的属性,但只接受命令输出作为条件。
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 中,模块可以定义为资源、类、文件、定义和模板的集合。Puppet 支持轻松重新分配模块,这对代码的模块化非常有帮助,因为您可以编写指定的通用模块,并且只需很少的简单代码更改就可以多次使用它。例如,这将启用 /etc/puppet 下的默认站点配置,并在 /etc/share/puppet 中使用由 Puppet 提供的模块。
模块配置
在任何 Puppet 模块中,我们都有两个分区,它们有助于定义代码结构和控制面额。
-
模块的搜索路径使用puppetmasterd或masterd 中以冒号分隔的目录列表进行配置,后者是 Puppet 主配置文件的后面部分,带有modulepath参数。
[puppetmasterd] ... modulepath = /var/lib/puppet/modules:/data/puppet/modules
-
fileserver.conf 中文件服务器模块的访问控制设置,该模块的路径配置始终被忽略,指定路径将产生警告。
可以通过设置 PUPPETLAB 环境变量在运行时添加搜索路径,该变量也必须是以冒号分隔的变量列表。
模块来源
Puppet 支持不同的位置来存储模块。任何模块都可以存储在任何特定机器的不同文件系统中。但是,存储模块的所有路径都必须在称为modulepath 的配置变量中指定,通常,这是一个路径变量,Puppet 会在其中扫描所有模块目录并在启动时加载它们。
合理的默认路径可以配置为 –
/etc/puppet/modules:/usr/share/puppet:/var/lib/modules.
或者,可以将 /etc/puppet 目录建立为一个特殊的匿名模块,它总是首先被搜索。
模块命名
Puppet 遵循特定模块的相同命名标准,其中模块名称必须是普通单词,匹配 [-\\w+](字母、单词、数字、下划线和破折号)并且不包含命名空间分隔符:: 或 /。虽然在模块层次结构方面可能允许,但对于新模块,它不能嵌套。
模块内部组织
当用户在 Puppet 中创建一个新模块时,它遵循相同的结构并包含清单、分布式文件、插件和模板,它们排列在特定的目录结构中,如以下代码所示。
MODULE_PATH/ downcased_module_name/ files/ manifests/ init.pp lib/ puppet/ parser/ functions provider/ type/ facter/ templates/ README
无论何时创建模块,它都会在 manifests 目录内的指定修复位置包含init.pp清单文件。此清单文件是一个默认文件,它首先在任何特定模块中执行,并包含与该特定模块关联的所有类的集合。额外的.pp文件可以直接添加到 manifests 文件夹下。如果我们要添加额外的 .pp 文件,它们应该以类命名。
使用模块实现的关键特性之一是代码共享。一个模块本质上应该是自包含的,这意味着你应该能够从任何地方包含任何模块并将其放到模块路径上,当 Puppet 启动时会加载它。在模块的帮助下,可以在 Puppet 基础设施编码中获得模块化。
例子
考虑安装固定 auto.homes 映射并从模板生成 auto.master 的 autofs 模块。
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") } }
文件系统将具有以下文件。
MODULE_PATH/ autofs/ manifests/ init.pp files/ auto.homes templates/ auto.master.erb
模块查找
Puppet 遵循预定义的结构,其中在定义的结构中包含多个目录和子目录。这些目录包含模块执行某些操作所需的不同类型的文件。一点幕后魔法确保正确的文件与正确的上下文相关联。所有模块搜索都在模块路径中,一个以冒号分隔的目录列表。
对于文件服务器上的文件引用,使用类似的引用,以便对 puppet 的引用://$servername/modules/autofs/auto.homes 解析为模块路径中的文件 autofs/files/auto.homes。
要使模块既可用于命令行客户端又可用于 puppet master,可以使用 from puppet:///path 的 URL。即没有明确服务器名称的 URL。Puppet和puppetd对此类 URL 的处理略有不同。Puppet 在本地文件系统中搜索无服务器 URL。
模板文件的搜索方式类似于清单和文件:提及模板(“autofs/auto.master.erb”)将使 puppetmaster 首先在$templatedir/autofs/auto.master.erb 中查找文件,然后模块路径上的autofs/templates/auto.master.erb。有了 Puppet 下所有东西的 Puppet 版本,它就可以使用了。这称为模块自动加载。Puppet 将尝试从模块自动加载类和定义。
木偶 – 文件服务器
Puppet 遵循客户端和服务器的概念,设置中的一台机器作为服务器机器运行,上面运行 Puppet 服务器软件,其余的机器作为客户端运行,上面运行 Puppet 代理软件。文件服务器的此功能有助于在多台机器上复制文件。Puppet 中文件服务功能的这一特性是中央 Puppet 守护进程的一部分。Puppetmasterd 和客户端函数在获取文件属性作为文件对象方面起着关键作用。
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 的文件服务功能通过支持文件服务模块来抽象本地文件系统拓扑。我们将按以下方式指定文件服务模块。
“puppet://server/modules/module_name/sudoers”
文件格式
在 Puppet 目录结构中,文件服务器配置默认位于/etc/puppet/fileserver.config目录下,如果用户希望更改此默认配置文件路径,可以使用新的 config 标志来完成puppetmasterd。配置文件类似于 INI 文件,但并不完全相同。
[module] path /path/to/files allow *.domain.com deny *.wireless.domain.com
如上面的代码片段所示,所有三个选项都在配置文件中表示。模块名称有点放在括号中。路径是唯一必需的选项。默认安全选项是拒绝所有访问,因此如果未指定允许行,则任何人都可以使用将配置的模块。
路径可以包含 %d、%h 和 %H 中的任何一个或全部,它们会被其域名、主机名和完全限定的主机名动态替换。所有都取自客户端的 SSL 证书(因此,如果主机名和证书名称不匹配,请小心)。这在创建模块时非常有用,其中每个客户端的文件都完全分开保存。例如,对于私有主机密钥。
[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。
安全
Puppet 支持保护 Puppet 文件服务器上的文件的两个基本概念。这是通过允许访问特定文件并拒绝访问不需要的文件来实现的。默认情况下,Puppet 不允许访问任何文件。它需要明确定义。可以在文件中用于允许或拒绝访问的格式是使用 IP 地址、名称或全局允许。
如果客户端没有直接连接到 Puppet 文件服务器,例如使用反向代理和 Mongrel,那么文件服务器将看到所有连接都来自代理服务器而不是 Puppet 客户端。在上述情况下,以主机名为基础限制主机名是最佳实践。
定义文件结构时需要注意的一个关键点是,所有的拒绝语句都在允许语句之前解析。因此,如果任何拒绝语句与主机匹配,则该主机将被拒绝,如果在即将到来的文件中未写入允许语句,则该主机将被拒绝。此功能有助于设置任何特定站点的优先级。
主机名
在任何文件服务器配置中,可以通过两种方式指定文件主机名:使用完整的主机名或使用 * 通配符指定整个域名,如下例所示。
[export] path /usr allow brcleprod001.brcl.com allow *.brcl.com deny brcleprod002.brcl.com
IP地址
在任何文件服务器配置中,可以使用完整的 IP 地址或通配符地址将文件地址指定为类似于主机名。还可以使用 CIDR 系统表示法。
[export] path /usr allow 127.0.0.1 allow 172.223.30.* allow 172.223.30.0/24
全局允许
当用户希望每个人都可以访问特定模块时使用全局允许。为此,单个通配符有助于让每个人都访问该模块。
[export] path /export allow *
木偶 – 事实与事实
Puppet 支持将多个值保存为环境变量。Puppet 通过使用factor支持此功能。在 Puppet 中,facter 是一个独立的工具,用于保存环境级别的变量。In 可以认为类似于 Bash 或 Linux 的 env 变量。有时,存储在事实中的信息与机器的环境变量之间可能存在重叠。在 Puppet 中,键值对被称为“事实”。每个资源都有自己的事实,而在 Puppet 中,用户可以建立自己的自定义事实。
# facter
Facter 命令可用于列出所有不同的环境变量及其相关值。这些事实集合带有现成的事实,被称为核心事实。可以将自定义事实添加到集合中。
如果只想查看一个变量。可以使用以下命令完成。
# facter {Variable Name} Example [root@puppetmaster ~]# facter virtual virtualbox
因子对 Puppet 很重要的原因是,因子和事实在整个 Puppet 代码中都可以作为“全局变量”使用,这意味着它可以在任何时间点在代码中使用,无需任何其他引用。
测试示例
[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", } }
测试它
[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作为普通变量替换了该值。
在 Puppet 中,可以使用和定义三种类型的事实 –
- 核心事实
- 自定义事实
- 外部事实
核心事实在顶层定义,并且可以在代码中的任何位置访问。
傀儡事实
就在代理向主服务器请求目录之前,代理首先以键值对的形式编译自身可用的完整信息列表。代理的信息由一个名为 facter 的工具收集,每个键值对被称为一个事实。以下是代理的常见事实输出。
[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 数据被视为全局变量。
这些事实随后可作为顶级变量使用,Puppet 主控可以使用它们为请求代理编译 Puppet 目录。因子在清单中作为带有 $ 前缀的普通变量被调用。
例子
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的事实扣除。
[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
自定义事实
以上我们看到的所有事实都是机器的核心事实。可以通过以下方式将此自定义事实添加到节点 –
- 使用“export FACTER …语法”
- 使用 $LOAD_PATH 设置
- 因子库
- 插件同步
使用“export FACTER”语法
可以使用导出 FACTER_{fact’s name} 语法手动添加事实。
例子
[root@puppetagent1 facter]# export FACTER_tallest_mountain="Everest" [root@puppetagent1 facter]# facter tallest_mountain Everest
使用 $LOAD_PATH 设置
在 Ruby 中,$LOAD_PATH 相当于 Bash 特殊参数。虽然它类似于 bash $PATH 变量,但实际上 $LOAD_PATH 并不是一个环境变量,而是一个预定义的变量。
$LOAD_PATH 有一个同义词“$:”。此变量是一个用于搜索和加载值的数组。
[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
让我们举一个创建目录因子并添加.pp文件并向其附加内容的示例。
[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 文件中。
[root@puppetagent1 facter]# cat newadded_facts.rb Facter.add('tallest_mountain') do setcode "echo Everest" end
Facter 的工作方式是扫描 $LOAD_PATH 中列出的所有文件夹,并寻找一个名为 factorer 的导演。一旦找到该特定文件夹,它就会将它们加载到文件夹结构中的任何位置。如果它找到了这个文件夹,那么它就会在那个 facter 文件夹中查找任何 Ruby 文件,并在内存中加载关于任何特定配置的所有定义的事实。
使用 FACTERLIB
在 Puppet 中,FACTERLIB 的工作方式与 $LOAD_PATH 非常相似,但只有一个关键区别,它是一个操作系统级别的环境参数,而不是一个 Ruby 特殊变量。默认情况下,可能未设置环境变量。
[root@puppetagent1 facter]# env | grep "FACTERLIB" [root@puppetagent1 facter]#
要测试 FACTERLIB,我们需要执行以下步骤。
在以下结构中创建一个名为 test_facts 的文件夹。
[root@puppetagent1 tmp]# tree /tmp/test_facts/ /tmp/some_facts/ ├── vipin │ └── longest_river.rb └── testing └── longest_wall.rb
将以下内容添加到 .rb 文件中。
[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
使用导出语句。
[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
测试新因子。
[root@puppetagent1 /]# facter longest_river Nile [root@puppetagent1 /]# facter longest_wall China Wall
外部事实
当用户希望应用在供应时创建的一些新事实时,外部事实非常有用。外部事实是在虚拟机配置阶段(例如使用 vSphere、OpenStack、AWS 等)将元数据应用于虚拟机的关键方法之一
Puppet 可以使用创建的所有元数据及其详细信息来确定目录中应该存在哪些详细信息,哪些将被应用。
创建外部事实
在代理机器上,我们需要创建一个如下所述的目录。
$ mkdir -p /etc/facter/facts.d
在目录中创建一个 Shell 脚本,内容如下。
$ 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"
更改脚本文件的权限。
$ chmod u+x /etc/facter/facts.d/external-facts.sh
完成后,我们现在可以看到与键/值对一起存在的变量。
$ facter hostgroup dev $ facter environment development
可以在 Puppet 中编写自定义事实。作为参考,请使用来自 Puppet 站点的以下链接。
https://docs.puppet.com/facter/latest/fact_overview.html#writing-structured-facts
傀儡 – 资源
资源是 Puppet 用于设计和构建任何特定基础设施或机器的关键基本单元之一。它们主要用于建模和维护系统配置。Puppet 有多种类型的资源,可以用来定义系统架构,或者用户有杠杆来构建和定义新的资源。
清单文件或任何其他文件中的 Puppet 代码块称为资源声明。代码块是用一种称为声明式建模语言 (DML) 的语言编写的。以下是它的外观示例。
user { 'vipin': ensure => present, uid => '552', shell => '/bin/bash', home => '/home/vipin', }
在 Puppet 中,任何特定资源类型的资源声明都是在代码块中完成的。在以下示例中,用户主要由四个预定义参数组成。
-
资源类型– 在上面的代码片段中,它是用户。
-
资源参数– 在上面的代码片段中,它是 Vipin。
-
属性– 在上面的代码片段中,它是确保、uid、shell、home。
-
值– 这些是对应于每个属性的值。
每种资源类型都有自己定义定义和参数的方式,用户有权选择他希望资源的外观。
资源类型
Puppet 中有不同类型的可用资源,它们具有自己的功能方式。可以使用“describe”命令和“-list”选项查看这些资源类型。
[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
资源标题
在上面的代码片段中,我们将资源标题设为 vipin,它对于同一代码文件中使用的每个资源都是唯一的。这是此用户资源类型的唯一标题。我们不能有同名的资源,因为它会导致冲突。
可以使用 Resource 命令查看使用类型 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', }
列出特定用户的资源
[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’, }
属性和值
任何资源的主体都由一组属性值对组成。在这里可以为给定资源的属性指定值。每种资源类型都有自己的一组属性,可以使用键值对进行配置。
描述可用于获取有关特定资源属性的更多详细信息的子命令。在以下示例中,我们拥有有关用户资源及其所有可配置属性的详细信息。
[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 – 资源抽象层
在 Puppet 中,资源抽象层 (RAL) 可以被视为整个基础设施和 Puppet 设置工作的核心概念化模型。在 RAL 中,每个字母都有自己的重要意义,定义如下。
资源 [R]
一个资源可以被认为是用于在 Puppet 中对任何配置进行建模的所有资源。它们基本上是内置资源,默认情况下存在于 Puppet 中。它们可以被视为属于预定义资源类型的一组资源。它们类似于任何其他编程语言中的 OOP 概念,其中对象是类的实例。在 Puppet 中,它的资源是一个资源类型的实例。
抽象 [A]
抽象可以被视为一个关键特性,其中资源是独立于目标操作系统定义的。换句话说,在编写任何清单文件时,用户无需担心目标机器或存在于该特定机器上的操作系统。抽象地说,资源提供了关于 Puppet 代理上需要存在的内容的足够信息。
Puppet 将处理幕后发生的所有功能或魔法。无论资源和操作系统如何,Puppet 都会负责在目标机器上实现配置,用户无需担心 Puppet 在幕后做了什么。
在抽象中,Puppet 将资源与其实现分离。这种特定于平台的配置存在于提供商处。我们可以使用多个子命令及其提供程序。
层 [L]
可以根据资源集合定义整个机器设置和配置,并且可以通过 Puppet 的 CLI 界面进行查看和管理。
用户资源类型示例
[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'.
测试资源
在Puppet中,直接测试一个资源,就是先申请一个自己想使用的资源来配置一个目标节点,这样机器的状态就会随之改变。
为了测试,我们将在本地应用资源。因为我们有一个上面预定义的资源user = vipin。应用资源的一种方法是通过 CLI。这可以通过将完整资源重新写入单个命令,然后将其传递给资源子命令来完成。
puppet resource user vipin ensure = present uid = '505' shell = '/bin/bash' home = '/home/vipin'
测试应用的资源。
[root@puppetmaster ~]# cat /etc/passwd | grep "vipin" vipin:x:505:501::/home/vipin:/bin/bash
上面的输出显示资源已应用到系统,我们创建了一个名为 Vipin 的新用户。建议您自行测试,因为上述所有代码都经过测试并且是工作代码。
人偶 – 模板
模板化是一种以标准格式获取事物的方法,可以在多个位置使用。在 Puppet 中,使用 erb 支持模板和模板,它是标准 Ruby 库的一部分,可以在 Ruby 之外的其他项目中使用,如 Ruby on Rails 项目。作为一种标准做法,需要对 Ruby 有基本的了解。当用户尝试管理模板文件的内容时,模板化非常有用。当配置无法由内置 Puppet 类型管理时,模板起着关键作用。
评估模板
使用简单的函数评估模板。
$value = template ("testtemplate.erb")
可以指定模板的完整路径,也可以拉取 Puppet 的模板目录中的所有模板,该目录通常位于 /var/puppet/templates。可以通过运行 puppet –configprint templatedir 来找到目录位置。
模板总是由解析器而不是客户端评估,这意味着如果使用 puppetmasterd,那么模板只需要在服务器上,永远不需要将它们下载到客户端。客户端在使用模板和将文件的所有内容指定为字符串之间的看法没有区别。这清楚地表明 puppetmasterd 在 puppet 启动阶段首先学习客户端特定的变量。
使用模板
以下是为测试站点生成 tomcat 配置的示例。
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" } }
以下是模板定义。
<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 加载这些配置文件。
Include /etc/apache2/trac/[^.#]*
组合模板
使用以下命令可以轻松组合两个模板。
template('/path/to/template1','/path/to/template2')
模板中的迭代
Puppet 模板也支持数组迭代。如果访问的变量是一个数组,则可以对其进行迭代。
$values = [val1, val2, otherval]
我们可以有如下的模板。
<% values.each do |val| -%> Some stuff with <%= val %> <% end -%>
上述命令将产生以下结果。
Some stuff with val1 Some stuff with val2 Some stuff with otherval
模板中的条件
该ERB模板支持条件句。以下构造是一种将内容有条件地放入文件的快速简便的方法。
<% if broadcast != "NONE" %> broadcast <%= broadcast %> <% end %>
模板和变量
除了填写文件内容之外,还可以使用模板来填写变量。
testvariable = template('/var/puppet/template/testvar')
未定义的变量
如果需要在使用之前检查变量是否已定义,则以下命令有效。
<% if has_variable?("myvar") then %> myvar has <%= myvar %> value <% end %>
范围外变量
可以使用 lookupvar 函数显式查找范围外的变量。
<%= scope.lookupvar('apache::user') %>
示例项目模板
<#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 类被定义为资源的集合,这些资源组合在一起以使目标节点或机器处于所需状态。这些类在位于 Puppet 模块内的 Puppet 清单文件中定义。使用类的主要目的是减少任何清单文件或任何其他 Puppet 代码中的相同代码重复。
以下是 Puppet 类的示例。
[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}", } }
在上面的例子中,我们有两个用户需要存在的客户端。可以注意到,我们重复了相同的资源两次。在组合两个节点时不执行相同任务的一种方法。
[root@puppetmaster manifests]# cat site.pp node 'Brcleprod001','Brcleprod002' { user { 'vipin': ensure => present, uid => '101', shell => '/bin/bash', home => '/home/homer', } }
以这种方式合并节点来执行配置不是一个好的做法。这可以通过创建一个类并将创建的类包含在节点中来简单地实现,如下所示。
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 中的每个语法都有自己的特性。因此,选择的语法取决于条件。
参数化类
在上面的例子中,我们已经看到了如何创建一个类并将其包含在一个节点中。现在有些情况下我们需要在每个节点上有不同的配置,例如需要在每个节点上使用相同的类有不同的用户。此功能在 Puppet 中使用参数化类提供。新类的配置将如下例所示。
[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 清单时,每个节点的输出将如下所示。
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
还可以设置类参数的默认值,如下面的代码所示。
[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 像任何其他编程语言一样支持函数,因为 Puppet 的基本开发语言是 Ruby。它支持两种类型的函数,称为语句名称和右值函数。
-
语句独立存在,没有任何返回类型。它们用于执行独立任务,例如在新清单文件中导入其他 Puppet 模块。
-
Rvalue返回值并且只能在语句需要值时使用,例如赋值或 case 语句。
Puppet 函数执行背后的关键是,它只在 Puppet master 上执行,而不在客户端或 Puppet 代理上执行。因此,他们只能访问 Puppet master 上可用的命令和数据。已经存在不同类型的功能,甚至用户也有权根据需要创建自定义功能。下面列出了一些内置函数。
文件功能
文件资源的文件功能是在Puppet中加载一个模块,并以字符串的形式返回想要的输出。它查找的参数是 <module name>/<file> 引用,它有助于从 Puppet 模块的文件目录加载模块。
像 script/tesingscript.sh 将从 <module name>/script/files/testingscript.sh 加载文件。函数具有读取和接受绝对路径的能力,这有助于从磁盘上的任何位置加载文件。
包含函数
在 Puppet 中,include 函数与任何其他编程语言中的 include 函数非常相似。它用于声明一个或多个类,从而评估这些类中存在的所有资源,并最终将它们添加到目录中。它的工作方式是,include 函数接受类名、类列表或以逗号分隔的类名列表。
使用include语句时要记住的一件事是,它可以在一个类中多次使用,但有一个限制,即只包含一个类一次。如果包含的类接受一个参数,包含函数将使用 <class name>::<parameter name> 作为查找键自动查找它们的值。
包含函数不会导致类在声明时包含在类中,因此我们需要使用包含函数。它甚至不会在声明的类和围绕它的类中创建依赖项。
在 include 函数中,只允许使用类的全名,不允许使用相对名称。
定义函数
在 Puppet 中,定义的函数有助于确定给定类或资源类型的定义位置,并返回一个布尔值与否。还可以使用定义来确定是否定义了特定资源或定义的变量是否具有值。使用定义函数时要记住的关键点是,该函数至少接受一个字符串参数,可以是类名、类型名、资源引用或“$name”形式的变量引用。
为本地和定义的函数类型(包括模块提供的类型)定义函数检查。类型和类通过它们的名称匹配。该函数通过使用资源引用来匹配资源减速度。
定义函数匹配
# Matching resource types defined("file") defined("customtype") # Matching defines and classes defined("testing") defined("testing::java") # Matching variables defined('$name') # Matching declared resources defined(File['/tmp/file'])
Puppet – 自定义函数
如前一章所述,函数为用户提供了开发自定义函数的权限。Puppet 可以通过使用自定义函数来扩展其解释能力。自定义函数有助于增加和扩展 Puppet 模块和清单文件的功能。
编写自定义函数
在编写函数之前,有几件事需要牢记。
-
在 Puppet 中,函数由编译器执行,这意味着所有函数都在 Puppet master 上运行,它们不需要处理任何 Puppet 客户端。功能只能与代理交互,前提是信息以事实的形式存在。
-
Puppet master 捕获自定义函数,这意味着如果对 Puppet 功能进行一些更改,则需要重新启动 Puppet master。
-
函数将在服务器上执行,这意味着该函数需要的任何文件都应该存在于服务器上,如果该函数需要直接访问客户端计算机,则无法执行任何操作。
-
有完全两种不同类型的函数可用,一种是返回值的 Rvalue 函数和不返回任何内容的语句函数。
-
包含函数的文件名应与文件中的函数名相同。否则,它不会自动加载。
放置自定义函数的位置
所有自定义函数都作为单独的.rb文件实现并分布在模块中。需要将自定义函数放在 lib/puppet/parser/function 中。可以从以下位置的.rb文件加载函数。
- $libdir/puppet/parser/functions
- Ruby $LOAD_PATH 中的 puppet/parser/functions 子目录
创建新函数
使用puppet::parser::Functions模块中的newfunction方法创建或定义新函数。需要将函数名称作为符号传递给newfunction方法和作为块运行的代码。下面的例子是一个函数,用于向/user目录下的文件写入一个字符串。
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
一旦用户声明了函数,就可以在清单文件中使用它,如下所示。
write_line_to_file('/user/vipin.txt, "Hello vipin!")
傀儡 – 环境
在软件开发和交付模型中,有不同类型的测试环境用于测试特定产品或服务。作为标准实践,主要有开发、测试和生产三种环境,其中每种环境都有自己的设置配置。
Puppet 支持与 Ruby on Rails 相同的多环境管理。创建这些环境背后的关键因素是提供一种简单的机制来管理不同级别的 SLA 协议。在某些情况下,机器总是需要在没有任何容忍和使用旧软件的情况下启动。其中其他环境是最新的并用于测试目的。它们用于升级更重要的机器。
Puppet 建议坚持使用标准的生产、测试和开发环境配置,然而,在这里它甚至为用户提供了根据需求创建自定义环境的杠杆作用。
环境目标
根据环境拆分设置的主要目标是,Puppet 可以有不同的模块和清单来源。然后可以在不影响生产节点的情况下测试测试环境中配置的更改。这些环境还可用于在不同的网络源上部署基础设施。
在 Puppet Master 上使用环境
环境的重点是测试需要将文件的哪个清单、模块、模板发送给客户端。因此,Puppet 必须配置为为这些信息提供特定于环境的源。
Puppet 环境的实现只需将 pre-environment 部分添加到服务器的 puppet.conf 并为每个环境选择不同的配置源。然后优先使用这些环境前部分而不是主要部分。
[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 目录中的任何模块.
在有或没有任何环境的情况下运行 Puppet 将默认为 site.pp 文件和主配置部分的 manifest 和 modulepath 值中指定的目录。
只有少数配置对配置预环境真正有意义,所有这些参数都围绕指定用于编译客户端配置的文件。
以下是参数。
-
Modulepath – 在 Puppet 中,作为基本的标准模式,最好有一个所有环境共享的标准模块目录,然后是一个可以存储自定义模块的预环境目录。模块路径是 Puppet 查找所有与环境相关的配置文件的位置。
-
Templatedir – 模板目录是保存所有相关模板版本的位置。该模块应该优先于这些设置,但是它允许在每个环境中具有给定模板的不同版本。
-
清单– 这定义了用作入口点脚本的配置。
有了多个模块,Puppets 有助于获得配置的模块化。可以在 Puppet 中使用多个环境,如果主要依赖模块,这种环境会更好。通过将更改封装在模块中,可以更轻松地将更改迁移到环境中。文件服务器使用特定于环境的模块路径;如果从模块提供文件,而不是单独的挂载目录,则此环境将能够获取特定于环境的文件,最后当前环境也将在清单文件中的 $environment 变量中可用。
设置客户端环境
所有与环境配置相关的配置都在 puppet.conf 文件中完成。要指定 Puppet 客户端应该使用哪种环境,可以在客户端的 puppet.conf 文件中为环境配置变量指定一个值。
[puppetd] environment = Testing
配置文件中的上述定义定义了配置文件在我们的情况下正在测试的环境。
还可以使用以下命令在命令行上指定这一点:
#puppetd -–environment = testing
或者,Puppet 还支持在环境配置中使用动态值。与定义静态值不同,开发人员可以利用创建自定义事实来创建基于某些其他客户端属性或外部数据源的客户端环境。首选的方法是使用自定义工具。这些工具能够指定节点的环境,并且通常更擅长指定节点信息。
人偶搜索路径
Puppet 使用简单的搜索路径来确定需要在目标机器上应用哪些配置。同样,Puppet 中的搜索路径在尝试获取需要应用的适当值时非常有用。下面列出了多个位置,Puppet 在其中搜索需要应用的值。
- 命令行中指定的值
- 在特定于环境的部分中指定的值
- 在可执行文件特定部分中指定的值
- 主要部分中指定的值
Puppet – 类型和提供者
Puppet 类型用于单独的配置管理。Puppet 有不同的类型,如服务类型、包类型、提供者类型等。其中每种类型都有提供者。提供程序处理不同平台或工具上的配置。例如,包类型有 aptitude、yum、rpm 和 DGM 提供程序。种类很多,Puppet涵盖了一个很好的需要管理的频谱配置管理项。
Puppet 使用 Ruby 作为其基础语言。所有存在的 Puppet 类型和提供程序都是用 Ruby 语言编写的。由于它遵循标准编码格式,因此可以简单地创建它们,如管理存储库的 repo 示例所示。在这里,我们将创建类型 repo 和提供者的 svn 和 git。回购类型的第一部分是类型本身。类型通常存储在 lib/puppet/type 中。为此,我们将创建一个名为repo.rb的文件。
$ touch repo.rb
在文件中添加以下内容。
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,它有助于添加想要添加的任何级别的详细信息。下一个语句是可保证的;它创建了一个基本的确保属性。Puppet 类型使用ensure属性来确定配置项的状态。
例子
service { "sshd": ensure => present, }
确保语句告诉 Puppet 除了三种方法:创建、销毁和存在于提供者中。这些方法提供以下功能 –
- 创建资源的命令
- 删除资源的命令
- 检查资源是否存在的命令
然后我们需要做的就是指定这些方法及其内容。Puppet 创建了围绕它们的支持基础设施。
接下来,我们定义一个名为 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 的钩子。在 provider 部分,我们定义了 git 和 svn 来检查我们定义的存储库的有效性。
最后,在代码中,我们又定义了一个名为 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 钩子创建一个检查适当性值的块。
Subversion 提供程序用例
让我们从使用上面创建的类型的 subversion 提供程序开始。
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”。
接下来,我们将提供者定义为块 Puppet::Type.type(:repo).provide(:svn) do 它告诉 Puppet 这是名为 repo 的类型的提供者。
然后,我们添加了desc,它允许向提供程序添加一些文档。我们还定义了此提供程序将使用的命令。在下一行中,我们将检查资源的创建、删除和存在等功能。
创建资源
完成上述所有操作后,我们将创建一个资源,该资源将在我们的类和清单文件中使用,如以下代码所示。
repo { "wp": source => "http://g01063908.git.brcl.org/trunk/", path => "/var/www/wp", ensure => present, }
木偶 – RESTful API
Puppet 使用 RESTful API 作为 Puppet master 和 Puppet 代理之间的通信通道。以下是访问此 RESTful API 的基本 URL。
https://brcleprod001:8140/{environment}/{resource}/{key} https://brcleprod001:8139/{environment}/{resource}/{key}
REST API 安全性
Puppet 通常负责安全和 SSL 证书管理。但是,如果希望在集群外使用 RESTful API,则需要在尝试连接到机器时自己管理证书。Puppet 的安全策略可以通过 rest authconfig 文件进行配置。
测试 REST API
Curl 实用程序可用作休息 RESTful API 连接的基本实用程序。以下是我们如何使用 REST API curl 命令检索节点目录的示例。
curl --cert /etc/puppet/ssl/certs/brcleprod001.pem --key /etc/puppet/ssl/private_keys/brcleprod001.pem
在下面的一组命令中,我们只是设置 SSL 证书,根据 SSL 目录的位置和正在使用的节点的名称,它会有所不同。例如,让我们看看下面的命令。
curl --insecure -H 'Accept: yaml' https://brcleprod002:8140/production/catalog/brcleprod001
在上面的命令中,我们只发送一个标头,指定我们想要返回的一种或多种格式,以及一个用于在生产环境中生成brcleprod001目录的 RESTful URL ,将生成以下输出。
--- &id001 !ruby/object:Puppet::Resource::Catalog aliases: {} applying: false classes: [] ...
让我们假设另一个示例,我们希望从 Puppet 主服务器获取 CA 证书。它不需要使用自己签名的 SSL 证书进行身份验证,因为这是在进行身份验证之前所必需的。
curl --insecure -H 'Accept: s' https://brcleprod001:8140/production/certificate/ca -----BEGIN CERTIFICATE----- MIICHTCCAYagAwIBAgIBATANBgkqhkiG9w0BAQUFADAXMRUwEwYDVQQDDAxwdXBw
Puppet Master 和 Agent 共享 API 参考
GET /certificate/{ca, other} curl -k -H "Accept: s" https://brcelprod001:8140/production/certificate/ca curl -k -H "Accept: s" https://brcleprod002:8139/production/certificate/brcleprod002
Puppet 主 API 参考
经过身份验证的资源(需要有效的签名证书)。
目录
GET /{environment}/catalog/{node certificate name} curl -k -H "Accept: pson" https://brcelprod001:8140/production/catalog/myclient
证书吊销列表
GET /certificate_revocation_list/ca curl -k -H "Accept: s" https://brcleprod001:8140/production/certificate/ca
证书申请
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
报告 提交报告
PUT /{environment}/report/{node certificate name} curl -k -X PUT -H "Content-Type: text/yaml" -d "{key:value}" https://brcleprod002:8139/production
节点 – 关于特定节点的事实
GET /{environment}/node/{node certificate name} curl -k -H "Accept: yaml" https://brcleprod002:8140/production/node/puppetclient
状态 – 用于测试
GET /{environment}/status/{anything} curl -k -H "Accept: pson" https://brcleprod002:8140/production/certificate_request/puppetclient
Puppet 代理 API 参考
在任何机器上设置新代理时,默认情况下 Puppet 代理不侦听 HTTP 请求。它需要通过在 puppet.conf 文件中添加“listen=true”在 Puppet 中启用。这将使 Puppet 代理能够在 Puppet 代理启动时侦听 HTTP 请求。
事实
GET /{environment}/facts/{anything} curl -k -H "Accept: yaml" https://brcelprod002:8139/production/facts/{anything}
Run – 使客户端像 puppetturn 或 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 节点上执行应用配置和清单的实时测试,我们将使用实时工作演示。这可以直接复制和粘贴以测试配置如何工作。如果用户希望使用相同的代码集,他需要具有相同的命名约定,如下面的代码片段所示。
让我们从创建一个新模块开始。
创建新模块
测试和应用 httpd 配置的第一步是创建一个模块。为此,用户需要将其工作目录更改为 Puppet 模块目录并创建基本模块结构。结构创建可以手动完成,也可以使用 Puppet 为模块创建样板。
# cd /etc/puppet/modules # puppet module generate Live-module
注– Puppet 模块生成命令要求模块名称采用 [username]-[module] 格式以符合 Puppet forge 规范。
新模块包含一些基本文件,包括清单目录。该目录已经包含一个名为 init.pp 的清单,它是模块的主清单文件。这是模块的空类声明。
class live-module { }
该模块还包含一个包含名为init.pp的清单的测试目录。此测试清单包含对 manifest/init.pp 中的 live-module 类的引用:
include live-module
Puppet 将使用此测试模块来测试清单。现在我们准备将配置添加到模块中。
安装 HTTP 服务器
Puppet 模块将安装运行 http 服务器所需的包。这需要一个资源定义来定义 httpd 包的配置。
在模块的清单目录中,创建一个名为 httpd.pp 的新清单文件
# touch test-module/manifests/httpd.pp
此清单将包含我们模块的所有 HTTP 配置。出于分离目的,我们将 httpd.pp 文件与 init.pp 清单文件分开
我们需要将以下代码放在 httpd.pp 清单文件中。
class test-module::httpd { package { 'httpd': ensure => installed, } }
这段代码定义了一个名为 httpd 的 test-module 子类,然后为 httpd 包定义了一个包资源声明。ensure => installed 属性检查是否安装了所需的包。如果没有安装,Puppet 会使用 yum 工具来安装它。接下来,是在我们的主清单文件中包含这个子类。我们需要编辑 init.pp 清单。
class test-module { include test-module::httpd }
现在,是时候测试可以按如下方式完成的模块了
# puppet apply test-module/tests/init.pp --noop
puppet apply 命令应用存在于目标系统清单文件中的配置。在这里,我们使用 test init.pp,它指的是 main init.pp。–noop 执行配置的试运行,它只显示输出但实际上不执行任何操作。
以下是输出。
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 包。
运行 httpd 服务器
安装完httpd服务器后,我们需要使用其他资源减速启动服务:服务
我们需要编辑 httpd.pp 清单文件并编辑以下内容。
class test-module::httpd { package { 'httpd': ensure => installed, } service { 'httpd': ensure => running, enable => true, require => Package["httpd"], } }
以下是我们从上述代码中实现的目标列表。
-
在确保=>运行状态检查该服务正在运行,如果不是那么它使能它。
-
该启用=> true属性集服务在系统启动时运行起来。
-
的需要=>封装[“的httpd”]属性定义一个资源减速等之间的顺序关系。在上面的例子中,它保证了httpd服务在http包安装后启动。这会在服务和相应的包之间创建依赖关系。
运行 puppet apply 命令再次测试更改。
# 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
配置 httpd 服务器
完成上述步骤后,我们将安装并启用 HTTP 服务器。下一步是向服务器提供一些配置。默认情况下,httpd 在 /etc/httpd/conf/httpd.conf 中提供了一些默认配置,它提供了一个 webhost 端口 80。我们将添加一些额外的 host 来为 web-host 提供一些用户特定的设施。
模板将用于提供额外的端口,因为它需要一个变量输入。我们将创建一个名为 template 的目录,并在新目录中添加一个名为 test-server.config.erb 的文件并添加以下内容。
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,用于存储系统的完全限定域名。这被称为系统事实。
在生成每个相应系统的傀儡目录之前,从每个系统收集系统事实。Puppet 使用 facter 命令获取此信息,并且可以使用 facter 获取有关系统的其他详细信息。我们需要在 httpd.pp 清单文件中添加高亮行。
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", } }
这有助于实现以下目标 –
-
这为服务器配置文件 (/etc/httpd/conf.d/test-server.conf) 添加了文件资源声明。该文件的内容是之前创建的 test-serverconf.erb 模板。在添加此文件之前,我们还会检查安装的 httpd 包。
-
这将添加第二个文件资源声明,为 Web 服务器创建一个目录 (/var/www/test-server)。
-
接下来,我们使用notify => Service[“httpd”] 属性添加配置文件和 https 服务之间的关系。这将检查是否有任何配置文件更改。如果存在,则 Puppet 会重新启动该服务。
接下来是在主清单文件中包含 httpd_port。为此,我们需要结束主 init.pp 清单文件并包含以下内容。
class test-module ( $http_port = 80 ) { include test-module::httpd }
这将 httpd 端口设置为默认值 80。接下来是运行 Puppet apply 命令。
以下将是输出。
# 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
配置防火墙
为了与服务器通信,需要一个开放端口。这里的问题是不同类型的操作系统使用不同的方法来控制防火墙。在 Linux 的情况下,低于 6 的版本使用 iptables,版本 7 使用 firewalld。
使用适当服务的决定在某种程度上由 Puppet 使用系统事实及其逻辑来处理。为此,我们需要先检查操作系统,然后运行相应的防火墙命令。
为了实现这一点,我们需要在 testmodule::http 类中添加以下代码片段。
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'], } }
上面的代码执行以下操作 –
-
使用操作系统majrelease确定使用的操作系统是版本 6 还是版本 7。
-
如果版本是 6,那么它运行所有必需的配置命令来配置 Linux 6 版本。
-
如果操作系统版本为 7,则它运行配置防火墙所需的所有必需命令。
-
两个操作系统的代码片段都包含一个逻辑,可确保配置仅在安装 http 包后运行。
最后,运行 Puppet apply 命令。
# 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
配置 SELinux
由于我们正在使用版本 7 及更高版本的 Linux 机器,因此我们需要对其进行配置以进行 http 通信。默认情况下,SELinux 限制对 HTTP 服务器的非标准访问。如果我们定义自定义端口,那么我们需要配置 SELinux 以提供对该端口的访问。
Puppet 包含一些资源类型来管理 SELinux 功能,例如布尔值和模块。在这里,我们需要执行 semanage 命令来管理端口设置。这个工具是 policycoreutils-python 包的一部分,它默认没有安装在红帽服务器上。为了实现上述目的,我们需要在 test-module::http 类中添加以下代码。
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, }
上面的代码执行以下操作 –
-
require => Package[‘policycoreutils-python’] 确保我们安装了所需的 python 模块。
-
Puppet 使用 semanage 使用 httpd_port 作为验证打开端口。
-
before => 服务确保在 httpd 服务启动之前执行此命令。如果 HTTPD 在 SELinux 命令之前启动,则 SELinux 服务请求和服务请求失败。
最后,运行 Puppet apply 命令
# 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服务。
在 Web 主机中复制 HTML 文件
通过以上步骤我们就完成了http服务器的配置。现在,我们已经准备好安装基于 Web 的应用程序的平台,Puppet 也可以对其进行配置。为了测试,我们将一些示例 html 索引网页复制到服务器。
在 files 目录中创建一个 index.html 文件。
<html> <head> <title>Congratulations</title> <head> <body> <h1>Congratulations</h1> <p>Your puppet module has correctly applied your configuration.</p> </body> </html>
在 manifest 目录中创建一个 manifest app.pp 并添加以下内容。
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::http 类在应用 test-module::app 之前成功完成配置。
最后,我们需要在主 init.pp 清单中包含一个新清单。
class test-module ( $http_port = 80 ) { include test-module::httpd include test-module::app }
现在,运行 apply 命令来实际测试正在发生的事情。以下将是输出。
# 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 文件被复制到网络主机的结果。
完成模块
通过以上所有步骤,我们创建的新模块就可以使用了。如果我们想创建模块的存档,可以使用以下命令完成。
# puppet module build test-module