官术网_书友最值得收藏!

  • DevOps:Puppet,Docker,and Kubernetes
  • Thomas Uphill John Arundel Neependra Khare Hideto Saito Hui Chuan Chloe Lee Ke Jou Carol Hsu
  • 773字
  • 2021-07-09 18:32:58

Using virtual resources

Virtual resources in Puppet might seem complicated and confusing but, in fact, they're very simple. They're exactly like regular resources, but they don't actually take effect until they're realized (in the sense of "made real"); whereas a regular resource can only be declared once per node (so two classes can't declare the same resource, for example). A virtual resource can be realized as many times as you like.

This comes in handy when you need to move applications and services between machines. If two applications that use the same resource end up sharing a machine, they would cause a conflict unless you make the resource virtual.

To clarify this, let's look at a typical situation where virtual resources might come in handy.

You are responsible for two popular web applications: WordPress and Drupal. Both are web apps running on Apache, so they both require the Apache package to be installed. The definition for WordPress might look something like the following:

class wordpress {
  package {'httpd':
    ensure => 'installed',
  }
  service {'httpd':
    ensure => 'running',
    enable => true,
  }
}

The definition for Drupal might look like this:

class drupal {
  package {'httpd':
    ensure => 'installed',
  }
  service {'httpd':
    ensure => 'running',
    enable => true,
  }
}

All is well until you need to consolidate both apps onto a single server:

node 'bigbox' {
  include wordpress
  include drupal
}

Now Puppet will complain because you tried to define two resources with the same name: httpd.

Using virtual resources

You could remove the duplicate Apache package definition from one of the classes, but then nodes without the class including Apache would fail. You can get around this problem by putting the Apache package in its own class and then using include apache everywhere it's needed; Puppet doesn't mind you including the same class multiple times. In reality, putting Apache in its own class solves most problems but, in general, this method has the disadvantage that every potentially conflicting resource must have its own class.

Virtual resources can be used to solve this problem. A virtual resource is just like a normal resource, except that it starts with an @ character:

@package { 'httpd': ensure => installed }

You can think of it as being like a placeholder resource; you want to define it but you aren't sure you are going to use it yet. Puppet will read and remember virtual resource definitions, but won't actually create the resource until you realize the resource.

To create the resource, use the realize function:

realize(Package['httpd'])

You can call realize as many times as you want on the resource and it won't result in a conflict. So virtual resources are the way to go when several different classes all require the same resource, and they may need to coexist on the same node.

How to do it...

Here's how to build the example using virtual resources:

  1. Create the virtual module with the following contents:
    class virtual {
      @package {'httpd': ensure => installed }
      @service {'httpd': 
        ensure  => running,
        enable  => true,
        require => Package['httpd']
      }
    }
  2. Create the Drupal module with the following contents:
    class drupal {
      include virtual
      realize(Package['httpd'])
      realize(Service['httpd'])
    }
    
  3. Create the WordPress module with the following contents:
    class wordpress {
      include virtual
      realize(Package['httpd'])
      realize(Service['httpd'])
    }
  4. Modify your site.pp file as follows:
    node 'bigbox' {
      include drupal
      include wordpress
    }
  5. Run Puppet:
    bigbox# puppet agent -t
    Info: Caching catalog for bigbox.example.com
    Info: Applying configuration version '1413179615'
    Notice: /Stage[main]/Virtual/Package[httpd]/ensure: created
    Notice: /Stage[main]/Virtual/Service[httpd]/ensure: ensure changed 'stopped' to 'running'
    Info: /Stage[main]/Virtual/Service[httpd]: Unscheduling refresh on Service[httpd]
    Notice: Finished catalog run in 6.67 seconds
    

How it works...

You define the package and service as virtual resources in one place: the virtual class. All nodes can include this class and you can put all your virtual services and packages in it. None of the packages will actually be installed on a node or services started until you call realize:

class virtual {
  @package { 'httpd': ensure => installed }
}

Every class that needs the Apache package can call realize on this virtual resource:

class drupal {
  include virtual
  realize(Package['httpd'])
}

Puppet knows, because you made the resource virtual, that you intended to have multiple references to the same package, and didn't just accidentally create two resources with the same name. So it does the right thing.

There's more...

To realize virtual resources, you can also use the collection spaceship syntax:

Package <| title = 'httpd' |>

The advantage of this syntax is that you're not restricted to the resource name; you could also use a tag, for example:

Package <| tag = 'web' |>

Alternatively, you can just specify all instances of the resource type, by leaving the query section blank:

Package <| |>
主站蜘蛛池模板: 邹城市| 获嘉县| 保德县| 喀喇沁旗| 桃园市| 辽源市| 保山市| 建平县| 佛冈县| 惠州市| 黄浦区| 钟山县| 西和县| 新绛县| 嘉禾县| 那坡县| 张家界市| 广州市| 五指山市| 祁连县| 延庆县| 武强县| 曲阳县| 延边| 东莞市| 贺州市| 安远县| 上栗县| 长治市| 酉阳| 清涧县| 始兴县| 平山县| 蓝山县| 阳城县| 汨罗市| 融水| 曲水县| 友谊县| 海兴县| 修武县|