Using Stored Configuration

Version 9 (Stefan Schulte, 11/23/2010 08:15 pm)

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 1
three database back-ends: SQLite (the default), 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 1
If you fail to install the postgres gem then you will receive the
170 6 Jeff McCune
following error:
171 6 Jeff McCune
172 7 Jeff McCune
    err: Could not retrieve configuration: Uncaught exception no such file to load -- postgres in method puppetmaster.getconfig
173 1
174 1
For PostgreSQL you will also need to create the database and create
175 1
an appropriate role and password.
176 1
177 1
# Configuring basic storeconfigs
178 1
179 1
Now we need to configure stored configuration in Puppet itself.
180 1
There are three types of database adapters available for us, the
181 1
default sqlite3, MySQL and PostgreSQL. For the latter back-end
182 1
databases we also have available a number of options that let us
183 1
specify a particular user, password and the location of a database
184 1
socket. Let's walk through the steps required to configure the most
185 1
basic SQLite backend.
186 1
187 1
-   Configure puppet.conf:
188 6 Jeff McCune
189 7 Jeff McCune
        [puppetmasterd]
190 7 Jeff McCune
        storeconfigs = true
191 7 Jeff McCune
        dbadapter = sqlite3
192 7 Jeff McCune
        dblocation = /var/lib/puppet/storeconfigs.sqlite
193 1
194 6 Jeff McCune
-   "Thin" stored configuration (optional) - from 0.25.0 we can
195 7 Jeff McCune
    also use the "thin" stored configuration option. This only collects
196 7 Jeff McCune
    and stores to the database exported resources, tags and host facts.
197 7 Jeff McCune
    To use "thin" stored configuration configure it in your
198 7 Jeff McCune
    puppet.conf:
199 6 Jeff McCune
200 7 Jeff McCune
        [puppetmasterd]
201 7 Jeff McCune
        storeconfigs = true
202 9 Stefan Schulte
        thin_storeconfigs = true
203 7 Jeff McCune
        dbadapter = sqlite3
204 7 Jeff McCune
        dblocation = /var/lib/puppet/storeconfigs.sqlite
205 1
206 1
-   Start the puppetmasterd daemon
207 1
208 1
-   Start the puppetd client
209 1
210 1
211 1
Now storeconfigs should be enabled and running.
212 1
213 1
Note that if you intend to use PuppetShow, you may need to include
214 1
a dblocation setting under puppetmasterd, pointing to the default
215 1
location. Also note that SQLite is not very happy with high volume
216 1
usage (more than 5 or 10 hosts), and will report locking failures
217 1
during operation.
218 1
219 1
# Configuring storeconfigs for MySQL
220 1
221 6 Jeff McCune
-   Create a puppet database, and grant privileges. Replace
222 7 Jeff McCune
    password below with an appropriate password:
223 6 Jeff McCune
224 7 Jeff McCune
        # mysql -u root -p
225 7 Jeff McCune
        mysql> create database puppet;
226 7 Jeff McCune
        mysql> grant all privileges on puppet.* to puppet@localhost identified by 'password';
227 1
228 1
-   Configure your [puppetmasterd] section to reflect these
229 7 Jeff McCune
    settings:
230 1
231 7 Jeff McCune
        [puppetmasterd]
232 7 Jeff McCune
        storeconfigs = true
233 7 Jeff McCune
        dbadapter = mysql
234 7 Jeff McCune
        dbuser = puppet
235 7 Jeff McCune
        dbpassword = password
236 7 Jeff McCune
        dbserver = localhost
237 7 Jeff McCune
        dbsocket = /var/run/mysqld/mysqld.sock
238 1
239 1
-   Start the puppetmasterd daemon
240 1
241 1
-   Start the puppetd client
242 1
243 1
244 1
You can also find some information on
245 1
[[My\_Sql\_Stored\_Configuration\_Patterns|Recipes/MySQLStored
246 1
Configuration]] .
247 1
248 1
To optimize some often run Puppet queries on your MySQL database,
249 1
use the following index:
250 6 Jeff McCune
251 7 Jeff McCune
    create index exported_restype_title on resources (exported, restype, title(50));
252 1
253 1
# Configuring storeconfigs for PostgreSQL
254 1
255 1
By default (on RHEL/CentOS, other distros unknown), you will have
256 1
to su - to the postgres user to do any administrative work such as
257 1
database creation.
258 1
259 1
-   Set up the database:
260 1
261 7 Jeff McCune
        # su - postgres
262 7 Jeff McCune
        $ psql template1
263 7 Jeff McCune
        template1=# create database puppet;
264 7 Jeff McCune
        CREATE DATABASE
265 7 Jeff McCune
        create user puppet with unencrypted password 'password';
266 7 Jeff McCune
        CREATE ROLE
267 7 Jeff McCune
        template1=# grant create on database puppet to puppet;
268 1
269 1
270 1
Note that Puppet requires the CREATE right to do automatic table
271 1
creation to initialize the database.
272 6 Jeff McCune
273 1
-   Configure your [puppetmasterd] section to reflect these
274 7 Jeff McCune
    settings:
275 6 Jeff McCune
276 7 Jeff McCune
        [puppetmasterd]
277 7 Jeff McCune
        storeconfigs = true
278 7 Jeff McCune
        dbadapter = postgresql
279 7 Jeff McCune
        dbuser = puppet
280 7 Jeff McCune
        dbpassword = password
281 7 Jeff McCune
        dbserver = localhost
282 7 Jeff McCune
        dbname = puppet
283 1
284 1
-   Start the puppetmasterd daemon
285 1
286 1
-   Start the puppetd client
287 1
288 1
-   Check /var/log/messages (or wherever you have Puppet set to
289 7 Jeff McCune
    log) for the message for an ''Initialized database'' message when
290 7 Jeff McCune
    the first client checks in.
291 1
292 1
293 1
# Installing Queuing Support for Storeconfigs
294 6 Jeff McCune
295 6 Jeff McCune
Puppet queueing is a feature which is designed to take some load
296 1
off of the Puppet master by transferring the task of updating the
297 1
database to a separate program which is named puppetqd (the Puppet
298 1
Queue Daemon).
299 1
300 1
To add support for queuing to an existing storeconfigs
301 1
configuration, you only need to install a queue broker, configure
302 1
your Puppet master, and configure your puppetqd.
303 1
304 1
While many message queue services exist, currently Puppet only
305 1
supports the Stomp protocol. We have tested using StompServer and
306 1
ActiveMQ. While StompServer is easy to set up and configure, we
307 1
suggest you use ActiveMQ -- if you need queueing, you need it
308 1
because of scalability, and StompServer simply isn't built for
309 1
scaling up to enterprise needs.
310 1
311 1
Queuing is available from release 0.25.0 onwards. It is NOT
312 1
available in the 0.24.x releases.
313 1
314 1
## Installing StompServer
315 1
316 1
First make sure you have the Ruby development package. On a Red
317 1
Hat-based system, this would be:
318 1
319 7 Jeff McCune
    yum install ruby-devel
320 6 Jeff McCune
321 1
Or on a Debian or Ubuntu-based system:
322 1
323 7 Jeff McCune
    apt-get install ruby1.8-dev
324 6 Jeff McCune
325 1
StompServer is available as a gem, so you can install via:
326 1
327 7 Jeff McCune
    gem install stompserver
328 1
329 1
## Installing ActiveMQ
330 6 Jeff McCune
331 6 Jeff McCune
Download and install ActiveMQ: e.g.,:
332 1
333 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
334 7 Jeff McCune
    $ tar zxvf apache-activemq-5.2.0-bin.tar.gz
335 1
336 1
# Configuring queuing storeconfigs
337 1
338 1
## Configuring the queuing broker
339 1
340 1
### Configuring StompServer
341 1
342 6 Jeff McCune
Configuration can either be done on the command line or via a
343 1
config file. For example, the following command-line:
344 1
345 7 Jeff McCune
    stompserver -q dbm
346 1
347 1
will start the stompserver on the default port of 61613 and use a
348 1
DBM file as its backing store (i.e., while messages have not yet
349 1
been picked up by puppetqd, they will be stored in a DBM file).
350 6 Jeff McCune
351 6 Jeff McCune
The configuration file:
352 6 Jeff McCune
353 7 Jeff McCune
    $ cat /etc/puppet/puppet-queue.conf
354 7 Jeff McCune
    :daemon: true
355 7 Jeff McCune
    :working_dir: /tmp/stompserver
356 7 Jeff McCune
    :storage: .queue
357 7 Jeff McCune
    :queue: file
358 7 Jeff McCune
    :auth: false
359 7 Jeff McCune
    :debug: false
360 7 Jeff McCune
    :group:
361 7 Jeff McCune
    :user:
362 7 Jeff McCune
    :host: 127.0.0.1
363 7 Jeff McCune
    :port: 61613
364 1
365 1
configures the stompserver to use a file backing store.
366 6 Jeff McCune
367 1
Then run the stompserver:
368 1
369 7 Jeff McCune
    stompserver -C /etc/puppet/puppet-queue.conf
370 1
371 1
Consult the stompserver's README.txt for additional information on
372 1
installation and configuration.
373 1
374 1
### Configuring ActiveMQ
375 1
376 1
Create an activemq.xml file (based on the samples provided in the
377 1
source), and enable stomp. The sample configuration uses the
378 1
default backing store, AMQ, (which is a transactional journal in
379 6 Jeff McCune
ActiveMQ 5) and only requires the one-line change below to enable
380 6 Jeff McCune
stomp on port 61613:
381 1
382 7 Jeff McCune
    <transportConnectors> <transportConnector name="stomp" uri="stomp://localhost:61613"/> </transportConnectors>
383 1
384 6 Jeff McCune
You can then start ActiveMQ:
385 1
386 7 Jeff McCune
    activemq
387 1
388 1
You should consult the ActiveMQ documentation for additional
389 1
information on configuring ActiveMQ.
390 1
391 1
## Configuring Puppet
392 1
393 1
You need to configure both puppetmasterd and puppetqd to use
394 1
queuing.
395 1
396 1
In this example, we're keeping our stored configuration information
397 1
in sqlite3 -- if you're using PostgreSQL, MySQL, or others, your
398 1
dbadapter and dblocation information will differ).
399 1
400 1
Please refer to the basic stored configuration section on the wiki
401 1
for details about creating the database for MySQL or PostgreSQL.
402 1
403 1
First we need to install the Stomp client. You can do this from a
404 6 Jeff McCune
gem:
405 1
406 7 Jeff McCune
    gem install stomp
407 1
408 1
Next, we need to configure Puppet itself. Note that the
409 1
configuration of the Puppet master and the puppetqd is the same:
410 1
this is because they both need to read information out of the same
411 1
database (i.e., the database is a cache). Thus, a puppet.conf would
412 6 Jeff McCune
contain:
413 6 Jeff McCune
414 7 Jeff McCune
    [main]
415 7 Jeff McCune
      queue_type = stomp
416 7 Jeff McCune
      queue_source = stomp://localhost:61613
417 7 Jeff McCune
      dbadapter = sqlite3
418 7 Jeff McCune
      dblocation = /var/lib/puppet/storeconfigs.sqlite
419 7 Jeff McCune
    [puppetmasterd]
420 7 Jeff McCune
      async_storeconfigs = true
421 1
422 6 Jeff McCune
Note that these can all be put onto a command line:
423 6 Jeff McCune
424 7 Jeff McCune
    puppetmasterd --async_storeconfigs --queue_type=stomp --queue_source="stomp://localhost:61613" \
425 7 Jeff McCune
      --dbadapter sqlite3 --dblocation /var/lib/puppet/storeconfigs.sqlite
426 1
427 1
Also note that the dblocation is not needed for MySQL or PostgreSQL
428 1
dbadapters.
429 1
430 1
You then need to run the puppetqd daemon.
431 1
432 1
> puppetqd
433 1
434 1
# Bootstrapping into stored configuration
435 1
436 1
If you have a lot of hosts, turning on stored configuration might
437 1
crush your database server. The main problem is that data for every
438 1
host needs to be INSERTed into the database. Once you get past that
439 1
hurdle there's much less SQL activity. Here are some notes about
440 1
how we (usg.edu folks) got over the hurdle. The main bottleneck for
441 1
us was CPU--IO wait wasn't an issue.
442 1
443 1
First we tuned our MySQL server (all based on masterzen's
444 1
recommendations). We added these lines to the [mysqld] section of
445 1
my.cnf:
446 6 Jeff McCune
447 7 Jeff McCune
    innodb_buffer_pool_size=2G
448 7 Jeff McCune
    innodb_log_file_size=256M
449 7 Jeff McCune
    innodb_log_buffer_size=64M
450 7 Jeff McCune
    innodb_additional_mem_pool_size=20M
451 7 Jeff McCune
    innodb_flush_method = O_DIRECT
452 1
453 8 Nick Fagerlund
Next we stopped puppetd on half of our ~400 servers. This, plus
454 1
the MySQL changes above, allowed our server to survive the initial
455 1
stored configuration hit of our other 200 servers. After the first
456 1
200 were in stored configuration we ran puppetd --test --tags
457 1
SMALLMODULE on the second half of our hosts. Later we restarted
458 1
puppetd.
459 1
460 1
Our clients check in once an hour. About 15 hosts check in per
461 1
minute. The puppetmasterd and mysqld run on the same server (along
462 1
with a few other applications). Our server has 8 CPUs and 12G of
463 1
RAM.
464 1
465 1
Here's a fine blog post by masterzen about this issue:
466 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/)