Module: check_mk
Branch: master
Commit: 4fe5cad19fe28d84dc6c744ae1f141aed26d0db5
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=4fe5cad19fe28d…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Apr 19 12:27:16 2018 +0200
5988 docker_container_diskstat: Check disk usage of docker containers
Change-Id: I3fe1d5bf03fbe8760e3eeea7d73e6cd6a62bee92
---
.werks/5988 | 11 +++
agents/check_mk_agent.linux | 7 ++
checkman/docker_container_diskstat | 20 ++++++
checks/docker_container_diskstat | 136 +++++++++++++++++++++++++++++++++++++
4 files changed, 174 insertions(+)
diff --git a/.werks/5988 b/.werks/5988
new file mode 100644
index 0000000..5f41f30
--- /dev/null
+++ b/.werks/5988
@@ -0,0 +1,11 @@
+Title: docker_container_diskstat: Check disk usage of docker containers
+Level: 1
+Component: checks
+Class: feature
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.6.0i1
+Date: 1524133606
+
+
diff --git a/agents/check_mk_agent.linux b/agents/check_mk_agent.linux
index c4fbf40..b172403 100755
--- a/agents/check_mk_agent.linux
+++ b/agents/check_mk_agent.linux
@@ -489,10 +489,17 @@ if [ -z "$MK_IN_CONTAINER" ]; then
fi
else
echo '<<<docker_container_diskstat>>>'
+ echo "[time]"
+ date +%s
for F in io_service_bytes io_serviced; do
echo "[$F]"
cat "/sys/fs/cgroup/blkio/blkio.throttle.$F"
done
+ echo "[names]"
+ for F in /sys/block/*; do
+ echo -n "${F##*/} " ;
+ cat "$F/dev";
+ done
fi
diff --git a/checkman/docker_container_diskstat b/checkman/docker_container_diskstat
new file mode 100644
index 0000000..6df80a0
--- /dev/null
+++ b/checkman/docker_container_diskstat
@@ -0,0 +1,20 @@
+title: Docker container disk throughput
+agents: linux
+catalog: app/docker
+license: GPL
+distribution: check_mk
+description:
+ This check measures the throughput of block devices (disks) of docker
+ containers. You can either have a single check for every single disk or a
+ summary check (which is the default) summing up the throughput of all disks.
+
+ This check measures the memory usage of a docker container respecting
+ either the memory limits of the docker node or the limit configured
+ for the container.
+
+ Use the "Main memory usage (UNIX / Other Devices)" rule set to configure
+ thresholds on the memory usage.
+
+item:
+ Either {"SUMMARY"} for a summarized check of all disks or the name of the
+ disk device, e.g. {"sda"}.
diff --git a/checks/docker_container_diskstat b/checks/docker_container_diskstat
new file mode 100644
index 0000000..695ea2c
--- /dev/null
+++ b/checks/docker_container_diskstat
@@ -0,0 +1,136 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2014 mk(a)mathias-kettner.de |
+# +------------------------------------------------------------------+
+#
+# This file is part of Check_MK.
+# The official homepage is at
http://mathias-kettner.de/check_mk.
+#
+# check_mk 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 in version 2. check_mk is distributed
+# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
+# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU General Public License for more de-
+# tails. You should have received a copy of the GNU General Public
+# License along with GNU Make; see the file COPYING. If not, write
+# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301 USA.
+
+def parse_docker_container_diskstat(info):
+ node_sections = _parse_sub_sections(info)
+
+ disks = {}
+ for node_name, node_info in node_sections.items():
+ timestamp = node_info["time"]
+
+ for device_id, device in node_info["devices"].items():
+ # Filter out unwanted things
+ if device["name"].startswith("loop"):
+ continue
+
+ # Skip devices without counts
+ if "ios" not in device or "bytes" not in device:
+ continue
+
+ disks[(node_name, device["name"])] = timestamp, device
+
+ return disks
+
+
+def _parse_sub_sections(info):
+ node_sections = {}
+
+ node = None
+ for line in info:
+ node = line[0]
+
+ if line[1] == "[io_service_bytes]":
+ phase = "bytes"
+ elif line[1] == "[io_serviced]":
+ phase = "ios"
+ elif line[1] == '[names]':
+ phase = "names"
+ elif line[1] == '[time]':
+ phase = "time"
+ else:
+ if line[1] == "Total":
+ continue
+
+ sections = node_sections.setdefault(node, {})
+
+ if phase == "time":
+ sections["time"] = int(line[1])
+ continue
+
+ devices = sections.setdefault("devices", {})
+
+ if phase == "names":
+ major, minor = map(int, line[2].split(":"))
+ else:
+ major, minor = map(int, line[1].split(":"))
+
+ device_id = node, major, minor
+ device = devices.setdefault(device_id, {})
+
+ if phase == "names":
+ device["name"] = line[1]
+ else:
+ device_phase = device.setdefault(phase, {})
+ device_phase[line[2]] = int(line[3])
+
+ return node_sections
+
+
+def inventory_docker_container_diskstat(parsed):
+ return inventory_diskstat_generic(parsed.keys())
+
+
+def check_docker_container_diskstat(item, params, parsed):
+ disks = {}
+ for (node_name, device_name), (timestamp, device) in parsed.items():
+ counter_base = "diskstat.%s." % device_name
+
+ # Docker container information is provided via piggyback in the most cases. In
case
+ # we got no new data simply skip this check
+ previous_timestamp = get_item_state(counter_base + "time")
+ if previous_timestamp == timestamp:
+ raise MKCounterWrapped('No time difference')
+ set_item_state(counter_base + "time", timestamp)
+
+ read_ios_rate = get_rate(counter_base + "read_ios", timestamp,
device["ios"]["Read"], onwrap=0.0)
+ write_ios_rate = get_rate(counter_base + "write_ios", timestamp,
device["ios"]["Write"], onwrap=0.0)
+ total_ios_rate = read_ios_rate + write_ios_rate
+ read_bytes_rate = get_rate(counter_base + "read_bytes", timestamp,
device["bytes"]["Read"], onwrap=0.0)
+ write_bytes_rate = get_rate(counter_base + "write_bytes", timestamp,
device["bytes"]["Write"], onwrap=0.0)
+ total_bytes_rate = read_bytes_rate + write_bytes_rate
+
+ disks[device_name] = {
+ "node" : node_name,
+ "read_ios" : read_ios_rate,
+ "write_ios" : write_ios_rate,
+ "read_throughput" : read_bytes_rate,
+ "write_throughput" : write_bytes_rate,
+ }
+
+ return check_diskstat_dict(item, params, disks)
+
+
+check_info["docker_container_diskstat"] = {
+ "parse_function" : parse_docker_container_diskstat,
+ "inventory_function" : inventory_docker_container_diskstat,
+ "check_function" : check_docker_container_diskstat,
+ "service_description" : "Disk IO %s",
+ "has_perfdata" : True,
+ "group" : "diskstat",
+ "node_info" : True, # add first column with actual host name
+ "includes" : [ "diskstat.include" ],
+}
+