Table of Contents

objetivo

Nesta wiki vou abordar o funcionamento do puppet em modo cliente/servidor ou também conhecido como agente/master, esta wiki é a continuação dos estudos da wiki Puppet em modo autônomo (serverless).

Na wiki Puppet Autônomo abordamos os seguintes recursos do Puppet:

  • RAL (Resource Abstraction Layer),
  • Resource Types,
    • Parâmetros,
    • Meta-Parâmetros, pa
    • Funções,
    • Classes,
    • Módulos,
    • Variáveis,
    • Condicionais,
    • Repetidores,
    • Seletores,
    • Templates,
    • Definições,
    • Filebucket,

    Agora nós vamos aprender a usar esses recursos no modo cliente/servidor.

sobre o puppet

O Puppet essencialmente é um framework opensource e um conjunto de ferramentas e soluções para gerência de configurações.

O puppet faz parte de uma nova geração de sistemas para automatização de servidores e serviços, ele nos permite tratar a infraestrutura como código.

Ele é composto por uma linguagem declarativa que nos permite expressar as configurações que os nossos servidores, sistemas e serviços devem ter, fazendo isto através de uma sintaxe simples e prática, sendo natural para sysadmins.

Ele nos oferece duas formas de funcionamento, a primeira podemos chamar de autônoma, neste modo nós criamos e executamos nossas configurações localmente. Além do modo autônomo, o puppet também funciona no modelo cliente (agente) e servidor (master) para distribuir estas configurações para todo o parque de servidores através da rede.

Aqui vamos estudar e compreender o modo cliente/servidor.

colaboradores e agradecimentos

Agradeço o apoio dos bons amigos Douglas Andrade, Daniel Sobral, Ulysses Almeida e José Pissin que foram a grande motivação para escrever as wikis sobre o Puppet.

Agradeço também ao @coredump por ter apresentado ao puppet para a equipe de sysadmins no projeto EBC.

Agradeço também aos leitores do blog/wiki por mandarem sugestões e correções durante a elaboração desta página.

premissas e dependências

Inicio essa wiki partindo da premissa de que você já estudou os seguintes posts e wikis:

O entendimento pleno desta wiki se apóia e depende destes, portanto acesse as URLS e leia o conteúdo com calma e tranquilidade antes de prosseguir.

cenário

Para elaboração desta wikipage utilizei os seguintes recursos:

2 máquinas virtuais rodando em VMWARE Fusion

  • puppetmaster.hacklab, 192.168.17.130
  • puppetagent.hacklab, 192.168.17.131

Sistema operacional Debian Squeeze 64 bits rodando nas VM's.

Disco de 4 gigas, 128 MB de ram.

A melhor forma de aprender é fazendo junto, portanto, instale 2 VM's com Debian e deixe-as prontas para uso antes de prosseguir com esta wiki.

puppet teoria

Vamos abordar de forma rápida vários aspectos e características da comunicação cliente/servidor.

api rest

Tanto o puppet agent quanto o puppet master possuem uma API REST que é usada para a comunicação entre eles.

Exemplos de estrutura básica das URLS para acessar estas API's:

https://yourpuppetmaster:8140/{environment}/{resource}/{key}
https://yourpuppetclient:8139/{environment}/{resource}/{key}

Mais informações:

http://docs.puppetlabs.com/guides/rest_api.html

rede

O funcionamento em rede é bastante simples, utiliza-se o protocolo TCP para a comunicação entre agente e master, a comunicação do agente com o master é feita através da porta TCP 8140, e a comunicação do master com o agent se dá através da porta TCP 8139. É importante ressaltar que toda a comunicação é segura, utilizando o protocolo SSL.

certificados

Como eu já informei, toda a comunicação entre agente é master é segura, para isto utilizamos SSL.

No ato da instalação do puppetmaster é gerado um certificado do master.

No ato da instalação de um puppet agent é gerado um certificado para este agente.

Para um agente se comunicar com o servidor ele precisa ser previamente autorizado no master, sem esse procedimento de autorização, um agente simplesmente não terá condições de se comunicar com o master para obter suas configurações.

funcionamento

Na wiki puppet autônomo nós vimos como se dá o processamento de um ou vários manifests e a geração do catálogo com as configurações que deverão ser aplicadas, no modo cliente/servidor os passos são similares

A aplicação das configurações no modo cliente/servidor segue os seguinte passos:

  • Agente requisita ao Master o catálogo para máquina em que está instalado
    • Agente envia junto com a solicitação os dados e o estado atual da máquina
  • Master Classifica as informações recebidas
    • Master verifica quem é o sistema/máquina e o que ele precisa ter instalado/configurado
  • Master avalia as configurações declaradas para aquela máquina
  • Master compila as informações e devolve para o agente
  • Agente recebe os dados compilados e produz um catálogo com as configurações que devem ser aplicadas
  • Agente inicia a aplicação do catálogo no sistema
    • Agente verifica estado atual do sistema (query)
    • Agente aplica configurações do catálogo - se houver (enforce)
    • Agente comunica seu estado ao nó master após aplicação do catálogo
      1. Sistema reflete as configurações que foram declaradas para ele

      Abaixo uma representação gráfica deste passos:

Gráfico retirado do site puppetlabs.

puppet mão-na-massa

hostname e dominio

É muito importante que nas duas vms você esteja com o hostname devidamente configurado, ao se logar faça o seguinte:

puppetmaster

primeiro torne-se root

su -

agora ajuste o hostname da sessão em que está logado

hostname puppetmaster.hacklab

vamos também configurar o arquivo hostname

echo puppetmaster.hacklab > /etc/puppet/hostname

e não se esqueça do mais importante, arquivo /etc/hosts

echo 192.168.17.130 puppetmaster.hacklab puppetmaster puppet >> /etc/hosts

com isto já podemos começar a trabalhar na vm puppetmaster, mantenha essa sessão aberta.

puppetagent

primeiro torne-se root

su -

agora ajuste o hostname da sessão em que está logado

hostname puppetagent.hacklab

vamos também configurar o arquivo hostname

echo puppetagent.hacklab > /etc/puppet/hostname

e não se esqueça do mais importante, arquivo /etc/hosts

echo 192.168.17.130 puppetagent.hacklab puppetagent agent >> /etc/hosts

e adicione também uma entrada para o puppetmaster

echo 192.168.17.130 puppetmaster.hacklab puppetmaster puppet >> /etc/hosts

com isto já podemos começar a trabalhar na vm puppetagent, mantenha essa sessão aberta.

configurando repositório

Configure os repositórios tanto no master quando do agent.

sources.list

você pode simplesmente inserir uma linha em sources.list

deb http://apt.puppetlabs.com squeeze main

após teremos que instalar a chave do puppetlabs

gpg --recv-key 4BD6EC30
gpg -a --export 4BD6EC30 | apt-key add -

puppetlabs-release

ou se preferir instale o pacote da puppetlabs-release, este já configura o repo e instala a chave

wget http://apt.puppetlabs.com/pool/squeeze/main/p/puppetlabs-release/puppetlabs-release_1.0-5_all.deb
dpkg -i puppetlabs-release_1.0-5_all.deb

esse pacote vai criar um arquivo chamado puppetlabs.list em /etc/apt/sources.lists.d/

puppetmaster

instalando o master

desde que você já tenha configurado os repositórios do puppetlabs, primeiro atualize os indices

root@puppetmaster:/etc# aptitude update

e depois instale o pacote

root@puppetmaster:/etc# aptitude install puppetmaster

saída

The following NEW packages will be installed:
  augeas-lenses{a} debconf-utils{a} facter{a} libaugeas-ruby1.8{a} libaugeas0{a} libruby{a} libruby1.8{a} libshadow-ruby1.8{a} puppet-common{a} 
  puppetmaster puppetmaster-common{a} ruby1.8{a} 
0 packages upgraded, 12 newly installed, 0 to remove and 14 not upgraded.
Need to get 264 kB/4,385 kB of archives. After unpacking 16.9 MB will be used.
Do you want to continue? [Y/n/?] y
Get:1 http://apt.puppetlabs.com/ squeeze/main puppetmaster all 2.7.19-1puppetlabs2 [264 kB]
Fetched 264 kB in 2s (104 kB/s)                       
Selecting previously deselected package augeas-lenses.
(Reading database ... 33990 files and directories currently installed.)
Unpacking augeas-lenses (from .../augeas-lenses_0.7.2-1_all.deb) ...
Selecting previously deselected package debconf-utils.
Unpacking debconf-utils (from .../debconf-utils_1.5.36.1_all.deb) ...
Selecting previously deselected package libruby1.8.
Unpacking libruby1.8 (from .../libruby1.8_1.8.7.302-2squeeze1_amd64.deb) ...
Selecting previously deselected package ruby1.8.
Unpacking ruby1.8 (from .../ruby1.8_1.8.7.302-2squeeze1_amd64.deb) ...
Selecting previously deselected package facter.
Unpacking facter (from .../facter_1.6.11-1puppetlabs1_all.deb) ...
Selecting previously deselected package libaugeas0.
Unpacking libaugeas0 (from .../libaugeas0_0.7.2-1_amd64.deb) ...
Selecting previously deselected package libaugeas-ruby1.8.
Unpacking libaugeas-ruby1.8 (from .../libaugeas-ruby1.8_0.3.0-1.1_amd64.deb) ...
Selecting previously deselected package libruby.
Unpacking libruby (from .../archives/libruby_4.5_all.deb) ...
Selecting previously deselected package libshadow-ruby1.8.
Unpacking libshadow-ruby1.8 (from .../libshadow-ruby1.8_1.4.1-8_amd64.deb) ...
Selecting previously deselected package puppet-common.
Unpacking puppet-common (from .../puppet-common_2.7.19-1puppetlabs2_all.deb) ...
Selecting previously deselected package puppetmaster-common.
Unpacking puppetmaster-common (from .../puppetmaster-common_2.7.19-1puppetlabs2_all.deb) ...
Selecting previously deselected package puppetmaster.
Unpacking puppetmaster (from .../puppetmaster_2.7.19-1puppetlabs2_all.deb) ...
Processing triggers for man-db ...
Setting up augeas-lenses (0.7.2-1) ...
Setting up debconf-utils (1.5.36.1) ...
Setting up libruby1.8 (1.8.7.302-2squeeze1) ...
Setting up ruby1.8 (1.8.7.302-2squeeze1) ...
Setting up facter (1.6.11-1puppetlabs1) ...
Setting up libaugeas0 (0.7.2-1) ...
Setting up libaugeas-ruby1.8 (0.3.0-1.1) ...
Setting up libruby (4.5) ...
Setting up libshadow-ruby1.8 (1.4.1-8) ...
Setting up puppet-common (2.7.19-1puppetlabs2) ...
Setting up puppetmaster-common (2.7.19-1puppetlabs2) ...
Starting puppet queue.
Setting up puppetmaster (2.7.19-1puppetlabs2) ...
Starting puppet master.

Pronto, puppetmaster instalado.

verificando portas

verifique se a porta 8140 está aberta

root@puppetmaster:/etc# netstat -ntpl|grep 8140
tcp        0      0 0.0.0.0:8140            0.0.0.0:*               LISTEN      2133/ruby1.8

só para garantir reinicie a máquina e veja se o serviço sobe sem problemas por padrão.

verificando serviço

outra forma de verificar se o puppet está rodando via passenger é acessar o endereço

https://ip_do_servidor:8140/

se receber o retorno abaixo, seu puppetmaster está funcionando.

The environment must be purely alphanumeric, not ''

acessando puppetmaster

o puppemaster também possuia um agente puppet rodando, este agente vai procurar sempre o puppetmaster através do nome puppet ou puppet.dominio em sua rede, portando vamos fazer alguns pequenos ajustes.

via dns

se possível crie um registro de DNS tipo A com o nome puppet apontando para máquina puppetmaster , se não for possível registro do tipo A, faça um registro do tipo CNAME, e no resolv.conf você precisa apontar para esse servidor de DNS e colocar search nomedodominio para que funcione adequadmente.

via hosts

caso a configuração de DNS não seja uma opção, uma forma de resolver é inserir uma entrada no /etc/hosts

192.168.31.130 puppet.dominio puppet

isso será suficiente para o agente funcionar

via puppet.conf

se ainda não for uma opção, pode ainda editar o arquivo /etc/puppet.conf e inserir a diretiva

server=nomedoservidor

na seção [agente], mas prefira sempre a configuração de DNS.

testando master

ao instalar o puppetmaster, o puppet-agent também é instalado, através dele podemos verificar se está tudo funcionando adequadamente no master.

root@puppetmaster:~# puppet agent --test

saída

info: Caching catalog for puppetmaster.localdomain
info: Applying configuration version '1347301751'
info: Creating state file /var/lib/puppet/state/state.yaml
notice: Finished catalog run in 0.02 seconds

se você tiver um retorno como este, está tudo funcionando bacana.

estrutura master

O puppetmaster uma vez instalado vai criar alguns arquivos e diretórios no /etc, precisamos entender cada um para prosseguir.

arquivos e diretórios master

Ao instalar você verá o seguinte conteúdo no diretório /etc/puppet

puppet:/etc/puppet# ls -lah
total 40K
drwxr-xr-x  5 root root 4.0K May 15 16:27 .
drwxr-xr-x 70 root root 4.0K May 15 16:25 ..
-rw-r--r--  1 root root 2.5K Apr 10 15:23 auth.conf
-rw-r--r--  1 root root  459 Apr 11 00:19 fileserver.conf
drwxr-xr-x  2 root root 4.0K Apr  5 13:01 manifests
drwxr-xr-x  2 root root 4.0K Apr  5 13:01 modules
-rw-r--r--  1 root root  462 Apr 11 00:19 puppet.conf
drwxr-xr-x  2 root root 4.0K Apr  5 13:01 templates
arquivo auth.conf

O arquivo auth.conf define acls que determinam quais recursos os agentes podem consultar no servidor puppet

/etc/puppet/auth.conf
# This is an example auth.conf file, which implements the
# defaults used by the puppet master.
#
# The ACLs are evaluated in top-down order. More general
# stanzas should be towards the bottom of the file and more
# specific ones at the top, otherwise the general rules
# take precedence and later rules will not be evaluated.
#
# Supported syntax:
# Each stanza in auth.conf starts with a path to mach, followed
# by optional modifiers, and finally, a series of allow or deny
# directives. 
#
# Example Stanza
# ---------------------------------
# path /path/to/resource     # simple prefix match
# # path ~ regex             # alternately, regex match
# [environment envlist]
# [method methodlist]
# [auth[enthicated] {yes|no|on|off|any}]
# allow [host|backreference|*]
# deny [host|backreference|*]
# allow_ip [ip|cidr|ip_wildcard|*]
# deny_ip [ip|cidr|ip_wildcard|*]
#
# The path match can either be a simple prefix match or a regular 
# expression. `path /file` would match both `/file_metadata` and
# `/file_content`. Regex matches allow the use of backreferences
# in the allow/deny directives.
# 
# The regex syntax is the same as for Ruby regex, and captures backreferences
# for use in the `allow` and `deny` lines of that stanza
#
# Examples:
# path ~ ^/path/to/resource    # equivalent to `path /path/to/resource`
# allow *
#
# path ~ ^/catalog/([^/]+)$    # permit access only for the
# allow $1                     # node whose cert matches the path
#
# environment:: restrict an ACL to a comma-separated list of environments
# method:: restrict an ACL to a comma-separated list of HTTP methods
# auth:: restrict an ACL to an authenticated or unauthenticated request
# the default when unspecified is to restrict the ACL to authenticated requests
# (ie exactly as if auth yes was present).
#
 
### Authenticated paths - these apply only when the client
### has a valid certificate and is thus authenticated
 
# allow nodes to retrieve their own catalog
path ~ ^/catalog/([^/]+)$
method find
allow $1
 
# allow nodes to retrieve their own node definition
path ~ ^/node/([^/]+)$
method find
allow $1
 
# allow all nodes to access the certificates services
path /certificate_revocation_list/ca
method find
allow *
 
# allow all nodes to store their reports
path /report
method save
allow *
 
# unconditionally allow access to all file services
# which means in practice that fileserver.conf will
# still be used
path /file
allow *
 
### Unauthenticated ACL, for clients for which the current master doesn't
### have a valid certificate; we allow authenticated users, too, because
### there isn't a great harm in letting that request through.
 
# allow access to the master CA
path /certificate/ca
auth any
method find
allow *
 
path /certificate/
auth any
method find
allow *
 
path /certificate_request
auth any
method find, save
allow *
 
# this one is not stricly necessary, but it has the merit
# of showing the default policy, which is deny everything else
path /
auth any
arquivo fileserver.conf

O arquivo fileserver.conf define quais redes podem acessar arquivos presentes no servidor puppet, você precisa declarar de forma explítica, veja o exemplo abaixo, mais a frente vamos mexer neste arquivo.

/etc/puppet/fileserver.conf
# This file consists of arbitrarily named sections/modules
# defining where files are served from and to whom
 
# Define a section 'files'
# Adapt the allow/deny settings to your needs. Order
# for allow/deny does not matter, allow always takes precedence
# over deny
#[files]
#  path /etc/puppet/files
#  allow *.example.com
#  deny *.evil.example.com
#  allow 192.168.0.0/24
 
#[plugins]
#  allow *.example.com
#  deny *.evil.example.com
#  allow 192.168.0.0/24
arquivo puppet.conf

O arquivo puppet.conf contém tanto configurações do agent quanto do master, por hora ele tem isto:

[main]
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
factpath=$vardir/lib/facter
templatedir=$confdir/templates
diretório manifests

No diretório manifests nós iremos declarar as configurações chamadas de manifests e os nodes que vão utilizá-las.

diretório modules

No diretório módulos ficam os módulos do puppet, veremos mais sobre módulos a frente.

diretório templates

O diretório templates tem os arquivos de configuração dinâmicos. Estes arquivos tem a extensão .erb, eles contém variáveis e estruturas de repetição, através deles podemos construir arquivos com dados específicos do node.

outros

Dependendo de como for usar o Puppet, muitos outros arquivos e diretórios serão criados nessa estrutura, vai depender de cada cenário e implementação.

puppetagent

vamos presumir que você já configurou o master perfeitamente, agora vamos então para a configuração do agent.

instalando agent

após ter configurado o repositório, execute:

aptitude update
aptitude install puppet

habilitando o puppet

Durante a instalação do puppet, recebemos a seguinte mensagem

puppet not configured to start, please edit /etc/default/puppet to enable

Para habilitar o puppet, edite o arquivo

root@puppetagent:~# vim /etc/default/puppet

E mude o valor da variável START para YES.

START=yes

Reinicie o puppet agent

root@puppetagent:~# /etc/init.d/puppet restart
Restarting puppet agent.

acessando puppetmaster

o agente vai procurar sempre o puppetmaster através do nome puppet ou puppet.dominio

via dns

se possível crie um registro de DNS tipo A com o nome puppet apontando para máquina puppetmaster , se não for possível registro do tipo A, faça um registro do tipo CNAME.

via hosts

caso a configuração de DNS não seja uma opção, uma forma de resolver é inserir uma entrada no /etc/hosts

192.168.17.131 puppet puppet.dominio

isso será suficiente para o agente funcionar, coloque o ip do seu puppetmaster

via puppet.conf

se ainda não for uma opção, pode ainda editar o arquivo /etc/puppet.conf e inserir a diretiva

server=nomedoservidor

na seção [agent], mas prefira a configuração de DNS dentre as 3 opções.

estrutura agent

Quando instalamos o agente, ele nos traz o seguintes arquivos e diretórios dentro de /etc/puppet.

drwxr-xr-x 2 root root 4096 Aug 27 19:11 manifests
drwxr-xr-x 2 root root 4096 Aug 27 19:11 modules
-rw-r--r-- 1 root root  364 Aug 27 17:35 puppet.conf
drwxr-xr-x 2 root root 4096 Aug 27 19:11 templates

Basicamente tem as mesmas funções descritas na estrutura do master, porém não são utilizadas no modo cliente/servidor uma vez que os agentes buscam as configurações no puppetmaster.

primeiro contato

aqui vamos apresentar o primeiro contato entre o puppetmaster e o puppetagent, no agente rode o comando abaixo:

root@puppetagent:~# puppet agent --test

a saída será similar a esta.

info: Creating a new SSL key for puppetagent.hacklab
info: Caching certificate for ca
info: Creating a new SSL certificate request for puppetagent.hacklab
info: Certificate Request fingerprint (md5): D6:17:3E:B6:D9:43:DB:08:F7:F1:53:38:3B:A9:21:49
Exiting; no certificate found and waitforcert is disabled 

observe que ao rodar o agent ele gerou um certificado digital e depois gerou uma requisição de assinatura do certificado e parou por ali pois ainda não está devidamente autorizado a utilizar recursos do puppetmaster.

é importante ressaltar que ele só gerou essa saída pois encontrou o servidor puppet graças ao ajuste no /etc/hosts, portanto fique atento as configurações de DNS ou do HOSTS.

certificados

a comunicação entre agente e master (cliente/servidor) é feita por uma relação de confiança estabelecida através de certificado digital, nenhum servidor com puppetagent pode utilizar os recursos do servidor puppetmaster se este não for explicitamente autorizado.

a autorização funciona da seguinte forma:

  • ao rodar o agente pela primeira vez em um servidor com puppetagent este vai gerar uma certificado e uma requisição de assinatura de certificado.
    1. esta requisição será enviada para o servidor puppetmaster, lá deveremos verificar quais as requisições de assinatura de certificado estão pendentes, e se for o caso, assiná-las.
    2. a partir do momento que forem assinadas o servidor puppetagent estará apto a se comunicar com o servidor puppetmaster, estando então devidamente autorizado a buscar seu 'catálogo' de configurações.
    3. no servidor puppetmaster - por sua vez, você poderá declarar as configurações para o servidor com o puppetagent.

    assinando certificados

para verificar certificados com pendência de assinaturas rode o comando abaixo no puppetmaster

root@puppetmaster:~# puppet cert --list
"puppetagent.hacklab" (D6:17:3E:B6:D9:43:DB:08:F7:F1:53:38:3B:A9:21:49)  

se este for um servidor legítimo, autorizado a utilizar o puppetmaster, assine o certificado com o comando:

root@puppetmaster:~# puppet cert --sign puppetagent.hacklab
notice: Signed certificate request for puppetagent.hacklab

para verificar todos servidores com puppetagent devidamente autorizados rode o comando:

root@puppetmaster:~# puppet cert --list --all
+ "puppetagent.hacklab"  (E9:17:9E:AD:ED:0E:4F:90:9D:6E:A9:46:A1:C6:59:07)
+ "puppetmaster.hacklab" (80:A0:C1:89:3B:26:A8:45:F6:12:8D:39:70:E9:C1:D9)

para remover a autorização de um servidor rode

puppet:/etc/puppet/manifests# puppet cert --clean nomedoservidor

conferindo resultado

após assinar o certificado, autorizando o puppetagent a utilizar o puppetmaster, vamos rodar novamente o comando e avaliar a saída

root@puppetagent:~# puppet agent --test

saída

info: Caching catalog for puppetagent.hacklab
info: Applying configuration version '1347304611'
notice: Finished catalog run in 0.11 seconds

perceba que agora ele conseguiu se comunicar com o servidor perfeitamente, apesar de não ter feito muita coisa, ainda, afinal ainda não declaramos nenhum tipo de configuração para o servidor puppetagent.

vale lembrar que além do controle de quem pode ou não usar os recursos do puppetmaster, o certificado também serve para estabelecer uma conexão segura (SSL) entre puppetagent e puppetmaster, protegendo assim toda a comunicação que ocorre entre eles.

empurrando configurações

vamos empurrar uma configuração bem simples, vamos instalar o pacote ntp e declarar que ele deve estar rodando.

para isto eu preciso declarar o node (servidor com puppet agent) e declarar uma classe com as configurações para o ntp.

vamos aprender a declarar cada uma a seguir.

declarando node

a declaração de node é bastante simples, você declara o nome do node e suas configurações em blocos.

node "nome.dominio" {
 
     bloco de configurações
 
}

veja o exemplo abaixo em que delcaro um pacote e um serviço.

node "nome.dominio" {
 
	package { 'ntp':
		ensure => present,
	}
 
	service { 'ntp':
		ensure     => running,
	}
}

podemos declarar também classes e módulos ao invés de colocar a configuração diretamente, veremos isto mais a frente.

arquivo site.pp

Agora precisamos juntar essas duas configurações em um arquivo chamado site.pp , o qual é o arquivo que o puppet vai buscar dentro de manifests sempre que um agent solicitar suas configurações.

vamos acessar o diretório

cd /etc/puppet/manifests

agora vamos criar um arquivo chamado site.pp

vim site.pp

e dentro dele colocar as duas configurações mencionadas acima

/etc/puppet/manifests/site.pp
node "nome.dominio" {
 
	package { 'ntp':
		ensure => present,
	}
 
	service { 'ntp':
		ensure     => running,
	}
}

bacana, agora só falta aplicar lá no servidor puppetagent

aplicando configurações

vamos rodar novamente o puppet para verificar se tem alguma configuração a ser aplicada

puppetagent:/etc/puppet/manifests# puppet agent --test
info: Caching catalog for puppetagent
info: Applying configuration version '1337190190'
notice: /Stage[main]/Ntpd/Package[ntp]/ensure: ensure changed 'purged' to 'present'
notice: Finished catalog run in 7.22 seconds

agora vamos observar, o puppetagent se conectou ao puppetmaster, informou suas configurações atuais, recebeu o catálogo do servidor, comparou e aplicou as mudanças necessárias, com isto o pacote ntp foi instalado, veja a mensagem abaixo:

notice: /Stage[main]/Ntpd/Package[ntp]/ensure: ensure changed 'purged' to 'present'
notice: Finished catalog run in 7.22 seconds

podemos verificar via dpkg se realmente foi insalado

puppetagent:~# dpkg --list|grep ntp
ii  ntp                                1:4.2.6.p2+dfsg-1+b1         Network Time Protocol daemon and utility programs

e podemos verificar via invoke se o processo está rodando, conforme declaramos

puppetagent:~# invoke-rc.d ntp status
NTP server is running.

dá para ver que a configuração declarada foi aplicada com sucesso.

modificações no ambiente

vamos agora por o puppet a prova, para isto basta modificarmos o estado do sistema, assim poderemos avaliar se o puppet vai conseguir detectar e corrigir a mudança que nós fizemos.

desligando o ntp

vou desligar o ntp para verificar se o puppet vai ligá-lo.

puppetagent:~# invoke-rc.d ntp stop
Stopping NTP server: ntpd.

o puppet roda por padrão a cada 30 minutos, mas vamos rodar o agente manualmente para testar seu comportamento

puppetagent:~# puppet agent --test
info: Caching catalog for puppetagent
info: Applying configuration version '1337190353'
notice: /Stage[main]/Ntpd/Service[ntp]/ensure: ensure changed 'stopped' to 'running'
notice: Finished catalog run in 0.26 seconds

bacana, o puppet viu que o serviço estava parado e como declaremos que ele deve estar sempre rodando, ele mudou o estado do serviço para 'running'.

removendo o pacote

agora vamos fazer um novo teste, vamos remover o pacote ntp e ver como puppet vai lidar com isto

puppetagent:~# aptitude purge ntp

The following packages will be REMOVED:  
  libopts25{u} ntp{p} 
0 packages upgraded, 0 newly installed, 2 to remove and 1 not upgraded.
Need to get 0 B of archives. After unpacking 1290 kB will be freed.
Do you want to continue? [Y/n/?] y
(Reading database ... 31882 files and directories currently installed.)
Removing ntp ...
Stopping NTP server: ntpd. 
Purging configuration files for ntp ...
Processing triggers for man-db ...
(Reading database ... 31848 files and directories currently installed.)
Removing libopts25 ...

após remover o pacote, vamos rodar o puppet manualmente

puppetagent:/etc/puppet# puppet agent --test  
info: Caching catalog for puppetagent
info: Applying configuration version '1337190353'
notice: /Stage[main]/Ntpd/Package[ntp]/ensure: ensure changed 'purged' to 'present'
notice: Finished catalog run in 2.62 seconds

bacana, o puppet percebeu que o pacote não está presente, e como declaramos que ele deve estar instalado e rodando, ele instalou o pacote novamente.

organizando master

Neste ponto você provavelmente já passou por todos os exemplos da wiki Puppet Serverless, já fez a instalação do puppetmaster e empurrou uma configuração simples para uma máquina com o agente, fechando então o entendimento do conceito autônomo e master/agente.

Agora vamos focar na organização dos arquivos e diretórios do puppetmaster para funcionamento em um ambiente produtivo, vou repassar algumas dicas de organização da estrutura de configuração que aprendi na EBC com o @dcsobral, esta estrutura é bem eficiente e fácil de administrar - na minha opinião.

diretório /etc/puppet

diretório files

Vamos criar o diretório files em /etc/puppet, ele será utilizado para armazenar os arquivos que devem ser distribuídos para os nodes.

cd /etc/puppet
mkdir files

arquivo fileserver.conf

Vamos editar o arquivo fileserver.conf e permitir que as máquinas de nossa rede acessem o diretório files e módules.

Aqui estou trabalhando com o domínio hacklab e rede 192.168.17.0/24, veja o arquivo abaixo:

/etc/puppet/fileserver.pp
# This file consists of arbitrarily named sections/modules
# defining where files are served from and to whom
 
# Define a section 'files'
# Adapt the allow/deny settings to your needs. Order
# for allow/deny does not matter, allow always takes precedence
# over deny
[files]
  path /etc/puppet/files
  allow *.hacklab
  deny *.evil
  allow_ip 192.168.17.0/24
 
[modules]
  path /etc/puppet/modules
  allow *.hacklb
  deny *.evil
  allow_ip 192.168.17.0/24

Com estas configurações nossos nodes estarão aptos a solicitar e receber arquivos do master.

diretório /etc/puppet/manifests

Vamos criar aqui alguns arquivos e diretórios, acompanhe.

diretório classes

As classes simples e genéricas eu costumo colocar dentro do diretório /etc/puppet/manifests/classes, pois fica fácil de encontrar e modificar, quando uma classe começa a crescer e se tornar mais complexa prefiro criar um módulo com seu ecossistema independente lá no diretório /etc/puppet/modules, vai depender de cada caso.

Criando o diretório classes

cd /etc/puppet/manifests
mkdir nodes
cd nodes

exemplos

hosts.pp

Abaixo um exemplo de classe simples se genérica, crie um arquivo chamado hosts.pp em /etc/puppet/manifests/classes com o conteúdo abaixo:

/etc/puppet/manifests/classes/hosts.pp
class hosts {
 
     # declarando arquivo hosts
 
     file { '/etc/hosts':
        ensure => present,
        owner  => 'root',
        group  => 'root',
        mode   => 644,
    }
 
    # declarando entrada fqdn no arquivo hosts
 
    host { "$fqdn":
        ensure       => present,
        ip           => "$ipaddress",
	host_aliases => "$hostname",
        require      => File['/etc/hosts'],
    }
 
    # declarando entrada puppet no arquivo hosts
 
    host { 'bacula':
	ensure       => present,
        ip           =>  '10.196.8.93',
        require => File['/etc/hosts'],
    }
 
    # declarando entrada zabbix no arquivo hosts
 
    host { 'zabbix':
	ensure       => present,
        ip           =>  '10.196.8.86',
        require => File['/etc/hosts'],
    }
 
    # servidor ntp
 
    host { 'ntp':
	ensure       => present,
        ip           =>  '10.192.32.32',
        require => File['/etc/hosts'],
    }
 
    # declarando entrada localhost no arquivo hosts
 
    host { 'localhost':
        ensure  => present,
        ip      => '127.0.0.1',
        require => File['/etc/hosts'],
    }
 
}

Cuidado ao aplicar esse manifests em seu puppetmaster, caso você tenha colocado a entrada puppet no /etc/hosts e não no DNS, esse manifests provavelmente irá substituir a linha, prefira usar isso nos nodes.

utils.pp

Outro exemplo, vamos criar o arquivo utils.pp no diretório /etc/puppet/manifests/classes com o conteúdo abaixo:

/etc/puppet/manifests/classes/util.pp
class utils { 
 
	# declarando que o tzdata tem que estar sempre em sua ultima versao
 
	package { 'tzdata': ensure => latest }
 
	# declarando que os seguintes pacotes devem estar presentes (sysadmin packages)
 
	package { [ 'screen',
		'lynx',
		'elinks',
		'rsync',
		'telnet',
		'ftp',
		'wget',
		'bzip2',
		'unzip',
		'traceroute',
		'tcpdump',
		'iptraf',
                'ccze',
                'htop',
		'less',
                'dnsutis',
		'nmap', ]:
		ensure  => installed,
	}
 
}
linux-server.pp

Outro exemplo, vamos criar o arquivo linux-server.pp, esse arquivo vai conter a classe base para todas os servidores linux, é ela que fará o papel de padronização destes nodes, essa classe é simples, nela vamos agrupar algumas classes chave.

Crie o arquivo linux-server.pp em /etc/puppet/manifests/classes com o conteúdo abaixo

/etc/puppet/manifests/classes/linux-server.pp
class linux-server {
 
        include hosts
        include utils
 
        # outros exemplos para o futuro
 
        # include aptrepos
        # include vimeditor
        # include ntp
        # include locale
        # include timezone
        # include users
        # include suoders
        # include ssh:server
        # include snmp::server
        # include zabbix::agent
        # include puppet::agent
        # include bacula::agent
        # include localmta::postfix
}
 

Veja que incluímos apenas as duas classes que criamos e o resto está comentado.

A diretiva include dentro de uma classe especifica o carregamento de uma outra classe.

diretório nodes

Eu prefiro colocar os arquivos com os nodes em um diretório separado, para isto eu crio o diretório nodes e dentro dele eu crio vários arquivos, normalmente agrupo os nodes por contextos.

Criando o diretório nodes

cd /etc/puppet/manifests
mkdir nodes
cd nodes

Criando um arquivo para o puppetagent e puppetmaster e declarando suas configurações.

node "puppetmaster" {
 
        include linux-server
        package { 'vim': ensure => present }
 
}
 
 
node "puppetagent" {
 
        include linux-server
        package { 'vim': ensure => present }
 
}

contextos

Agora veja alguns exemplo de arquivos por contexto

apache.pp

Arquivo apache.pp agrupando servidores com este contexto:

/etc/puppet/manifests/nodes/apache.pp
node "apache01.dominio" {
   include apache2
   include php5
   include aplicacao
}
node "apache02.dominio" {
   include apache2
   include php5
   include aplicacao
}
node "apache03.dominio" {
   include apache2
   include php5
   include aplicacao
}
haproxy.pp

Arquivo haproxy.pp agrupando servidores com este contexto.

/etc/puppet/manifests/nodes/haproxy.pp
node "haproxy01.dominio" {
   include haproxy
   include haproxy:poolphp
}
node "haproxy02.dominio" {
   include haproxy
   include haproxy:poolphp
}

Fica ao seu critério criar um arquivo por servidor, usar contextos como o exemplo acima, o importante é criar uma estrutura em que fique fácil para sua equipe encontrar e modificar as configurações de um ou vários nodes.

diretório definitions

Este diretório servirá para carregar alguma definition que seja de natureza global, deixe ele criado, em uma próxima wiki vou abordar isto.

arquivo globals.pp

Normalmente existem algumas configurações que são mais genéricas ou globais, para isto vamos criar um arquivo chamado globals.pp em /etc/puppet/manifests e inserir o conteúdo abaixo:

/etc/puppet/manifests/globals.pp
# definindo provedores para alguns sistemas
 
case $operatingsystem {
    'Debian': {
        Package { provider => 'aptitude' }
    }
    'RedHat': {
        case $operatingsystemrelease {
            '4'    : {
                Package { provider => 'up2date' }
            }
        }
    }
}
 
# Definindo configurações do filebucket
 
filebucket { 'main':
  server => puppet,
  path   => false,
  # Due to a known issue, path must be set to false for remote filebuckets.
}
 
# Especificando o target default do filebucket
# Aqui declaro que os nodes devem arquivar os arquivos modificados no puppetmaster.
 
File { backup => main }

O arquivo é simples e direto, nele especifiquei qual o gerenciador de pacote que e desejo que o puppet use em Debian e em RHEL 4.0, além disto também declarei como deve funcionar o filebucket nos nodes.

arquivo modules.pp

Os módulos do Puppet ficam localizados por default em /etc/puppet/modules, porém precisamos carregá-los de forma explícita, eu tenho muitos módulos, mas nem todos estão sendo utilizados, para dizer qual módulo deve ser carregado eu uso o arquivo modulos.pp em /etc/puppet/manifests e dentro dele especifico quais os módulos que desejo utilizar.

Crie o arquivo e inseria o conteúdo abaixo:

/etc/puppet/manifests/modules.pp
# exemplos
# import "ssh"
# import "users"
# import "locales"
# import "vim"
# import "postfix"
# import "puppet"
# import "ntp"
# import "yum"
# import "zabbix-agent"
# import "expressolivre"
# import "snmp"

Não preciso especificar o PATH para chegar nos modules pois isto já é default no puppet, ele vai procurar em /etc/puppet/modules.

No momento não temos nenhum módulo criado, logo a frente veremos isto.

arquivo site.pp

Dentro do diretório /etc/puppet/manifests precisamos ter o arquivo site.pp, ele é o arquivo principal a ser carregado no puppetmaster.

Agora que criamos uma nova estrutura de arquivos e diretórios dentro de /etc/puppet/manifests, precisamos então declarar estas mudanças no arquivo site.pp, veja como ficará nosso arquivo com a estrutura que construímos:

/etc/puppet/manifest/site.pp
import "globals.pp"         # Global variables
import "classes/*.pp"       # Site-specific classes
import "nodes/*.pp"         # Node files
 
# ainda sem uso
#import "modules.pp"         # Modules
#import "definitions/*.pp"   # Site-specific classes

Poderia ainda declarar uma classe genérica para todos os nós, no mesmo arquivo, vide exemplo:

node default {
    include linux-server  
}

Isso fica a seu critério, eu prefiro não usar esse configuração node default.

Vale ainda lembrar que o site.pp é de fato o único arquivo obrigatório dentro de /etc/puppet/manifests, o resto depende apenas do sysadmin, organize da forma que achar mais adequado.

O import é um recurso que pode ser utilizado no site.pp e no init.pp para fazermos o carregamento de manifests com classes e definições.

Só declare um diretório caso exista arquivos *.pp dentro dele, do contrário o puppet vai reclamar.

trabalhando com classes

conceito

Lá na Wiki Puppet Autônomo nós vimos a definição simples de uma classe, vamos relembrar.

No puppet as classes são coleções de recursos que podem ser aplicadas a um node.
  
Uma classe contém blocos de códigos - configurações puppet - que podem ser ligados ou desligadas 
conforme demanda.
  
Pense que uma classe pode agrupar diversos recursos parametrizados para executar uma configuração. 
  
Podemos criar uma classe chamada postfix que vai agrupar recursos para instalar o pacote postfix, 
empurrar os arquivos de configuração main.cf e master.cf e definir aspectos e funcionamento 
do daemon do postfix (master), e com a classe pronta, podemos aplicá-la a um node.

exemplo de classe

Vamos a um exemplo de classe simples, seguindo a metodologia TRIO (pacote + arquivo + serviço) que nós vimos na wiki Puppet Autônomo, neste exemplo vou abordar o POSTFIX.

class postfix {
 
	# declarando pacote postfix
 
	package { "postfix":
		ensure => present,
	}
 
        # declarando arquivo de configuração main.cf
 
	file { '/etc/postfix/main.cf':
		ensure  => present,
		source  => "/root/puppet/examples/postfix/main.cf",
		notify  => Service["postfix"],
		require => Package["postfix"],
	}
 
        # declarando serviço postfix
 
	service { "postfix":
		ensure     => running,
		enable     => true,
		hasrestart => true,
		hasstatus  => true,
		require    => Package['postfix'],
	}
 
}

Observe uma classe montada da forma como aprendemos, método trio, simples e direta, porém veja a forma como nós aprendemos a empurrar um arquivo

source  => "/root/puppet/examples/postfix/main.cf",

Quando estávamos construindo manifests localmente, bastava definir o arquivo de origem com um PATH absoluto, porém no modo cliente/servidor isso não vai funcionar, afinal esse arquivo não vai existir no servidor onde está rodando o puppet agent, ele só existe no puppetmaster, portanto temos de declarar esse arquivo de outro jeito, vamos aprender como fazer agora.

empurrando arquivos

Vimos no exemplo de classe a seguinte forma de empurrar arquivos

source  => "/root/puppet/examples/postfix/main.cf",

Para adaptar isto ao modo cliente/servidor, vamos colocar esse arquivo main.cf no diretório /etc/puppet/files, podemos criar um subdiretório postfix lá, ficando /etc/puppet/files/postfix e vamos declarar o arquivo da seguinte forma:

source  => "puppet:///files/postfix/main.cf",

Veja que files é o diretório /etc/puppet/files, postfix é o subdiretório e main.cf o arquivo que está dentro deste subdiretório, a configuração completa ficaria assim:

/etc/puppet/manifests/classes/postfix.pp
class postfix {
 
	# declarando pacote postfix
 
	package { "postfix":
		ensure => present,
	}
 
        # declarando arquivo de configuração main.cf
 
	file { '/etc/postfix/main.cf':
		ensure  => present,
                source  => "puppet:///files/postfix/main.cf",
		notify  => Service["postfix"],
		require => Package["postfix"],
	}
 
        # declarando serviço postfix
 
	service { "postfix":
		ensure     => running,
		enable     => true,
		hasrestart => true,
		hasstatus  => true,
		require    => Package['postfix'],
	}
 
}

Bacana, agora conseguimos empurrar o arquivo do servidor puppet para o node de forma elegante.

Lembre-se de ajustar o arquivo /etc/puppet/fileserver.conf para permitir que seu node ou sua rede consiga acessar esses arquivos.

declarando classes

Após criarmos a classe postfix em /etc/puppet/manifests/classes/postfix.pp vamos declarar esse classe no node.

Lembrando que criarmos um diretório /etc/puppet/manifest/nodes, vamos criar entao um manifest lá dentro chamado mailserver.pp com o conteúdo abaixo:

/etc/puppet/manifests/nodes/mailserver.pp
node "smtp01.dominio" {
     include postfix
}

Pronto, isto é suficiente para que o node smtp01.dominio receba as configuracões do manifest postfix.pp.

trabalhando com módulos

conceitos

Na wiki Puppet Autônomo nós já vimos como funcionam os módulos, vamos relembrar e vamos entender como empurrar arquivos via módulos.

entendendo a estrutura

Para entender a estrutura de um módulos veja o diagrama abaixo

CorSignificado
Azul Diretório Principal
Verde Sub-diretórios Default do Puppet
Roxo Sub-diretório sugestão
Vermelho Manifest init.pp arquivo obrigatório em todos os módulos

directory: module

Você vai substituir o nome module pelo nome do seu módulo, por exemplo apache.

directory: manifests

Contém todos os manifests do módulo e o arquivo init.pp, obrigatório.

file: init.pp

É o arquivo em que declaramos nossa classe principal, ela deve ter o mesmo nome do módulo. Esse é o manifest default de carregamento do seu módulo.

directory: files

Aqui colocamos os arquivos que serão usados e referenciados pelas classes e definições

directory: templates

Aqui colocamos os templates que serão usados pelas classes e definições

directory: lib

Este diretório conterá plugins, podem ser fatos (facts) ou tipos de recursos (resource tyes) criados por você.

criando estrutura

Vou transformar a classe Postfix em um módulo, vamos lá.

mão na massa

Acesse do diretório do puppet

cd /etc/puppet

Acesse o diretório de módulos

cd modules

Crie o diretório para seu módulo

mkdir postfix

Acesse o diretório do módulo

cd postfix

Crie o diretório manifests

mkdir manifests

Crie o diretório manifests

mkdir templates

Crie o diretório manifests

mkdir lib

Crie o diretório manifests

mkdir files

Acesse o diretório manifests

cd manifests

Crie o diretório classes

mkdir classes

Crie o diretório definitions

mkdir definitions

Acesse o diretório classes

cd classes

exemplo de módulo

Agora vamos criar o arquivo postfix.pp dentro de /etc/puppet/modules/postfix/manifests/classes com o conteúdo abaixo:

class postfix {
 
	# declarando pacote postfix
 
	package { "postfix":
		ensure => present,
	}
 
        # declarando arquivo de configuração main.cf
 
	file { '/etc/postfix/main.cf':
		ensure  => present,
                source  => "puppet:///files/postfix/main.cf",
		notify  => Service["postfix"],
		require => Package["postfix"],
	}
 
        # declarando serviço postfix
 
	service { "postfix":
		ensure     => running,
		enable     => true,
		hasrestart => true,
		hasstatus  => true,
		require    => Package['postfix'],
	}
 
}

Crie o arquivo main.cf em /etc/puppet/modules/postfix/files

###
### Arquivo gerenciado pelo puppet, não altere localmente, as alterações serão desfeitas.
###

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no

append_dot_mydomain = no

readme_directory = no

smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

myhostname = puppetagent.hacklab
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = puppetagent.hacklab, localhost.hacklab, , localhost
relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command = procmail -a "$EXTENSION"
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all

O arquivo postfix.pp de /etc/puppet/manifests/classes deve ser apagado.

Apague também o diretório /etc/puppet/files/postfix.

Agora vamos editar o arquivo init.pp que fica em /etc/puppet/modules/postfix/manifests/init.pp e inserir o seguinte:

import classes/*.pp

Com isso estamos orientando o init.pp a carregar todas os manifests dentro do diretório classes, caso tenha uma definição, faz um importe também (import definitions/*.pp).

Legal agora no arquivo /etc/puppet/manifests/modules.pp você precisa colocar uma linha orientando o carregamento deste módulo, veja o exemplo abaixo:

include postfix

Beleza, com isso esse módulo já será carregado e suas classes podem ser aproveitadas pelos nodes.

empurrando arquivos

Se vocês perceberam, o diretório do módulo contém um subdiretório chamado files, porém a referência em nosso manifest postfix.pp está apontando para o /etc/puppet/files, veja abaixo:

source  => "puppet:///files/postfix/main.cf",

Agora vamos aprender a ajustar essa referência de origem, inicialmente mova o arquivo main.cf

mv /etc/puppet/files/postfix/main.cf /etc/puppet/modules/postfix/files/

Agora vamos ajustar a referência de origem

source  => "puppet:///modules/postfix/main.cf",

Veja que a referência muda de files para postfix que é o nome do módulo, simples assim, você pode trabalhar com subdiretórios também, caso prefira, pode criar um subdiretório em /etc/puppet/modules/postfix/files chamado confs, e mover o arquivo para lá, se fizer isso a referência mudaria para:

source  => "puppet:///modules/postfix/confs/main.cf",

Só isso.

declarando módulos

Apesar de termos criado um módulo, a referência permanece a mesma, afinal o nome da classe dentro do módulo é a mesma.

/etc/puppet/manifests/nodes/mailserver.pp
node "smtp01.dominio" {
     include postfix
}

testando

root@puppetagent:~# puppet agent --test

saída

root@puppetagent:~# puppet agent --test
Info: Retrieving plugin
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find class postfix for puppetagent.hacklab on node puppetagent.hacklab
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

se isso ocorreu, você não importou corretamente o módulo postfix no arquivo modules.pp, confira o arquivo e rode novamente.

root@puppetagent:~# puppet agent --test

saída

Info: Retrieving plugin
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find class postfix for puppetagent.hacklab on node puppetagent.hacklab
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

se isso ocorreu, você não importou o arquivo modules.pp no arquivo site.pp, confira o arquivo e rode novamente.

root@puppetagent:~# puppet agent --test

saída

/Stage[main]/Postfix/Package[postfix]/ensure: created
Error: /Stage[main]/Postfix/File[/etc/postfix/main.cf]: Could not evaluate: Error 400 on SERVER: Not authorized to call find on /file_metadata/postfix/main.cf Could not retrieve file metadata for puppet:///postfix/main.cf: Error 400 on SERVER: Not authorized to call find on /file_metadata/postfix/main.cf
/Stage[main]/Postfix/Service[postfix]: Dependency File[/etc/postfix/main.cf] has failures: true
Warning: /Stage[main]/Postfix/Service[postfix]: Skipping because of failed dependencies
Finished catalog run in 12.27 seconds

se isso ocorreu, provavelmente você não declarou o diretório modules no arquivo fileserver.conf, confira o arquivo, ajuste, reinicie o puppetmaster e rode o puppet novamente no agente.

root@puppetagent:~# puppet agent --test

saída

Info: Retrieving plugin
Info: Caching catalog for puppetagent.hacklab
Info: Applying configuration version '1349442855'
/Stage[main]/Postfix/Package[postfix]/ensure: ensure changed 'purged' to 'present'
/Stage[main]/Postfix/File[/etc/postfix/main.cf]/content: 
--- /etc/postfix/main.cf	2012-10-05 10:14:21.000000000 -0300
+++ /tmp/puppet-file20121005-6148-uh1kwk-0	2012-10-05 10:14:27.000000000 -0300
@@ -1,3 +1,7 @@
+###
+### Arquivo gerenciado pelo puppet, não altere localmente, as alterações serão desfeitas.
+###
+
 # See /usr/share/postfix/main.cf.dist for a commented, more complete version
 
 
root@puppetagent:~# puppet agent --test
Info: Retrieving plugin
Info: Caching catalog for puppetagent.hacklab
Info: Applying configuration version '1349442855'
/Stage[main]/Postfix/Package[postfix]/ensure: ensure changed 'purged' to 'present'
/Stage[main]/Postfix/File[/etc/postfix/main.cf]/content: 
--- /etc/postfix/main.cf	2012-10-05 10:14:21.000000000 -0300
+++ /tmp/puppet-file20121005-6148-uh1kwk-0	2012-10-05 10:14:27.000000000 -0300
@@ -1,3 +1,7 @@
+###
+### Arquivo gerenciado pelo puppet, não altere localmente, as alterações serão desfeitas.
+###
+
 # See /usr/share/postfix/main.cf.dist for a commented, more complete version
 
 
Info: /Stage[main]/Postfix/File[/etc/postfix/main.cf]: Filebucketed /etc/postfix/main.cf to main with sum a9b852b498950544c2ea8f63aa9cd3bd
/Stage[main]/Postfix/File[/etc/postfix/main.cf]/content: content changed '{md5}a9b852b498950544c2ea8f63aa9cd3bd' to '{md5}9d8f1c32d3a0674f0bd72b6692d97b04'
Info: /Stage[main]/Postfix/File[/etc/postfix/main.cf]: Scheduling refresh of Service[postfix]
/Stage[main]/Postfix/Service[postfix]: Triggered 'refresh' from 1 events
Finished catalog run in 17.21 seconds

Agora a configuração foi aplicada.

cases e exemplos

classe editor

requisitos

  • instalar o pacote vim
  • identificar o tipo de sistema operacional (Debian/Ubuntu ou RHEL/CENTOS)
  • empurrar arquivo vimrc de acordo com o OS
  • definir o nome do pacote vim de acordo com o OS
  • especificar que os arquivos devem ter permissão 664, owner root, group root.
  • especificar que os arquivos só devem ser empurrados se o pacote vim estiver instalado.
  • especificar que se for debian, após a instalação do pacote deve-se definir que o vim é o editor padrão
  • só deve-se definir vim como editor padrão caso o editor padrão seja outro

    código

De posse dos requisitos, vamos usar a DSL do puppet para criar uma solução.

Eu criei um arquivo com nome editor.pp em /etc/puppet/manifests/classes para escrever a solução proposta.

class editor {
 
      # detectando o sistema operacional para
      # definir algumas variaveis
 
      case $operatingsystem {
                CentOS,RedHat: {
                        $vim        = 'vim-enhanced'
                        $vimpath    = '/etc'
                        $vimfile    = 'vimrc.el'
                }
                Debian,Ubuntu: {
                        $vim        = 'vim'
                        $vimpath    = '/etc/vim'
                        $vimfile    = 'vimrc.debian'
                }
        }
 
    # declarando o pacote
 
    package { "$vim":
        ensure => present,
        alias  => 'vim',
    }
 
    # declarando o arquivo de configuracao
 
    file { "$vimpath/vimrc":
        ensure  => present,
	source  => "puppet:///files/vim/$vimfile",
        owner   => "root",
        group   => "root",
        mode    => "644",
	require => Package["$vim"],
    }
 
    # caso seja debian/ubuntu rodo o update-alternatives
    # para definir vim como editor padrao do sistema
 
    case $operatingsystem {
       'Debian', 'Ubuntu': {
            exec { "update-alternatives --set editor /usr/bin/vim.basic":
                path    => "/usr/bin:/usr/sbin:/bin",
                unless  => "test /etc/alternatives/editor -ef /usr/bin/vim.basic",
		require => Package["$vim"],
            }
        }
    }
}

Esta solução atende a todos os requisitos.

Não se esqueça de criar os arquivos vimrc.rhel e vimrc.debian dentro de files/vim.

teste

declarar essa classe para o puppetagent

node "puppetagent.hacklab" {
   include editor
 }

e vamos executar o puppet

root@puppetagent:~# puppet agent --test

saída

  root@puppetagent:/etc/puppet/manifests/classes# puppet agent --test
  info: Caching catalog for puppetmaster.hacklab
  info: Applying configuration version '1348692464'
  notice: /Stage[main]/Editor/Package[vim]/ensure: ensure changed 'purged' to 'present'
  notice: /Stage[main]/Editor/File[/etc/vim/vimrc]/ensure: defined content as    '{md5}6761ffa9ad48e24126b5ae7cd54f7577'
  notice: /Stage[main]/Editor/Exec[update-alternatives --set editor /usr/bin/vim.basic]/returns: executed successfully
  notice: Finished catalog run in 3.24 seconds

vamos verificar se o pacote foi instalado

root@puppetagent:~# dpkg --list |grep vim
ii  vim                                 2:7.2.445+hg~cb94c42c0e1a-1  Vi IMproved - enhanced vi editor

agora vamos verificar as permissões dos arquivos

root@puppetagent:~# ls -lah /etc/vim/vimrc
-rw-r--r-- 1 root root 2.2K Sep 26 17:48 /etc/vim/vimrc

analisando a saída e as verificações, pudemos ver que ele instalou o vim, empurrou o arquivo vimrc com as devidas permissões e rodou o update-alternatives, processando o manifest que fizemos com precisão.

classe snmpd

requisitos

  • Instalar o pacote snmpd
  • Tratar o tipo de sistema operacional (Debian ou Ubuntu) e especificar o nome correto do pacote
  • Empurrar o arquivo snmpd.conf
  • Empurrar o arquivo snmptrapd.conf
  • Empurrar o arquivo snmpd (/etc/default)
  • Os arquivos devem ter permissão 664, owner root, group root.
  • Os arquivos só devem ser empurrados se o pacote snmpd estiver instalado.
  • Quando o arquivo for criado ou modificado ele deve reiniciar o servidor snmpd.
  • O node deve sempre procurar arquivo.nomedonode primeiro e depois ir para o arquivo default
  • O serviço snmpd deve estar rodando e ativado no boot
  • O controle do serviço snmpd depende do pacote snmpd e dos arquivos snmpd.conf, snmpd e snmptrapd.conf

código

De posse dos requisitos, vamos usar a DSL do puppet para criar uma solução.

Eu criei um arquivo com nome snmpd.pp em /etc/puppet/manifests/classes para escrever a solução proposta.

/etc/puppet/manifests/classes/snmpd.pp
class snmpd {
 
    $snmp = $operatingsystem ? {
        'Debian' => 'snmpd',
        'Ubuntu' => 'snmpd',
        default  => 'net-snmp',
    }
 
    package { "$snmp":
        ensure => present,
        alias  => 'snmpd',
    }
 
    file { '/etc/snmp/snmpd.conf':
        ensure  => present,
        owner   => 'root',
        group   => 'root',
        mode    => 644,
        source  => [
                   "puppet:///files/snmp/snmpd.conf.$fqdn",
                   "puppet:///files/snmp/snmpd.conf",
                   ],
        alias   => 'configuracao-snmpd',
        require => Package['snmpd'],
        notify  => Service['snmpd'],
    }
 
    file { '/etc/default/snmpd':
        ensure  => present,
        owner   => 'root',
        group   => 'root',
        mode    => 644,
        source  => [ 
                   "puppet:///files/snmp/snmpd.$fqdn",
                   "puppet:///files/snmp/snmpd",
                   ],
        alias   => 'configuracao-default-snmpd',
        require => Package['snmpd'],
        notify  => Service['snmpd'],
    }
 
    file { '/etc/snmp/snmptrapd.conf':
        ensure  => present,
        owner   => 'root',
        group   => 'root',
        mode    => 644,
        source  => [ 
                   "puppet:///files/snmp/snmptrapd.conf.$fqdn",
                   "puppet:///files/snmp/snmptrapd.conf",
                   ],
        alias   => 'configuracao-snmptrap',
        require => Package['snmpd'],
        notify  => Service['snmpd'],
    }
 
     service { 'snmpd':
        ensure     => running,
        enable     => true,
        hasrestart => true,
        hasstatus  => false,
        require    => [
            Package['snmpd'],
            File['configuracao-snmpd'],
            File['configuracao-snmptrap'],
            File['configuracao-default-snmpd'],
        ],
    }
}

Esta solução atende a todos os requisitos.

Só falta colocar os arquivos em /etc/puppet/files/snmpd, não se esqueça disto.

teste

declarar essa classe para o puppetagent

  node "puppetagent.hacklab" {
     include snmpd
   }
  

e vamos executar o puppet

root@puppetagent:~# puppet agent --test

saída

info: Caching catalog for puppetagent.hacklab
info: Applying configuration version '1347637165'
notice: /Stage[main]/Snmpd/Package[snmpd]/ensure: ensure changed 'purged' to 'present'
notice: /Stage[main]/Snmpd/File[/etc/snmp/snmptrapd.conf]/content: 
--- /etc/snmp/snmptrapd.conf	2011-01-05 13:14:26.000000000 -0200
+++ /tmp/puppet-file20120914-3539-1vqnokg-0	2012-09-14 12:41:27.000000000 -0300
@@ -15,4 +15,3 @@
 #
 # PLEASE: read the snmptrapd.conf(5) manual page as well!
 #
-

info: /Stage[main]/Snmpd/File[/etc/snmp/snmptrapd.conf]: Filebucketed /etc/snmp/snmptrapd.conf to main with sum a2ee110581a5a9a1e2252400cb176bcc
notice: /Stage[main]/Snmpd/File[/etc/snmp/snmptrapd.conf]/content: content changed '{md5}a2ee110581a5a9a1e2252400cb176bcc' to '{md5}83cbb8f0006f532dfa33c739f8e5fed9'
notice: /Stage[main]/Snmpd/File[/etc/snmp/snmptrapd.conf]/mode: mode changed '0600' to '0644'
info: /Stage[main]/Snmpd/File[/etc/snmp/snmptrapd.conf]: Scheduling refresh of Service[snmpd]
info: /Stage[main]/Snmpd/File[/etc/snmp/snmptrapd.conf]: Scheduling refresh of Service[snmpd]
notice: /Stage[main]/Snmpd/File[/etc/snmp/snmpd.conf]/content: 
--- /etc/snmp/snmpd.conf	2011-01-05 13:14:26.000000000 -0200
+++ /tmp/puppet-file20120914-3539-wr4sm6-0	2012-09-14 12:41:27.000000000 -0300
@@ -1,3 +1,9 @@
+#
+# As the snmp packages come without MIB files due to license reasons, loading
+# of MIBs is disabled by default. If you added the MIBs you can reenable
+# loaging them by commenting out the following line.
+mibs :
+root@puppetagent:/etc/snmp# cat snmpd.conf 
 ###############################################################################
 #
 # EXAMPLE.conf:

info: /Stage[main]/Snmpd/File[/etc/snmp/snmpd.conf]: Filebucketed /etc/snmp/snmpd.conf to main with sum a5007383dd9c4ef73500e3df8c080665
notice: /Stage[main]/Snmpd/File[/etc/snmp/snmpd.conf]/content: content changed '{md5}a5007383dd9c4ef73500e3df8c080665' to '{md5}0b82a6f3eb9af14abb76168db25d1e62'
notice: /Stage[main]/Snmpd/File[/etc/snmp/snmpd.conf]/mode: mode changed '0600' to '0644'
info: /Stage[main]/Snmpd/File[/etc/snmp/snmpd.conf]: Scheduling refresh of Service[snmpd]
info: /Stage[main]/Snmpd/File[/etc/snmp/snmpd.conf]: Scheduling refresh of Service[snmpd]
notice: /Stage[main]/Snmpd/Service[snmpd]: Triggered 'refresh' from 4 events
notice: Finished catalog run in 18.82 seconds

vamos verificar se o pacote foi instalado

root@puppetagent:~# dpkg --list |grep snmpd
ii  snmpd                               5.4.3~dfsg-2                 SNMP (Simple Network Management Protocol) agents

agora vamos verificar as permissões dos arquivos

root@puppetagent:~# ls -lah /etc/default/snmpd /etc/snmp/snmpd.conf /etc/snmp/snmptrapd.conf
-rw-r--r-- 1 root root  723 Jan  5  2011 /etc/default/snmpd
-rw-r--r-- 1 root root 7.1K Sep 14 12:41 /etc/snmp/snmpd.conf
-rw-r--r-- 1 root root  678 Sep 14 12:41 /etc/snmp/snmptrapd.conf

e por último vamos verificar se o snmpd está rodando

root@puppetagent:~# /etc/init.d/snmpd status
snmpd is running.

perfeito.

modulo ntp

requisitos

  • Verificar se a distribuição é Debian, Ubuntu, RHEL ou CENTOS
  • Declarar as variáveis $packagename, $servicename e $conf_file de acordo com o SO
  • Instalar o pacote NTP
  • Empurrar o arquivo de configuração NTP
    • Só fazer isto se o pacote estiver instalado
    • O arquivo deve pertencer ao usuário root, grupo root e ter permissão 644
  • Declarar que o serviço NTP deve estar rodando e habilitado no boot
    • Só fazer isso se o pacote estiver instalado e se o arquivo de configuração estiver presente

mão-na-massa

crie o diretório ntp

mkdir ntp

entre no diretório

cd ntp

crie o subdir files

mkdir files

crie o subdir manifests

mkdir manifests

entre no subdir manifests

cd manifests

crie o subdir classes

mkdir classes

entre no subdir classes

cd classes

crie o arquivo ntp.pp

vim ntp.pp 

insira os seguinte conteúdo

class ntp {
 
	# tratando distribuições
 
  	case $operatingsystem {
        	CentOS,RedHat: { 
		  	$package_name = 'ntp'
	          	$service_name = 'ntpd'
	          	$conf_file    = 'ntp.conf.el'
		}
		Debian,Ubuntu: { 
			$package_name = 'ntp'
			$service_name = 'ntp'
			$conf_file    = 'ntp.conf.debian'
		}
	}
 
	# declarando o pacote
 
	package { "$package_name":
		ensure => present,
	}
 
        # declarando o arquivo de configuração
 
	file { '/etc/ntp.conf':
		ensure  => present,
		source  => "puppet:///ntp/${conf_file}",
		notify  => Service["$service_name"],
		require => Package["$package_name"],
	}
 
	# declarando o serviço
 
	service { "$service_name":
		ensure     => running,
		enable     => true,
		hasrestart => true,
		hasstatus  => true,
		require    => [ Package['ntp'], File['/etc/ntp.conf' ], ],
	}
 
}

salve o arquivo

:wq

retorne ao diretório manifests

cd ..

crie o arquivo init.pp

touch init.pp

edite arquivo

vim init.pp

Insira a linha abaixo

import "classes/*.pp"

Salve o arquivo

:wq

Crie os dois arquivos ntp.conf.el e ntp.conf.debian no diretório files. Fazendo isto nosso módulo está pronto para testarmos.

testando módulo

declare esse módulo em algum node

node xpto {
    include ntp
}

no node, execute o puppet

puppet agent --test

acompanhe a saída

info: Caching catalog for puppetmaster.hacklab
info: Applying configuration version '1349105440'
notice: /Stage[main]/Ntp/Package[ntp]/ensure: ensure changed 'purged' to 'present'
notice: /Stage[main]/Ntp/File[/etc/ntp.conf]/content: 
--- /etc/ntp.conf	2010-10-17 11:35:26.000000000 -0200
+++ /tmp/puppet-file20121001-2558-1l2emqx-0	2012-10-01 12:33:20.000000000 -0300
@@ -1,55 +1,16 @@
-# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help
-
 driftfile /var/lib/ntp/ntp.drift
-
-
-# Enable this if you want statistics to be logged.
-#statsdir /var/log/ntpstats/
-
 statistics loopstats peerstats clockstats
+
 filegen loopstats file loopstats type day enable
 filegen peerstats file peerstats type day enable
 filegen clockstats file clockstats type day enable
 
+server ntp.dominio iburst dynamic
 
-# You do need to talk to an NTP server or two (or three).
-#server ntp.your-provider.example
-
-# pool.ntp.org maps to about 1000 low-stratum NTP servers.  Your server will
-# pick a different set every time it starts up.  Please consider joining the
-# pool: <http://www.pool.ntp.org/join.html>
-server 0.debian.pool.ntp.org iburst
-server 1.debian.pool.ntp.org iburst
-server 2.debian.pool.ntp.org iburst
-server 3.debian.pool.ntp.org iburst
-
-
-# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for
-# details.  The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions>
-# might also be helpful.
-#
-# Note that "restrict" applies to both servers and clients, so a configuration
-# that might be intended to block requests from certain clients could also end
-# up blocking replies from your own upstream servers.
-
-# By default, exchange time with everybody, but don't allow configuration.
 restrict -4 default kod notrap nomodify nopeer noquery
 restrict -6 default kod notrap nomodify nopeer noquery
-
-# Local users may interrogate the ntp server more closely.
 restrict 127.0.0.1
 restrict ::1
 
-# Clients from this (example!) subnet have unlimited access, but only if
-# cryptographically authenticated.
-#restrict 192.168.123.0 mask 255.255.255.0 notrust
-
-
-# If you want to provide time to your local subnet, change the next line.
-# (Again, the address is an example only.)
-#broadcast 192.168.123.255
-
-# If you want to listen to time broadcasts on your local subnet, de-comment the
-# next lines.  Please do this only if you trust everybody on the network!
-#disable auth
-#broadcastclient
+disable kernel
+logfile   /var/log/ntp.log

info: /Stage[main]/Ntp/File[/etc/ntp.conf]: Filebucketed /etc/ntp.conf to main with sum 3e250ecaf470e1d3a2b68edd5de46bfd
notice: /Stage[main]/Ntp/File[/etc/ntp.conf]/content: content changed '{md5}3e250ecaf470e1d3a2b68edd5de46bfd' to '{md5}b54a36abe675e96723eb2e5562195c91'
info: /Stage[main]/Ntp/File[/etc/ntp.conf]: Scheduling refresh of Service[ntp]
notice: /Stage[main]/Ntp/Service[ntp]: Triggered 'refresh' from 1 events
notice: Finished catalog run in 16.80 seconds

vamos conferir se o pacote está instalado

root@puppetmaster:~# dpkg --list|grep ntp
ii  ntp                                 1:4.2.6.p2+dfsg-1+b1         Network Time Protocol daemon and utility programs

vamos conferir se o arquivo está com as permissões declaradas

root@puppetmaster:~# ls -la /etc/ntp.conf 
-rw-r--r-- 1 root root 446 Oct  1 12:33 /etc/ntp.conf

vamos conferir se o serviço está rodando

root@puppetmaster:~# /etc/init.d/ntp status
NTP server is running.
 

bacana, fez tudo que o foi delcarado, atendendo a todos os requisitos.

modulo postfix

escalando

problema

O puppetmaster vem um com servidor web embutido chamado webrick, ele funciona bem para ambientes com pouca complexidade e com até uns 25 nodes, qualquer coisa acima disto fica lento - eu particularmente cheguei até 70 nodes - e instável, em resumo o webrick não escala.

Quando eu falo de configurações pouco complexas, me refero a apenas padronizar os nodes com a classe linux-server, sem chegar ainda no nível de controle de serviços, neste caso, como mencionei, tive experiências com até 69 nodes rodando, mas é realmente o limite.

soluções

apache + passenger

Vamos mostrar como instalar o pacote puppetmaster-passenger, esse pacote instala o puppetmaster integrado ao apache2 usando o módulo passenger, ele escala e aguenta demanda graças ao apache, com ele já tivemos cerca de 250 nodes sendo atendidos satisfatóriamente e de forma simultânea.

Faça um bkp do suas configurações só por garantia

tar cvf /root/puppet-etc.tar /etc/puppet

Pronto, agora vamos remover o puppetmaster pois ele está rodando e ouvindo a mesma porta que o apache vai usar.

aptitude remove puppetmaster

Agora vamos instalar o puppetmaster-passenger

aptitude install puppetmaster-passenger

Você vai observar durante a instalação que houve a geração de um certificado.

...
Setting up puppetmaster-passenger (2.7.19-1puppetlabs2) ...
notice: Signed certificate request for ca
notice: Rebuilding inventory file
notice: puppetmaster.localdomain has a waiting certificate request
notice: Signed certificate request for puppetmaster.hacklab
notice: Removing file Puppet::SSL::CertificateRequest puppetmaster.localdomain at '/var/lib/puppet/ssl/ca/requests/puppetmaster.hacklab.pem'
notice: Removing file Puppet::SSL::CertificateRequest puppetmaster.localdomain at   

'/var/lib/puppet/ssl/certificate_requests/puppetmaster.localdomain.pem'

...

verificando módulos

verifique se os módulos passenger, ssl e headers estão habilitados, sem um deles não estiver ligado a aplicação não vai funcionar adequadamente.

puppetmaster:/etc/apache2/conf.d# a2enmod passenger
Module passenger already enabled

puppetmaster:/etc/apache2/conf.d# a2enmod ssl
Module ssl already enabled
  
puppetmaster:/etc/apache2/conf.d# a2enmod headers
Enabling module headers.
Run '/etc/init.d/apache2 restart' to activate new configuration! 

se necessário for, reinicie o apache2.

/etc/init.d/apache2 restart

configurações

Em suas configurações dentro de /etc/puppet nada muda

testando

Tem que estar funcionando perfeitamente

root@puppetagent:~# puppet agent --test

Saída

info: Caching catalog for puppetagent.hacklab
info: Applying configuration version '1347633654'
notice: Finished catalog run in 0.73 seconds

Beleza, está funcionando, agora você tem um ambiente que aguenta uma demanda bem maior graças ao apache2.

unicorn

em construção…

dicas

agrupando classes e modulos

Em alguns cenários a configuração de um node poderá incluir diversas classes e definições.

node "frontend01.dominio" {
 
	include linux-server
 
	include expresso::dns
	include expresso::rsyslog
	include expresso::aptrepo
 
	include apache::prefork
	include apache::service::expresso-prefork
 
	include apache::frontend
 
	include apache::libapache2-mod-fcgid
	include apache::libapache2-mod-php5
 
	include apache::enable-mod-rewrite
	include apache::enable-mod-fcgid
	include apache::enable-mod-php5
 
	include apache::php5
	include apache::php5-imap
	include apache::php5-gd
	include apache::php5-pgsql
	include apache::php5-ldap
	include apache::php5-memcache
	include apache::php5-xcache
	include apache::php5-suhosin
	include apache::php5-curl
	include apache::php5-cli
 
	include memcached::frontend
	include cyrus::frontend
	include sasl::frontend
	include pgbouncer::frontend
	include davical::frontend
 
	include aspell

Sugiro que seja criada uma classe em /etc/puppet/manifests/classes apenas para agrupar e organizar as configurações, isso vai nos permitir declarar apenas esta classe no node.

class expresso-frontend {
 
	include linux-server
 
	include expresso::dns
	include expresso::rsyslog
	include expresso::aptrepo
 
	include apache::prefork
	include apache::service::expresso-prefork
 
	include apache::frontend
 
	include apache::libapache2-mod-fcgid
	include apache::libapache2-mod-php5
 
	include apache::enable-mod-rewrite
	include apache::enable-mod-fcgid
	include apache::enable-mod-php5
 
	include apache::php5
	include apache::php5-imap
	include apache::php5-gd
	include apache::php5-pgsql
	include apache::php5-ldap
	include apache::php5-memcache
	include apache::php5-xcache
	include apache::php5-suhosin
	include apache::php5-curl
	include apache::php5-cli
 
	include memcached::frontend
	include cyrus::frontend
	include sasl::frontend
	include pgbouncer::frontend
	include davical::frontend
 
	include aspell
}

Ficaria algo assim.

node frontend01.dominio {
 
   include expresso-frontend
 
}

Bem mais limpo e organizado.

path para arquivos

limpando reports

Como o tempo o diretório /var/lib/puppet/reports vai ficando cheio de arquivos com o estado dos nodes, é um histórico que vai comer espaço em seu disco, podendo te causar um incidente por conta de disk full.

Para não correr esse risco eu criei uma classe bem simples que limpa os arquivos com idade maior que 2 semanas.

class cleanreports {
 
        tidy { "/var/lib/puppet/reports/":
                age     => "2w",
                matches => "*.yaml",
                recurse => true ,
        }
}

Importe essa classe no node puppetmaster e fique tranquilo.

node puppetmaster {
     include cleanreports
}

problemas conhecidos

nao encontrou o servidor

caso não tenha sido configurado o dns, host ou puppet.conf com o endereço do servidor puppet, provavelmente vai receber este erro.

root@puppetmaster:/etc/apt# puppet agent --test
err: Could not retrieve catalog from remote server: getaddrinfo: Name or service not known
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
err: Could not send report: getaddrinfo: Name or service not known

para corrigir isto veja as instruções em 'acessando master'.

não encontrou o node

Caso você rode

puppet agent --test

E o retorno seja esse abaixo

Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Could not find default node or by name with 'puppetmaster.hacklab, puppetmaster' on node puppetmaster.hacklab
Warning: Not using cache on failed catalog
Error: Could not retrieve catalog; skipping run

Significa que o node não foi declarado no puppet master, em algum lugar do site.pp você precisará declarar este node, veja o exemplo abaixo.

node "nomedonode.dominio" {

}

Rodando novamente o comando

puppet agent --test

Veja a saída

Info: Retrieving plugin
Info: Caching catalog for nomedonode.dominio
Info: Applying configuration version '1349436897'
Finished catalog run in 0.04 seconds

Agora funcionou.

erro no pacote puppetmaster-passenger

Se receber um erro como este durante a inicialização do apache2 com passenger

yntax error on line 3 of /etc/apache2/sites-enabled/puppetmaster:
Invalid command 'PassengerHighPerformance', perhaps misspelled or defined by a module not included in the server configuration
Action 'configtest' failed.
The Apache error log may have more information.
 failed!
invoke-rc.d: initscript apache2, action "restart" failed.
dpkg: error processing puppetmaster-passenger (--configure):
 subprocess installed post-installation script returned error exit status 1
Errors were encountered while processing:
 puppetmaster-passenger

Significa que por algum motivo o módulo passenger não foi habilitado, faça isso manualmente

a2enmode passenger

Após reinicie o apache2

/etc/init.d/apache2 restart

Saída

Restarting web server: apache2 ... waiting .  

Pronto, problema resolvido.

referências



puppetmaster.txt · Last modified: 2012/12/14 17:27 by gutocarvalho
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0