- Puppet 5 Beginner's Guide(Third Edition)
- John Arundel
- 992字
- 2021-07-08 10:07:55
Services
The third most important Puppet resource type is the service: a long-running process that either does some continuous kind of work, or waits for requests and then acts on them. For example, on most systems, the sshd
process runs all the time and listens for SSH login attempts.
Puppet models services with the service
resource type. The service
resources look like the following example (you can find this in service.pp
in the /examples/
directory. From now on, I'll just give the filename of each example, as they are all in the same directory):
service { 'sshd': ensure => running, enable => true, }
The ensure
parameter governs whether the service should be running or not. If its value is running
, then as you might expect, Puppet will start the service if it is not running. If you set ensure
to stopped
, Puppet will stop the service if it is running.
Services may also be set to start when the system boots, using the enable
parameter. If enable
is set to true
, the service will start at boot. If, on the other hand, enable
is set to false
, it will not. Generally speaking, unless there's a good reason not to, all services should be set to start at boot.
Getting help on resources with puppet describe
If you're struggling to remember all the different attributes of all the different resources, Puppet has a built-in help feature that will remind you. Run the following command, for example:
puppet describe service
This will give a description of the service
resource, along with a complete list of attributes and allowed values. This works for all built-in resource types as well as many provided by third-party modules. To see a list of all the available resource types, run the following command:
puppet describe --list
The package-file-service pattern
It's very common for a given piece of software to require these three Puppet resource types: the package
resource installs the software, the file
resource deploys one or more configuration files required for the software, and the service
resource runs the software itself.
Here's an example using the MySQL database server (package_file_service.pp
):
package { 'mysql-server': ensure => installed, notify => Service['mysql'], } file { '/etc/mysql/mysql.cnf': source => '/examples/files/mysql.cnf', notify => Service['mysql'], } service { 'mysql': ensure => running, enable => true, }
The package
resource makes sure the mysql-server
package is installed.
The config file for MySQL is /etc/mysql/mysql.cnf
, and we use a file
resource to copy this file from the Puppet repo so that we can control MySQL settings.
Finally, the service
resource ensures that the mysql
service is running.
Notifying a linked resource
You might have noticed a new attribute, called notify
, in the file
resource in the previous example:
file { '/etc/mysql/mysql.cnf': source => '/examples/files/mysql.cnf', notify => Service['mysql'], }
What does this do? Imagine you've made a change to the mysql.cnf
file and applied this change with Puppet. The updated file will be written to a disk, but because the mysql
service is already running, it has no way of knowing that its config file has changed. Therefore, your changes will not actually take effect until the service is restarted. However, Puppet can do this for you if you specify the notify
attribute on the file
resource. The value of notify
is the resource to notify about the change, and what that involves depends on the type of resource that's being notified. When it's a service, the default action is to restart the service. (We'll find out about the other options in Chapter 4, Understanding Puppet resources.)
Usually, with the package-file-service pattern, the file notifies the service, so whenever Puppet changes the contents of the file, it will restart the notified service to pick up the new configuration. If there are several files that affect the service, they should all notify the service, and Puppet is smart enough to only restart the service once, however many dependent resources are changed.
The name of the resource to notify is specified as the resource type, capitalized, followed by the resource title, which is quoted and within square brackets: Service['mysql']
.
Resource ordering with require
In the package-file-service example, we declared three resources: the mysql-server
package, the /etc/mysql/mysql.cnf
file, and the mysql
service. If you think about it, they need to be applied in that order. Without the mysql-server
package installed, there will be no /etc/mysql/
directory to put the mysql.cnf
file in. Without the package or the config file, the mysql
service won't be able to run.
A perfectly reasonable question to ask is, "Does Puppet apply resources in the same order in which they're declared in the manifest?" The answer is usually yes, unless you explicitly specify a different order, using the require
attribute.
All resources support the require
attribute, and its value is the name of another resource declared somewhere in the manifest, specified in the same way as when using notify
. Here's the package-file-service example again, this time with the resource ordering specified explicitly using require
(package_file_service_require.pp
):
package { 'mysql-server': ensure => installed, } file { '/etc/mysql/mysql.cnf': source => '/examples/files/mysql.cnf', notify => Service['mysql'], require => Package['mysql-server'], } service { 'mysql': ensure => running, enable => true, require => [Package['mysql-server'], File['/etc/mysql/mysql.cnf']], }
You can see that the mysql.cnf
resource requires the mysql-server
package. The mysql
service requires both the other resources, listed as an array within square brackets.
When resources are already in the right order, you don't need to use require
, as Puppet will apply the resources in the order you declare them. However, it can be useful to specify an ordering explicitly, for the benefit of those reading the code, especially when there are lots of resources in a manifest file.
In older versions of Puppet, resources were applied in a more or less arbitrary order, so it was much more important to express dependencies using require
. Nowadays, you won't need to use it very much, and you'll mostly come across it in legacy code.