by R.I. Pienaar | Jul 3, 2010 | Code
A very typical scenario I come across on many sites is the requirement to monitor something like Puppet across 100s or 1000s of machines.
The typical approaches are to add perhaps a central check on your puppet master or to check using NRPE or NSCA on every node. For this example the option exist to easily check on the master and get one check but that isn’t always easily achievable.
Think for example about monitoring mail queues on all your machines to make sure things like root mail isn’t getting stuck. In those cases you are forced to do per node checks which inevitably result in huge notification storms in the event that your mail server was down and not receiving the mail from the many nodes.
MCollective has had a plugin that can run NRPE commands for a long time, I’ve now added a nagios plugin using this agent to combine results from many hosts.
Sticking with the Puppet example, here are my needs:
- I want to know if anywhere some puppet machine isn’t successfully doing runs.
- I want to be able to do puppetd –disable and not get alerts for those machines.
- I do not want to change any configs when I am adding new machines, it should just work.
- I want the ability to do monitoring on subsets of machines on different probes
This is a pretty painful set of requirements for nagios on its own to achieve. Easy with the help of MCollective.
Ultimately, I just want this:
OK: 42 WARNING: 0 CRITICAL: 0 UNKNOWN: 0 |
OK: 42 WARNING: 0 CRITICAL: 0 UNKNOWN: 0
Meaning 42 machines – only ones currently enabled – are all running happily.
The NRPE Check
We put the NRPE logic on every node. A simple check command in /etc/nagios/nrpe.d/check_puppet_run.cfg:
command[check_puppet_run]=/usr/lib/nagios/plugins/check_file_age -f /var/lib/puppet/state/state.yaml -w 5400 -c 7200 |
command[check_puppet_run]=/usr/lib/nagios/plugins/check_file_age -f /var/lib/puppet/state/state.yaml -w 5400 -c 7200
In my case I just want to know there are successful runs happening, if I wanted to know the code is actually compiling correctly I’d monitor the local cache age and size.
Determining if Puppet is enabled or not
Currently this is a bit hacky, I’ve filed tickets with Puppet Labs to improve this. The way to determine if puppet is disabled is to check if the lock file exist and if its 0 bytes. If it’s not zero bytes it means a puppetd is currently doing a run – there will be a pid in it. Or the puppetd crashed and there’s a stale pid preventing other runs.
To automate this and integrate into MCollective I’ve made a fact puppet_enabled. We’ll use this in MCollective discovery to only monitor machines that are enabled. Get this onto all your nodes perhaps using Plugins in Modules.
The MCollective Agent
You want to deploy the MCollective NRPE Agent to all your nodes, once you’ve got it right you can test it easily using something like this:
% mc-nrpe -W puppet_enabled=1 check_puppet_run
* [ ============================================================> ] 47 / 47
Finished processing 47 / 47 hosts in 395.51 ms
OK: 47
WARNING: 0
CRITICAL: 0
UNKNOWN: 0 |
% mc-nrpe -W puppet_enabled=1 check_puppet_run
* [ ============================================================> ] 47 / 47
Finished processing 47 / 47 hosts in 395.51 ms
OK: 47
WARNING: 0
CRITICAL: 0
UNKNOWN: 0
Note we’re restricting the run to only enabled hosts.
Integrating into Nagios
The last step is to add this to nagios. I create SSL certs and a specific client configuration for Nagios and put these in it’s home directory.
The check-mc-nrpe plugin works best with Nagios 3 as it will return subsequent lines of output indicating which machines are in what state so you get the details hidden behind the aggregation in alerts. It also outputs performance data for total node, each status and also how long it took to do the check.
The nagios command would be something like this:
define command{
command_name check_mc_nrpe
command_line /usr/sbin/check-mc-nrpe --config /var/log/nagios/.mcollective/client.cfg -W $ARG1$ $ARG2$
} |
define command{
command_name check_mc_nrpe
command_line /usr/sbin/check-mc-nrpe --config /var/log/nagios/.mcollective/client.cfg -W $ARG1$ $ARG2$
}
And finally we need to make a service:
define service{
host_name monitor1
service_description mc_puppet-run
use generic-service
check_command check_mc_nrpe!puppet_enabled=1!check_puppet_run
notification_period awakehours
contact_groups sysadmin
} |
define service{
host_name monitor1
service_description mc_puppet-run
use generic-service
check_command check_mc_nrpe!puppet_enabled=1!check_puppet_run
notification_period awakehours
contact_groups sysadmin
}
Here are a few other command examples I use:
All machines with my Puppet class “pki”, check the age of certs:
check_command check_mc_nrpe!pki!check_pki |
check_command check_mc_nrpe!pki!check_pki
All machines with my Puppet class “bacula::node”, make sure the FD is running:
check_command check_mc_nrpe!bacula::node!check_fd |
check_command check_mc_nrpe!bacula::node!check_fd
…and that they were backed up:
check_command check_mc_nrpe!bacula::node!check_bacula_main |
check_command check_mc_nrpe!bacula::node!check_bacula_main
Using this I removed 100s of checks from my monitoring platform, saving on resources and making sure I can do my critical monitor tasks better.
Depending on the quality of your monitoring system you might even get a graph showing the details hidden behind the aggregation:
The above is a graph showing a series of servers where the backup ran later than usual, I had 2 alerts only, would have had more than 30 before aggregation.
Restrictions for Probes
The last remaining requirement I had was to be able to do checks on different probes and restrict them. My Collective is one big one spread all over the world which means sometimes things are a bit slow discovery wise.
So I have many nagios servers doing local checks. Using MCollective discovery I can now easily restrict checks, for example If I only wanted to check machines in the USA and I had a fact country I only have to change my command line in the service declaration:
check_command check_mc_nrpe!puppet_enabled=1 country=us!check_puppet_run |
check_command check_mc_nrpe!puppet_enabled=1 country=us!check_puppet_run
This will then via MCollective discovery just monitor machines in the US.
What to monitor this way
As this style of monitoring is done using Discovery you would need to think carefully about what you monitor this way. It’s totally conceivable that if a node is under high CPU load that it wont respond to discovery commands in time, and so wont get monitored!
You would then for example not want to monitor things like load averages or really critical services this way, but we all have a lot of peripheral things like zombie process counts and a lot of other places where aggregation makes a lot of sense, in those cases by all means consider this approach.
by R.I. Pienaar | Jun 27, 2010 | Code
I’ve recorded a screencast that walks you through the process of developing a SimpleRPC Agent, give it a DDL and also a simple client to communicate with it.
The tutorial creates a small echo agent that takes input and return it unmodified. It validates that you are sending a string and has a sample of dealing with intermittent failure.
Once you’ve watched this, or even during, you can use the following links are reference material: Writing Agents, Data Definition Language and Writing Clients.
You can view it directly on blip.tv which will hopefully be better quality.
I used a few VIM Snippets during the demo to boilerplate the agent and DDL, you’ll find these in the tarball for the upcoming 0.4.7 release in the ext/vim directory, they are already on GitHub too.
by R.I. Pienaar | Jun 25, 2010 | Uncategorized
I mentioned in my recent post about mcollective Road Map about the DDL.
The DDL is used to describe agents in a way that is accessible by other programs, web applications, client libraries and so forth to help those various client tools to configure themselves correctly.
An actual example of a DDL file can be found here if you want to have a good look at it and full docs here.
I’ve created a short video showing the DDL and some of the features of the upcoming 0.4.7 release, you probably want to view it full screen to really see what’s going on.
And a quick note about the colors, I know people tend to feel strongly about this kind of thing, you can disable them in the config file of the client ๐
This is also my first attempt at using blip.tv, please let me know if you see any problems.
by R.I. Pienaar | Jun 14, 2010 | Code
I’ve had two successive Marionette Collective releases recently, I was hoping to have one big one but I was waiting for the Stomp maintainers to do a release and it was taking a while.
These two releases are both major feature releases covering major feature sets. See lower down for a breakdown of it all.
We’re nearing feature completeness for the SimpleRPC layer as I am adding a number of features of interest to Enterprise and Large users especially around security and web UIs.
Once we’re at the end of this cycle I’ll do a 1.0.0 release and then from there move onto the next major feature cycle. The next cycle will focus on queuing long running tasks, background scheduling, future scheduling of tasks and a lot of related work. I posted some detail about these plans to the list recently.
Over the new few days or weeks I’ll do a number of Screencasts exploring some of these new features in depth, for now the list of what’s new:
Security
Connectivity
We can use Ruby Gem Stomp 1.1.6 which brings a lot of enhancements:
-
Connection pools for failover between multiple ActiveMQs
- Lots of tunables about the connection pools such as retry frequencies etc
- SSL TLS between node and ActiveMQ
Writing Web and Dynamic UIs
- A DDL that describes agents, inputs and outputs:
- Creates auto generated documentation
- Can be used to auto generate user interfaces
- The client library will only make requests that validate against the DDL
- In future input validations will move into the DDL and will be done automatically for you
- Web UI’s can bypass or do their own discovery and use the DDL to auto generate user interfaces
Usability
-
Fire-and-Forget style requests, for when you just want something done but do not care about results, these requests are very quick as they do not do any discovery.
- Agents can now be reloaded without restarting the daemon
- A new mc-inventory tool that can be used to view facts, agents and classes for a node
- Many UI enhancements to the CLI tools
by R.I. Pienaar | May 23, 2010 | Uncategorized
The unix pgrep utility is great, it lets you grep through your process list and find interesting things. I wanted to do something similar but for my entire server group so built something quick ontop of MCollective.
I am using the Ruby sys-proctable gem to do the hard work, it returns a massive amount of information about each process and have written a simple agent on top of this.
The agent supports grepping the process tree but also supports kill and pgre+kill though I have not yet implemented more than the basic grep on the command line. Frankly the grep+kill combination scares me and I might remove it. A simple grep slipup and you will kill all processes on all your machine ๐ Sometimes too much power is too much and should just be avoided.
At the moment mc-pgrep outputs a set format but I intend to make that configurable on the command line, here’s a sample:
% mc-pgrep -C /dev_server/ ruby
* [ ============================================================> ] 4 / 4
dev1.my.com
root 9833 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
root 21608 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
dev2.my.com
root 14568 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
root 31595 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
dev3.my.com
root 1620 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
root 14093 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
dev4.my.com
root 3231 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
root 20557 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
---- process list stats ----
Matched hosts: 4
Matched processes: 8
Resident Size: 37.264KB
Virtual Size: 629.578MB |
% mc-pgrep -C /dev_server/ ruby
* [ ============================================================> ] 4 / 4
dev1.my.com
root 9833 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
root 21608 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
dev2.my.com
root 14568 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
root 31595 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
dev3.my.com
root 1620 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
root 14093 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
dev4.my.com
root 3231 /usr/lib/ruby/gems/1.8/gems/passenger-2.2.2/lib/phusion_pass
root 20557 ruby /usr/sbin/mcollectived --pid=/var/run/mcollectived.pid
---- process list stats ----
Matched hosts: 4
Matched processes: 8
Resident Size: 37.264KB
Virtual Size: 629.578MB
You can also limit it to only find zombies with the -z option.
This has been quite interesting for me, if I limit the pgrep to “.” (the pattern is regex) every machine will send back a Sys::ProcTable hash for all its processes. This is a 50 to 70 KByte payload per server. I’ve so far seen no problem getting his much traffic through ActiveMQ + MCollective and processing it all in a very short time:
% time mc-pgrep -F "country=/uk|us/" .
---- process list stats ----
Matched hosts: 20
Matched processes: 1958
Resident Size: 1.777MB
Virtual Size: 60.072GB
mc-pgrep -F "country=/uk|us/" . 0.19s user 0.06s system 7% cpu 3.420 total |
% time mc-pgrep -F "country=/uk|us/" .
---- process list stats ----
Matched hosts: 20
Matched processes: 1958
Resident Size: 1.777MB
Virtual Size: 60.072GB
mc-pgrep -F "country=/uk|us/" . 0.19s user 0.06s system 7% cpu 3.420 total
That 3.4 seconds is with a 2 second discovery overhead client machine in Germany and the filter matching UK and US machines – all the way to the West Coast – my biggest delay here is network and not MC or ActiveMQ.
The code can be found at my GitHub account and still a bit of a work in progress, wiki pages will follow once I am happy with it.
And as an aside, I am slowly migrating at least my code to GitHub if not wiki and ticketing. So far my Plugins have moved, MC will move soon too.