Big Picture
Version 20 (Joe Foley, 01/10/2012 01:59 pm)
| 1 | 1 | # Big picture |
|
|---|---|---|---|
| 2 | 1 | ||
| 3 | 1 | Puppet is a **declarative language** for expressing system |
|
| 4 | 1 | configuration, a **client and server** for distributing it, and a |
|
| 5 | 1 | **library** for realizing the configuration. |
|
| 6 | 1 | ||
| 7 | 1 | Rather than approaching server management by automating current |
|
| 8 | 1 | techniques, Puppet reframes the problem by providing a language to |
|
| 9 | 1 | express the relationships between servers, the services they |
|
| 10 | 1 | provide, and the primitive objects that compose those services. |
|
| 11 | 1 | Rather than handling the detail of how to achieve a certain |
|
| 12 | 1 | configuration or provide a given service, Puppet users can simply |
|
| 13 | 1 | express their desired configuration using the abstractions they're |
|
| 14 | 1 | used to handling, like service and node, and Puppet is responsible |
|
| 15 | 1 | for either achieving the configuration or providing the user enough |
|
| 16 | 1 | information to fix any encountered problems. |
|
| 17 | 1 | ||
| 18 | 20 | Joe Foley | This document is a supplement to the [Puppet Introduction](http://docs.puppetlabs.com/guides/introduction.html) and it is assumed that readers are familiar with the contents of that document. |
| 19 | 1 | ||
| 20 | 1 | ## Less Detail, More Information |
|
| 21 | 1 | ||
| 22 | 1 | A correct configuration must obviously provide the appropriate |
|
| 23 | 1 | details, but a configuration tool should understand that the |
|
| 24 | 1 | details are generally the easy part. The hard part of system |
|
| 25 | 1 | configuration is understanding the complex relationships between |
|
| 26 | 1 | services and the objects that comprise those services. One of the |
|
| 27 | 1 | primary goals of Puppet is to allow users to push the details into |
|
| 28 | 1 | lower levels of the configuration and pull the relationships into |
|
| 29 | 1 | the foreground. |
|
| 30 | 1 | ||
| 31 | 1 | For instance, take a typical Apache web server deployment. Puppet |
|
| 32 | 1 | allows one to encapsulate all of the primitives necessary for |
|
| 33 | 1 | successful deployment into one reusable object, and that object can |
|
| 34 | 1 | even be abstracted to support multiple apache versions. Here's how |
|
| 35 | 1 | a simple apache definition might look for a Debian server (Debian |
|
| 36 | 1 | uses apache for 1.x versions and apache2 for 2.x versions): |
|
| 37 | 1 | ||
| 38 | 1 | define apache(version, conf, user, group) { |
|
| 39 | 1 | # abstract across apache1 and apache2 |
|
| 40 | 1 | $name = $version ? { |
|
| 41 | 1 | 1 => "apache", |
|
| 42 | 1 | 2 => "apache2", |
|
| 43 | 1 | } |
|
| 44 | 1 | package{ $name: |
|
| 45 | 1 | install => true, |
|
| 46 | 1 | } |
|
| 47 | 1 | ||
| 48 | 1 | file { "$conf": |
|
| 49 | 1 | user => "$user", |
|
| 50 | 1 | group => "$group", |
|
| 51 | 1 | source => "$conf", |
|
| 52 | 1 | } |
|
| 53 | 1 | ||
| 54 | 1 | # we want the service to restart if the config file changes |
|
| 55 | 1 | # or if the package gets upgraded |
|
| 56 | 1 | service { "$name": |
|
| 57 | 1 | running => true, |
|
| 58 | 1 | subscribe => [file["$conf"], package["$name"]], |
|
| 59 | 1 | } |
|
| 60 | 1 | } |
|
| 61 | 1 | ||
| 62 | 1 | Now, with this configuration, one can easily set multiple servers |
|
| 63 | 1 | up to run different versions of apache. The key benefit here is |
|
| 64 | 1 | that the information necessary to run apache correctly is separated |
|
| 65 | 1 | from the decision to do so on a given host. For example: |
|
| 66 | 1 | ||
| 67 | 1 | # import our apache definition file |
|
| 68 | 1 | import "apache" |
|
| 69 | 1 | ||
| 70 | 1 | node server1 { |
|
| 71 | 1 | # use a locally-available config file |
|
| 72 | 1 | apache { |
|
| 73 | 1 | version => 1, |
|
| 74 | 1 | conf => "/nfs/configs/apache/server1.conf", |
|
| 75 | 1 | user => "www-data", |
|
| 76 | 1 | group => "www-data", |
|
| 77 | 1 | } |
|
| 78 | 1 | } |
|
| 79 | 1 | ||
| 80 | 1 | node server2 { |
|
| 81 | 1 | # use a config that we pull from elsewhere |
|
| 82 | 1 | apache { |
|
| 83 | 1 | version => 2, |
|
| 84 | 1 | conf => "http://configserver/configs/server2/httpd.conf" |
|
| 85 | 1 | user => "www-data", |
|
| 86 | 1 | group => "www-data", |
|
| 87 | 1 | } |
|
| 88 | 1 | } |
|
| 89 | 1 | ||
| 90 | 1 | Notice that our node configuration only specifies 1) that a given |
|
| 91 | 1 | server is running Apache, and 2) the information necessary to |
|
| 92 | 1 | differentiate this instance of apache from another instance. If a |
|
| 93 | 1 | given detail is going to be the same for all apache instances (such |
|
| 94 | 1 | as the fact that the service should be running and that it should |
|
| 95 | 1 | be restarted if the configuration file changes), then that detail |
|
| 96 | 1 | does not have to be specified every time an Apache instance is |
|
| 97 | 1 | configured. |
|
| 98 | 1 | ||
| 99 | 1 | ## Describing Configuration |
|
| 100 | 1 | ||
| 101 | 1 | Puppet's declarative language separates the "what" of the |
|
| 102 | 1 | configuration from the "how". The "how" is pushed into the library, |
|
| 103 | 1 | which generally provides the ability to manage a given entity on |
|
| 104 | 1 | multiple platforms, isolating the Puppet user from platform |
|
| 105 | 1 | details. |
|
| 106 | 1 | ||
| 107 | 1 | **Language Example: Class Hierarchy Using Inherit** |
|
| 108 | 1 | ||
| 109 | 1 | Inheritance can be used to override default values defined in base |
|
| 110 | 1 | classes: |
|
| 111 | 1 | ||
| 112 | 1 | class base { |
|
| 113 | 1 | ||
| 114 | 1 | ||
| 115 | 1 | ||
| 116 | 1 | file { "/etc/sudoers": |
|
| 117 | 1 | owner => "root", |
|
| 118 | 1 | group => "root", |
|
| 119 | 1 | mode => 440 |
|
| 120 | 1 | } |
|
| 121 | 1 | } |
|
| 122 | 1 | ||
| 123 | 1 | # FreeBSD has a "wheel" group instead of a "root" group |
|
| 124 | 1 | class freebsd inherits base { |
|
| 125 | 1 | file [ "/etc/sudoers" ] { |
|
| 126 | 1 | group => "wheel", |
|
| 127 | 1 | } |
|
| 128 | 1 | ||
| 129 | 1 | } |
|
| 130 | 1 | ||
| 131 | 1 | ## Distributing Configuration |
|
| 132 | 1 | ||
| 133 | 1 | The Puppet framework Library consists of a client and server. |
|
| 134 | 1 | ||
| 135 | 1 | (picture/diagram: client, server, site-config -> host-config) |
|
| 136 | 1 | ||
| 137 | 1 | A Puppet server is aware of the full configuration. As some |
|
| 138 | 1 | component's configuration aspects depend on the configuration of |
|
| 139 | 1 | other components (e.g. the firewall config includes the ports used |
|
| 140 | 1 | by webservers), generating configuration for a component requires |
|
| 141 | 1 | being aware of full configuration. |
|
| 142 | 1 | ||
| 143 | 1 | A Puppet client that runs on a specific host (or perhaps the same |
|
| 144 | 1 | host as its Puppet Server) is generally only concerned with the |
|
| 145 | 1 | components to be configured on that host. |
|
| 146 | 1 | ||
| 147 | 1 | Puppet Clients normally request or "pull" configuration from their |
|
| 148 | 19 | Ken Barber | server. The Server processes the configuration request for the host |
| 149 | 1 | using a pre-generated tree model of the classes and definitions |
|
| 150 | 1 | from the site-config. |
|
| 151 | 1 | ||
| 152 | 1 | When configuration needs to be "pushed" to the clients, the Server |
|
| 153 | 1 | can be asked to attempt to trigger each client to request "pull" a |
|
| 154 | 1 | new host configuration. |
|
| 155 | 1 | ||
| 156 | 1 | Example: Puppet server, library |
|
| 157 | 1 | ||
| 158 | 9 | James Turnbull | You can read more about the Puppet language in the [[Language_Tutorial|Language Tutorial]]. |
| 159 | 1 | ||
| 160 | 1 | ## Realizing the Configuration |
|
| 161 | 1 | ||
| 162 | 1 | The Puppet Client Library contains the component knowledge of how |
|
| 163 | 1 | to reach desired states and configurations for several objects: |
|
| 164 | 1 | File, Package, etc. |
|
| 165 | 1 | ||
| 166 | 1 | Example: Puppet Client, library: |
|
| 167 | 1 | ||
| 168 | 1 | ...todo: file: transfer, mode, ownership... |
|
| 169 | 1 | ||
| 170 | 9 | James Turnbull | You can read more about the Puppet language in the [[Language_Tutorial|Language Tutorial]]. |
| 171 | 1 | ||
| 172 | 1 | Some components such as the webserver and firewall, from the |
|
| 173 | 12 | James Turnbull | simple-website example, require additional code to reach "closure". |
| 174 | 1 | "Closure" is when the component is entirely responsible for |
|
| 175 | 1 | implementing its own configuration. |
|
| 176 | 1 | ||
| 177 | 1 | Much as database applications abstract the mechanics of storing, |
|
| 178 | 1 | indexing, and searching their data, a component ideally should |
|
| 179 | 11 | James Turnbull | abstract the specifics of how to store, confirm, and implement its requested configuration. |