On and off I use puppet in my lab to configure various things. I recently started doing some work with Cloudera manager. What I’ve found when I do lab work is that I generally create and tear down environments multiple times during the course of a project. Cloudera manager has its own configuration and deployment engine for Hadoop cluster’s but requires the nodes to have some requirements set before deployment. I created the following manifests to set the enviornement based off the pre-req’s in the install guide
NOTE: After publishing this blog a colleage informed me that CDM actually creates the users and groups for you. This is a case of failing to RTFM. On the bright side you can still use the manifests below as samples on user, group, host file deployment, and password creation.
Im definetly a puppet hack so there may be better ways to do this, but here is what worked for me
INSTALL
First I installed puppet on my master (CentOS6.4)
rpm -ivh http://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-7.noarch.rpm
yum install puppet-server
Same thing for the nodes, but agent only
rpm -ivh http://yum.puppetlabs.com/el/6/products/x86_64/puppetlabs-release-6-7.noarch.rpm
yum install puppet
Then on the nodes I used vim to edit the /etc/puppet/puppet.conf file adding the following 2 lines at the end of the file
#Puppet Master
server = cdhmanager
#Local Hostname
certname = chdnode1
Then I start the puppet service on the master and nodes, and set it to auto start
MASTER:
service puppet-master start
chkconfg puppet-master on
NODES:
service puppet-master start
chkconfg puppet-master on
The nodes will contact the master and I accepted their certs. On the master:
puppet cert --sign –all
Manifests
For configuration I created 3 modules; homedir, hostfile, and users. On the master, under the /etc/puppet/modules directory I created a directory for each module. Under each module directory I created the “manifests” directory. This is where I placed the init.pp file for the corresponding module. My /etc/puppet/module directory structure looks like this:
Init.pp files
users init.pp – This file creates the users, passwords and groups. Since this is a test environment I used the /etc/shadow file to retrieve the hash for the root password, and I used it for each user.
Pay close attention as not all the information from the grep is needed. Everything after (:) is discarded.
homedir init.pp – This file creates the home directory for each user created by the users init.pp
hostfile init.pp – This file copies the correct hosts file to /etc/hosts. In the hostfile directory there is a sub directory called files. I copied the host file I wanted to use into this directory.
Each init.pp begins with declaring a class. These “classes” are used by the site.pp file. If I wanted to use each init.pp file locally I would remove the class definition and just apply the file. However, in a master, node setup, the site.pp file is used to push a module to the node, and this is done by defining the module as a class. More on the site.pp in a minute. Here are the init.pp files
Users init.pp file:
class users {
group {'cloudera-scm':
ensure => present,
}
user {'cloudera-scm':
ensure => present,
gid => 'cloudera-scm',
shell => '/bin/bash',
home => '/home/cloudera-scm',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'mapred':
ensure => present,
}
user {'mapred':
ensure => present,
gid => 'mapred',
shell => '/bin/bash',
home => '/home/mapred',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'hdfs':
ensure => present,
}
user {'hdfs':
ensure => present,
gid => 'hdfs',
shell => '/bin/bash',
home => '/home/hdfs',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'zookeeper':
ensure => present,
}
user {'zookeeper':
ensure => present,
gid => 'zookeeper',
shell => '/bin/bash',
home => '/home/zookeeper',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'yarn':
ensure => present,
}
user {'yarn':
ensure => present,
gid => 'yarn',
shell => '/bin/bash',
home => '/home/yarn',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'httpfs':
ensure => present,
}
user {'httpfs':
ensure => present,
gid => 'httpfs',
shell => '/bin/bash',
home => '/home/httpfs',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'hbase':
ensure => present,
}
user {'hbase':
ensure => present,
gid => 'hbase',
shell => '/bin/bash',
home => '/home/hbase',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'hive':
ensure => present,
}
user {'hive':
ensure => present,
gid => 'hive',
shell => '/bin/bash',
home => '/home/hive',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'hue':
ensure => present,
}
user {'hue':
ensure => present,
gid => 'hue',
shell => '/bin/bash',
home => '/home/hue',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'oozie':
ensure => present,
}
user {'oozie':
ensure => present,
gid => 'oozie',
shell => '/bin/bash',
home => '/home/oozie',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'flume':
ensure => present,
}
user {'flume':
ensure => present,
gid => 'flume',
shell => '/bin/bash',
home => '/home/flume',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
group {'hadoop':
ensure => present,
}
group {'impala':
ensure => present,
}
user {'impala':
ensure => present,
gid => 'impala',
shell => '/bin/bash',
home => '/home/impala',
managehome => 'true',
password => '$6$LAYfwgC5UgDDSrhz$9u5lURmy9RP8d6sdmCY3YKwS0XMcQjU2ynl06xMUe9hvO4IOl6ESJaHuxzuOyaLGzoKSlB6s3Ov5SqQZ9TcER.',
}
}
Homedir init.pp file:
class homedir {
file { "/home/cloudera-scm":
ensure => "directory",
owner => "cloudera-scm",
group => "cloudera-scm",
}
file { "/home/mapred":
ensure => "directory",
owner => "mapred",
group => "mapred",
}
file { "/home/hdfs":
ensure => "directory",
owner => "hdfs",
group => "hdfs",
}
file { "/home/zookeeper":
ensure => "directory",
owner => "zookeeper",
group => "zookeeper",
}
file { "/home/yarn":
ensure => "directory",
owner => "yarn",
group => "yarn",
}
file { "/home/httpfs":
ensure => "directory",
owner => "httpfs",
group => "httpfs",
}
file { "/home/hbase":
ensure => "directory",
owner => "hbase",
group => "hbase",
}
file { "/home/hive":
ensure => "directory",
owner => "hive",
group => "hive",
}
file { "/home/hue":
ensure => "directory",
owner => "hue",
group => "hue",
}
file { "/home/oozie":
ensure => "directory",
owner => "oozie",
group => "oozie",
}
file { "/home/flume":
ensure => "directory",
owner => "flume",
group => "flume",
}
file { "/home/impala":
ensure => "directory",
owner => "impala",
group => "impala",
}
}
Hostfile init.pp file:
class hostfile {
file {'/etc/hosts':
ensure => directory,
mode => '0755',
owner => 'root',
group => 'root',
source => 'puppet:///modules/hostfile/hosts',
}
}
In the /etc/puppet/manifest directory is a file called site.pp. The great thing about declaring a class in the init.pp files and using one file (site.pp) to push configuration to nodes is I can just expand this file as needed.
site.pp
node 'chdnode1' {
include users
include hostfile
include homedir
}
node 'chdnode2' {
include users
include hostfile
include homedir
}
node 'chdnode3' {
include users
include hostfile
include homedir
}
Finally I can check the config against the node with this command, run on the node
puppet agent –-test
Then I can apply the configuration
puppet agent apply