dimecres, 18 de setembre del 2013

Installing puppetmaster with puppet

Working in a demo for a puppet masterclass, I decided to use a puppet agent to install and configure puppet-server and puppetdb. Here explains the process.

Demo VM

I used vagrant and Virtualbox to deploy a VM to show the demo, once installed both, run the following:

mkdir demopuppet
cd demopuppet
vagrant box add centos_i386 http://developer.nrel.gov/downloads/vagrant-boxes/CentOS-6.4-i386-v20130427.box
vagrant init centos_i386
vagrant up


You can find more boxes here, get one with puppet agent already installed.

Yum repositories

I will explain the code by functionality.
First of all, yum repositories. The first thing I did was to install epel and puppetlabs rpm and then, I realized I could use puppet itself to install them. 

puppet resource yumrepo epel >> puppetinstall.pp
puppet resource yumrepo puppetlabs-products >> puppetinstall.pp
puppet resource yumrepo puppetlabs-deps >> puppetinstall.pp

Then, on looking that exit, I realized that to give a demo solution, the content had to be edited to avoid gpgcheck (installing keys with puppet is a little more complicated if you only want a .pp as an exit). So the final result was:

#Repositories needed to install puppetmaster
yumrepo { 'epel':
  descr          => 'Extra Packages for Enterprise Linux 6 - $basearch',
  enabled        => '1',
  failovermethod => 'priority',
  gpgcheck       => '0',
  mirrorlist     => 'https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch',
}
yumrepo { 'puppetlabs-deps':
  baseurl  => 'http://yum.puppetlabs.com/el/6/dependencies/$basearch',
  descr    => 'Puppet Labs Dependencies El 6 - $basearch',
  enabled  => '1',
  gpgcheck => '0',
}
yumrepo { 'puppetlabs-products':
  baseurl  => 'http://yum.puppetlabs.com/el/6/products/$basearch',
  descr    => 'Puppet Labs Products El 6 - $basearch',
  enabled  => '1',
  gpgcheck => '0',
}

But I didn't like a solution that reduces quality, so although is good to use yumrepo, I thing the best solution is the one following:

package {'epel-release':
  ensure => 'installed',
  source => 'http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm',
  provider => 'rpm',
}
package {'puppetlabs-release':
  ensure => 'installed',
  source => 'http://yum.puppetlabs.com/el/6/products/i386/puppetlabs-release-6-7.noarch.rpm',
  provider => 'rpm',
}

Packages 

All these packages have to be installed after repositories are settled, so we will set a dependency. Vim and screen are not really needed, but I love them :-).

package{
  ['vim-enhanced',
   'screen',
   'puppet-server',
   'puppetdb',
   'puppetdb-terminus',
  ]:
    ensure => installed,
    require => [ Package['puppetlabs-release'], Package['epel-release'] ],
}

Puppet configurations

Remember that we are working in a demo procedure, so this changes are to avoid some good (but manual) practices. First one is enable autosign certificates, to allow any node to authenticate into puppetmaster without human intervention.

# Enables autosign node certificates
file {'/etc/puppet/autosign.conf':
  ensure  => present,
  content => "*\n",
  require => Package['puppet-server'],
  notify  => Service['puppetmaster'],
}

Next one is setting a new hostname to work with defaults. Puppetmaster and nodes search for a domain name called 'puppet', so if we want to work with defaults, we have to set the correct hostname. I searched a little and found the following (lost source, sorry)

#Set master hostname into puppet.localdomain
file { "/etc/hostname":
    ensure => present,
    owner => root,
    group => root,
    mode => 644,
    content => "puppet.localdomain\n",
    notify => Exec["set-hostname"],
  }
  exec { "set-hostname":
    command => "/bin/hostname -F /etc/hostname",
    unless => "/usr/bin/test `hostname` = `/bin/cat /etc/hostname`",
  }

# Set some more names to localhost
host { 'localhost':
  ensure       => 'absent',
}
host { 'localhost4':
  ensure       => 'present',
  host_aliases => ['puppet', 'puppet.localdomain', 'puppetdb', 'localhost', 'localhost.localdomain',  'localhost4.localdomain4'],
  ip              => '127.0.0.1',
  target        => '/etc/hosts',
  require      => Exec['set-hostname'],
}
host { 'localhost6':
  ensure       => 'present',
  host_aliases => ['puppet', 'puppet.localdomain', 'puppetdb', 'localhost', 'localhost.localdomain',  'localhost6.localdomain6'],
  ip           => '::1',
  target       => '/etc/hosts',
  require      => Exec['set-hostname'],
}

Puppet Service

We managed well with configurations, now we can set the service.

# Configure puppetmaster to be started
service {'puppetmaster':
  ensure => running,
  enable => true,
  require => Exec['set-hostname'],
}

PuppetDB configurations

As we can see here, puppetdb installation is not as easy as 'yum install', we need to manually create files routes.yaml, puppetdb.conf and add some stuff into puppet.conf. I have also seen that when installing for first time, for a strange reason does not set https access, so I have to add an exec to assure this config.

#PuppetDB service configuration
service {'puppetdb':
  ensure => running,
  enable => true,
  require => Service['puppetmaster']
}
$puppetdb_conf = '[main]
server = puppet
'
file{"/etc/puppet/puppetdb.conf":
  content => $puppetdb_conf,
  require => Package['puppetdb-terminus'],
  notify  => Service['puppetmaster'],
}
$puppetdb_route = '---
master:
  facts:
    terminus: puppetdb
    cache: yaml
'
file{"/etc/puppet/routes.yaml":
  content => $puppetdb_route,
  require => Package['puppetdb-terminus'],
  notify  => Service['puppetmaster'],
}
#Workarround since there is no len in augeas for puppet.conf
exec{"config-puppetdb":
  command => 'echo "[master]" >> /etc/puppet/puppet.conf; echo "  storeconfigs = true" >> /etc/puppet/puppet.conf; echo "  storeconfigs_backend = puppetdb" >> /etc/puppet/puppet.conf;',
  unless => 'grep "\[master\]" /etc/puppet/puppet.conf',
  path => ['/bin'],
  require => Package['puppetdb-terminus'],
  notify  => Service['puppetmaster'],
}
#Workarround for first install problem
exec{"puppetdb-ssl-setup":
  command => 'puppetdb-ssl-setup',
  path => ['/bin', '/sbin', '/usr/sbin', '/usr/bin'],
  require => Package['puppetdb'],
  notify => Service['puppetdb'],
}

Execution

So, when we finally have all this code, we just need to execute this instruction:

sudo puppet apply /vagrant/puppetinstall.pp

And let the magic flow...

Demo

After all this, the real demo can be a script like that:

#!/bin/bash
sudo puppet module install puppetlabs-apache
sudo puppet module install puppetlabs-firewall
sudo touch /etc/puppet/manifests/site.pp
sudo chmod a+w /etc/puppet/manifests/site.pp
cat > /etc/puppet/manifests/site.pp <<EOF
node 'puppet' {
  require firewall
  #PuppetDB access and apache standard ports
  firewall{ '100 allow apache and puppetdb access':
    port   => [80,8080,443],
    proto  => tcp,
    action => accept,
  }
  class{ 'apache': }
}
EOF
sudo chmod 644 /etc/puppet/manifests/site.pp
sudo puppet agent -t -d

And let people see your puppetdb instance working (show them some API calls) and your brand new apache working.

Here follows my gist with twice files:

Cap comentari:

Publica un comentari a l'entrada