banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Containers

banshee/containers-collection/containers/kubernetes/https/

events

How many warning events each reason counts in a Kubernetes cluster, by its API.

  • containers
  • kubernetes
  • k8s
  • events
  • warning
  • https
  • api

by banshee1 installation1 version

v1Latest

Published on October 27, 2026. First version.

Keen 1.0.0 · 89 lines
// The warning events of a Kubernetes cluster, or of one namespace, by its API with the token of a service
// account (GET /api/v1/events?fieldSelector=type=Warning, or /api/v1/namespaces/<namespace>/events): how
// many times each reason was reported (BackOff, FailedScheduling, FailedMount, Unhealthy...). The API keeps
// an event one hour by default (the --event-ttl of the API server): the counts are those of that window.
// Its watch is not checked by default: a cluster in good health reports warnings too.
// The address is the API server's, the host's: https://<host:address>:<port>/.
need('protocol:http');
$address = need('host:address');
$token = need('protocol:http:token');
$port = variable('kubernetes:port', 'integer', array(
    'label'   => 'API port',
    'help'    => 'The port of the Kubernetes API server: 6443 for a cluster set up by kubeadm, often 443 for a managed one.',
    'default' => 6443,
));
$namespace = variable('kubernetes:namespace', 'text', array(
    'label'    => 'Namespace',
    'help'     => 'Only the events of this namespace, for a service account allowed in it alone. Empty: all namespaces.',
    'required' => false,
));

per('reason', 'Reasons');
output('count', 'number', array('label' => 'Warnings', 'per' => 'reason'));

watch.above('warnings', 'Warning events', 'count', array('warning' => 0, 'enabled' => false));

// The items of a list, read page by page: the API cuts a list at limit items and gives, under
// metadata.continue, the token of the next page, until the last. $query, when not empty, is added to the
// parameters of the address. The token goes in the header Authorization: Bearer; the answer is not secret,
// its body having carried none.
function api_list($base, $path, $query, $token) {
    $items = array();
    $next = '';
    while (true) {
        $url = $base . $path . '?limit=500';
        if ($query != '') {
            $url = $url . '&' . $query;
        }
        if ($next != '') {
            $url = $url . '&continue=' . url.encode($next);
        }
        $answer = http.get($url, headers=array('Authorization' => 'Bearer ' . $token));
        if ($answer['status'] == 401) {
            fail('misconfigured', 'Kubernetes refuses the token, code 401');
        }
        if ($answer['status'] == 403) {
            fail('misconfigured', 'The service account may not list ' . $path . ', code 403');
        }
        if ($answer['status'] != 200) {
            fail('unreachable', 'Kubernetes answers ' . $path . ' with code ' . $answer['status']);
        }
        $page = json.read($answer['body']);
        foreach ($page['items'] as $item) {
            $items = list.add($items, $item);
        }
        $next = list.get($page['metadata'], 'continue', '');
        if ($next == '') {
            break;
        }
    }
    return $items;
}

$path = '/api/v1/events';
if ($namespace != '') {
    $path = '/api/v1/namespaces/' . url.encode($namespace) . '/events';
}

// {"type": "Warning", "reason": "BackOff", "count": 12, "involvedObject": {...}, "message": "..."}. How many
// times the event occurred: series.count when the event is a series, count otherwise; an event that writes
// neither occurred once.
$counts = array();
foreach (api_list('https://' . $address . ':' . $port, $path, 'fieldSelector=' . url.encode('type=Warning'), $token) as $event) {
    $reason = list.get($event, 'reason', '');
    if ($reason == '') {
        $reason = 'unknown';
    }
    $seen = list.get($event, 'count', 0);
    $series = list.get($event, 'series', array());
    if (list.has($series, 'count')) {
        $seen = $series['count'];
    }
    if ($seen < 1) {
        $seen = 1;
    }
    $counts[$reason] = list.get($counts, $reason, 0) + $seen;
}
foreach ($counts as $reason => $count) {
    value('count', $count, $reason);
}