Add Docker scripts

This commit is contained in:
Daniel Berteaud 2022-01-12 16:23:50 +01:00
parent a73021a2d5
commit a24f4adb81
4 changed files with 728 additions and 0 deletions

9
zabbix_conf/docker.conf Normal file
View File

@ -0,0 +1,9 @@
# Discover Docker items
# $1 can be containers, networks, volumes
UserParameter=container.docker.discovery[*],/usr/bin/sudo /var/lib/zabbix/bin/disco_docker_sudo --what $1
# Type: Agent or Agent (active)
# container.docker.check.all[type,id]
# Where type is what to monitor (global, container, network, volume)
# id is the id of the item to monitor. Can be a name or an ID. For the global check, there's no ID
UserParameter=container.docker.check[*],/usr/bin/sudo /var/lib/zabbix/bin/check_docker_sudo --$1 $2

View File

@ -0,0 +1,90 @@
#!/usr/bin/perl
use strict;
use warnings;
use JSON;
use Getopt::Long;
use File::Which;
use Date::Parse;
my $docker = which('docker');
my $json = {};
my $pretty = 0;
my ($global, $container, $network, $volume) = undef;
GetOptions(
'global' => \$global,
'container=s' => \$container,
'network=s' => \$network,
'volume=s' => \$volume,
'pretty' => \$pretty
);
# Sanitize args
if (defined $container and not $container =~ m/^[a-zA-Z0-9\-_]+/){
die "Invalid container ID $container\n";
} elsif (defined $network and not $network =~ m/^[a-zA-Z0-9\-_]+/){
die "Invalid network ID\n";
} elsif (defined $volume and not $volume =~ m/^[a-zA-Z0-9\-_]+/){
die "Invalid volume name\n";
}
# Default formating
my $format = '{{ json . }}';
my $cmd;
if ($global){
$json->{info} = from_json(qx($docker info --format '$format'));
} elsif (defined $container) {
$json->{inspect} = from_json(qx($docker container inspect $container --format '$format'));
$json->{stats} = from_json(qx($docker container stats $container --format '$format' --no-stream));
# Remove percent sign so Zabbix can get raw value
foreach my $stat (qw(MemPerc CPUPerc)){
$json->{stats}->{$stat} =~ s/%$//;
}
# Extract mem usage vs mem limit, net in vs net out and blk read vs blk write
($json->{stats}->{MemCurrent}, $json->{stats}->{MemLimit}) = split(/\s*\/\s*/, $json->{stats}->{MemUsage});
($json->{stats}->{NetIOIn}, $json->{stats}->{NetIOOut}) = split(/\s*\/\s*/, $json->{stats}->{NetIO});
($json->{stats}->{BlockIORead}, $json->{stats}->{BlockIOWrite}) = split(/\s*\/\s*/, $json->{stats}->{BlockIO});
# Convert into Bytes
foreach my $stat (qw(MemCurrent MemLimit NetIOIn NetIOOut BlockIORead BlockIOWrite)){
$json->{stats}->{$stat} = convert_unit($json->{stats}->{$stat});
}
# Compute a useful Uptime from the StartedAt value
if ($json->{inspect}->{State}->{Running}){
$json->{stats}->{Uptime} = int(time() - str2time($json->{inspect}->{State}->{StartedAt}));
} else {
$json->{stats}->{Uptime} = 0;
}
} elsif (defined $network){
$json->{inspect} = from_json(qx($docker network inspect $network --format '$format'));
} elsif (defined $volume){
$json->{inspect} = from_json(qx($docker volume inspect $volume --format '$format'));
}
print to_json($json, { pretty => $pretty }) . "\n";
sub convert_unit {
my $val = shift;
my $suffix_multiplier = {
ki => 1024,
Ki => 1024,
Mi => 1024 * 1024,
Gi => 1024 * 1024 * 1024,
Ti => 1024 * 1024 * 1024 * 1024,
Pi => 1024 * 1024 * 1024 * 1024 * 1024,
k => 1000,
K => 1000,
M => 1000 * 1000,
G => 1000 * 1000 * 1000,
T => 1000 * 1000 * 1000 * 1000,
P => 1000 * 1000 * 1000 * 1000 * 1000
};
if ($val =~ m/^(\d+(\.\d+)?)(Ki|Mi|Gi|Ti|Pi|K|M|G|T|P)?B/){
$val = int($1 * $suffix_multiplier->{$3}) if (defined $3 and defined $suffix_multiplier->{$3});
# Remove the Bytes suffix if remaining
$val =~ s/B$//;
}
return $val;
}

View File

@ -0,0 +1,68 @@
#!/usr/bin/perl
use warnings;
use strict;
use JSON;
use Getopt::Long;
use File::Which;
use Data::Dumper;
my $what = 'containers';
my $pretty = 0;
GetOptions(
'what=s' => \$what,
'pretty' => \$pretty
);
my $json = [];
my $docker = which('docker');
# If the docker cli is not available, terminate now
if (not defined $docker){
print $json . "\n";
exit(0);
}
my $format;
my $cmd;
if ($what =~ m/^containers?/){
$format = '{' .
'"{#DOCKER_CONTAINER_ID}":"{{ .ID }}",' .
'"{#DOCKER_CONTAINER_IMAGE}": "{{ .Image }}",' .
'"{#DOCKER_CONTAINER_NAME}":"{{ .Names }}",' .
'"{#DOCKER_CONTAINER_STATE}": "{{ .State }}"' .
'}';
$cmd = "$docker container list --all --format '$format'";
} elsif ($what =~ m/^networks?/){
$format = '{' .
'"{#DOCKER_NET_ID}":"{{ .ID }}",' .
'"{#DOCKER_NET_NAME}":"{{ .Name }}",' .
'"{#DOCKER_NET_DRIVER}":"{{ .Driver }}",' .
'"{#DOCKER_NET_SCOPE}":"{{ .Scope }}"' .
'}';
$cmd = "$docker network list --format '$format'";
} elsif ($what =~ m/^volumes?/){
$format = '{' .
'"{#DOCKER_VOL_NAME}":"{{ .Name }}",' .
'"{#DOCKER_VOL_DRIVER}":"{{ .Driver }}",' .
'"{#DOCKER_VOL_SCOPE}":"{{ .Scope }}"' .
'}';
$cmd = "$docker volume list --format '$format'";
} else {
print <<_EOF
Usage: $0 --what=<item to discover> [--pretty]
with available item being
* containers : list containers, including stopped ones
* networks : list networks
* volumes : list volumes
_EOF
}
foreach my $line (qx($cmd)){
chomp $line;
push @{$json}, from_json($line);
}
print to_json($json, { pretty => $pretty }) . "\n";
exit(0);

View File

@ -0,0 +1,561 @@
zabbix_export:
version: '5.4'
date: '2022-01-12T15:22:36Z'
groups:
-
uuid: 7df96b18c230490a9a0a9e2307226338
name: Templates
templates:
-
uuid: 722c34dae28f471b992685f75b217e84
template: Template_App_Docker
name: Template_App_Docker
groups:
-
name: Templates
items:
-
uuid: b35116a368e94b0698951010ddb496b5
name: 'Docker: Number of paused container'
type: DEPENDENT
key: 'container.docker.check[global,ContainersPaused]'
delay: '0'
history: 30d
trends: 1095d
units: '!container(s)'
preprocessing:
-
type: JSONPATH
parameters:
- $.info.ContainersPaused
master_item:
key: 'container.docker.check[global]'
-
uuid: ff406b09a49f42ef80e004f7b8737c9b
name: 'Docker: Number of running container'
type: DEPENDENT
key: 'container.docker.check[global,ContainersRunning]'
delay: '0'
history: 30d
trends: 1095d
units: '!container(s)'
preprocessing:
-
type: JSONPATH
parameters:
- $.info.ContainersRunning
master_item:
key: 'container.docker.check[global]'
triggers:
-
uuid: 85e456243c714349b34ff6504d122004
expression: 'change(/Template_App_Docker/container.docker.check[global,ContainersRunning])=1'
name: 'Number of running containers changed to {ITEM.LASTVALUE1}'
priority: INFO
-
uuid: 69c12d97c6604c608fba4d2c0d4875bb
name: 'Docker: Number of stopped container'
type: DEPENDENT
key: 'container.docker.check[global,ContainersStopped]'
delay: '0'
history: 30d
trends: 1095d
units: '!container(s)'
preprocessing:
-
type: JSONPATH
parameters:
- $.info.ContainersStopped
master_item:
key: 'container.docker.check[global]'
-
uuid: c6831879964a4a3a90fc82530e6a0d43
name: 'Docker: Number of containers'
type: DEPENDENT
key: 'container.docker.check[global,Containers]'
delay: '0'
history: 30d
trends: 1095d
units: '!container(s)'
preprocessing:
-
type: JSONPATH
parameters:
- $.info.Containers
master_item:
key: 'container.docker.check[global]'
-
uuid: 1da51785c3d34faf8ba7ab17d0b46b38
name: 'Docker: Live restore status'
type: DEPENDENT
key: 'container.docker.check[global,LiveRestoreEnabled]'
delay: '0'
history: 7d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.info.LiveRestoreEnabled
master_item:
key: 'container.docker.check[global]'
triggers:
-
uuid: 85a2fc38a6bb42e183de3d4687f466e8
expression: 'last(/Template_App_Docker/container.docker.check[global,LiveRestoreEnabled])<>"true" and {$DOCKER_WARN_NO_LIVE_RESTORE}=1'
name: 'Docker live restore isn''t enabled'
priority: WARNING
-
uuid: ab2d3bd636964a21b764b2f33f2e109e
name: 'Docker: server version'
type: DEPENDENT
key: 'container.docker.check[global,ServerVersion]'
delay: '0'
history: 15d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.info.ServerVersion
master_item:
key: 'container.docker.check[global]'
triggers:
-
uuid: 8c535ff0d73240c395226ee91a8096c4
expression: '(last(/Template_App_Docker/container.docker.check[global,ServerVersion])<>last(/Template_App_Docker/container.docker.check[global,ServerVersion],#6))=1'
name: 'Docker version changed ({ITEM.LASTVALUE1})'
priority: WARNING
-
uuid: d5c424dc767c4a5ea1ee441e76770411
name: 'Docker global info'
key: 'container.docker.check[global]'
history: '0'
trends: '0'
value_type: TEXT
discovery_rules:
-
uuid: e459f638e15f495db3e4a9060e60f7c8
name: 'Docker: container discovery'
key: 'container.docker.discovery[containers]'
lifetime: 7d
item_prototypes:
-
uuid: 7f3fddee7aed48c8acc26e9aa98df298
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO Read'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIORead]'
delay: '0'
history: 30d
trends: 1095d
units: B/s
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.BlockIORead
-
type: CHANGE_PER_SECOND
parameters:
- ''
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: 27f4e3e3a33c412ead03200de17bc9b5
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO Write'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIOWrite]'
delay: '0'
history: 30d
trends: 1095d
units: B/s
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.BlockIOWrite
-
type: CHANGE_PER_SECOND
parameters:
- ''
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: f59ee387b12740fc90ff6d990422e92d
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: CPU'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc]'
delay: '0'
history: 30d
trends: 1095d
value_type: FLOAT
units: '%'
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.CPUPerc
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: f56ddbaef3af4fa898ae2403a812db3c
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Dead'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Dead]'
delay: '0'
history: 7d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.inspect.State.Dead
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: e09f311feb1749cc88e8c51c8425c324
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Error'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Error]'
delay: '0'
history: 7d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.inspect.State.Error
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: b75ac0b193d2451e8ee3ce0950b7b07a
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Image'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Image]'
delay: '0'
history: 7d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.inspect.Config.Image
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: ba301501bbec40e6add5a47d2fd0ee15
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory usage'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemCurrent]'
delay: '0'
history: 30d
trends: 1095d
units: B
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.MemCurrent
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: 5895cddf57fd4b5e8917593cba941491
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory limit'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemLimit]'
delay: '0'
history: 30d
trends: 1095d
units: B
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.MemLimit
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: 640bce04f3fc483fa495ac72208effa7
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory used (%)'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc]'
delay: '0'
history: 30d
trends: 1095d
value_type: FLOAT
units: '%'
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.MemPerc
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
trigger_prototypes:
-
uuid: 9fdd469b0866409ca7889288eb5f229a
expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc])>{$DOCKER_MEM_PCT_WARN}'
recovery_mode: RECOVERY_EXPRESSION
recovery_expression: 'last(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemPerc])<({$DOCKER_MEM_PCT_WARN}-2)'
name: 'Container {#DOCKER_CONTAINER_NAME} memory usage is at {ITEM.LMASTVALUE1}'
priority: AVERAGE
-
uuid: eb58fb55bc0442319650e32a8ba1faf4
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network in'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOIn]'
delay: '0'
history: 30d
trends: 1095d
units: B/s
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.NetIOIn
-
type: CHANGE_PER_SECOND
parameters:
- ''
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: 6a97e94be7d1432fb11a92072ea9e55f
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network out'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOOut]'
delay: '0'
history: 30d
trends: 1095d
units: B/s
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.NetIOOut
-
type: CHANGE_PER_SECOND
parameters:
- ''
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: 7be56a29b2464c5e96c2f4f2b3e02fba
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: OOMKilled'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},OOMKilled]'
delay: '0'
history: 7d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.inspect.State.OOMKilled
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: a5ed78ba8acf43a488b3833d14e39381
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Number of processes'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},PIDs]'
delay: '0'
history: 30d
trends: 1095d
units: '!process(es)'
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.PIDs
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: 1213e0b7fc824442b50ab4ff4cd1047b
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Restarting'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Restarting]'
delay: '0'
history: 7d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.inspect.State.Restarting
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: 418b35e93f114be986ecdd5a9d259283
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Status'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status]'
delay: '0'
history: 7d
trends: '0'
value_type: CHAR
preprocessing:
-
type: JSONPATH
parameters:
- $.inspect.State.Status
-
type: DISCARD_UNCHANGED_HEARTBEAT
parameters:
- 1h
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
trigger_prototypes:
-
uuid: 45e35825ed184b0290d1bc1ed27e48e4
expression: 'find(/Template_App_Docker/container.docker.check[container,{#DOCKER_CONTAINER_NAME},Status],,"regexp","^(running|exited)$")<>1'
name: 'Container {#DOCKER_CONTAINER_NAME} status is {ITEM.LASTVALUE1}'
priority: WARNING
manual_close: 'YES'
-
uuid: ab2c34de197f4ea197e607604c936f34
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Uptime'
type: DEPENDENT
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},Uptime]'
delay: '0'
history: 30d
trends: 1095d
units: s
preprocessing:
-
type: JSONPATH
parameters:
- $.stats.Uptime
master_item:
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
-
uuid: b232a5b3aedd4072a56460dd041579b1
name: 'Docker: container {#DOCKER_CONTAINER_NAME}: Info'
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME}]'
history: '0'
trends: '0'
value_type: TEXT
graph_prototypes:
-
uuid: 4a9aa378970045399303dcead39c1e53
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: CPU'
graph_items:
-
sortorder: '1'
drawtype: GRADIENT_LINE
color: F63100
item:
host: Template_App_Docker
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},CPUPerc]'
-
uuid: 7cd7cd8fd24d492ab7995a882b7bf9af
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Disk IO'
graph_items:
-
sortorder: '1'
drawtype: FILLED_REGION
color: FFAB91
item:
host: Template_App_Docker
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIORead]'
-
sortorder: '2'
drawtype: FILLED_REGION
color: A5D6A7
item:
host: Template_App_Docker
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},BlockIOWrite]'
-
uuid: 0fec757ff2f34e4fbab3be8ea455bc5f
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Memory'
graph_items:
-
sortorder: '1'
color: 2774A4
item:
host: Template_App_Docker
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},MemCurrent]'
-
uuid: 948dccce10c54510810a64612933ca89
name: 'Docker: Container {#DOCKER_CONTAINER_NAME}: Network'
graph_items:
-
sortorder: '1'
drawtype: FILLED_REGION
color: B39DDB
item:
host: Template_App_Docker
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOIn]'
-
sortorder: '2'
drawtype: FILLED_REGION
color: 80DEEA
item:
host: Template_App_Docker
key: 'container.docker.check[container,{#DOCKER_CONTAINER_NAME},NetIOOut]'
macros:
-
macro: '{$DOCKER_MEM_PCT_WARN}'
value: '80'
-
macro: '{$DOCKER_WARN_NO_LIVE_RESTORE}'
value: '1'
graphs:
-
uuid: 9c9aba9c46e145c7a8acd208edb1d147
name: 'Docker: Number of containers'
type: STACKED
graph_items:
-
sortorder: '1'
color: 1A7C11
item:
host: Template_App_Docker
key: 'container.docker.check[global,ContainersPaused]'
-
sortorder: '2'
color: F63100
item:
host: Template_App_Docker
key: 'container.docker.check[global,ContainersRunning]'
-
sortorder: '3'
color: 2774A4
item:
host: Template_App_Docker
key: 'container.docker.check[global,ContainersStopped]'