Module: check_mk
Branch: master
Commit: be297ace6a79b4f480d7bfa4c75fcba59f16889e
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=be297ace6a79b4…
Author: Óscar Nájera <on(a)mathias-kettner.de>
Date: Thu Dec 20 18:04:58 2018 +0100
Check kubernetes Pods custom metrics, cpu, memory, fs
CMK-1476
Change-Id: I8d136d94cd405cb6a86e549e676c844cf691c332
---
checkman/k8s_pods_cpu | 13 ++++
checkman/k8s_pods_fs | 13 ++++
checkman/k8s_pods_memory | 13 ++++
checks/k8s_pods_cm | 128 +++++++++++++++++++++++++++++++++
cmk/special_agents/agent_kubernetes.py | 10 +--
5 files changed, 172 insertions(+), 5 deletions(-)
diff --git a/checkman/k8s_pods_cpu b/checkman/k8s_pods_cpu
new file mode 100644
index 0000000..684b830
--- /dev/null
+++ b/checkman/k8s_pods_cpu
@@ -0,0 +1,13 @@
+title: Kubernetes pods CPU resources
+agents: linux
+catalog: containerization/kubernetes
+license: GPL
+distribution: check_mk
+description:
+ This check monitors the pods' cpu usage inside a namespace of a Kubernetes node.
+
+item:
+ The namespace whose cpu resources are monitored
+
+inventory:
+ One service per namespace is created.
diff --git a/checkman/k8s_pods_fs b/checkman/k8s_pods_fs
new file mode 100644
index 0000000..634ee14
--- /dev/null
+++ b/checkman/k8s_pods_fs
@@ -0,0 +1,13 @@
+title: Kubernetes pods Filesystem resources
+agents: linux
+catalog: containerization/kubernetes
+license: GPL
+distribution: check_mk
+description:
+ This check monitors the pods' filesystem usage inside a namespace of a Kubernetes
node.
+
+item:
+ The namespace whose filesystem resources are monitored
+
+inventory:
+ One service per namespace is created.
diff --git a/checkman/k8s_pods_memory b/checkman/k8s_pods_memory
new file mode 100644
index 0000000..bd2569d
--- /dev/null
+++ b/checkman/k8s_pods_memory
@@ -0,0 +1,13 @@
+title: Kubernetes pods memory resources
+agents: linux
+catalog: containerization/kubernetes
+license: GPL
+distribution: check_mk
+description:
+ This check monitors the pods' memory usage inside a namespace of a Kubernetes node.
+
+item:
+ The namespace whose memory resources are monitored
+
+inventory:
+ One service per namespace is created.
diff --git a/checks/k8s_pods_cm b/checks/k8s_pods_cm
new file mode 100644
index 0000000..037969e
--- /dev/null
+++ b/checks/k8s_pods_cm
@@ -0,0 +1,128 @@
+#!/usr/bin/python
+# -*- encoding: utf-8; py-indent-offset: 4 -*-
+# +------------------------------------------------------------------+
+# | ____ _ _ __ __ _ __ |
+# | / ___| |__ ___ ___| | __ | \/ | |/ / |
+# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
+# | | |___| | | | __/ (__| < | | | | . \ |
+# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
+# | |
+# | Copyright Mathias Kettner 2018 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.
+
+from cmk.special_agents.agent_kubernetes import parse_frac_prefix
+
+
+def parse_mul_prefix(value):
+ # type: (str) -> int
+ if value.endswith('k'):
+ return 1000 * int(value[:-1])
+ return int(value)
+
+
+@get_parsed_item_data
+def check_k8s_pods_memory(item, _no_params, metrics):
+
+ rss = 0
+ swap = 0
+ usage_bytes = 0
+ max_usage_bytes = 0
+
+ for pod_data in metrics:
+ rss += parse_mul_prefix(pod_data['metrics']['memory_rss'])
+ swap += parse_mul_prefix(pod_data['metrics']['memory_swap'])
+ usage_bytes +=
parse_mul_prefix(pod_data['metrics']['memory_usage_bytes'])
+ max_usage_bytes +=
parse_mul_prefix(pod_data['metrics']['memory_max_usage_bytes'])
+
+ yield check_levels(rss, 'rss', _no_params,
human_readable_func=get_bytes_human_readable)
+ yield check_levels(swap, 'swap', _no_params,
human_readable_func=get_bytes_human_readable)
+ yield check_levels(
+ usage_bytes, 'usage_bytes', _no_params,
human_readable_func=get_bytes_human_readable)
+ yield check_levels(
+ max_usage_bytes,
+ 'max_usage_bytes',
+ _no_params,
+ human_readable_func=get_bytes_human_readable)
+
+
+check_info['k8s_pods_memory'] = {
+ 'parse_function': parse_k8s,
+ 'inventory_function': discover(),
+ 'check_function': check_k8s_pods_memory,
+ 'service_description': 'Memory usage for Pods in %s namespace',
+ 'includes': ['k8s.include'],
+}
+
+
+@get_parsed_item_data
+def check_k8s_pods_cpu(item, _no_params, metrics):
+
+ system = 0
+ user = 0
+ usage = 0
+
+ for pod_data in metrics:
+ system += parse_frac_prefix(pod_data['metrics']['cpu_system'])
+ user += parse_frac_prefix(pod_data['metrics']['cpu_user'])
+ usage += parse_frac_prefix(pod_data['metrics']['cpu_usage'])
+
+ yield check_levels(system, 'system', _no_params)
+ yield check_levels(user, 'user', _no_params)
+ yield check_levels(usage, 'usage', _no_params)
+
+
+check_info['k8s_pods_cpu'] = {
+ 'parse_function': parse_k8s,
+ 'inventory_function': discover(),
+ 'check_function': check_k8s_pods_cpu,
+ 'service_description': 'CPU usage for Pods in %s namespace',
+ 'includes': ['k8s.include'],
+}
+
+
+@get_parsed_item_data
+def check_k8s_pods_fs(item, _no_params, metrics):
+
+ inodes = 0
+ reads = 0
+ writes = 0
+ limit_bytes = 0
+ usage_bytes = 0
+
+ for pod_data in metrics:
+ inodes += parse_frac_prefix(pod_data['metrics']['fs_inodes'])
+ reads += parse_frac_prefix(pod_data['metrics']['fs_reads'])
+ writes += parse_frac_prefix(pod_data['metrics']['fs_writes'])
+ limit_bytes +=
parse_mul_prefix(pod_data['metrics']['fs_limit_bytes'])
+ usage_bytes +=
parse_mul_prefix(pod_data['metrics']['fs_usage_bytes'])
+
+ yield check_levels(inodes, 'inodes', _no_params)
+ yield check_levels(reads, 'reads', _no_params)
+ yield check_levels(writes, 'writes', _no_params)
+ yield check_levels(
+ limit_bytes, 'limit_bytes', _no_params,
human_readable_func=get_bytes_human_readable)
+ yield check_levels(
+ usage_bytes, 'usage_bytes', _no_params,
human_readable_func=get_bytes_human_readable)
+
+
+check_info['k8s_pods_fs'] = {
+ 'parse_function': parse_k8s,
+ 'inventory_function': discover(),
+ 'check_function': check_k8s_pods_fs,
+ 'service_description': 'FS usage for Pods in %s namespace',
+ 'includes': ['k8s.include'],
+}
diff --git a/cmk/special_agents/agent_kubernetes.py
b/cmk/special_agents/agent_kubernetes.py
index 5efe7a0..03951d3 100644
--- a/cmk/special_agents/agent_kubernetes.py
+++ b/cmk/special_agents/agent_kubernetes.py
@@ -95,7 +95,7 @@ def setup_logging(verbosity):
logging.basicConfig(level=lvl, format=fmt)
-def parse_cpu(value):
+def parse_frac_prefix(value):
# type: (str) -> float
if value.endswith('m'):
return 0.001 * float(value[:-1])
@@ -199,11 +199,11 @@ class Node(Metadata):
return view
capacity, allocatable = self._status.capacity, self._status.allocatable
if capacity:
- view['capacity']['cpu'] +=
parse_cpu(capacity.get('cpu', '0.0'))
+ view['capacity']['cpu'] +=
parse_frac_prefix(capacity.get('cpu', '0.0'))
view['capacity']['memory'] +=
parse_memory(capacity.get('memory', '0.0'))
view['capacity']['pods'] += int(capacity.get('pods',
'0'))
if allocatable:
- view['allocatable']['cpu'] +=
parse_cpu(allocatable.get('cpu', '0.0'))
+ view['allocatable']['cpu'] +=
parse_frac_prefix(allocatable.get('cpu', '0.0'))
view['allocatable']['memory'] +=
parse_memory(allocatable.get('memory', '0.0'))
view['allocatable']['pods'] +=
int(allocatable.get('pods', '0'))
return view
@@ -253,14 +253,14 @@ class Pod(Metadata):
continue
limits = resources.limits
if limits:
- view['limits']['cpu'] +=
parse_cpu(limits.get('cpu', 'inf'))
+ view['limits']['cpu'] +=
parse_frac_prefix(limits.get('cpu', 'inf'))
view['limits']['memory'] +=
parse_memory(limits.get('memory', 'inf'))
else:
view['limits']['cpu'] += float('inf')
view['limits']['memory'] += float('inf')
requests = resources.requests
if requests:
- view['requests']['cpu'] +=
parse_cpu(requests.get('cpu', '0.0'))
+ view['requests']['cpu'] +=
parse_frac_prefix(requests.get('cpu', '0.0'))
view['requests']['memory'] +=
parse_memory(requests.get('memory', '0.0'))
return view