Intro
This is set in the Manageable Puppet Infrastructure, but should be quite useable if you’re not using it.
You want to manage multiple clients within a single environment. (You probably don’t want to create seperate environments or puppetmasters, because that creates quite a bit of overhead in the long run).
But how do we keep things flexible? It’s quite simple, use Hiera and classes in a smart way and you’re there!
One note; this simple setup only works if you do not have any naming conflicts in the modules. e.g. customer1 needs puppetlabs/apache and another needs another module named apache. In that case, you do need seperate environments.
Get that $customer variable filled
You’ll need a way to let Puppet know what customer a node belongs to. There are several ways:
Facter variables can be overridden quite easily. Use the ENC or Hiera!
- Getting the info from Hiera, see below.
- Set it from the ENC.
Adding a global $customer variable
In my site.pp:
$customer = hiera('customer')
node default {
hiera_include('roles')
}
Example: hieradata/hosts/myserver.customer.com.yaml
---
customer: mycustomer1
That’s an easy way to get the $customer (global) variable filled!
Putting it to use!
Roles
With the MPI, you’ve created a baserole that applies to all hosts.
We can still use that, just be aware that those resources/includes apply to ALL customers.
Also, we’d like a baseclass for each customer. Within the roles-module, that’s a piece of cake.
modules/role/
└── manifests
├── base.pp # class role::base { (applies to all nodes)
├── mycustomer1
│ ├── app.pp # class role::mycustomer1::app {
│ ├── base.pp # class role::mycustomer1::base { (applies to all nodes of mycustomer1)
│ ├── db.pp # class role::mycustomer1::db {
│ └── smarthost.pp # class role::mycustomer1::smarthost {
└── mycustomer2
├── app.pp # class role::mycustomer2::app {
├── base.pp # class role::mycustomer2::base {
├── db.pp # class role::mycustomer2::db {
└── lamp.pp # class role::mycustomer2::lamp {
Hiera
You can add a level for customer-specific settings.
:hierarchy:
- "hosts/%{clientcert}" # Host-specific settings
- "customer/%{customer}" # Customer specific settings
- "osfamily/%{osfamily}" # Settings based on OS
- "environment/%{environment}" # Environment specific settings
- common # Common settings for all nodes.
Now, we can add a yaml file for each customer and assign the role::customer::base there.
Example: hieradata/customer/mycustomer1.yaml
---
roles:
- role::mycustomer1::base
Of course, you can add other customer-specific settings as well here!
Feedback is welcome, leave a message!