- Why Bcfg2
- Theory and Specifications
I have been tasked with setting up a configuration management system for our servers. After having looking at the three main contenders (apologies, if I missed any) – cfengine, puppet and bcfg2, I settled on bcfg2. I have setup and used cfengine to maintain a heterogeneous set of machines in a previous job – and it quickly turned out to be pretty overwhelming. It could have been that I simply did not grok it all and that there were elegant ways to structure those configuration files, but I didn’t see it. My cfengine configuration turned out to be this huge mess of conjugations and dozens of little shell scripts that did all the work in the background. Also, I had some mysterious cases where a box would randomly decide its configuration was out of sync and would reimage itself. In anycase, I didn’t want to relive all that. Puppet seemed like a cleaner cfengine, but nothing radically different from it. I was afraid I would end up maintaining just as many tiny scripts and such. The syntax files did seem a lot cleaner, but still seemed like they were another metalanguage (I attended the authors presentation at the 2007 OSCON and he said that most of the entries were just ruby code).
This brings me to bcfg2 – it uses plain xml files. This seemed like a good choice to me given that most of the information for servers tends to be organized into logical groups anyway. Also, xml can be parsed easily using a variety of scripting libraries. I had a few conversations with the lead developers and they are pretty responsive. I read success stories of folks managing cluster farms and integrating it with other systems to do bare metal installations etc, and so I decided to give it a shot. The configuration and the theory behind bcfg2 however is another story. I hope this page helps newbies make sense of the arcane terms used in the bcfg2 documentation. Once you understand the terms and how the configuration is structured those terms start to make sense, but I had to struggle through it.
A bcfg2 system consists of a central server and a bunch of machines that run the bcfg2 client. The configuration for your entire environment is setup on the server. One of the basic configuration entities is a group. A group is a set of related configuration specifications. A client can be explicitly assigned to a group (on the server) or can chose to get its configuration from a different group (using a command line switch). Configuration files on the server are located in the /var/bcfg2 directory by default, but that location can be changed in the config file (/etc/bcfg2.conf). I maintain ours in /etc/bcfg2/.
Bcfg2 configuration can be split into server side and client side components. The server side of things is mostly your specifications on how the system should look like, the client side of things is mostly queries for the current state of the system. I have not used the client side components much and so I am ignoring them for now. When you setup the configuration, you only deal with the server side of things. The bcfg2 client program is smart enough to enforce the client side of the specifications for you (this is one of bcfg2s strengths). A few components interact on the server side to generate the final configuration file that is used by the client. Once you understand how these work, you can follow the docs on the bcfg2 website and go from there.
The server configuration is specified into the Metadata, Base and Bundler directories. I will go over each of these directories and explain how/why they are used.
The Metadata directory will contain group and client descriptions. These groups tell the server about the different kinds of machine and configuration groups in your environment. In my case, this contains groups like rhel4_group, rhel5_group, php_group etc. Note that these groups can then be used to form bigger groups, for example I also a rhel5_php group that includes the rhel5 and the php groups. All this stuff is specified in the groups.xml file. There is also a clients.xml file in this directory that associates host machines with a unique group. In general you will have a many (hosts) to one (group) mapping in this file.
The Base and Bundler directories will contain skeletons of your desired configuration. Bundles are generally used to group related specification entries into a singe set. Base specifications are generally used to list assorted groups of files that aren’t necessarily related to each other. Consider this example – lets say you were specifying the different components in a physical server in the Base and Bundler directories. Your configuration files would then group these components into related units (like raid array and related disks, power supplies and related wiring, etc). Lets say you had a “critical server” group of machines in your infrastructure. Your configuration specifications (in the Base and Bundler directories) would say that a server belonging to this group should have a raid array, dual nics, and redundant power supplies.
The other related details of these servers are specified in the Cfg, Rules, Pkgmgr and Svcmgr directories. These specify that if a host belongs to this “critical server” group, then it should have two gigabit nics and that it should have 7.2k rpm scsi disks in the raid array. Lets say your manager comes along and says that the new mail server you are building has to have super expensive Hitachi 10k disks, then you would then specify this individual servers configuration explicitly. This server would inherit everything else in the “critical server” group, but would use these expensive Hitachi disks.
Think of the above example as you map your specifications to the configuration files. As a concrete example, lets say you wanted all servers in your network to run nrpe. You would specify an nrpe Bundle, that says that every server that is associated with this group, should have a. the nrpe package, b. the nrpe service enabled and c. the correct nrpe.cfg file. All of these specifications (structure) go into the Bundle directory. Next, you specify that every host in the rhel4 group should have nrpe version 2.5.2 installed. This is specified in the Pkgmgr directory. The component that make this association is called a Generator. Similarly, you would probably distribute a configuration file that is common to all rhel4 – i386 hosts. This file goes into the Cfg directory. For rhel4 64 bit machines you may have a different configuration file. This one is also specified in the Cfg directory, but with a G20_x86_64 suffix, that tells the Cfg generator that this file is meant for machines in the x86_64 group.
For your configurations to work, the bcfg2 server has to make these three associations. The client (or host) should belong to a group (Metadata). You should have a set of abstract configuration definitions (Structure) that map these groups to desired properties. You should have Generators specifications that map the Structures defined earlier to concrete files/rules.
HTH.
