Set sysctl.conf parameters with Puppet
This was a breeze in CFEngine... But I'm in a Puppet environment now, and need to be able to assign/ensure/check certain sysctl.conf variables. In the CFEngine world, I could simply check for specific lines within a config file... I've found a small reference to a sysctl module on the Puppet wiki and a project in github that appears to do what I want.
But neither are really documented well. I'm simply looking for a way to edit a couple of values like net.core.rmem_default
and net.core.wmem_max
. In the format of the project hosted on github, the config in my init.pp manifest should look like:
class sysctl {
sysctl::value {
"net.core.rmem_default": value => "9000000";
"net.core.wmem_default": value => "9000000";
"net.core.rmem_max": value => "16777216";
"net.core.wmem_max": value => "16777216";
}
}
Going through forums and mailing lists, there seems to be confusion over the difference between Puppet plugins and modules. The terms are almost used interchangeably... I ended up needing to enable pluginsync on my clients in order to get past some hairy errors. I thought this was a module!
The current client errors:
info: Loading downloaded plugin /var/lib/puppet/lib/puppet/type/sysctl.rb
info: Loading downloaded plugin /var/lib/puppet/lib/puppet/provider/sysctl/parsed.rb
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Puppet::Parser::AST::Resource failed with error
ArgumentError: Invalid resource type sysctl::value at /var/lib/puppet/base/modules/sysctl/manifests/init.pp:12 on node shimano.deore.abc.net
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
Any thoughts on how to accomplish this with the least amount of pain?
Edit: Am I affected by this bug?
Edit: Fixed using Augeas library as suggested by Jeff Ferland and from the Puppet wiki.
I created a sysctl
module...
class sysctl {
# nested class/define
define conf ( $value ) {
# $name is provided by define invocation
# guid of this entry
$key = $name
$context = "/files/etc/sysctl.conf"
augeas { "sysctl_conf/$key":
context => "$context",
onlyif => "get $key != '$value'",
changes => "set $key '$value'",
notify => Exec["sysctl"],
}
}
file { "sysctl_conf":
name => $operatingsystem ? {
default => "/etc/sysctl.conf",
},
}
exec { "/sbin/sysctl -p":
alias => "sysctl",
refreshonly => true,
subscribe => File["sysctl_conf"],
}
}
...and another module to set the relevant settings...
class prod_sysctl {
include sysctl
sysctl::conf {
# increase PID rollover value
"kernel.pid_max": value => "1048576";
}
}
Solution 1:
Specific answer: Immediately speaking, you're calling sysctl::value, but value isn't declared in your sysctl class. See this example that uses a sysctl::conf declaration. Without the define value
, there is no sysctl::value subclass for you to call.
General answer and guidance: The Augeas construct (see also its type reference documentation) that is part of current versions of Puppet allows maintaining lines in a configuration file and even respects context, so it can manage files such as a git configuration. The example below is both to demonstrate functionality and to point you to a great reference collection of Puppet configs -- the live configuration store for Wikipedia servers.
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = https://gerrit.wikimedia.org/r/p/operations/puppet
[branch "production"]
remote = origin
merge = refs/heads/production
One simple example from the above configuration documentation would be this:
augeas { "sshd_config":
context => "/files/etc/ssh/sshd_config",
changes => [
"set PermitRootLogin no",
],
}
So, if you want to manage your /etc/sysctl.conf, enter the following:
augeas { "sysctl":
context => "/files/etc/sysctl.conf",
changes => [
"set kernel.sysrq = 0",
#and whatever other lines are interesting to you
],
}
The Augeas example also has a construct for a sysctl class based on Augeus that is similar to what you posted in your question, so that may also shed some light.
Solution 2:
I've used this module in the past with RHEL5: puppet-sysctl
To use it, you'll have to install the module to your modules folder (probably /etc/puppet/modules/sysctl) include the class on your node: (include sysctl) and then call the def resource like this:
class s_sysctl::rhel_defaults {
include sysctl
# Controls IP packet forwarding
sysctl::set_value { "net.ipv4.ip_forward":
value => 0
}
# Controls source route verification
sysctl::set_value { "net.ipv4.conf.default.rp_filter": value => 1 }
}
So you might be wondering, where does this code actually go? I like to organize my puppet tree like this:
site.pp -> nodes.pp -> roles.pp -> /etc/puppet/site-modules/s_sysctl -> /etc/puppet/modules/sysctl
So that way, site-modules contains hiera data, or tunables, and the modules stay generic, plugable and "modular".