多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
### 使用虚拟资源 什么是虚拟资源(Virtual Resource),我们为什么需要它们? 下面我们来看一个可能会使用虚拟资源的典型例子。 你负责管理 facesquare 和 twitstagram 两个应用程序,他们都是运行在 Apache 上的 Web 应用程序。 facesquare 的定义看起来可能像这样: ``` class app::facesquare { package { "apache2-mpm-worker": ensure => installed } } ``` twitstagram 的定义看起来可能像这样: ``` class app::twitstagram { package { "apache2-mpm-worker": ensure => installed } } ``` 一切都很好,直到你需要将两个应用程序同时应用到单台服务器上: ``` node micawber { include app::facesquare include app::twitstagram } ``` 现在 Puppet 会出错,因为你试图用相同的名字 apache2-mpm-worker 定义两个 package 资源。 错误输出信息如下: ``` err: Could not retrieve catalog from remote server: Error 400 on SERVER: Duplicate definition: Package[apache2-mpm-worker] is already defined in file /etc/puppet/modules/app/manifests/facesquare.pp at line 2; cannot redefine at /etc/puppet/modules/app/manifests/twitstagram.pp:2 on node cookbook.bitfieldconsulting.com ``` 你可以从其中的一个类中移除重复的包定义,但是这样话,如果试图在另一个服务器包含 app 类时,就会因为没有准备好 Apache 而失败。 通过在自己的类中放置 Apache 的包资源并使用 include apache 包含它,你就可以解决这个问题, 因为 Puppet 不介意多次包含一个相同的类。但是这有一个缺点,即每个具有潜在冲突的资源都必须有它自己的类。 虚拟资源可以解决这个问题。虚拟资源就像是个普通的资源,特别之处在于它以 @ 字符开始,例如: ``` @package { "apache2-mpm-worker": ensure => installed } ``` 你可以把它看作是个 “FYI(仅供参考)” 资源:我只是告诉 Puppet 这个资源存在,但不希望用它做任何事情。 Puppet 将会读取并记住虚拟资源定义,但实际上不会创建这个资源,直到你明确指出要创建此资源。 要创建这个资源,使用如下的 realize 函数: ``` realize( Package["apache2-mpm-worker"] ) ``` 对于你想要的资源,可以多次调用 realize 而且不会产生冲突。 因此,虚拟资源用于:当在几个不同的类中都需要相同的资源,且它们可能会在相同的节点上共存的情况。 #### 操作步骤 1. 创建名为 app 的新模块: ``` # mkdir -p /etc/puppet/modules/app/manifests ``` 2. 使用如下内容创建 /etc/puppet/modules/app/manifests/facesquare.pp 文件: ``` class app::facesquare { realize( Package["apache2-mpm-worker"] ) } ``` 3. 使用如下内容创建 /etc/puppet/modules/app/manifests/twitstagram.pp 文件: ``` class app::twitstagram { realize( Package["apache2-mpm-worker"] ) } ``` 4. 使用如下内容创建 /etc/puppet/modules/admin/manifests/virtualpackages.pp 文件: ``` class admin::virtual-packages { @package { "apache2-mpm-worker": ensure =&gt; installed } } ``` 5. 在一个节点上包含如下代码: ``` node cookbook { include admin::virtual-packages include app::facesquare include app::twitstagram } ``` 6. 运行 Puppet。 #### 工作原理 你可以在 admin::virtual-packages 类中定义一个包的虚拟资源。 所有节点都可以包含这个类,并且你可以将所有虚拟资源都放在此类中。 这些虚拟资源都不会实际安装到节点上,直到你调用 realize: ``` class admin::virtual-packages { @package { "apache2-mpm-worker": ensure => installed } } ``` 每个需要 Apache 包的类都可以对虚拟资源调用 realize : ``` class app::twitstagram { realize( Package["apache2-mpm-worker"] ) } ``` Puppet 知道如何处理它,因为你设置了相应的虚拟资源,你打算多次引用同一个包, 而不会意外地创建具有相同名子的两个资源。所以,这正确地实现了我们的需求。 #### 更多用法 为了实现(realize)虚拟资源,你也可以使用 **collection** 语法: ``` Package <| title = "apache2-mpm-worker" |> ``` 使用这种语法的好处是,你不仅可以指定资源名,而且可以指定 tag,例如: ``` Package <| tag = "security" |> ``` 或者,你可以指定资源类型的所有实例,在查询部分保留一个空格即可: ``` Package <| |> ``` #### 参见本书 * 本章的 [使用虚拟资源管理用户](#ch06sec02) 一节