Featured post

Quiz: Data PreProcessing

Sunday, 30 June 2019

Puppet



Chapter 1

Getting Started with Puppet



1.1 How Puppet Works



-Ravi is a DevOps person in charge of managing company infrastructure
- He manually configure or do changes on all the virtual machines
- It takes weeks or may be months depending on the size of infrastructure.
 


-Is there a way to manage this better?
- What if he can deploy change concurrently to all the systems

Puppet helps to automate repetitive and error prone tasks
-Provision servers
-Deploy application
-Proactively manage infrastructure

It helps to automate full infrastructure- Like OS, network, middleware, application.
 

Ravi can manage resources by writing in Puppet’s Simple Language. It will work on Linux, Solaris, AIX, windows,etc.

It also possible to deploy in different env, like public, private and hybrid clouds.




1.2 What is Puppet?


·        Ruby based
·        Can run in Client-Server or standalone model
·        Developed by Luke Kanies
·        used to manage a host throughout its lifecycle: from initial build and installation, to upgrades, maintenance, and finally to end-of-life
·        designed to continuously interact with your hosts, unlike provisioning tools which build your hosts and leave them unmanaged.
·        Uses puppet declarative language( focus is what instead of how)
Four Major challenges in keeping up the configuration of systems and application:
1>    ensuring that servers we deploy have consistent base configurations
2>    remediating inconsistent or incorrect configurations
3>    deploying applications in a consistent and reliable way
4>    automating all of these things

Three Components of puppet operating model:
1>    Deployment
2>    Configuration Language and resource Abstraction Layer
3>    Transactional Layer



1.3 Why can’t we achieve above things by script


·        Take lot of time – Write, Test and Debug
·        Procedural – goes in multiple of line to achieve a result, focus on how.
·        Mulitple ways of doing same thing, difficult for other person to understand
·        Need different code for different OS
·        For Same OS, different version have diff commands



1.4 Why Puppet?

·        Overcomes shortcomings of other configuration management tools.
e.g: Chef- Ruby is req, CEconfig- Complex
·        Puppet programs are Declarative
·        Focus is “What” instead of “How”, less complex


1.5 Change Management


·        Enforcing a particular state
·        To maintain consistency

1.6  Provisioning


·        transition from one system state to another system state that's expected and this is generally used in building servers.
·        It’s actually installing and configuring the software each time rather than just copying the image which is not a clean method.
e.g: On a server having basic operating system, we want to make it a Web server. Below are the automated steps.
1> Installation
2> Copy configuration
3> Copy web files or some testing codes
4> Install security updates
5> Start the service

1.7 Automation


·        Automation is the most basic part of Puppet
·        Can update files, change network devices, update the system
E.g:
There is urgent requirement to update a security file on 500 servers ASAP.
Just update the playbook and it will be pushed automatically. If there is any issue with a particular server, remove it from load balancer and investigate the cause.




1.8 Orchestration


·        It’s different from automation. Automation used on a single system whereas orchestration takes the automation and coordinates the process between multiple systems.
·        Cannot have orchestration without automation.


1.9 Advantages

 



1.10 Architecture


·        Usually deployed in a simple client-server model
·        Server = Puppet Master  (Linux Server), Puppet Master application is written in Ruby on Rails
·        Client = Nodes
·        Master and Nodes communicate via SSL over TCP/8140
·        Nodes pull config from Master
·        Each individual configuration item in a Puppet program is called a resource declaration









Chapter 2

Installing and Configuring the Puppet Master


2.1 Lab Setup


Master – Redhat 7
Client1- CentOS 7
Client2- Ubuntu 14.04.1 LTS

2.2 Installation


·        Install OracleVirtual Box and Vagrant
·        Install CentOS and Ubuntu


2.3 Booting the PuppetMaster


Steps:
1>    Add the CentOS Box to Vagrant
Go to the directory where CentOS
$cd puppet
$vagrant box add centos65-base centos65.box
#to verify the box is added
$vagrant box list

2>    Booting the Puppet Master Server
$cd puppetmaster
$vagrant up

3>    Installing Nano, Git and NTP
$sudo yum –y install nano git ntp
$sudo service ntpd start
$sudo chkconfig ntpd on
$chkconfig | grep ntpd


2.4 Installing the PuppetMaster


Add the puppet repository: to download puppet binaries.
$sudo yum –y install https://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm
 $sudo yum –y install puppet-server

To check the version of Puppet Master
#puppet master –version


2.5 Setting Up Directory Environments


Directory Env allow to maintain various env like test, dev and prod on same puppet master.
Puppet Loads the site manifest by Default (pp = Puppet Program)
/etc/puppet/manifests/site.pp
Tasks:
1>    Create a prod env
2>    Lower the env timeout
3>    Set DNS alternative names
Environment Configuration file: /etc/puppet/environments/production/environment.conf

Three Section /etc/puppet/puppet.conf ( file exists on both master and agent node)
1.      Master
2.      Agent
3.      Main
[main]
  logdir = /var/log/puppet
  rundir = /var/run/puppet
  ssldir = $vardir/ssl

[master]
  environmentpath = $confdir/environments
  basemodulepath = $confdir/modules:/opt/puppet/share/puppet/modules

[agent]
  classfile = $vardir/classes.txt
  localconfig = $vardir/localconfig


Creating directory structure
#mkdir –p /etc/puppet/environments/production/{modules,manifests}
#cd /etc/puppet/environments/production
#vi environment.conf
  modulepath = /etc/puppet/environments/production/modules
  environment_timeout = 5s

#cd /etc/puppet/
#vi puppet.conf    ( there is no master section : create it)
[main]
……
    dns_alt_names = puppet, puppetmaster, puppetmaster.company.com

[master]
    environmentpath = $confdir/environments
    basemodulepath = $confdir/modules:/opt/puppet/share/modules/

[agent]
….




2.6 Security: Dealing with SELinux


Put it into permissive mode.
#setenforce permissive
File: /etc/sysconfig/selinux


2.7 Puppet Master: Generating Certificates


To generate Certificates: need to perform only one time
#puppet master –verbose –no-daemonize
Break it ^c
#ls –la  /var/lib/puppet/ssl

Suppose we want to re-generate the keys if the current ones are compromised. Delete ssl (rm –r /var/lib/puppet/ssl)



2.8 Configuring the IPtables Firewalls


IPTables Blocks everything except ICMP and Secure Shell.
Permit other nodes to connect PuppetMaster at TCP/8140.
File Path = /etc/sysconfig/iptables
#vi /etc/sysconfig/iptables
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8140 -j ACCEPT

#service iptables restart






















Chapter 3

Installing and Configuring the Puppet Agent


3.1 Boot the client1 and client2 server


Add the Ubuntu image in Vagrant on Windows CMD in the image  directory
$cd
$vagrant box add trusty64 trusty-server-clouding-amd64-vagrant-disk1.box
Go to the directory where vagrant file is there and run below
$vagrant up
Both client will be up


3.2 Adding the PuppetMaster to the hosts file


On both client:
#echo 192.168.56.201 puppetmaster >> /etc/hosts

3.3 Installing the Puppet Agent on CentOS


#yum –y install puppet

Now open the /etc/puppet/puppet.conf file, without server entry puppet agent will not function.
#vi /etc/puppet/puppet.conf
[agent]
    server =  puppetmaster


3.4 Installing the Puppet Agent on Ubuntu


#wget  https://apt.puppetlabs.com/puppetlabs-release-trusty.deb
#dpkg -i puppetlabs-release-trusty.deb
#apt-get update
#apt-get install puppet

Now open the /etc/puppet/puppet.conf file, without server entry puppet agent will not function.
#vi /etc/puppet/puppet.conf
[agent]
    server =  puppetmaster

Enable the agent, required in Ubuntu.
#puppet agent --enable




3.5 Generating Certificate from Client


On both client nodes run below command:
#puppet agent --verbose --no-daemonize –onetime


3.6 Signing Agent Certificates


PuppetMaster by default don’t accept the certificates
#puppet cert list
# puppet cert sign client1
# puppet cert sign client2
#puppet cert list all




















Chapter 4

Puppet Concept





4.1 Resource Declaration


Each individual configuration item in a Puppet program is called a resource declaration.
To manage resources on a target system, you should declare them in Puppet manifests.

Resource Declaration answer two basic questions:
·        What aspect – user, service , package, file
·        What state – stop, start

******************************
type { title:
attribute => value,
}
******************************




4.2 Package Resource


To browse the resource package, run below command:

*************************************
# puppet resource package
package { 'GeoIP':
  ensure => '1.5.0-11.el7',
}
package { 'NetworkManager':
  ensure => '1.4.0-17.el7_3',
}
package { 'NetworkManager-libnm':
  ensure => '1.4.0-17.el7_3',
}
package { 'NetworkManager-team':
  ensure => '1.4.0-17.el7_3',
}

************************************************************

Package resource Type:
package { ‘ntp’:
  ensure => ‘installed’,
 }



4.3 File Resource


Description:
Manages files, including their content, ownership, and permissions.
File contents can be managed directly with the content attribute, or downloaded from a remote source using the source attribute

file { ‘/readme.txt’:
  ensure => ‘present’,
  content => “Comments are here”,
}


Run below command to check the various attributes of file /etc.
******************************************************
# puppet resource file /etc
file { '/etc':
  ensure   => 'directory',
  ctime    => '2017-03-17 09:11:06 -0400',
  group    => '0',
  mode     => '755',
  mtime    => '2017-03-17 09:10:43 -0400',
  owner    => '0',
  selrange => 's0',
  selrole  => 'object_r',
  seltype  => 'etc_t',
  seluser  => 'system_u',
  type     => 'directory',
}

*****************************************************





4.4 Service Resource


Manage running services

e.g:
service { ‘ntpd’:
  ensure => ‘running’ ,
  enable => true ,   #(note: Boolean attributes shouldn’t be in quotes, in quotes it takes all true)
}

Run below command to check all the services on the server
******************************************************
# puppet resource service
service { 'NetworkManager-dispatcher.service':
  ensure => 'stopped',
  enable => 'true',
}
service { 'NetworkManager-wait-online.service':
  ensure => 'running',
  enable => 'false',
}
service { 'NetworkManager.service':
  ensure => 'running',
  enable => 'true',
}

*****************************************************************



4.5 Configuration Run

The process of running a Puppet program and applying the desired configuration.
1>    the node connects to the Puppet Master on TCP port 8140
2>    the node then sends facts about itself
3>    the Master has to classify the node (means finding the matching node definition in the Puppet manifest)
4>    the Master then takes this information along with the facts sent from the node, and it compiles a catalog
5>    the catalog contains two things, the desired state of each resource and any dependencies the resource requires
6>    the Master sends the catalog to the node
7>    the node then applies the catalog, enforcing the desired configuration
8>    reports the results to the master
9>    the configuration run is complete


4.6 Facter


Facter is a standalone tool that house’s environment-level variables.
Each key-value in facter is referred to as “facts”
Command:
# facter
architecture => x86_64
augeasversion => 1.4.0
bios_release_date => 12/01/2006
bios_vendor => innotek GmbH
bios_version => VirtualBox
blockdevice_sda_model => VBOX HARDDISK
blockdevice_sda_size => 8589934592
blockdevice_sda_vendor => ATA
blockdevice_sr0_model => CD-ROM
blockdevice_sr0_size => 1073741312
blockdevice_sr0_vendor => VBOX
blockdevices => sda,sr0
boardmanufacturer => Oracle Corporation
boardproductname => VirtualBox
boardserialnumber => 0
facterversion => 2.4.6
……….

Chapter 5

Creating Manifests


·        Puppet programs are stored in files called manifests.
·        A manifest is just a regular text file with a .pp extension that contains Puppet code.
·        A Puppet manifest consists of various elements such as node definitions, resource declarations, variables, and classes that control what configuration get applied to what nodes.
·        full path of directory will be /etc/puppet/environments/production/manifests
·        Puppet will automatically load all of the .pp files in this directory


5.1 Node Definitions


#vi /etc/puppet/environments/production/manifests/nodes.pp
node ‘client1’ {
}

node ‘client2’{
}


5.2 Managing Files


·        Earlier we looked at three common resource types for managing: packages, files, and services.
·        to incorporate these resource types into our new manifest
Create a simple text file on each server that says, "Created by Puppet", and then appends the date and time that the file was created
Make  the entry in nodes.pp
  file { '/info.txt':
    ensure  => 'present',
    content => inline_template("Created by Puppet at <%= Time.now %>\n"),
  }

5.3 Client Firebucket


·        Before Puppet modifies or deletes a file, it stores the old copy in what's called the client Filebucket
·        Client Filebucket is stored on the node, not on the Puppet Master
·        File : /var/lib/puppet/clientbucket
·        For restoring the file, hash is required. If we don’t know than it can be obtained from /var/log/messages
Command:
# puppet filebucket -l --bucket /var/lib/puppet/clientbucket restore /info.txt 741ed14b73948aecb650c9c368926ff1
Here:
“l” : local means the file is on local server.
Bucket: The full path of clientbucket directory
Last entry: hash value from /var/log/messages
 
If we just want to know the content but don’t  want to restore: replace restore option with get in above command
# puppet filebucket -l --bucket /var/lib/puppet/clientbucket get /info.txt 741ed14b73948aecb650c9c368926ff1


5.4 Managing Packages


On puppetmaster: nodes.pp
  package { 'ntp':
    ensure => 'installed',
  }
On Client: CentOS
# puppet agent --verbose --no-daemonize –onetime
Once the ntp is installed, verify:
CentOS:
# yum info ntp
Installed Packages
Name        : ntp
Arch        : x86_64


Ubuntu:
# ls /usr/sbin/ntpd -la
-rwxr-xr-x 1 root root 671440 Oct  5 12:35 /usr/sbin/ntpd


Now the package is installed. Will now have to make sure it runs.




5.5 Managing Services


On Puppetmaster:

  service { 'ntpd':
    ensure  => 'running',
    enable  => true,
  }

Please note that true will not come under quotes.Also, the service name in Ubuntu is ntp. So, we have different service name. Will check later how to deal with this.

On client run below command:
# puppet agent --verbose --no-daemonize –onetime


Now we delete the ntp package and run again the puppet agent command:


Here, puppet determined that first the package need to be installed and after that only services can be brought up. However, there are chances that it can get it wrong. Will see how to take care of this later.







5.6 Selectors


·        On our client1 server which runs CentOS, the ntp service is called ntpd.
·        On the client2 Ubuntu server it's called ntp.
·        We had to specify separate resource declarations with different titles under each node definition in our manifest
·        Not an efficient way
·        If we are having many different nodes, it becomes unmanageable.
·        To make it scalable and readable by using a Puppet feature called a selector
·        Uses variables
e.g:
$ntpservice = $osfamily ? {
  ‘redhat’ =>  ‘ntpd’,
  ‘debian’ =>  ‘ntp’,
   default  =>  ‘ntp’,
}

How to use it:
Replace:
  service { 'ntpd':
    ensure  => 'running',
    enable  => true,
  }


With:
  service { $ntpservice:
    ensure  => 'running',
    enable  => true,
  }


5.7 Classes

·        At this point, we have a lot of repetition in our code.
·        Issues: inefficient, doesn’t scale very well,  difficult to read and understand.
·        Should not repeat the code.
·        Class can be used to clean up the code and arrange it better.
·        Puppet Class is very different from Object Oriented Class.
·        A Puppet class is simply a named collection of resources.
·        Adv:  class is that you can write it once and then reuse it throughout the Puppet programs
e.g:
class linux {
  package { ‘ntp’:
    ensure  =>  ‘installed’,
  }
}

node  ‘wiki’ {
  { class ‘linux’:}
}

nodes.pp

node 'client1' {
  class { 'linux': }
}

node 'client2' {
  class { 'linux': }
}

class linux {

  $ntpservice = $osfamily ? {
    'redhat' =>  'ntpd',
    'debian' =>  'ntp',
    default  =>  'ntp',
  }

  file { '/info.txt':
    ensure  => 'present',
    content => inline_template("Created by Puppet at <%= Time.now %>\n"),
  }

  package { 'ntp':
    ensure => 'installed',
  }

  service { $ntpservice :
    ensure  => 'running',
    enable  => true,
  }
}



5.8 Using Variables


We can use variables in another way to avoid repetition.
Suppose we have three packages we want to install, Nano, Git, and Screen.
Instead of writing resource for each, we can use variables to write it once.

class linux {
  $packlist = ['git', 'nano', 'screen']

  package { $packlist:
    ensure => 'installed',
  }  
…….
Old Entries
……..
}
Package might not installed in the order in which they are specified.


 



Chapter 6

Creating and Using Modules



6.1 Definition

Modules are directories with a predictable structure.
Puppet can automatically load manifests, files, and plugins from modules in its modulepath.



6.2 Finding Modules


Use puppet master --configprint modulepath to see where Puppet expects to find modules on your system.
# puppet master --configprint modulepath
/etc/puppet/environments/production/modules


6.3 Creating Modules


#cd /etc/puppet/environments/production/modules/
#puppet module generate yourname-mediawiki –environment production
#mv yourname-mediawiki mediawiki
#cd mediawiki/manifests

Check the file init.pp. It is having one class called mediawiki.



6.4 Module Structure


Collection of Puppet code organized into a predictable file structure.
Parent Directory is having below 7 Directories
·        Manifests
·        Files
·        Templates
·        Lib
·        Facts.d
·        Tests
·        Spec


6.5 Manifests

Puppet code unique to the module, including classes, resource declarations, and variables
Every Puppet module contains an init.pp file in the manifest directory.
The init.pp file, has an empty class declaration for the mediawiki class.
The init.pp manifest is automatically loaded this means is that we can actually invoke this mediawiki class from inside our nodes.pp manifest the same way we invoked our linux class earlier.


6.6 Files

Contains files that we want to push to the Puppet nodes usually configuration files.
E.g: IPtables, SELinux.
This is for only static files that don't change.
For dynamic files, will use next directory Templates.


6.7 Templates

This directory holds ERB templates.
We can have entire file template that contains a mix of static and dynamic content that we can modify or customize with variables and facts
Use the template function to create a string by rendering a template.
Use the content attribute to fill file contents with a string.
Template files are referenced as modulename/filename.erb
**************************************************************
Apache/templates/vhost.erb
To use this template:
file {'/etc/apache2/sites-enabled/wordpress.conf': 
  ensure  => file, 
  content => template('apache/vhost.erb'),
}
***************************************************************


6.8 Lib

Contains custom facts.
Custom facts require to write Ruby code.

6.9 Facts.d:


Contains external facts.
These are similar to custom facts, except instead of using Ruby to write custom facts, we can use any script or executable.

6.10 Tests and spec:

For doing unit testing and requires some knowledge of Ruby.


6.11 Customising Module


Create below entry inside class mediawiki
# cat /etc/puppet/environments/production/modules/mediawiki/manifests/init.pp
class mediawiki {

  $phpmysql  = $osfamily ? {
    'redhat' => 'php-mysql',
    'debian' => 'php5-mysql',
    default  => 'php-mysql',
  }

  package { $phpmysql:
    ensure => 'present',
  }

}








6.12 How to use class from a module inside a node definition


Now include above class inside each node definition in nodes.pp

# cat /etc/puppet/environments/production/manifests/nodes.pp              
node 'client1' {

  class { 'linux': }
  class { 'mediawiki': }

}

node 'client2' {

  class { 'linux': }
  class { 'mediawiki': }

}

class linux {

  $packlist = ['git', 'nano', 'screen']

  package { $packlist:
    ensure => 'installed',
  }

  $ntpservice = $osfamily ? {
    'redhat' =>  'ntpd',
    'debian' =>  'ntp',
    default  =>  'ntp',
  }

  file { '/info.txt':
    ensure  => 'present',
    content => inline_template("Created by Puppet at <%= Time.now %>\n"),
  }

  package { 'ntp':
    ensure => 'installed',
  }

  service { $ntpservice :
    ensure  => 'running',
    enable  => true,
  }

}

Run the agent command on both server client1 and client2.

# puppet agent --verbose --no-daemonize –onetime





Ubuntu:
# service --status-all | grep -i mysql




6.13 Conditionals


If we want to install a package only on CentOS but not on Ubuntu then we use conditionals.

Add this in init.pp inside mediawiki class.
  if $osfamily == 'redhat' {
    package { 'php-xml':
      ensure => 'present',
    }
  }

Run the agent command on both server client1 and client2. This package php-xml got  installed  only on client1.

# puppet agent --verbose --no-daemonize –onetime

CentOS:
# systemctl list-unit-files | grep -i mysql

When you run:
#yum install mysql
command by default it installs MariaDB not MySQL.
So try the following command:
#yum list installed | grep mariadb
if mariadb-server is missing try this following command:
#yum install mariadb-server
it installs the server package then start the service:
#systemctl start mariadb





Or create below entries in nodes.pp
***************************************************
$packlist = ['nano', 'screen', 'mariadb', 'mariadb-server']

  package { $packlist:
    ensure => 'installed',
  }
  if $osfamily == 'redhat' {
  service { 'mariadb':
      ensure => 'running',
    }
  }
*********************************************















Chapter 7

Project



7.1 The Apache Module


Install the Apache Module, run below command on puppetserver
# puppet module install puppetlabs-apache --modulepath /etc/puppet/environments/production/modules/
Go to below link:

Make below entries inside mediawiki class in init.pp inside mediawiki manifests
class mediawiki {

  $phpmysql  = $osfamily ? {
    'redhat' => 'php-mysql',
    'debian' => 'php5-mysql',
    default  => 'php-mysql',
  }

  package { $phpmysql:
    ensure => 'present',
  }
  if $osfamily == 'redhat' {
    package { 'php-xml':
      ensure => 'present',
    }
  }
  class { '::apache':
    docroot    => '/var/www/html',
    mpm_module => 'prefork',
    subscribe  => Package[$phpmysql],
  }

  class { '::apache::mod::php' :}
}


Run the agent command on both server client1 and client2. This package php-xml got  installed  only on client1.

# puppet agent --verbose --no-daemonize –onetime

Check apache is running
CentOS:
#service httpd status

Ubuntu:
#service apache2 status




7.2 The vcsrepo Module


We need to fetch the mediawiki application files from mediawiki's Github repository and place them in Apache's document root directory, which is /var/www/html.
Files are located at github.com/wikimedia/mediawiki.git, but Puppet does not have a built-in method to use Git.
Vcsrepo module will simply use Git to copy down the mediawiki files and put them wherever we want.
Install the vcsrepo:
# puppet module install puppetlabs-vcsrepo --modulepath /etc/puppet/environments/production/modules/


On below link:

Update Mediawiki class inside init.pp.
class mediawiki {

  $phpmysql  = $osfamily ? {
    'redhat' => 'php-mysql',
    'debian' => 'php5-mysql',
    default  => 'php-mysql',
  }

  package { $phpmysql:
    ensure => 'present',
  }
  if $osfamily == 'redhat' {
    package { 'php-xml':
      ensure => 'present',
    }
  }
  class { '::apache':
    docroot    => '/var/www/html',
    mpm_module => 'prefork',
    subscribe  => Package[$phpmysql],
  }

  class { '::apache::mod::php' :}

  vcsrepo { '/var/www/html':
    ensure   => 'present',
    provider => 'git',
    source   => "https://github.com/wikimedia/mediawiki.git",
    revision => 'REL1_23',
  }

}

Run the agent command on both server client1 and client2.
# puppet agent --verbose --no-daemonize –onetime


It failed on Ubuntu as there is a file index.html inside /var/www/html. So, we need to make sure it get deleted.
Add below entry in init.pp on puppetmaster.
********************************
  file { '/var/www/html/index.html':
    ensure  => 'absent',
  }
*********************************
It failed  again as the order was not correct. Before  the file get deleted, it started to download the file from github.
In next chapter will see how to take care of ordering.


7.3 Resource Ordering


Ensure that Puppet deletes /var/www/html/index.html file before  invoking vcsrepo.
Can be achieved using an ordering row.
Ordering Row Syntax:
File[‘/var/www/html/index.html’] -> Vcsrepo[‘/var/www/html’]
Init.pp
class mediawiki {

  $phpmysql  = $osfamily ? {
    'redhat' => 'php-mysql',
    'debian' => 'php5-mysql',
    default  => 'php-mysql',
  }

  package { $phpmysql:
    ensure => 'present',
  }
  if $osfamily == 'redhat' {
    package { 'php-xml':
      ensure => 'present',
    }
  }
  class { '::apache':
    docroot    => '/var/www/html',
    mpm_module => 'prefork',
    subscribe  => Package[$phpmysql],
  }

  class { '::apache::mod::php' :}

  vcsrepo { '/var/www/html':
    ensure   => 'present',
    provider => 'git',
    source   => "https://github.com/wikimedia/mediawiki.git",
    revision => 'REL1_23',
  }

  file { '/var/www/html/index.html':
    ensure  => 'absent',
  }

  File['/var/www/html/index.html'] -> Vcsrepo['/var/www/html']

}

Create the file as it was deleted during last run
#touch /var/www/html/index.html
Run the agent command on both server client1 and client2.
# puppet agent --verbose --no-daemonize –onetime

This time it ran successfully.

7.4 The MySQL Module


Install the Mysql module
# puppet module install puppetlabs-mysql --modulepath /etc/puppet/environments/production/modules/
Go to the link
Make below entry in file /etc/puppet/environments/production/modules/mediawiki/manifests/init.pp
class mediawiki {

  $phpmysql  = $osfamily ? {
    'redhat' => 'php-mysql',
    'debian' => 'php5-mysql',
    default  => 'php-mysql',
  }

  package { $phpmysql:
    ensure => 'present',
  }
  if $osfamily == 'redhat' {
    package { 'php-xml':
      ensure => 'present',
    }
  }
  class { '::apache':
    docroot    => '/var/www/html',
    mpm_module => 'prefork',
    subscribe  => Package[$phpmysql],
  }

  class { '::apache::mod::php' :}

  vcsrepo { '/var/www/html':
    ensure   => 'present',
    provider => 'git',
    source   => "https://github.com/wikimedia/mediawiki.git",
    revision => 'REL1_23',
  }

  file { '/var/www/html/index.html':
    ensure  => 'absent',
  }

  File['/var/www/html/index.html'] -> Vcsrepo['/var/www/html']

  class { '::mysql::server':
    root_password  =>  'training',
  }

}
Run the agent command on both server client1 and client2.
# puppet agent --verbose --no-daemonize --onetime


Ubuntu:
# service mysql status
mysql start/running, process 4546
# mysql -u root -p
Enter password:training
Welcome to the MySQL monitor.  Commands end with ; or \g.
mysql> \q
Bye



7.5 The Firewall Module


Install the firewall module
# puppet module install puppetlabs-firewall --modulepath /etc/puppet/environments/production/modules/

Make below entry in file /etc/puppet/environments/production/modules/mediawiki/manifests/init.pp
class mediawiki {

  $phpmysql  = $osfamily ? {
    'redhat' => 'php-mysql',
    'debian' => 'php5-mysql',
    default  => 'php-mysql',
  }

  package { $phpmysql:
    ensure => 'present',
  }
  if $osfamily == 'redhat' {
    package { 'php-xml':
      ensure => 'present',
    }
  }
  class { '::apache':
    docroot    => '/var/www/html',
    mpm_module => 'prefork',
    subscribe  => Package[$phpmysql],
  }

  class { '::apache::mod::php' :}

  vcsrepo { '/var/www/html':
    ensure   => 'present',
    provider => 'git',
    source   => "https://github.com/wikimedia/mediawiki.git",
    revision => 'REL1_23',
  }

  file { '/var/www/html/index.html':
    ensure  => 'absent',
  }

  File['/var/www/html/index.html'] -> Vcsrepo['/var/www/html']

  class { '::mysql::server':
    root_password  =>  'training',
  }

  class { '::firewall' : }

  firewall { '000 allow http access':
    port   => '80',
    proto  => 'tcp',
    action => 'accept',
  }

}


Ubuntu:
#iptables -L











Now go to browser and type the IP address of clients


Go through various option and complete the installation.



When we visited the MediaWiki site on the wiki server, MediaWiki made us go through a configuration process that generated a configuration settings file, which had then asked us to download, save, and then re-upload to the server. Now we need to automate this. We will achieve this by using File templates.

Database name: wiki
Database username: root
Database password: training
Database name: wiki
Name of wiki: wiki
Your username: root
Password: training



Chapter 8

Creating File Templates



8.1 Introduction


  File templates allow us to take a static file like a configuration file and insert dynamic content into it wherever we want.
The file MediaWiki gave us to download was called LocalSettings.php
This file contains configuration like the wiki Sitename, the MySQL database name, the root password, and so on.
Most of this information, which sits on the right side of the equal signs, is information that we put in manually during the MediaWiki setup process.
In other words, everything to the right of the equal signs is dynamic content.
We will use puppet to fill this dynamic content and generate a valid useable LocalSettings.php file using a file template.
A template is a regular text file with a .erb extension (embedded Ruby block).
ERB - starting with the <%=, and ending with a %> sign


8.2 Creating File Templates


Will start with working configuration file like LocalSettings.php file.
We need to take the dynamic content areas that you want Puppet to manage, and replace those with embedded Ruby blocks.
$wgSitename = "wiki";
$wgMetaNamespace = "Wiki";
$wgServer = "http://192.168.56.203";
$wgDBserver = "localhost";
$wgDBname = "wiki";
$wgDBuser = "root";
$wgDBpassword = "training";
$wgUpgradeKey = "9e7812b95263dc6c";
Left Hand Side= All PHP variable ( the file LocalSettings.php is php file)
These variables are used by mediawiki, puppet is not having any information about these.
We're going to replace the values on the right of the = sign.
LocalSettings.erb
$wgSitename = "<%= wikisitename %>";
$wgMetaNamespace = "<%= wikimetanamespace %>";
$wgServer = "<%= wikiserver %>";
$wgDBserver = "<%= wikidbserver %>";
$wgDBname = "<%= wikidbname %>";
$wgDBuser = "<%= wikidbuser %>";
$wgDBpassword = "<%= wikidbpassword %>";
$wgUpgradeKey = "<%= wikiupgradekey %>";

Replace above variables with right side value in the original file.
As MediaWiki module is going to use this template, will place original file under template directory.

#mkdir /etc/puppet/environments/production/modules/mediawiki/templates

Copy the file inside above directory.


8.3 Using Templates in Modules


Template takes a file with a mix of static and dynamic content and uses it to generate a new file
Here we want our template to generate the LocalSettings.php file.
MediaWiki told us to place the LocalSettings.php file in the root of the MediaWiki installation which is /var/www/html on wiki server.
We will use the file resource type to use our template.
This file resource will go to MediaWiki modules init.pp manifest, not the nodes manifest.
/etc/puppet/environments/production/modules/mediawiki/manifests/init.pp
file { ‘LocalSettings.php’ :
  path      => ‘/var/www/html/LocalSettings.php’,
  ensure  => ‘file’,
  content => template(‘mediawiki/LocalSettings.erb’),
}

The template uses Puppet variables to populate portions of the configuration file.
These variables are defined in nodes.pp file.
/etc/puppet/environments/production/manifests/nodes.pp

node 'client2' {

  $wikisitename = 'wiki'
  $wikimetanamespace = 'Wiki'
  $wikiserver = "http://192.168.56.203
  $wikidbserver = 'localhost'
  $wikidbname = 'wiki'
  $wikidbuser = 'root'
  $wikidbpassword = 'training'
  $wikiupgradekey = 'puppet'

  class { 'linux': }
  class { 'mediawiki': }

}

Add below entry in init.pp file inside mediawiki class.

  file { 'LocalSettings.php':
    path    => '/var/www/html/LocalSettings.php',
    ensure  => 'file',
    content => template("mediawiki/LocalSettings.erb"),
  }


Verification:
Go to browser and tyoe the IP address of client. It should falg message that mediawiki is successfully installed.


























Chapter 9

Configuring Hiera


In last chapter, we observed that the variables assigned under our wiki node definition called node scope.
Drawback: We have to keep all of these variables in our nodes manifest under each and every node definition.

We will address this problem by using Hiera.


Advantage of Hiera
·        Provides a separate place to store node specific data.
·        Not tied to any module or manifest – independent.
·        Help minimize the repetition.

9.1 Using Hiera Data in Modules


The best place for module-specific variable assignments is in the module itself.

/etc/puppet/environments/production/modules/mediawiki/manifests/init.pp
  $wikimetanamespace = hiera('mediawiki::wikimetanamespace')
  $wikisitename            = hiera('mediawiki::wikisitename')
  $wikiserver                = hiera('mediawiki::wikiserver')
  $wikidbserver            = hiera('mediawiki::wikidbserver')
  $wikidbuser               = hiera('mediawiki::wikidbuser')
  $wikidbpassword       = hiera('mediawiki::wikidbpassword')
  $wikiupgradekey       = hiera('mediawiki::wikiupgradekey')

Explanation:
mediawiki::wikimetanamespace  -> This is called  Key

Key value pair is similar to variable assignment. It's just that instead of setting a Puppet variable equal to a particular value, you set a key equal to a particular value.

When Puppet encounters a hiera function call with a key, it does a look-up on that key to retrieve the value associated with it.

It goes and look into a text file in YAML format.

When used with Hiera, these YAML files are called data sources.

If there are many YAML files  and they are containing overlapping keys than which value does puppet consider. For this it checks the Hiera configuration file, which is located, by default, at /etc/puppet/hiera.yaml.

*********************
:backends:
  - yaml
:yaml:
  :datadir:
:hierarchy:
  - "%{clientcert}"
  - clientdefault
**********************

First Two Lines: Means we're going to use YAML for our Hiera data, as opposed to a different type of         data structure.

Next Two Lines: Indicates where our YAML files are stored. Here there's no directory listed so it's going to use the default, which is /var/lib/hiera.
Last Part Hierarchy: To decide which file to use.When Puppet does a Hiera look-up, it starts at the top of this list and checks the first file. Clientcert is a variable containing the hostname of the node that runs the Puppet agent. In our case its client2, so it will look for client2.yaml and it will check that for Hiera data. It will search for  this file in default directory - /var/lib/hiera. If  puppet don’t find the client2.yaml file it will go down to clientdefault and check the clientdefault.yaml.


9.2 Creating YAML Data Sources


 The .yaml files which will store the key value pairs for our MediaWiki module are called data sources.
Will create three data sources, client1.yaml, client2.yaml and clientdefault.yaml inside /var/lib/hiera.
Create below three files:
/var/lib/hiera/client2.yaml
---
mediawiki::wikisitename: wiki
mediawiki::wikimetanamespace: Wiki
mediawiki::wikiserver: http://192.168.56.203
mediawiki::wikidbname: wiki

/var/lib/hiera/client3.yaml
---
mediawiki::wikisitename: wiki
mediawiki::wikimetanamespace: Wiki
mediawiki::wikiserver: http://192.168.56.204
mediawiki::wikidbname: wiki
/var/lib/hiera/clientdefault.yaml
---
mediawiki::wikidbserver: localhost
mediawiki::wikidbuser: root
mediawiki::wikidbpassword: training
mediawiki::wikiupgradekey: puppet


9.3 Assigning Classes in Hiera


We still have a couple of class declarations being repeated.

/etc/puppet/environments/production/manifests/nodes.pp

node 'client2' {
  hiera_include('classes')
}

node 'client3' {
  hiera_include('classes')
}

/var/lib/hiera/client2.yaml
---
classes:
  - mediawiki
  - linux
mediawiki::wikisitename: wiki
mediawiki::wikimetanamespace: Wiki
mediawiki::wikiserver: http://192.168.56.203
mediawiki::wikidbname: wiki


/var/lib/hiera/client3.yaml
---
classes:
  - mediawiki
  - linux
mediawiki::wikisitename: wiki
mediawiki::wikimetanamespace: Wiki
mediawiki::wikiserver: http://192.168.56.204
mediawiki::wikidbname: wiki


Enabling Hiera

Restart puppetmaster enable puppet to pick up the changes made to the hiera.yaml configuration file.























Chapter 10

Version Control


Version control allows us to take snapshots of our Puppet configuration, including our configuration files, manifests, modules, and Hiera data.
Can recover easily if we make changes that breaks the puppet.


10.1 Automating the Puppet Agent


Till now we were running the puppet agent manually.
In a production environment it is designed to run automaticall.
Frequency of the configuration run is  called Run Interval.
By default Run Interval = 30 Min.

To change default Run Interval:  On each client server edit below file.

/etc/puppet/puppet.conf
*******************
[main]
runinterval=60
*******************

To make the agents run automatically once the server boots up.
CentOS 6:
#chkconfig puppet on
#service puppet start

CentOS 7:
#systemctl enable puppet
#systemctl start puppet
Ubuntu:
File: /etc/default/puppet
START=yes
#service puppet start


10.2 Setup a Git Repository




git config --global user.name "XYZ"
git config --global user.email "XYZ@gmail.com"
cd /etc/puppet/environments/production/
git init
git add .
git commit -m "Initial Commit"


10.3 Recovering from Committed Mistakes





10.4 Recovering from Uncommitted Mistakes