Puppet Without Root
Spencer Krum
UTi Worldwide Inc.
Books
Pro Puppet 2nd Ed.*
Beginning Puppet**
*With Jeff Mccune, James Turnbull, William Van Hevelingen, and Ben Kero
**With William Van Hevelingen, and Ben Kero
Intro
UTi History
UTi Goals
DevOps Role
Limitations
Intro (cont.)
Installing the Puppet client
Running the Puppet Client
Package, File, Service
Rootless Module
Intro (cont.)
Installing Puppet Master as nonroot
Installing Apache as nonroot
Installing Passenger as nonroot
Upgrading Puppet as nonroot
UTi History
UTi Goals
DevOps Role
Limitations
No Root Acess
Each devopser has a user
Sudo to the application user
(appserv,webserv,swmgmt,tibco,fico)
Application user has limited sudo access
Limitations (cont)
Limited homedir space
/opt/app LVM volume, big, but not massive (20G)
Oracle Enterprise 5, not often updated
Few development libraries
Installing the Puppet client
Libyaml built from source, separate
Ruby built from source, separate
Puppet and facter from source, together
All installed using a --prefix
Installing the Puppet client
Puppet config in:
/opt/app/tibco/opt/puppet/etc/puppet/conf/puppet.conf
Ruby/yaml located in
/opt/app/tibco/opt/{ruby,yaml}
Installing the Puppet client
Drop the whole thing in via a tarball.
Massive sed -i on files.
Installing the Puppet client
Each client is in an environment
Conflate UTi environments and puppet
environments
Puppet vardir, libdir, ssldir all under opt
No control over dns so set server = machinename
Running the Puppet Client
Source a bash file to set RUBYLIB,
LD_LIBRARY_PATH
Run Puppet with --config argument to pick up the
config file, forks to background
@reboot cron to fire it up if the machine bounces
Multi User
Sometimes we want to run a service as the fico
user and a separate service as the tibco on the
same machine
Certname Abuse
Set certname = user-hostname in puppet.conf:
fico-devbuild1.go2uti.com
Two node definitions in site.pp now
Both users have puppet installed under
/opt/app/$USER/opt
Package, File, Service
Package
Two basic methods:
Wrap an untar command in a defined type
Recursive file resource (Puppet Package Manger)
Package
We use both
class uti_httpd::base {
file { "${home_path}/httpd":
ensure => directory,
owner => $owner,
group => $group,
source => 'puppet:///modules/uti_httpd',
recurse => remote
}
...
}
exec {"create-jdk-install-${install_root}":
command => "/bin/tar xvzf ${tarball_directo
cwd => $install_root,
creates => "${install_root}/${jdk_create_di
}
File
File Type works strangely when not running as
root
$owner, $group problem
Implementation around 'write' access.
File {
owner => $owner,
group => $group,
}
file { $install_root:
ensure => directory,
}
file { "${install_root}/keystore/":
ensure => directory,
require => File[$install_root]
}
Service
Possibly the best handled in a rootless
environment
Can't use real init system.
Can use the binary,start,status,stop parameters to
great effect
I want to look at the path
service { 'icinga':
ensure => running,
provider => base,
enable => true,
hasstatus => true,
hasrestart => true,
start => "${home_path}/icinga/init/ici
stop => "${home_path}/icinga/init/ici
restart => "${home_path}/icinga/init/ici
name => 'icinga'
}
Rootless Module
Rootless Module
Module to provide types and facts to rootless persons
tarfile type
jdk type
facts for user, group, tempdir
new file type for rootless environments
$tempname = regsubst($name, '/', '-', 'G')
file { "/var/tmp/${tempname}":
ensure => file,
content => $content,
}
exec { "copy-in-${name}":
command =>
"cat /var/tmp/${tempname} > ${name}",
subscribe => File["/var/tmp/${tempname}"],
notify => $notify,
}
Puppet Module Rootless
GitHub GoGo!
https://github.com/UTIWorldwide/puppet-module-rootless
puppet module install utiworldwide/rootless
Puppet Master as nonroot
3 Plabs Software
Puppet
Hiera
Facter
Puppet Master as nonroot
Other Software
Apache
Passenger
Libyaml
Libapr
Two generations
First Generation
Installed everything to /opt
Apache + libapr separate
Ruby, yaml separate
Puppet, facter, hiera conjoined
Two generations
Problems with first gen
No central log location
No way to upgrade
Conf files akwardly all over the place
Rack dir lived under puppet dir
Two generations
New generation
Everything rooted under a $HOME/local
BSD Ports style
Hiera, puppet, facter running from source
'init' scripts for everything in local/etc
Logs all go to local/var
Installation points
Use a bash function to expose the puppet command
puppet () {
. $FAKE_ROOT/bin/.ruby_setup.sh
$FAKE_ROOT/opt/puppet/bin/puppet $@
--confdir=$FAKE_ROOT/etc/puppet
}
Installation points
Passenger 4 reads your .bashrc, check for tty before
getting fancy
if `tty -s`; then
if env | grep TMOUT >/dev/null; then
exec env -u TMOUT bash
fi
fi
Installation points
Set LD_LIBRARY_PATH and RUBYLIB at the last
possible second, in the puppet function or in
etc/init.d/httpd
Installation points
Build passenger on an equivalent system and rsync it up,
its dependencies are many, and installing libcurl and
openssl from source is hard.
Installation points
Try to keep your env as similar to a rooted environment as
you can.
Tell lies to tell the truth.
Outro
Questions?
Spencer Krum
github.com/nibalizer
nibalizer on irc.freenode.net
Book from Apress
http://www.apress.com/9781430260400

Puppet without Root - PuppetConf 2013