Using Stored Configuration

Version 13 (Nicolas Jungers, 09/24/2011 05:50 am)

1 1
# Using Stored Configurations
2 1
3 1
Puppet uses a technique called stored configuration, enabled with
4 1
the storeconfigs configuration option, to store data in a database.
5 1
This technique makes use of the Ruby on Rails framework and one of
6 12 Nick Fagerlund
three database back-ends: SQLite (the default; not suitable for production use), MySQL or
7 1
PostgreSQL. Additionally, a message queue can be used to improve a
8 1
puppetmaster's client response time. Currently stored
9 1
configurations are principally used by exported resources.
10 1
11 1
It is important to note that once a node is in the stored
12 1
configuration database it will not be automatically purged - even
13 1
if you remove the corresponding node from your configuration. If
14 1
you wish to purge nodes from your database you will need to do this
15 1
manually. There is a script in the ext directory that purges nodes
16 1
from stored configuration.
17 1
18 1
# Installing Prerequisites
19 1
20 1
To make use of stored configuration you will need to install some
21 1
prerequisites principally the database back-end you wish to use and
22 1
the Rails framework.
23 1
24 1
## Rails
25 1
26 1
**Puppet 0.24.8 and older**
27 1
28 1
Rails version 2.2.2 or earlier.
29 1
30 4 James Turnbull
**Puppet 0.25 and later**
31 1
32 1
Rails version 2.2.2 or greater.
33 1
34 5 Jeff McCune
**Warning**
35 5 Jeff McCune
36 5 Jeff McCune
Jeff McCune <jeff@puppetlabs.com>
37 5 Jeff McCune
2010-10-01
38 5 Jeff McCune
39 7 Jeff McCune
With Puppet version 0.25.5 and MySQL on Enterprise Linux 5 you must update the Active Record gem to version 2.3.5 in order to avoid the error:
40 1
41 7 Jeff McCune
    err: Could not retrieve catalog from remote server: Error 400 on SERVER: Mysql::
42 7 Jeff McCune
    Error: MySQL server has gone away: SELECT * FROM `hosts` WHERE (`hosts`.`name` =
43 7 Jeff McCune
     'foo.puppetlabs.lan')  LIMIT 1
44 7 Jeff McCune
    warning: Not using cache on failed catalog
45 7 Jeff McCune
    err: Could not retrieve catalog; skipping run
46 1
47 7 Jeff McCune
In order to update the gem to this specific version, it is possible to install the gem into the puppet home directory:
48 1
49 7 Jeff McCune
    sudo -H -E -u puppet -s
50 7 Jeff McCune
    bash-3.2$ gem install activerecord -v 2.3.5
51 7 Jeff McCune
    WARNING:  Installing to ~/.gem since /usr/lib/ruby/gems/1.8 and
52 7 Jeff McCune
              /usr/bin aren't both writable.
53 7 Jeff McCune
    WARNING:  You don't have /var/lib/puppet/.gem/ruby/1.8/bin in your PATH,
54 7 Jeff McCune
              gem executables will not run.
55 7 Jeff McCune
    Successfully installed activesupport-2.3.5
56 7 Jeff McCune
    Successfully installed activerecord-2.3.5
57 7 Jeff McCune
    2 gems installed
58 7 Jeff McCune
    Installing ri documentation for activesupport-2.3.5...
59 7 Jeff McCune
    Installing ri documentation for activerecord-2.3.5...
60 7 Jeff McCune
    Installing RDoc documentation for activesupport-2.3.5...
61 7 Jeff McCune
    Installing RDoc documentation for activerecord-2.3.5...
62 7 Jeff McCune
    bash-3.2$ gem list
63 7 Jeff McCune
    
64 7 Jeff McCune
    *** LOCAL GEMS ***
65 7 Jeff McCune
    
66 7 Jeff McCune
    actionmailer (2.2.2)
67 7 Jeff McCune
    actionpack (2.2.2)
68 7 Jeff McCune
    activerecord (2.3.5, 2.2.3, 2.2.2)
69 7 Jeff McCune
    activeresource (2.2.2)
70 7 Jeff McCune
    activesupport (2.3.5, 2.2.3, 2.2.2)
71 7 Jeff McCune
    fastthread (1.0.7)
72 7 Jeff McCune
    passenger (2.2.11)
73 7 Jeff McCune
    rack (1.0.1)
74 7 Jeff McCune
    rails (2.2.2)
75 7 Jeff McCune
    rake (0.8.7)
76 7 Jeff McCune
    sqlite3-ruby (1.2.4)
77 1
78 1
Reference: http://projects.puppetlabs.com/issues/4694
79 1
80 1
**Installation**
81 1
82 1
We start by installing the rails Ruby Gem, either with the
83 1
distribution's package management (e.g. Debian/Ubuntu have a
84 1
'rails' package) or as a ruby gem.
85 1
86 1
To ensure a specific version of rails (not the latest available
87 1
from RubyForge) specify the optional '-v' parameter with the
88 1
version number you wish to install:
89 6 Jeff McCune
90 7 Jeff McCune
    gem install rails -v 2.2.2
91 1
92 1
## MySQL
93 1
94 1
For MySQL you will need to install a number of packages. For Red
95 1
Hat/Fedora the typical packages required would be:
96 1
97 7 Jeff McCune
    mysql
98 7 Jeff McCune
    mysql-devel
99 7 Jeff McCune
    mysql-server
100 6 Jeff McCune
101 1
Or for Debian/Ubuntu you would need the following packages.
102 1
libmysql-ruby provides the mysql gem, so installing via gems is
103 1
unneccesary:
104 1
105 7 Jeff McCune
    mysql-server
106 7 Jeff McCune
    libmysql-ruby
107 1
108 1
You may also need to install the mysql Ruby Gem (not required on
109 1
Debian/Ubuntu). You may need to specify the --with-mysql-config
110 1
option to tell Gems where to find your MySQL libraries and
111 1
headers:
112 1
113 7 Jeff McCune
    # gem install mysql -- --with-mysql-config=/usr/bin/mysql_config
114 1
115 1
You may require the ruby-devel package in order to install this
116 1
gem.
117 1
118 1
A word of warning - it is possible to be using stored
119 1
configurations with MySQL without installing the mysql gem. This is
120 1
because rails includes with it a simple Ruby based MySQL connector.
121 1
Relying on this connector is strongly discouraged, as it has been
122 1
observed to leak filehandles, leave open network and database
123 1
connections, and eventually cause puppetmasterd to become
124 1
completely unresponsive.
125 1
126 1
In order to check if you are using the unreliable Ruby based
127 1
connector, examine the rails.log file produced by puppetmasterd. If
128 6 Jeff McCune
you are using the Ruby one, you will find a message like this:
129 1
130 7 Jeff McCune
    WARNING: You're using the Ruby-based MySQL library that ships with Rails.
131 7 Jeff McCune
    This library is not suited for production. Please install the C-based MySQL
132 7 Jeff McCune
    library instead (gem install mysql).
133 6 Jeff McCune
134 6 Jeff McCune
If you find that warning, make sure you install the mysql gem,
135 1
which is based on the native MySQL libraries, before you begin
136 1
using stored configurations in production.
137 1
138 1
## SQLite3
139 1
140 1
For SQLite you will need to install the database package. For Red
141 6 Jeff McCune
Hat/Fedora the package required would be:
142 1
143 7 Jeff McCune
    sqlite
144 1
145 1
For Ubuntu/Debian, the packages required are (libsqlite3-ruby
146 6 Jeff McCune
contains the appropriate gem):
147 6 Jeff McCune
148 7 Jeff McCune
    sqlite3
149 7 Jeff McCune
    libsqlite3-ruby
150 1
151 1
You may also need to install the sqlite3-ruby Ruby Gem (not
152 1
required on Debian/Ubuntu):
153 1
154 7 Jeff McCune
    # gem install sqlite3-ruby
155 1
156 1
## PostgreSQL
157 1
158 1
For PostgreSQL you will need to install a number of packages. For
159 6 Jeff McCune
Red Hat/Fedora the typical packages required would be:
160 6 Jeff McCune
161 7 Jeff McCune
    postgresql
162 7 Jeff McCune
    postgresql-server
163 7 Jeff McCune
    postgresql-devel
164 6 Jeff McCune
165 1
You will also need to install the postgres Ruby Gem:
166 1
167 7 Jeff McCune
    # gem install postgres
168 1
169 13 Nicolas Jungers
or on more recent install:
170 13 Nicolas Jungers
171 13 Nicolas Jungers
    # gem install pg
172 13 Nicolas Jungers
173 1
If you fail to install the postgres gem then you will receive the
174 6 Jeff McCune
following error:
175 6 Jeff McCune
176 7 Jeff McCune
    err: Could not retrieve configuration: Uncaught exception no such file to load -- postgres in method puppetmaster.getconfig
177 13 Nicolas Jungers
178 13 Nicolas Jungers
If you get the error:
179 13 Nicolas Jungers
180 13 Nicolas Jungers
    err: Could not retrieve catalog from remote server: Error 400 on SERVER: NoMethodError: undefined method `fformat' for #<PGresult:0x.........>: SHOW client_min_messages
181 13 Nicolas Jungers
182 13 Nicolas Jungers
Try the pg gem instead of the postgres one.
183 1
184 1
For PostgreSQL you will also need to create the database and create
185 1
an appropriate role and password.
186 1
187 1
# Configuring basic storeconfigs
188 1
189 1
Now we need to configure stored configuration in Puppet itself.
190 1
There are three types of database adapters available for us, the
191 1
default sqlite3, MySQL and PostgreSQL. For the latter back-end
192 1
databases we also have available a number of options that let us
193 1
specify a particular user, password and the location of a database
194 12 Nick Fagerlund
socket.
195 1
196 12 Nick Fagerlund
Let's begin by walking through the steps to configure the SQLite backend.
197 12 Nick Fagerlund
**Note that this backend is not suitable for production-level use** -- it
198 12 Nick Fagerlund
can't handle high volume traffic, and will report locking failures if used
199 12 Nick Fagerlund
with more than five or ten hosts.
200 12 Nick Fagerlund
201 1
-   Configure puppet.conf:
202 6 Jeff McCune
203 7 Jeff McCune
        [puppetmasterd]
204 7 Jeff McCune
        storeconfigs = true
205 7 Jeff McCune
        dbadapter = sqlite3
206 10 James Turnbull
 
207 6 Jeff McCune
-   "Thin" stored configuration (optional) - from 0.25.0 we can
208 7 Jeff McCune
    also use the "thin" stored configuration option. This only collects
209 7 Jeff McCune
    and stores to the database exported resources, tags and host facts.
210 7 Jeff McCune
    To use "thin" stored configuration configure it in your
211 7 Jeff McCune
    puppet.conf:
212 6 Jeff McCune
213 7 Jeff McCune
        [puppetmasterd]
214 7 Jeff McCune
        storeconfigs = true
215 1
        thin_storeconfigs = true
216 7 Jeff McCune
        dbadapter = sqlite3
217 10 James Turnbull
 
218 1
-   Start the puppetmasterd daemon
219 1
220 1
-   Start the puppetd client
221 1
222 1
Now storeconfigs should be enabled and running.
223 1
224 1
Note that if you intend to use PuppetShow, you may need to include
225 1
a dblocation setting under puppetmasterd, pointing to the default
226 12 Nick Fagerlund
location.
227 1
228 1
# Configuring storeconfigs for MySQL
229 1
230 6 Jeff McCune
-   Create a puppet database, and grant privileges. Replace
231 7 Jeff McCune
    password below with an appropriate password:
232 6 Jeff McCune
233 7 Jeff McCune
        # mysql -u root -p
234 7 Jeff McCune
        mysql> create database puppet;
235 7 Jeff McCune
        mysql> grant all privileges on puppet.* to puppet@localhost identified by 'password';
236 1
237 1
-   Configure your [puppetmasterd] section to reflect these
238 7 Jeff McCune
    settings:
239 1
240 7 Jeff McCune
        [puppetmasterd]
241 7 Jeff McCune
        storeconfigs = true
242 7 Jeff McCune
        dbadapter = mysql
243 7 Jeff McCune
        dbuser = puppet
244 7 Jeff McCune
        dbpassword = password
245 7 Jeff McCune
        dbserver = localhost
246 7 Jeff McCune
        dbsocket = /var/run/mysqld/mysqld.sock
247 1
248 1
-   Start the puppetmasterd daemon
249 1
250 1
-   Start the puppetd client
251 1
252 1
253 1
You can also find some information on
254 1
[[My\_Sql\_Stored\_Configuration\_Patterns|Recipes/MySQLStored
255 1
Configuration]] .
256 1
257 1
To optimize some often run Puppet queries on your MySQL database,
258 1
use the following index:
259 6 Jeff McCune
260 7 Jeff McCune
    create index exported_restype_title on resources (exported, restype, title(50));
261 1
262 1
# Configuring storeconfigs for PostgreSQL
263 1
264 1
By default (on RHEL/CentOS, other distros unknown), you will have
265 1
to su - to the postgres user to do any administrative work such as
266 1
database creation.
267 1
268 1
-   Set up the database:
269 1
270 7 Jeff McCune
        # su - postgres
271 7 Jeff McCune
        $ psql template1
272 7 Jeff McCune
        template1=# create database puppet;
273 7 Jeff McCune
        CREATE DATABASE
274 7 Jeff McCune
        create user puppet with unencrypted password 'password';
275 7 Jeff McCune
        CREATE ROLE
276 7 Jeff McCune
        template1=# grant create on database puppet to puppet;
277 1
278 1
279 1
Note that Puppet requires the CREATE right to do automatic table
280 1
creation to initialize the database.
281 6 Jeff McCune
282 1
-   Configure your [puppetmasterd] section to reflect these
283 7 Jeff McCune
    settings:
284 6 Jeff McCune
285 7 Jeff McCune
        [puppetmasterd]
286 7 Jeff McCune
        storeconfigs = true
287 7 Jeff McCune
        dbadapter = postgresql
288 7 Jeff McCune
        dbuser = puppet
289 7 Jeff McCune
        dbpassword = password
290 7 Jeff McCune
        dbserver = localhost
291 7 Jeff McCune
        dbname = puppet
292 1
293 1
-   Start the puppetmasterd daemon
294 1
295 1
-   Start the puppetd client
296 1
297 1
-   Check /var/log/messages (or wherever you have Puppet set to
298 7 Jeff McCune
    log) for the message for an ''Initialized database'' message when
299 7 Jeff McCune
    the first client checks in.
300 1
301 1
302 1
# Installing Queuing Support for Storeconfigs
303 6 Jeff McCune
304 6 Jeff McCune
Puppet queueing is a feature which is designed to take some load
305 1
off of the Puppet master by transferring the task of updating the
306 1
database to a separate program which is named puppetqd (the Puppet
307 1
Queue Daemon).
308 1
309 1
To add support for queuing to an existing storeconfigs
310 1
configuration, you only need to install a queue broker, configure
311 1
your Puppet master, and configure your puppetqd.
312 1
313 1
While many message queue services exist, currently Puppet only
314 1
supports the Stomp protocol. We have tested using StompServer and
315 1
ActiveMQ. While StompServer is easy to set up and configure, we
316 1
suggest you use ActiveMQ -- if you need queueing, you need it
317 1
because of scalability, and StompServer simply isn't built for
318 1
scaling up to enterprise needs.
319 1
320 1
Queuing is available from release 0.25.0 onwards. It is NOT
321 1
available in the 0.24.x releases.
322 1
323 1
## Installing StompServer
324 1
325 1
First make sure you have the Ruby development package. On a Red
326 1
Hat-based system, this would be:
327 1
328 7 Jeff McCune
    yum install ruby-devel
329 6 Jeff McCune
330 1
Or on a Debian or Ubuntu-based system:
331 1
332 7 Jeff McCune
    apt-get install ruby1.8-dev
333 6 Jeff McCune
334 1
StompServer is available as a gem, so you can install via:
335 1
336 7 Jeff McCune
    gem install stompserver
337 1
338 1
## Installing ActiveMQ
339 6 Jeff McCune
340 6 Jeff McCune
Download and install ActiveMQ: e.g.,:
341 1
342 7 Jeff McCune
    $ wget http://www.apache.org/dyn/closer.cgi/activemq/apache-activemq/5.2.0/apache-activemq-5.2.0-bin.tar.gz
343 7 Jeff McCune
    $ tar zxvf apache-activemq-5.2.0-bin.tar.gz
344 1
345 1
# Configuring queuing storeconfigs
346 1
347 1
## Configuring the queuing broker
348 1
349 1
### Configuring StompServer
350 1
351 6 Jeff McCune
Configuration can either be done on the command line or via a
352 1
config file. For example, the following command-line:
353 1
354 7 Jeff McCune
    stompserver -q dbm
355 1
356 1
will start the stompserver on the default port of 61613 and use a
357 1
DBM file as its backing store (i.e., while messages have not yet
358 1
been picked up by puppetqd, they will be stored in a DBM file).
359 6 Jeff McCune
360 6 Jeff McCune
The configuration file:
361 6 Jeff McCune
362 7 Jeff McCune
    $ cat /etc/puppet/puppet-queue.conf
363 7 Jeff McCune
    :daemon: true
364 7 Jeff McCune
    :working_dir: /tmp/stompserver
365 7 Jeff McCune
    :storage: .queue
366 7 Jeff McCune
    :queue: file
367 7 Jeff McCune
    :auth: false
368 7 Jeff McCune
    :debug: false
369 7 Jeff McCune
    :group:
370 7 Jeff McCune
    :user:
371 7 Jeff McCune
    :host: 127.0.0.1
372 7 Jeff McCune
    :port: 61613
373 1
374 1
configures the stompserver to use a file backing store.
375 6 Jeff McCune
376 1
Then run the stompserver:
377 1
378 7 Jeff McCune
    stompserver -C /etc/puppet/puppet-queue.conf
379 1
380 1
Consult the stompserver's README.txt for additional information on
381 1
installation and configuration.
382 1
383 1
### Configuring ActiveMQ
384 1
385 1
Create an activemq.xml file (based on the samples provided in the
386 1
source), and enable stomp. The sample configuration uses the
387 1
default backing store, AMQ, (which is a transactional journal in
388 6 Jeff McCune
ActiveMQ 5) and only requires the one-line change below to enable
389 6 Jeff McCune
stomp on port 61613:
390 1
391 7 Jeff McCune
    <transportConnectors> <transportConnector name="stomp" uri="stomp://localhost:61613"/> </transportConnectors>
392 1
393 6 Jeff McCune
You can then start ActiveMQ:
394 1
395 7 Jeff McCune
    activemq
396 1
397 1
You should consult the ActiveMQ documentation for additional
398 1
information on configuring ActiveMQ.
399 1
400 1
## Configuring Puppet
401 1
402 1
You need to configure both puppetmasterd and puppetqd to use
403 1
queuing.
404 1
405 1
In this example, we're keeping our stored configuration information
406 1
in sqlite3 -- if you're using PostgreSQL, MySQL, or others, your
407 1
dbadapter and dblocation information will differ).
408 1
409 1
Please refer to the basic stored configuration section on the wiki
410 1
for details about creating the database for MySQL or PostgreSQL.
411 1
412 1
First we need to install the Stomp client. You can do this from a
413 6 Jeff McCune
gem:
414 1
415 7 Jeff McCune
    gem install stomp
416 1
417 1
Next, we need to configure Puppet itself. Note that the
418 1
configuration of the Puppet master and the puppetqd is the same:
419 1
this is because they both need to read information out of the same
420 1
database (i.e., the database is a cache). Thus, a puppet.conf would
421 6 Jeff McCune
contain:
422 6 Jeff McCune
423 7 Jeff McCune
    [main]
424 7 Jeff McCune
      queue_type = stomp
425 7 Jeff McCune
      queue_source = stomp://localhost:61613
426 7 Jeff McCune
      dbadapter = sqlite3
427 1
    [puppetmasterd]
428 7 Jeff McCune
      async_storeconfigs = true
429 7 Jeff McCune
430 1
Note that these can all be put onto a command line:
431 1
432 1
    puppetmasterd --async_storeconfigs --queue_type=stomp --queue_source="stomp://localhost:61613" \
433 10 James Turnbull
      --dbadapter sqlite3
434 1
435 1
You then need to run the puppetqd daemon.
436 1
437 1
> puppetqd
438 1
439 1
# Bootstrapping into stored configuration
440 1
441 1
If you have a lot of hosts, turning on stored configuration might
442 1
crush your database server. The main problem is that data for every
443 1
host needs to be INSERTed into the database. Once you get past that
444 1
hurdle there's much less SQL activity. Here are some notes about
445 1
how we (usg.edu folks) got over the hurdle. The main bottleneck for
446 1
us was CPU--IO wait wasn't an issue.
447 1
448 1
First we tuned our MySQL server (all based on masterzen's
449 1
recommendations). We added these lines to the [mysqld] section of
450 1
my.cnf:
451 6 Jeff McCune
452 7 Jeff McCune
    innodb_buffer_pool_size=2G
453 7 Jeff McCune
    innodb_log_file_size=256M
454 7 Jeff McCune
    innodb_log_buffer_size=64M
455 7 Jeff McCune
    innodb_additional_mem_pool_size=20M
456 7 Jeff McCune
    innodb_flush_method = O_DIRECT
457 1
458 8 Nick Fagerlund
Next we stopped puppetd on half of our ~400 servers. This, plus
459 1
the MySQL changes above, allowed our server to survive the initial
460 1
stored configuration hit of our other 200 servers. After the first
461 1
200 were in stored configuration we ran puppetd --test --tags
462 1
SMALLMODULE on the second half of our hosts. Later we restarted
463 1
puppetd.
464 1
465 1
Our clients check in once an hour. About 15 hosts check in per
466 1
minute. The puppetmasterd and mysqld run on the same server (along
467 1
with a few other applications). Our server has 8 CPUs and 12G of
468 1
RAM.
469 1
470 1
Here's a fine blog post by masterzen about this issue:
471 1
[http://www.masterzen.fr/2009/03/18/omg-storedconfigs-killed-my-database/](http://www.masterzen.fr/2009/03/18/omg-storedconfigs-killed-my-database/)
472 11 Zach Leslie
473 11 Zach Leslie
# Cleaning Stored Configs
474 11 Zach Leslie
475 11 Zach Leslie
On occasion, something about a system changes and you will need to clean out the stored configuration database for a given node.  This is fairly harmless to do because the information will repopulate the next time the node checks in with the master.
476 11 Zach Leslie
477 11 Zach Leslie
Download the cleaner script contained with the source:
478 11 Zach Leslie
479 11 Zach Leslie
https://github.com/puppetlabs/puppet/raw/master/ext/puppetstoredconfigclean.rb
480 11 Zach Leslie
481 11 Zach Leslie
Once you have the script in your puppet master, you can clean the information out of your stored configuration for a given node, but running the script like so:
482 11 Zach Leslie
483 11 Zach Leslie
    ./puppetstoredconfigclean.rb host1.example.com
484 11 Zach Leslie
485 11 Zach Leslie
This will remove all of the information about the node 'host1.example.com' from your stored configs database.
486 11 Zach Leslie
487 11 Zach Leslie
For more information on usage, you can run the script with --help like so:
488 11 Zach Leslie
489 11 Zach Leslie
    ./puppetstoredconfigclean.rb --help