Projet

Général

Profil

Paste
Télécharger au format
Statistiques
| Branche: | Révision:

root / plugins / lxc / lxc-multigraph @ 33b2f3ed

Historique | Voir | Annoter | Télécharger (10,2 ko)

1
#!/bin/bash
2
# -*- sh -*-
3

    
4
: << =cut
5

    
6
=head1 NAME
7

    
8
lxc-multigraph - Plugin to monitor LXC containers (v2.0)
9

    
10
=head1 CONFIGURATION
11

    
12
  [lxc-multigraph]
13
    user root
14

    
15
    # The memory usage of containers are by default drawn as stacked area
16
    # charts.  Alternatively a non-stacked graph with lines can be configured.
17
    # Default: true
18
    #env.ram_display_stacked true
19

    
20
    # lxc container path, default below
21
    #env.lxcpath /var/lib/lxc
22

    
23
    # exclude the following containers
24
    # (default none excluded)
25
    #env.exclude container1 container2
26

    
27
    # path where tasks sysfs files are stored,
28
    # set this if the various attempts in the
29
    # code don't work
30
    # (default none)
31
    #env.cgrouppath /sys/fs/cgroup/cpuacct/lxc/
32

    
33
=head1 INTERPRETATION
34

    
35
This plugin needs root privilege.
36

    
37
This plugin has been tested with lxc 3 and
38
lx2 (on Debian buster and Debian jessie,
39
respectively).
40

    
41
For the network graphs to work, you need
42
to have in every container's config file
43
a line defining the virtual network interface
44
path (else lxc will use a random name at
45
each container's start); see the lxc_netdev()
46
function below.
47

    
48
If using lxc 2, make sure you do not have cruft
49
in your container config files, you can test
50
it with:
51
   lxc-cgroup -o /dev/stdout -l INFO -n 104 cpuacct.usage
52
-- with 104 a valid lxc instance), if you
53
get a warning, fix the config file.
54

    
55
For the logins graph, the "users" command is required in each
56
container.
57

    
58
Tested on Debian buster and Debian jessie.
59

    
60
The double __ for values is for compatibility
61
with the previous implementation.
62

    
63
=head1 AUTHOR
64

    
65
vajtsz vajtsz@gmail.com
66
mitty  mitty@mitty.jp
67
alphanet schaefer@alphanet.ch (many changes and multigraph)
68

    
69
See https://framagit.org/alphanet/various-stuff
70
(plugins/lcx)
71

    
72
=head1 LICENSE
73

    
74
2-clause BSD License
75
or GPLv3 license or later, at your option
76

    
77
=head1 MAGIC MARKERS
78

    
79
 #%# family=auto
80
 #%# capabilities=autoconf
81

    
82
=cut
83

    
84
. "$MUNIN_LIBDIR/plugins/plugin.sh"
85

    
86

    
87
lxcpath=${lxcpath:-/var/lib/lxc}
88
# containers to be ignored
89
exclude=${exclude:-}
90
ram_display_stacked=${ram_display_stacked:-true}
91
# try to guess the location, if empty
92
cgrouppath=${cgrouppath:-}
93

    
94

    
95
# --- FUNCTIONS
96

    
97
function active_guests {
98
   local excludes="$1"
99
   local guest_name
100
   for guest_name in $(lxc-ls)
101
   do
102
      # handle optional exclude list in $1
103
      if ! echo "$excludes" | grep -qwF "$guest_name"; then
104
         if lxc-info -n "$guest_name" --state 2>/dev/null | grep -qw RUNNING; then
105
            echo "$guest_name"
106
         fi
107
      fi
108
   done
109
}
110

    
111

    
112
function lxc_cgroup {
113
   # lxc3 (lxc < 3: may output some warnings if there is cruft in your config dir)
114
   lxc-cgroup -o /dev/stdout -l INFO $* | sed 's/^.*lxc_cgroup.c:main:[0-9][0-9]* - //'
115
}
116

    
117

    
118
function lxc_netdev {
119
   local guest_name="$1"
120

    
121
   if [ -f "$lxcpath/$guest_name/config" ]; then
122
      # lxc 3 vs < 3
123
      (grep -EF '^lxc.net.0.veth.pair' "$lxcpath/$guest_name/config" 2>/dev/null \
124
         || grep -EF '^lxc.network.veth.pair' "$lxcpath/$guest_name/config"
125
      ) | awk '{print $NF;}'
126
   fi
127
}
128

    
129

    
130
# find proper sysfs and count it
131
# Debian 6.0: /sys/fs/cgroup/<container>/tasks
132
# Ubuntu 12.04 with fstab: /sys/fs/cgroup/lxc/<container>/tasks
133
# Ubuntu 12.04 with cgroup-lite: /sys/fs/cgroup/cpuacct/lxc/<container>/tasks
134
# Ubuntu 12.04 with cgroup-bin: /sys/fs/cgroup/cpuacct/sysdefault/lxc/<container>/tasks
135
# Ubuntu 14.04 /sys/fs/cgroup/systemd/lxc/<container>/tasks
136
# and with cgmanager on jessie
137
lxc_count_processes () {
138
   local guest_name="$1"
139
   local SYSFS
140

    
141
   [ -z "$guest_name" ] && return 0
142

    
143
   if [ -n "$cgrouppath" ]; then
144
      SYSFS="$cgrouppath/$guest_name/tasks"
145
      if [ -e "$SYSFS" ]; then
146
         wc -l <"$SYSFS"
147
         return
148
      fi
149
   fi
150

    
151
   for SYSFS in \
152
      "/sys/fs/cgroup/$guest_name/tasks" \
153
      "/sys/fs/cgroup/lxc/$guest_name/tasks" \
154
      "/sys/fs/cgroup/systemd/lxc/$guest_name/tasks" \
155
      "/sys/fs/cgroup/cpuacct/lxc/$guest_name/tasks" \
156
      "/sys/fs/cgroup/cpuacct/sysdefault/lxc/$guest_name/tasks"
157
   do
158
      if [ -e "$SYSFS" ]; then
159
         wc -l <"$SYSFS"
160
         return
161
      fi
162
   done
163

    
164
   if [ -e /usr/bin/cgm ]; then
165
      cgm getvalue cpu "lxc/$guest_name" tasks 2>/dev/null | wc -l
166
   else
167
      lxc_cgroup -n "$guest_name" tasks | wc -l
168
   fi
169
}
170

    
171

    
172
# --- BASIC DEFINES
173

    
174
active_guests=$(active_guests "$exclude")
175

    
176
# --- AUTOCONF
177

    
178
if [ "$1" = "autoconf" ]; then
179
   if [ ! -r /proc/net/dev ]; then
180
      echo "no (/proc/net/dev cannot be read)"
181
   elif [ ! -e "$lxcpath" ]; then
182
      echo "no ($lxcpath is not present)"
183
   else
184
      echo yes
185
   fi
186
   exit 0
187
fi
188

    
189
# --- CONFIG OUTPUT
190

    
191
if [ "$1" = "config" ]; then
192
   cat <<EOF
193
multigraph lxc_cpu
194
graph_title CPU Usage
195
graph_args -l 0 --base 1000
196
graph_vlabel USER_HZ
197
graph_category lxc
198
EOF
199

    
200
   for guest_name in $active_guests
201
   do
202
      for cpu_usage in user system
203
      do
204
         cat <<EOF
205
$(clean_fieldname "cpu_${cpu_usage}__${guest_name}").label $guest_name: $(echo "${cpu_usage:0:1}" | tr "[:lower:]" "[:upper:]")${cpu_usage:1}
206
$(clean_fieldname "cpu_${cpu_usage}__${guest_name}").type DERIVE
207
$(clean_fieldname "cpu_${cpu_usage}__${guest_name}").min 0
208
EOF
209
      done
210
   done
211

    
212
   cat <<EOF
213

    
214
multigraph lxc_cpu_time
215
graph_title CPU time
216
graph_args -l 0 --base 1000
217
graph_vlabel nanosec
218
graph_category lxc
219
EOF
220

    
221
   for guest_name in $active_guests
222
   do
223
      cat <<EOF
224
$(clean_fieldname "cpu_time__${guest_name}").label $guest_name: CPU time
225
$(clean_fieldname "cpu_time__${guest_name}").type DERIVE
226
$(clean_fieldname "cpu_time__${guest_name}").min 0
227
EOF
228
   done
229

    
230
   cat <<EOF
231

    
232
multigraph lxc_logins
233
graph_title Logins
234
graph_category lxc
235
EOF
236

    
237
   for guest_name in $active_guests
238
   do
239
      cat <<EOF
240
$(clean_fieldname "logins__${guest_name}").label $guest_name: logins
241
$(clean_fieldname "logins__${guest_name}").type GAUGE
242
EOF
243
   done
244

    
245
   cat <<EOF
246

    
247
multigraph lxc_net
248
graph_title Network traffic
249
graph_args --base 1000
250
graph_vlabel bits in (-) / out (+) per \${graph_period}
251
graph_category lxc
252
graph_info This graph shows the traffic of active LXC containers.
253
EOF
254

    
255
   for guest_name in $active_guests
256
   do
257
      device=$(lxc_netdev "$guest_name")
258
      if [ -z "$device" ]; then
259
         continue
260
      fi
261
      cat <<EOF
262
$(clean_fieldname "net__${guest_name}_down").label $guest_name
263
$(clean_fieldname "net__${guest_name}_down").type DERIVE
264
$(clean_fieldname "net__${guest_name}_down").graph no
265
$(clean_fieldname "net__${guest_name}_down").cdef $(clean_fieldname "net__${guest_name}_down"),8,*
266
$(clean_fieldname "net__${guest_name}_down").min 0
267
$(clean_fieldname "net__${guest_name}_up").label $guest_name
268
$(clean_fieldname "net__${guest_name}_up").type DERIVE
269
$(clean_fieldname "net__${guest_name}_up").negative $(clean_fieldname "net__${guest_name}_down")
270
$(clean_fieldname "net__${guest_name}_up").cdef $(clean_fieldname "net__${guest_name}_up"),8,*
271
$(clean_fieldname "net__${guest_name}_up").min 0
272
EOF
273
      if [ -r "/sys/class/net/$device/speed" ]; then
274
         megabit_per_second=$(cat "/sys/class/net/$device/speed")
275
         bps=$((megabit_per_second * 1000 * 1000))
276
         cat <<EOF
277
$(clean_fieldname "net__${guest_name}_down").max $bps
278
$(clean_fieldname "net__${guest_name}_up").max $bps
279
EOF
280
      fi
281
   done
282

    
283
   cat <<EOF
284

    
285
multigraph lxc_proc
286
graph_title Processes
287
graph_args -l 0 --base 1000
288
graph_vlabel Number of processes
289
graph_category lxc
290
EOF
291
   for guest_name in $active_guests
292
   do
293
      cat <<EOF
294
$(clean_fieldname "lxc_proc__${guest_name}").label $guest_name: processes
295
$(clean_fieldname "lxc_proc__${guest_name}").type GAUGE
296
$(clean_fieldname "lxc_proc__${guest_name}").min 0
297
EOF
298
   done
299

    
300
   cat <<EOF
301

    
302
multigraph lxc_ram
303
graph_title Memory
304
graph_args -l 0 --base 1024
305
graph_vlabel byte
306
graph_category lxc
307
EOF
308

    
309
   for guest_name in $active_guests
310
   do
311
      if [ "$ram_display_stacked" != "true" ]; then
312
         draw_style="LINE1"
313
      else
314
         draw_style="AREASTACK"
315
      fi
316

    
317
      cat <<EOF
318
$(clean_fieldname "mem_usage__${guest_name}").label ${guest_name}: Mem usage
319
$(clean_fieldname "mem_usage__${guest_name}").type GAUGE
320
$(clean_fieldname "mem_usage__${guest_name}").draw $draw_style
321
$(clean_fieldname "mem_cache__${guest_name}").label ${guest_name}: Cache
322
$(clean_fieldname "mem_cache__${guest_name}").type GAUGE
323
$(clean_fieldname "mem_active__${guest_name}").label ${guest_name}: Active
324
$(clean_fieldname "mem_active__${guest_name}").type GAUGE
325
$(clean_fieldname "mem_inactive__${guest_name}").label ${guest_name}: Inactive
326
$(clean_fieldname "mem_inactive__${guest_name}").type GAUGE
327
EOF
328
   done
329

    
330
   exit 0
331
fi
332

    
333
# --- DATA OUTPUT
334

    
335
echo "multigraph lxc_cpu"
336
for guest_name in $active_guests
337
do
338
   for cpu_usage in user system
339
   do
340
      echo "$(clean_fieldname "cpu_${cpu_usage}__${guest_name}").value $(lxc_cgroup -n "$guest_name" cpuacct.stat | grep "$cpu_usage" | awk '{ print $2; }')"
341
   done
342
done
343

    
344
echo "multigraph lxc_cpu_time"
345
for guest_name in $active_guests
346
do
347
   echo "$(clean_fieldname "cpu_time__${guest_name}").value $(lxc_cgroup -n "$guest_name" cpuacct.usage)"
348
done
349

    
350
echo "multigraph lxc_logins"
351
for guest_name in $active_guests
352
do
353
   echo "$(clean_fieldname "logins__${guest_name}").value $(lxc-attach -n "$guest_name" users | wc -w)"
354
done
355

    
356
echo "multigraph lxc_net"
357
for guest_name in $active_guests
358
do
359
   device=$(lxc_netdev "$guest_name")
360
   if [ -z "$device" ]; then
361
      value_up="U"
362
      value_down="U"
363
   else
364
      value_up=$(grep -E "^ *${device}:" /proc/net/dev | awk '{print $10;}')
365
      value_down=$(grep -E "^ *${device}:" /proc/net/dev | awk '{print $2;}')
366
   fi
367

    
368
   cat <<EOF
369
$(clean_fieldname "net__${guest_name}_up").value $value_up
370
$(clean_fieldname "net__${guest_name}_down").value $value_down
371
EOF
372
done
373

    
374
echo "multigraph lxc_proc"
375
for guest_name in $active_guests
376
do
377
   echo "$(clean_fieldname "lxc_proc__${guest_name}").value $(lxc_count_processes "$guest_name")"
378
done
379

    
380
echo "multigraph lxc_ram"
381
for guest_name in $active_guests
382
do
383
   cat <<EOF
384
$(clean_fieldname "mem_usage__${guest_name}").value $(lxc_cgroup -n "$guest_name" memory.usage_in_bytes)
385
$(clean_fieldname "mem_cache__${guest_name}").value $(lxc_cgroup -n "$guest_name" memory.stat | grep total_cache | awk '{print $2;}')
386
$(clean_fieldname "mem_active__${guest_name}").value $(lxc_cgroup -n "$guest_name" memory.stat | grep total_active_anon | awk '{print $2;}')
387
$(clean_fieldname "mem_inactive__${guest_name}").value $(lxc_cgroup -n "$guest_name" memory.stat | grep total_inactive_anon | awk '{print $2;}')
388
EOF
389
done