diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-06-17 01:56:04 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-06-17 01:56:04 +0000 |
commit | 644fd4e5ff3cf3a31370be48c7d960e74204477d (patch) | |
tree | 98619c04b07ac461935505abc95ac2d533e10108 /documentation/notcfengine.page | |
parent | f0907607347c26127dd566fbe5b19c8528d25f5d (diff) | |
download | puppet-644fd4e5ff3cf3a31370be48c7d960e74204477d.tar.gz puppet-644fd4e5ff3cf3a31370be48c7d960e74204477d.tar.xz puppet-644fd4e5ff3cf3a31370be48c7d960e74204477d.zip |
updating docs to work with webgen
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1293 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'documentation/notcfengine.page')
-rw-r--r-- | documentation/notcfengine.page | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/documentation/notcfengine.page b/documentation/notcfengine.page new file mode 100644 index 000000000..b96448e57 --- /dev/null +++ b/documentation/notcfengine.page @@ -0,0 +1,222 @@ +--- +inMenu: true +title: Puppet vs. Cfengine +--- + +[Cfengine](http://www.cfengine.org) is currently the most widely deployed +configuration management tool. In many ways, [Puppet](/projects/puppet) can +be thought of as a next-generation version of cfengine, in that many of +puppet's design goals are specifically derived from experience with cfengine +and are meant to overcome many of cfengine's weaknesses. + +This document summarizes the primary advances that Puppet makes over +cfengine's current state. + +# Abstraction + +Cfengine is a great way to scale common administrative practices -- you can +move from using SSH and a for loop to using Cfengine pretty smoothly. +However, there is just as much complexity present in either form. You still +have to handle file contents, and you still have to manage operating system +differences yourself -- you have to know whether it's ``useradd`` or +``adduser``, whether it's ``init`` or Sun's ``SMF``, and what the format of the +filesystem tab is. + +Puppet's primary goal is to provide enough abstraction so that you do not have +to know those details. You can speak in terms of users, services, or +filesystems, and Puppet will translate them to the appropriate commands on +each system. Puppet administrators are free to focus on the complexity of +their networks, rather than being forced to also handle that complexity plus +the complexity of the differences between the operating systems. + +# Dedication + +Puppet will be supported by an organization dedicated to creating +the best system automation software, and I expect to have a staff of at +least a few people dedicated to development, support, consulting, and custom +development. Constrast this with cfengine, which is supported by a professor +whose primary use for the software is in research into anomalies. + +Cfengine's author is only now starting to invest on community involvement in +its development; while its author has always accepted patches from the +community, he has been hesitant to provide standard project features like a +version repository and a bug database and as a result cfengine's large user +base has not resulted in a large development community. + +Because Reductive Labs is a commercial enterprise dependent on customer +satisfaction for its survival, our customers will have a large say in how best +to develop Puppet, and we'll be doing everything we can to develop a strong +community just as dedicated to Puppet and server automation as we are. Our +goal is also to have multiple developers dedicated full time to Puppet +development, which should significantly accelerate feature development +compared to cfengine. + +# Language Power + +While the two languages are superficially similar, the puppet language already +supports two critical features that cfengine forces you to hack around. +Puppet supports building higher level objects out of a set of low-level +objects including the ability to parameterize, and has a built-in ability to +express relationships between objects. For instance, here is how you might +define an 'apache' component:: + + define apache(docroot,htmlsource,configfile) { + # make sure the package is installed + package { apache: version => "2.0.51", installed => true } + + # pull down the data to serve + file { $docroot: source => $htmlsource } + + # and the config file + file { "/etc/apache/httpd.conf": source => $configfile } + + # restart the apache service if the package is reinstalled or if + # the config file changes; notice no need for 'define' statements + # or AddInstallable calls + service { apache: running => true, + requires => [ package[apache], file["/etc/apache/httpd.conf"] ] + } + } + + # You could now have different versions of this: + + apache { + docroot => "/var/wwwprod", + htmlsource => "nfs://fileserver/web/wwwprod", + configfile => "https://webserver/web/prod.conf" + } + + apache { + docroot => "/var/wwwdev", + htmlsource => "http://tmpserver/web/wwwdev", + configfile => "https://webserver/web/dev.conf" + } + +This simple level of abstraction already puts you far beyond what cfengine +can do. The initial goal is to provide ample power to express the true +complexity of a network configuration, but just as importantly we want to +support code sharing. There has been essentially zero success in sharing +configurations within the cfengine community because of how difficult basic +abstraction is with cfengine, so one of my primary goals with the language was +to make abstraction, within a network or across one, downright easy. + +# Decoupling + +Puppet is being written with all components decoupled from each other, using +clean and preferably industry-standard interfaces between them. Adding a new +action to cfengine requires modification of the entire functional stack +from the lexer and parser through to the backing library, while adding a new +type to Puppet can be as simple as dropping a ruby script into the right +directory. + +Puppet also uses the industry-standard XMLRPC protocol for communication +between Puppet clients and servers, so the protocol is easy to study and +either end could be replaced by another service if desired. + +# Interactivity + +Puppet is being designed to make it easy to get information back +out of it. For instance, it will be easy to figure out how many changes +happened on a given node, even in a given time frame and of a given type, +without having to parse log files or something. When puppet +ships, it will ship with a small add-on that will automatically graph all +of this info in RRD files so that you can just enable this and +automatically get graphs of change rates on your network. + +# Development Methodology + +Reductive Labs is a big believer in enhancing developer productivity. Puppet +is being written in Ruby because it is a high-level language that is easy to +use yet provides significant productivity enhancements over low-level +languages like C. Reductive Labs also strongly believes that unreadable code +is bad code; if you can't easily follow a code path in Puppet, then you've +found a bug. Lastly, we assiduosly unit test our code. We're always looking +for more ways to test our code, and every bug we quash gets turned into a unit +test so we know we'll never release that bug again. + +# Examples + +I've got some small configurations that exemplify some of the differences. +Here's how a simple centralized Apache configuration would look in the two +languages, for instance. The two manifests just download Apache's +configuration from a central server, restarting Apache if the files change at +all, and also making sure that Apache is always running. + +Here's how it looks in puppet:: + + # This would normally be in a separate file, e.g., classes/apache.pp + class apacheserver { + # Download the config from a central $server + file { "/etc/apache": + source => "puppet://server.domain.com/source/apache", + recurse => true, + owner => root, + group => root + } + + # Check that apache is running, and mark it to restart if + # the config files change + service { apache: + running => true, + subscribe => file["/etc/apache"] + } + } + + # Node "nodename" is an apache server + node nodename { + include apacheserver + } + +And here's how the same configuration looks in cfengine:: + + control: + # this class is necessary later + AddInstallable = ( restart_apache ) + + groups: + # Mark which nodes are apache servers + apacheserver = ( nodename ) + + # copy the files down from the central server, setting 'restart_apache' + # if any files changed + copy: + apacheserver:: + /source/apache + dest=/etc/apache server=$(server) owner=root group=root + define=restart_apache + + # Make sure the process is running + processes: + apacheserver:: + "apache" restart "/etc/init.d/apache startssl" + + # restart apache if the appropriate class is set + shellcommands: + apacheserver.restart_apache:: + "/etc/init.d/apache restart" + +There are a few specific items worth noting in this comparison: + +* The cfengine configuration is a bit inside out, in that each + statement has to mention the class associated with the work in question + (assuming you have multiple classes in your configuration). This encourages + you to organize your configuration based on the type of work being done + (e.g., copying or shellcommands), rather than the reason you're doing the + work (i.e., it's all for the Apache server). + +* The cfengine configuration uses the dynamically defined class + 'restart_Apache' to mark the relationship between the Apache configuration + files and the running Apache process, rather than allowing you to just + directly specify a relationship. + +* The cfengine configuration also separates the management of the Apache + process into two statements, one for starting if it happens to not be + running and one for restarting if the files change, whereas Puppet is able + to handle both functions in one statement. + +* The cfengine configuration requires at least two forward references (that + is, references to portions of the configuration that are further on). The + 'restart_apache' class must be set as 'AddInstallable' before it is used + anywhere, and the 'apacheserver' class must be set before any code is + associated with it. Neither of these is a big deal in small doses, but it + can get quite complicated as the configuration matures. |