sábado, 12 de junio de 2010

01-Puppet, configuración avanzada y etckeeper

Vamos a crear una estructura de directorios y archivos para usar Puppet y mantener configurada una red con varias máquinas y diferentes sistemas operativos (Windows no está soportado todavía). Para instalar puppet en el puppet master podemos ver los pasos en
http://yoadminsis.blogspot.com/2010/05/instalacion-de-puppet-y-configuracion.html

Creación de la estructura de directorios

Los manifiestos que contendrán las clases, recursos, nodos... tiene extensión .pp. Crearemos una estructura de directorios para contenerlos. Los manifiestos se encuentran por defecto en /etc/puppet/manifest y dentro site.pp que será el inicio del árbol de manifiestos. En site.pp tendremos sentencias import sobretodo para que se pueda separar los contenidos en diferentes ficheros .pp y, así, no hacer complejo e inmantenible el fichero site.pp.

Lo primero que vamos a hacer es instalar el programa etckeeper en el postmaster. Esto lo que hace es meter el directorio /etc en un sistema de control de versiones. Funciona con bazaar, git, mercurial y otros. Por defecto lo instala con bazaar. Meter el /etc en un sistema de control de versiones nos garantiza que podamos recuperar una versión anterior de los ficheros de configuración y mantener un control de cambios. Entre estos ficheros están los manifiestos de puppet.

$ sudo aptitude install etckeeper tree
...
$ sudo bzr log /etc
------------------------------------------------------------
revno: 1
committer: fjbejarano 
branch nick: ubults00 /etc repository
timestamp: Fri 2010-06-11 14:03:27 +0200
message:
  Initial commit

Como vemos, directamente se ha creado un repositorio con la versión 1 de /etc. Ahora cada vez que instalemos algo nuevo o cambiemos cualquier fichero o directorio de /etc podremos hacer un commit al repositorio después de probar que funciona. Tree es para mostrar gráficamente una estructura de directorios, no es necesario.

Creamos los siguientes ficheros y directorios en /etc/puppet/manifests. Pare ello he creado el siguiente script.

$ sudo vim /etc/puppet/cr_estructura_directorios_manifests.sh

#!/bin/bash
# Script para crear la estructura de directorios de los manifiestos
# de Puppet de forma inicial.
# Autor: Francisco J. Bejarano

###
# Directorio raiz

confdir="/etc/puppet/manifests"

######
# Funcion para crear el directorio raiz confdir

function cr_confdir {
        echo "El fichero de configuración de manifiestos no existe."
        mkdir -p $confdir
        echo "Creado el fichero de configuración de manifiestos."
}

######
# Función para crear los subdirectorios del directorio raíz de los manifiestos confdir

function cr_estructura {
        mkdir -p "$confdir/definitions" 2> /dev/null    #Contiene todas las definiciones
        mkdir -p "$confdir/groups" 2> /dev/null         #Contiene la configuración de grupos de usuarios
        mkdir -p "$confdir/os" 2> /dev/null             #Contiene clases para nodos con particularidades de sus sistemas operativos 
        mkdir -p "$confdir/users"       2> /dev/null    #Contiene la configuración de usuarios
        mkdir -p "$confdir/files"       2> /dev/null    #Contiene módulos de servidor de ficheros para ficheros distribuibles por Puppet
        mkdir -p "$confdir/templates" 2> /dev/null      #Contiene subdirectorios llamados como la clase que usan las plantillas ERB (de ruby)
                                                        #Estas plantillas crean contenidos de ficheros (como /etc/resolv.conf, por ejemplo)
                                                        #/etc/puppet/manifests/templates/nombreclase/nombreplantilla.erb, por ejemplo.
        echo "Creados los subdirectorios de configuración de manifiestos."

        if [ ! -e $confdir/site.pp ]; then
                echo "El fichero principal del manifiesto no existe."
                touch "$confdir/site.pp"

                # Contenido inicial del fichero site.pp
                echo "#Fichero principal de manifiestos" >> "$confdir/site.pp"
                echo -e "\n" >> "$confdir/site.pp"
                echo "#Importamos ficheros necesarios." >> "$confdir/site.pp"
                echo -e "\n" >> "$confdir/site.pp"
                echo "import templates.pp" >> "$confdir/site.pp"
                echo "import nodes.pp" >> "$confdir/site.pp"
                echo "import classes/*" >> "$confdir/site.pp"
                echo "import groups/*" >> "$confdir/site.pp"
                echo "import users/*" >> "$confdir/site.pp"
                echo "import os/*" >> "$confdir/site.pp"
                echo -e "\n" >> "$confdir/site.pp"
                echo "#Creamos un sistema de copia de seguridad. filebucket crea un repositorio" >> "$confdir/site.pp"
                echo "#en el servidor que le digamos (ubults00) y le llamamos main. Después con" >> "$confdir/site.pp"
                echo "#File le decimos que el backup de los ficheros que cambiemos localmente en" >> "$confdir/site.pp"
                echo "#el cliente Puppet los guarde en main. Como hemos puesto File con F" >> "$confdir/site.pp"
                echo "#mayúscula, hacemos que, por defecto, todos los recursos lo usen." >> "$confdir/site.pp"
                echo -e "\n" >> "$confdir/site.pp"
                echo "filebucket { main: server => "ubults00" }" >> "$confdir/site.pp"
                echo "File { backup => main }" >> "$confdir/site.pp"

                echo "Creado el fichero site.pp"
        fi

        if [ ! -e $confdir/templates.pp ]; then
                echo "El fichero principal de templates no existe."
                touch "$confdir/templates.pp"
                echo "Creado el fichero templates.pp"
        fi

        if [ ! -e $confdir/nodes.pp ]; then
                echo "El fichero principal de nodos no existe."
                touch "$confdir/nodes.pp"
                echo "Creado el fichero nodes.pp"
        fi
}


##########
# Programa principal

echo "Ejecutando script $0 para la creación inicial del directorio de manifiestos de Puppet."

if [ -d $confdir ]; then
        cr_estructura
else
        cr_confdir
        cr_estructura
fi

echo "Estructura de ficheros de manifiestos:"
tree $confdir
echo "Mostrando contenido de site.pp"
cat "$confdir/site.pp"
echo ""
echo "Script finalizado."

Damos permiso de ejecución a root y ejecutamos el script.

$ sudo chmod u+x cr_estructura_directorios_manifests.sh
$ sudo ./cr_estructura_directorios_manifests.sh
Ejecutando script ./cr_estructura_directorios_manifests.sh para la creación inicial del directorio de manifiestos de Puppet.
Creados los subdirectorios de configuración de manifiestos.
El fichero principal del manifiesto no existe.
Creado el fichero site.pp
El fichero principal de templates no existe.
Creado el fichero templates.pp
El fichero principal de nodos no existe.
Creado el fichero nodes.pp
Estructura de ficheros de manifiestos:
/etc/puppet/manifests
|-- definitions
|-- files
|-- groups
|-- nodes.pp
|-- os
|-- site.pp
|-- templates
|-- templates.pp
`-- users

6 directories, 3 files
Mostrando contenido de site.pp
#Fichero principal de manifiestos


#Importamos ficheros necesarios.


import templates.pp
import nodes.pp
import classes/*
import groups/*
import users/*
import os/*


#Creamos un sistema de copia de seguridad. filebucket crea un repositorio
#en el servidor que le digamos (ubults00) y le llamamos main. Después con
#File le decimos que el backup de los ficheros que cambiemos localmente en
#el cliente Puppet los guarde en main. Como hemos puesto File con F
#mayúscula, hacemos que, por defecto, todos los recursos lo usen.


filebucket { main: server => ubults00 }
File { backup => main }

Script finalizado.

Miramos que ha pasado con el control de versiones

$ sudo bzr status /etc
unknown:
  puppet/cr_estructura_directorios_manifests.sh
  puppet/manifests/definitions/
  puppet/manifests/files/
  puppet/manifests/groups/
  puppet/manifests/nodes.pp
  puppet/manifests/os/
  puppet/manifests/site.pp
  puppet/manifests/templates/
  puppet/manifests/templates.pp
  puppet/manifests/users/

$ sudo etckeeper commit "Creación del script inicial para la creación inicial de la estructura de ficheros de Puppet." 
Committing to: /etc/                                                                                                           
modified .etckeeper
added puppet/cr_estructura_directorios_manifests.sh
added puppet/manifests/definitions
added puppet/manifests/files
added puppet/manifests/groups
added puppet/manifests/nodes.pp
added puppet/manifests/os
added puppet/manifests/site.pp
added puppet/manifests/templates
added puppet/manifests/templates.pp
added puppet/manifests/users
Committed revision 2.                                                                                                          
$ sudo bzr status /etc
$ sudo bzr log /etc
------------------------------------------------------------
revno: 2
committer: fjbejarano 
branch nick: ubults00 /etc repository
timestamp: Sat 2010-06-12 14:17:20 +0200
message:
  Creación del script inicial para la creación inicial de la estructura de ficheros de Puppet.
------------------------------------------------------------
...

Como vemos podemos usar comandos bazaar y para hacer el commit podemos usar etckeeper que guardará los cambios en el repositorio bazaar automáticamente. En este caso la revisión 2. Al tener /etc gestionado con etckeeper, cuando instalemos un programa, este añadirá los ficheros y hará commit automaticamente después de instalarlo con todos los cambios de /etc. Todo esto podemos configurarlo en /etc/etckeeper. Además, etckeeper mantiene los permisos que necesita /etc.

Por ejemplo al instalar gpm (programa para usar el ratón en la consola) vemos como usa el sistema de control de versiones con lo que ha cambiado de /etc y crea la revision 3 con un mensaje y el paquete que ha cambiado. Es muy útil aunque no usemos puppet. Pongo puntos suspensivos para acortar la salida como siempre.

$ sudo aptitude install gpm
...
Se instalarán los siguiente paquetes NUEVOS:
  gpm 
0 paquetes actualizados, 1 nuevos instalados, 0 para eliminar y 0 sin actualizar.
...
Configurando gpm (1.20.4-3.2ubuntu2) ...

Creating config file /etc/gpm.conf with new version
Ignoring install-info called from maintainer script
The package gpm should be rebuilt with new debhelper to get trigger support

Committing to: /etc/                                                                                                           
added gpm.conf
added apm/event.d/gpm
added init.d/gpm
added rc0.d/K20gpm
added rc1.d/K20gpm
added rc2.d/S20gpm
added rc3.d/S20gpm
added rc4.d/S20gpm
added rc5.d/S20gpm
added rc6.d/K20gpm
Committed revision 3.                                                                                              ...
Escribiendo información de estado extendido... Hecho

$ sudo bzr log /etc
------------------------------------------------------------
revno: 3
committer: fjbejarano 
branch nick: ubults00 /etc repository
timestamp: Sat 2010-06-12 14:32:43 +0200
message:
  committing changes in /etc after apt run
  
  Package changes:
  +gpm 1.20.4-3.2ubuntu2
------------------------------------------------------------
...

Podemos quitar el repositorio inicial de la instalación con

$ sudo etckeeper uninit
** Warning: This will DESTROY all recorded history for /etc,
** including the bzr repository and ignore file.

Are you sure you want to do this? [yN] N
Aborting etckeeper uninit.

Después configuramos en /etc/etckeeper que use git, por ejemplo y meter en git /etc. Pero en principio nosotros usaremos bazaar que viene por defecto. Así que pulsamos N.

Por tanto, cuando hagamos cambios en los manifiestos usaremos etckeeper commit "mensaje de explicación de cambios" para guardar una nueva revisión de cambios en el servidor cuando hayamos probado que funcionan.

Para volver a una versión anterior, si hemos cometido un error. Por ejemplo, editamos el fichero, site.pp y hemos eliminado los imports sin querer (un poco raro pero sirve de ejemplo :-D) Editamos el fichero y eliminamos las lineas con imports, todas. Guardamos y hacemos lo siguiente.

$ sudo bzr status
modified:
  puppet/manifests/site.pp

$ sudo bzr diff manifests/site.pp
=== modified file 'puppet/manifests/site.pp'
--- puppet/manifests/site.pp    2010-06-12 12:17:20 +0000
+++ puppet/manifests/site.pp    2010-06-12 12:59:35 +0000
@@ -4,13 +4,6 @@
 #Importamos ficheros necesarios.
 
 
-import templates.pp
-import nodes.pp
-import classes/*
-import groups/*
-import users/*
-import os/*
-
 
 #Creamos un sistema de copia de seguridad. filebucket crea un repositorio
 #en el servidor que le digamos (ubults00) y le llamamos main. Después con

Como vemos en el status nos indica que un fichero ha cambiado pero no se ha metido en el repositorio todavía, con diff vemos los cambios que se han hecho y las diferencias del actual con la rev. 3 que es la última que teníamos. Aquí, lo normal es ver que hemos eliminado las lineas de import (símbolo menos (-) delante, el símbolo (+) es que hemos añadido las lineas) y corregirlo antes de hacer el commit, pero suponemos que no nos hemos dado cuenta y hacemos el commit.

$ sudo etckeeper commit "Cambios en site.pp"
Committing to: /etc/                                                                                                           
modified puppet/manifests/site.pp
Committed revision 4.
$ sudo bzr diff manifests/site.pp

Obviamente esto hace que todo falle. Para volver a la revision 3. Usando revert podemos revertir a una revisión que queramos (-r) una lista de fichero o todos los ficheros de una revisión si no ponemos una lista de ficheros. Si no ponemos -r se revertirá al último commit.

$ sudo bzr status /etc
$ sudo bzr log /etc
------------------------------------------------------------
revno: 4
committer: fjbejarano 
branch nick: ubults00 /etc repository
timestamp: Sat 2010-06-12 15:08:28 +0200
message:
  Cambios en site.pp
------------------------------------------------------------
...
$ sudo bzr revert -r 3 /etc/puppet/manifests/site.pp
 M  puppet/manifests/site.pp  
$ sudo bzr status /etc
modified:
  puppet/manifests/site.pp
$ sudo cat manifests/site.pp
#Fichero principal de manifiestos


#Importamos ficheros necesarios.


import templates.pp
import nodes.pp
import classes/*
import groups/*
import users/*
import os/*


#Creamos un sistema de copia de seguridad. filebucket crea un repositorio
...

Vemos que el fichero vuelve a tener las sentencias import y hacemos el commit correcto.

$ sudo etckeeper commit "Cambios en site.pp, correctos"
Committing to: /etc/                                                                                                           
modified puppet/manifests/site.pp
Committed revision 5.

Otra forma para hacerlo si nos hemos equivocado con un commit y nos damos cuenta justo al hacerlo es con uncommit, que nos devuelve al commit inmediatamente anterior.

$sudo bzr uncommit

Y con esto ya tenemos /etc del servidor puppet en un control de versiones y los directorios iniciales creados.
Related Posts with Thumbnails