DevOps:Puppet,Docker,and Kubernetes
上QQ阅读APP看书,第一时间看更新

Using roles and profiles

Well organized Puppet manifests are easy to read; the purpose of a module should be evident in its name. The purpose of a node should be defined in a single class. This single class should include all classes that are required to perform that purpose. Craig Dunn wrote a post about such a classification system, which he dubbed "roles and profiles" (http://www.craigdunn.org/2012/05/239/). In this model, roles are the single purpose of a node, a node may only have one role, a role may contain more than one profile, and a profile contains all the resources related to a single service. In this example, we will create a web server role that uses several profiles.

How to do it…

We'll create two modules to store our roles and profiles. Roles will contain one or more profiles. Each role or profile will be defined as a subclass, such as profile::base

  1. Decide on a naming strategy for your roles and profiles. In our example, we will create two modules, roles and profiles that will contain our roles and profiles respectively:
    $ puppet module generate thomas-profiles
    $ ln -s thomas-profiles profiles
    $ puppet module generate thomas-roles
    $ ln -s thomas-roles roles
    
  2. Begin defining the constituent parts of our webserver role as profiles. To keep this example simple, we will create two profiles. First, a base profile to include our basic server configuration classes. Second, an apache class to install and configure the apache web server (httpd) as follows:
    $ vim profiles/manifests/base.pp
    class profiles::base {
     include base
    }
    $ vim profiles/manifests/apache.pp
    class profiles::apache {
     $apache = $::osfamily ? {
     'RedHat' => 'httpd',
     'Debian' => 'apache2',
     }
     service { "$apache":
     enable => true,
     ensure => true,
     }
     package { "$apache":
     ensure => 'installed',
     }
    }
    
  3. Define a roles::webserver class for our webserver role as follows:
    $ vim roles/manifests/webserver.pp
    class roles::webserver {
     include profiles::apache
     include profiles::base
    }
    
  4. Apply the roles::webserver class to a node. In a centralized installation, you would use either an External Node Classifier (ENC) to apply the class to the node, or you would use Hiera to define the role:
      node 'webtest' {
        include roles::webserver
      }

How it works…

Breaking down the parts of the web server configuration into different profiles allows us to apply those parts independently. We created a base profile that we can expand to include all the resources we would like applied to all nodes. Our roles::webserver class simply includes the base and apache classes.

There's more…

As we'll see in the next section, we can pass parameters to classes to alter how they work. In our roles::webserver class, we can use the class instantiation syntax instead of include, and override it with parameters in the classes. For instance, to pass a parameter to the base class, we would use:

  class {'profiles::base':
    parameter => 'newvalue'
  }

where we previously used:

include profiles::base
Tip

In previous versions of this book, node and class inheritance were used to achieve a similar goal, code reuse. Node inheritance is deprecated in Puppet Version 3.7 and higher. Node and class inheritance should be avoided. Using roles and profiles achieves the same level of readability and is much easier to follow.