找回密码
 注册
查看: 4280|回复: 1

docker监控脚本

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2018-6-20 19:05:42 | 显示全部楼层 |阅读模式
监控套件有三个脚本,一个是自动发现主机上的docker容器脚本,另一个是用python写的获取每个docker容器的系统状态,包括CPU使用率,内存使用率以及网络资源使用率,最后这个脚本添加了一些我公司常用的应用的状态监控,包括应用占用内存,cpu资源以及进程的存活状态,至于读者们需要监控其他docker里面的应用,可以依照我的脚本来进行修改。
需要编辑自动发现docker中容器个数的脚本
# cat /usr/local/zabbix/scripts/docker_low_discovery.sh

: B" X$ B7 Q; E" ~, r9 n4 o$ Q
#!/bin/bash
2 V- D" h# k7 X9 R- p" I# v' N
#Fucation:docker low-level discovery
0 o  @  h3 y7 w- S' L& [# ?
docker() {

( o% ?2 D9 S/ P4 w& K& C; ~
            port=($(sudo docker ps -a|grep -v "CONTAINER ID"|awk '{print $NF}'))
* C* l) ~& U+ ~8 W, Q! b
            printf '{\n'
- k! Q9 n2 _# n# S- i8 g/ a4 r4 p
            printf '\t"data":[\n'

3 c1 Z" [+ D1 T3 @
               for key in ${!port[@]}

; E" d* F( i* D7 {1 G: \
                   do
: D8 F7 j4 C, J. u& d& K  ]% e
                       if [[ "${#port[@]}" -gt 1 && "${key}" -ne "$((${#port[@]}-1))" ]];then
) W. S3 ^( W+ t! F0 t. H" d; F7 o6 {
                          printf '\t {\n'

. H- ?" N, i3 h
                          printf "\t\t\t\"{#CONTAINERNAME}\":\"${port[${key}]}\"},\n"

4 Q* Q& f8 S+ V& N9 K
  
$ Z( D$ h) Q4 D0 w8 w$ f
                     else [[ "${key}" -eq "((${#port[@]}-1))" ]]
! h" [% m! l3 P
                          printf '\t {\n'

7 j8 [, ~) v- K8 u' p) |/ M
                          printf "\t\t\t\"{#CONTAINERNAME}\":\"${port[${key}]}\"}\n"
0 p1 b0 p" T4 Z0 J! l! @: x. C) ]
  
9 k& V1 h* D) F: E3 h  _
                       fi
+ v) K' x3 L" {' S6 p. H: u/ e
               done
& b0 ]1 ]. R2 w
  

, c" f4 r" o. ?+ G+ X& x+ G
                          printf '\t ]\n'
& e# W8 r- y( Y
                          printf '}\n'
$ b+ }4 l3 N+ {0 ^  A
}
1 `% h; m6 a% N5 s
case $1 in
' Y1 M6 T$ Z! Q) u. R, U
docker)

3 F+ Y/ |) `! o0 K- ~
docker
7 n' d6 A* \9 O( x) L+ d7 {% b
;;

1 o0 F' U! |- {9 m9 b
*)

' H5 D5 ~  M0 j9 d) J
echo "Usage:`basename $0` {docker}"
- u+ L2 I4 J7 ?( w: v
;;

9 q- q2 B/ b& P
esac
上面这个脚本是用来获取到docker里面应用的容器,并对其进行json化输出的,效果如下:
) @, t; J. p4 m
# sh /usr/local/zabbix/scripts/docker_low_discovery.sh docker

- E: I; L3 N2 z
{
" P7 V! n# Z# Y9 I
"data":[

1 @9 u1 n, c& |" A. y" ~. ?' Q
{
3 f% O" Z, s/ }( y4 G
"{#CONTAINERNAME}":"hopeful_brown"},
9 @' _8 v5 f& \8 O8 q4 ]4 v
{
: G% ^# A1 x3 \
"{#CONTAINERNAME}":"happy_einstein"}

* H$ y# m; R( \8 o
$ d0 r% V5 M9 ?) m
}
  C2 j  b) V  P- S1 ^
这样就能被zabbix_server获取到了,然后是python脚本,使用python获取docker的参数需要使用一个扩展包,可以通过pip或者easy_install安装docker-py扩展:
pip install docker-py或者easy_install docker-py或者不想这样安装的话可以去python官网下载docker-py的安装包,解压后使用docker docker-py-1.4.0/setup.py install命令安装,扩展包我将会打包放在附件中。

9 K8 B& B  F1 C( V& [6 [

- ^4 Q; x6 y- y; E5 U2 @4 h  k6 e
# cat /usr/local/zabbix/scripts/docker_monitor.py
' u/ d% k& x- M" U$ h' D
#!/usr/bin/env python

6 _( J% H, x& `* D
#-*- coding: utf-8 -*-

2 u! a  n! _8 Z6 k8 ~
#author:Xianglin Hu
0 ^2 f2 d  @% p7 d8 I1 m

  Y( x7 x# s& f9 l" f
from docker import Client
& j4 a: E5 D1 B/ i; S! j
import sys
/ k$ |( y. E# ?( ~# M7 \
import subprocess
7 D. b) B' c! E- e, G/ k/ Y3 G6 }
import os

, g7 u4 H* F  o" \5 E
  u' k6 D: h, x( s9 ?
def check_container_stats(container_name,collect_item):
' T) |( G6 I0 r# A7 u9 C
    container_collect=docker_client.stats(container_name)

+ t8 A$ Q- @" k0 k  M  q
    old_result=eval(container_collect.next())

+ c8 E( k; L5 ~
    new_result=eval(container_collect.next())

* E- f: r! a7 }' _3 d8 q, g
    container_collect.close()

2 t2 `! w1 |% K
    if collect_item == 'cpu_total_usage':

! r% J( Q5 s. K2 D/ R, e0 p
        result=new_result['cpu_stats']['cpu_usage']['total_usage'] - old_result['cpu_stats']['cpu_usage']['total_usage']

' K" C' s. _5 F1 {* p2 {8 |
    elif collect_item == 'cpu_system_usage':
/ K- T: f5 W: w4 W0 x
        result=new_result['cpu_stats']['system_cpu_usage'] - old_result['cpu_stats']['system_cpu_usage']

1 C; V1 U+ K! Y9 L3 a) h* \% G( ~
    elif collect_item == 'cpu_percent':

; J4 d3 U" r0 P0 u( D  f
        cpu_total_usage=new_result['cpu_stats']['cpu_usage']['total_usage'] - old_result['cpu_stats']['cpu_usage']['total_usage']

' \7 w3 b5 u( m% p( }
        cpu_system_uasge=new_result['cpu_stats']['system_cpu_usage'] - old_result['cpu_stats']['system_cpu_usage']

4 C2 D1 F4 c* A
        cpu_num=len(old_result['cpu_stats']['cpu_usage']['percpu_usage'])

0 j7 e" I3 F- ~& i9 c
        result=round((float(cpu_total_usage)/float(cpu_system_uasge))*cpu_num*100.0,2)
% E- [1 `2 E: @) \. h
    elif collect_item == 'mem_usage':

2 q/ V) c9 \- c: m: x
        result=new_result['memory_stats']['usage']
4 k$ K6 t+ ]) e1 F1 c
    elif collect_item == 'mem_limit':
8 N& {1 ?# y% ^' b+ a, }, ~
        result=new_result['memory_stats']['limit']

/ U% w5 N. B5 Y4 j$ b  q
    elif collect_item == 'mem_percent':
; A+ Z. D9 J! @4 D
        mem_usage=new_result['memory_stats']['usage']

- Q# }: r' N+ ?$ I- ^1 K
        mem_limit=new_result['memory_stats']['limit']
$ P% n' l- z% P: Z/ T
        result=round(float(mem_usage)/float(mem_limit)*100.0,2)

/ Y5 L/ v7 ]/ A% ^7 p3 d: B; q
    elif collect_item == 'network_rx_bytes':

9 O/ G- z2 Y3 ]6 l
        network_check_command="""sudo /usr/bin/docker exec %s cat /proc/net/dev|sed -n 3p|awk '{print $2,$10}'"""%container_name
  S3 m2 W$ b' j' h8 a* |* k; i
        result=os.popen(network_check_command).read().split()[0]
* h5 A( R7 J" F. Q
    elif collect_item == 'network_tx_bytes':
+ I) c+ I+ O) {- M: Z8 ~1 l
        network_check_command="""sudo /usr/bin/docker exec %s cat /proc/net/dev|sed -n 3p|awk '{print $2,$10}'"""%container_name
' I% w2 S5 t( ~. ~2 V. @3 T
        result=os.popen(network_check_command).read().split()[1]
7 Z2 S& Q8 @" g2 x5 s
    return result

/ D$ O; t& d; j- W
if __name__ == "__main__":
/ r7 ~1 ~1 u0 |! M' F6 K7 B
    docker_client = Client(base_url='unix://var/run/docker.sock', version='1.17')

0 U3 Q4 b8 d2 l4 {
    container_name=sys.argv[1]
3 x. o& K* B7 M6 M' ~8 j8 f' g
    collect_item=sys.argv[2]
- l* a4 E3 a0 O  T7 k/ b
    print check_container_stats(container_name,collect_item)

) C/ p1 B$ ~9 ?9 q. C
这里面使用到了docker里面的Client类,获取到某个docker容器的当前状态信息,然后进行运算,返回运算结果。但是容器当前信息那个dict中的network的key获取到的信息不准确,于是我使用了docker exec命令来获取docker容器内部的网络流量信息。这也是我在大神的基础上进行改进的地方,这里的改进将python脚本的执行时间缩短了,将有助于server获取duocker容器信息时减少长连接的数量,提升zabbix_server的性能。这里的docker exec命令将会在下一个脚本中大量使用来获取docker容器中的应用状态信息。

" i$ ^- p3 u6 ^" I' A6 ]+ h
下面是获取容器应用状态信息的脚本:
# cat docker_processmonitor.sh

! \% m; N4 ~7 M& U# o4 p3 x
#!/bin/bash

; z7 K. E# J7 _: W0 i
#license:GPL
2 l' G: U2 K) }9 w+ M3 N' Q
#mail:a714585725@qq.com
. v; P% n& U  ^2 ]2 Q
#date:2015.09.22

' I' M6 @% Z4 a9 P) U7 w" C
processmem(){
/ D2 o  y6 h- e) U+ W1 ]" }
        sudo /usr/bin/docker exec $1 ps aux|grep $2|grep -v "grep"|grep -v "processstatus.sh"|awk '{sum+=$6}; END{print sum}'

, z/ i$ Q1 d  G( u9 v7 m3 J0 v
}

' v& f7 Y) ?. V2 O" |
processcpu(){

% z6 Y& W& o; c7 f* @: q  [
        sudo /usr/bin/docker exec $1 ps aux|grep $2|grep -v "grep"|grep -v "processstatus.sh"|awk '{sum+=$3}; END{print sum}'

9 o0 _" O- Z. G
}

/ P; R. h- u2 G  ?9 ^6 ^1 V6 O
processport(){

' t- i9 F4 }7 W
        sudo /usr/bin/docker exec $1 ss -antlp|grep $2|grep LISTEN|wc -l

6 Z/ W' T2 x  d2 H; k
}

) u( _* i2 W9 c+ i
case "$3" in
$ u/ i& Y7 ^  g$ Z2 [# k" M
mem)
) H( W% Y/ w% `( b( T# Z. a
processmem $1 $2

/ w( H+ A4 ~6 O' U2 u! n0 O7 @7 ~
;;
* D# X# L2 J; }, i
cpu)
4 i( p1 D) g' n- `" l
processcpu $1 $2

2 i' Z( S8 L9 X% Q8 I& V6 M. D
;;
+ d) l# I& W9 o  \
port)
4 o6 v, |7 j; ?! P. o5 a
processport $1 $2

" N  s. {" J6 Y4 }# S/ v
;;
* v1 _9 L8 D# `" y) r
*)
5 L+ x) R7 r( }" x0 _! w
echo "Usage: $0 {docker_containername}{processname}{mem|cpu|port}"
0 ]* {, f' m. a& G+ z% g# y
;;

) v# }$ |! C% @" ^! O
esac

, \3 i) q8 y/ L( b6 T5 t

" {: c; m9 x9 d, C$ E+ H+ B
这个脚本其实没啥说的,从我以前写的那个脚本上面修改来的,使用了一个case来判断需要获取的docker容器的名称以及该容器中应用的状态信息,只不过这里获取docker容器状态信息使用的是docker exec命令来进行获取。另外这里面添加了对于应用是否存活的状态监测,那就是检测该应用是否侦听了网络端口,假如该应用侦听的网络端口个数为0的话,可以认为该应用存在异常。这些应用只是我公司使用比较多的应用,各位读者可以根据自己需求修改相应应用的监控。
由于docker是以root权限来启用的,而zabbix监控是使用zabbix用户来执行的,所以需要给予zabbix用户相应的权限,需要编辑visudo:
echo "zabbix ALL=(root) NOPASSWD:/bin/docker,/usr/bin/python,/usr/local/zabbix/scripts/docker_monitor.py,/usr/local/zabbix/scripts/docker_low_discovery.sh,/usr/local/zabbix/scripts/docker_processmonitor.sh">>/etc/sudoers
并且还需要注释掉这条记录:#Defaults    requiretty(PS:注意,这条记录是要求使用sudo命令时需要有终端界面,注释掉这一条之后就可以不需要终端执行sudo命令了。)

! C7 ~; j2 P5 }" q
# tail -3 /usr/local/zabbix/etc/zabbix_agentd.conf

6 A! g  p, ?* _6 w; c# z
UserParameter=docker_low_discovery
  • ,/bin/bash /usr/local/zabbix/scripts/docker_low_discovery.sh $1

  • 5 T9 V& `0 x% m& z0 D
    UserParameter=docker_stats
  • ,sudo /usr/bin/python /usr/local/zabbix/scripts/docker_monitor.py $1 $2

  • ! B6 a# R4 h- T, W% [
    UserParameter=docker_process
  • ,/bin/bash /usr/local/zabbix/scripts/docker_processmonitor.sh $1 $2  $3

  • ; M( N- U" o! J
    % ~# p% B0 ?* W9 O9 b$ e
    保存配置并重启zabbix_agentd服务,然后修改脚本的属主属组以及权限:
    chown zabbix.zabbix /usr/local/zabbix/scripts/*
    chmod 755 /usr/local/zabbix/scripts/*
    然后可以在zabbix_server端测试是否能够获取到相应的数据:
    [root@test1 ~]# /usr/local/zabbix-2.4.4/bin/zabbix_get -s x.x.x.x -k"docker_low_discovery[docker]"

    6 b- p- Y% Y- E6 y* `& O
    {
    3 H( v2 {4 r4 J: R2 ?$ u7 A
    "data":[

    * v. l+ ?3 n: B* a5 o' [
    {

    2 L5 Y0 i' g& D6 s' u$ w( l
    "{#CONTAINERNAME}":"hopeful_brown"},
    , ~- N+ s1 a' B% @% [( }4 o
    {

    7 ~9 g: e  x  q9 o8 z
    "{#CONTAINERNAME}":"happy_einstein"}
    $ c+ h+ D( p6 v" m; C( `
    ; S- K% _4 q% B( t/ |- V% s
    }
    8 p3 h3 x3 O0 w% }6 H
    [root@test1 ~]# /usr/local/zabbix-2.4.4/bin/zabbix_get -s x.x.x.x -k"docker_stats[happy_einstein,network_tx_bytes]"
    ; z/ V0 B' X$ H8 L! }& t6 p7 ^8 u
    9664252
    8 o& }. [3 A3 S9 U
    [root@test1 ~]# /usr/local/zabbix-2.4.4/bin/zabbix_get -s x.x.x.x -k"docker_process[happy_einstein,nginx,port]"
    % ^( F' N% a3 U, a5 G
    2
    " f$ Q" b) f! _, O2 l
    0 H% h6 E& J0 s6 Y( A* ?

    1

    主题

    0

    回帖

    12

    积分

    管理员

    积分
    12
    QQ
     楼主| 发表于 2018-6-20 19:10:02 | 显示全部楼层
    这里的IP地址我就用x.x.x.x代替了,这里应该填写客户端的IP地址。如上所示,能够正确获取到agentd的数据以后,然后就需要在zabbix_server这边配置监控模版了,关于监控模版的配置我在之前的文章中提及了很多次,相信大家应该都不会陌生了,这回就不详细描述模板的建立了,稍后我会将模板打包一起上传至附件中,这个模板目前还是半成品,各位可以根据模板进行修改,可以根据你们的需求来做,下面,演示一下监控出来的效果(PS:只是在测试环境小规模的部署,项目还不错,于是没有做成筛选出来。)
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

    GMT+8, 2026-6-12 02:18 , Processed in 0.017192 second(s), 23 queries .

    Powered by Discuz! X5.0

    © 2001-2026 Discuz! Team.

    快速回复 返回顶部 返回列表