diff --git a/Dockerfile b/Dockerfile index 515f7e4..6d0b36b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,20 +14,33 @@ RUN apt-get update && \ libapache2-mod-fcgid \ libcgi-fast-perl \ ssmtp \ + perl \ mailutils \ curl tzdata \ + munin-node \ autoconf \ + libfile-readbackwards-perl \ && apt-get clean && \ rm -rf /var/lib/apt/lists/* /var/tmp/* /tmp/* RUN (cp /etc/munin/apache24.conf /etc/apache2/sites-available/000-default.conf) && \ (sed -i 's/^Alias.*/Alias \/ \/var\/cache\/munin\/www\//g' /etc/apache2/sites-available/000-default.conf) && \ - (sed -i 's/Allow from .*/Satisfy Any/g' /etc/apache2/sites-available/000-default.conf) && \ + (sed -i 's/Allow from .*/Satisfy Any/g' /etc/apache2/sites-available/000-default.conf) && \ (sed -i 's/Order allow,deny.*/Allow from all/g' /etc/apache2/sites-available/000-default.conf) && \ (mkdir -p /var/run/munin && \ chown -R munin:munin /var/run/munin) && \ (chfn -f 'munin' root) && \ - (/usr/sbin/a2enmod fcgid) + (/usr/sbin/a2enmod fcgid) && \ + rm -rf /etc/munin/plugins && \ + mkdir -p /etc/munin/plugins + +COPY run.sh /usr/local/bin/run +COPY munin_stats /etc/munin/plugins/munin_stats +COPY munin_update /etc/munin/plugins/munin_update + +RUN chmod +x /etc/munin/plugins/munin_stats && \ + chmod +x /etc/munin/plugins/munin_update && \ + chmod +x /usr/local/bin/run COPY 000-default.conf /etc/apache2/sites-available/000-default.conf COPY logrotate-munin /etc/logrotate.d/munin @@ -36,10 +49,6 @@ COPY ssmtp.conf /etc/ssmtp/ssmtp.conf COPY revaliases /etc/ssmtp/revaliases COPY munin_mail.conf /etc/munin/munin-conf.d/munin_mail.conf -# copy launcher -COPY run.sh /usr/local/bin/run -RUN chmod +x /usr/local/bin/run - # persist VOLUME /var/lib/munin VOLUME /var/log/munin @@ -47,5 +56,9 @@ VOLUME /var/cache/munin EXPOSE 80 +# health check +HEALTHCHECK --interval=5m --timeout=3s \ + CMD curl -f http://localhost/munin/ || exit 1 + # launcher CMD ["/usr/local/bin/run"] diff --git a/munin.conf b/munin.conf index 83e7199..014f553 100644 --- a/munin.conf +++ b/munin.conf @@ -1,3 +1,7 @@ includedir /etc/munin/munin-conf.d +[munin-container] + address localhost + use_node_name yes + # remote host diff --git a/munin_stats b/munin_stats new file mode 100644 index 0000000..c03cab0 --- /dev/null +++ b/munin_stats @@ -0,0 +1,118 @@ +#!/usr/bin/perl +# +# Copyright (C) 2006-2009 Rodolphe QuiƩdeville +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 dated June, +# 1991. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# +# Magic markers (used by munin-node-configure and some installation scripts): +#%# family=auto +#%# capabilities=autoconf + +use strict; +use warnings; + +use Munin::Plugin; + + +my $missing_module = undef; +$missing_module = "File::ReadBackwards" unless (eval "require File::ReadBackwards"); + +my @logs = qw/update graph html limits/; +my $logdir = ($ENV{'logdir'} || $ENV{'MUNIN_LOGDIR'} || '/var/log/munin'); + +if ($ENV{'fields'}) { + @logs = split(/ +/, $ENV{'fields'}); +} + +sub uses_graph_cron { + my $log_file = $_[0]; + my $bw = File::ReadBackwards->new($log_file) or + die "can't read 'log_file' $!"; + if (defined(my $log_line = $bw->readline)) { + if ($log_line =~ ('.*graphing is cgi, do nothing$')) { + return 0; + } else { + return 1; + } + } else { + return 1; + } +} + + +if ($ARGV[0] and $ARGV[0] eq 'autoconf') { + my $munin_update_location = + "$Munin::Common::Defaults::MUNIN_LIBDIR/munin-update"; + + if (! -e $munin_update_location) { + print "no (munin-update was not found at $munin_update_location)\n"; + } elsif (! -x $munin_update_location) { + print "no ($munin_update_location was found, but is not executable)\n"; + } elsif (defined($missing_module)) { + print "no (missing Perl module: '$missing_module')\n"; + } else { + print "yes\n"; + } + exit 0; +} + +if ($ARGV[0] and $ARGV[0] eq "config") { + print "graph_title Munin processing time\n", + "graph_info This graph shows the run time of the four different processes making up a munin-master run. Munin-master is run from cron every 5 minutes and we want each of the programmes in munin-master to complete before the next instance starts. If munin-update uses too long time to run please see the munin-update graph to determine which host is slowing it down.\n", + "graph_args --base 1000 -l 0\n", + "graph_scale yes\n", + "graph_vlabel seconds\n", + "graph_category munin\n"; + foreach my $log (@logs) { + print "$log.label munin $log\n"; + print "$log.draw AREASTACK\n"; + + next unless $log eq "update" || $log eq "graph"; + + print_thresholds("$log", undef, undef, 240, 285); + } + exit 0; +} + + +if (defined($missing_module)) { + die "Failed to run due to missing Perl module '$missing_module'"; +} + +foreach my $log (@logs) { + my $logfile = "$logdir/munin-$log.log"; + my $time = 'U'; + + if (! -r $logfile) { + print "$log.extinfo Can't open $logfile for reading\n"; + print "$log.value $time\n"; + next; + } + + my $bw = File::ReadBackwards->new("$logdir/munin-$log.log") or + die "can't read 'log_file' $!"; + my $found_previous_finished = 0; + while(defined(my $log_line = $bw->readline) && $found_previous_finished == 0) { + if ($log_line =~ (/(finished|generated) \((\d+\.\d+)\ssec\)$/)) { + $time = $2; + $found_previous_finished = 1; + } + } + + if ($log ne "graph" || uses_graph_cron("$logdir/munin-$log.log")) { + print "$log.value $time\n"; + } +} diff --git a/munin_update b/munin_update new file mode 100644 index 0000000..174d87d --- /dev/null +++ b/munin_update @@ -0,0 +1,123 @@ +#!/bin/sh + +: <<=cut + +=head1 NAME + +munin_update - Munin plugin to graph the time to query about each host from the nodes. + +=head1 APPLICABLE SYSTEMS + +Munin master servers. + +=head1 CONFIGURATION + +Normally needs no configuration. You may configure it with the +following parameter: + + [munin*] + env.UPDATE_STATSFILE .../munin-update.stats + env.MUNIN_UPDATE_LOCACTION .../munin-update + +The first is the statistics file for munin update. + +The exact location of this file is package/site specific, but +munin_update will know where it is unless you have made changes. + +=head1 INTERPRETATION + +The script reads the munin-update "stats" file to determine how long +it takes to query the nodes about each host configured in Munin. + +Munin is run from cron every 5 minutes and before the next run of +munin-update the previous run needs to be done. Each run of +munin-update forks one process pr. host that needs to get data +collected, so all collection runs in parallel. + +Any host that is slow, for example slower than 4 miniutes, causes a +risk that the next run of munin-update must be canceled due to the +lateness of the previous run. In such cases there will be single line +gaps in the "by day" graph. + +Keep your hosts updating quickly and all will be well. + +=head1 MAGIC MARKERS + + #%# family=manual + #%# capabilities=autoconf + +=head1 BUGS + +Munin-update is always run at the same time as this plugin runs - +therefore the stats file may be incompletely written and the plugin +will likely show a incomplete list of hosts. It should be using +munin-update.old-stats, which is not currently even made. + +Munin-update removes the "domain" information on all hosts. If there +are two hosts with the same host name in different domains then one of +them will be disappeared by the munin-update collection process. + +=head1 AUTHOR + +The munin_update plugin has been included in munin for many years (at +least 2004). The most likely author is one of the original munin team. + +Documentation and updating to 2009 for Munin 1.4 by Nicolai Langfeldt. + +(C) 2004-2009 The Munin Team, Redpill Linpro AS + +=head1 LICENSE + +GPLv2 + +=cut + +. "$MUNIN_LIBDIR/plugins/plugin.sh" + + +UPDATE_STATSFILE=${UPDATE_STATSFILE:-$MUNIN_DBDIR/munin-update.stats} +MUNIN_UPDATE_LOCATION=${MUNIN_UPDATE_LOCATION:-$MUNIN_LIBDIR/munin-update} + + +if [ "$1" = "autoconf" ]; then + if [ -e "$MUNIN_UPDATE_LOCATION" ] ; then + echo "yes" + else + echo "no ($MUNIN_UPDATE_LOCATION is not present so this is not a munin-master)" + fi + exit 0 +fi + +if [ "$1" = "config" ]; then + [ -f "$UPDATE_STATSFILE" ] || { + echo 'graph_title Plugin error' + echo "graph_info Plugin cannot read stats file $UPDATE_STATSFILE" + echo 'error.label Error' + echo 'error.critical 1' + exit 0 + } + + echo 'graph_title Munin-update' + echo 'graph_vlabel seconds' + echo 'graph_category munin' + echo 'graph_info This graph shows the time it takes to collect data from each hosts that munin collects data on. Munin-master is run from cron every 5 minutes and we want each of the munin-update runs to complete before the next one starts. If munin-update uses too long time to run on one host run it with --debug to determine which plugin(s) are slow and solve the problem with them if possible.' + sed '/^UD|/!d; s/.*;//; s/|/ /;' < "$UPDATE_STATSFILE" | sort | + while read -r i j; do + name="$(clean_fieldname "$i")" + echo "$name.label $i" + warning=${warning:-240} critical=${critical:-285} print_thresholds "$name" + done + exit 0 +fi + +[ -f "$UPDATE_STATSFILE" ] || { + echo 'error.value 1' + echo "error.extinfo Plugin cannot read stats file $UPDATE_STATSFILE" + exit 0 +} + +sed '/^UD|/!d; s/.*;//; s/|/ /;' < "$UPDATE_STATSFILE" | sort | +while read -r i j; do + name="$(clean_fieldname "$i")" + echo "$name.value $j" +done diff --git a/run.sh b/run.sh index 34aa4d2..1991426 100644 --- a/run.sh +++ b/run.sh @@ -23,10 +23,6 @@ sed -i "s/^\( *address\) 127\.0\.0\.1\$/\1 $THISNODEIP/" /etc/munin/munin.conf THISSERVERNAME=${SERVERNAME:="munin"} sed -i "s/^\[localhost\.localdomain\]/\[$SERVERNAME\]/g" /etc/apache2/sites-available/000-default.conf -if [[ $DISABLELOCALNODE == "yes" ]] ; then - echo "includedir /etc/munin/munin-conf.d" > /etc/munin/munin.conf -fi - # configure mail notification if [[ -n "$MAILCONTACT" && -n "$MAILSERVER" && -n "$MAILPORT" && -n "$MAILUSER" && -n "$MAILPASSWORD" && -n "$MAILDOMAIN" ]] ; then