最近在搞zabbix監控docker以及docker內部應用狀態信息,網上找的資料好少,只找到了一個大神的一篇文章,用的是python實現監控docker容器的基本狀態,我在他給的腳本基礎上進行修改,另外,增長了docker內部經常使用應用的狀態監控,目前在測試環境上部署成功了,具體還須要在線上環境部署後才能檢驗出效果如何。python
好了,根據慣例,廢話講完了,開始進入正題了。nginx
首先,介紹下該監控套件有三個腳本,一個是自動發現主機上的docker容器腳本,另外一個是用python寫的獲取每一個docker容器的系統狀態,包括CPU使用率,內存使用率以及網絡資源使用率,最後這個腳本添加了一些我公司經常使用的應用的狀態監控,包括應用佔用內存,cpu資源以及進程的存活狀態,至於讀者們須要監控其餘docker裏面的應用,能夠依照個人腳原本進行修改。docker
首先,須要編輯自動發現docker中容器個數的腳本,內容以下:json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
# cat /usr/local/zabbix/scripts/docker_low_discovery.sh
#!/bin/bash
#Fucation:docker low-level discovery
docker() {
port=($(sudo docker ps -a|grep -v "CONTAINER ID"|awk '{print $NF}'))
printf '{\n'
printf '\t"data":[\n'
for key in ${!port[@]}
do
if [[ "${#port[@]}" -gt 1 && "${key}" -ne "$((${#port[@]}-1))" ]];then
printf '\t {\n'
printf "\t\t\t\"{#CONTAINERNAME}\":\"${port[${key}]}\"},\n"
else [[ "${key}" -eq "((${#port[@]}-1))" ]]
printf '\t {\n'
printf "\t\t\t\"{#CONTAINERNAME}\":\"${port[${key}]}\"}\n"
fi
done
printf '\t ]\n'
printf '}\n'
}
case $1 in
docker)
docker
;;
*)
echo "Usage:`basename $0` {docker}"
;;
esac
|
上面這個腳本是用來獲取到docker裏面應用的容器,並對其進行json化輸出的,效果以下:bash
1
2
3
4
5
6
7
8
9
|
# sh /usr/local/zabbix/scripts/docker_low_discovery.sh docker
{
"data":[
{
"{#CONTAINERNAME}":"hopeful_brown"},
{
"{#CONTAINERNAME}":"happy_einstein"}
]
}
|
這樣就能被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命令安裝,擴展包我將會打包放在附件中。app
1
|
下面是python腳本:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
# cat /usr/local/zabbix/scripts/docker_monitor.py
#!/usr/bin/env python
#-*- coding: utf-8 -*-
#author:Xianglin Hu
#email: a714585725@qq.com
from docker import Client
import sys
import subprocess
import os
def check_container_stats(container_name,collect_item):
container_collect=docker_client.stats(container_name)
old_result=eval(container_collect.next())
new_result=eval(container_collect.next())
container_collect.close()
if collect_item == 'cpu_total_usage':
result=new_result['cpu_stats']['cpu_usage']['total_usage'] - old_result['cpu_stats']['cpu_usage']['total_usage']
elif collect_item == 'cpu_system_usage':
result=new_result['cpu_stats']['system_cpu_usage'] - old_result['cpu_stats']['system_cpu_usage']
elif collect_item == 'cpu_percent':
cpu_total_usage=new_result['cpu_stats']['cpu_usage']['total_usage'] - old_result['cpu_stats']['cpu_usage']['total_usage']
cpu_system_uasge=new_result['cpu_stats']['system_cpu_usage'] - old_result['cpu_stats']['system_cpu_usage']
cpu_num=len(old_result['cpu_stats']['cpu_usage']['percpu_usage'])
result=round((float(cpu_total_usage)/float(cpu_system_uasge))*cpu_num*100.0,2)
elif collect_item == 'mem_usage':
result=new_result['memory_stats']['usage']
elif collect_item == 'mem_limit':
result=new_result['memory_stats']['limit']
elif collect_item == 'mem_percent':
mem_usage=new_result['memory_stats']['usage']
mem_limit=new_result['memory_stats']['limit']
result=round(float(mem_usage)/float(mem_limit)*100.0,2)
elif collect_item == 'network_rx_bytes':
network_check_command="""sudo /usr/bin/docker exec %s cat /proc/net/dev|sed -n 3p|awk '{print $2,$10}'"""%container_name
result=os.popen(network_check_command).read().split()[0]
elif collect_item == 'network_tx_bytes':
network_check_command="""sudo /usr/bin/docker exec %s cat /proc/net/dev|sed -n 3p|awk '{print $2,$10}'"""%container_name
result=os.popen(network_check_command).read().split()[1]
return result
if __name__ == "__main__":
docker_client = Client(base_url='unix://var/run/docker.sock', version='1.17')
container_name=sys.argv[1]
collect_item=sys.argv[2]
print check_container_stats(container_name,collect_item)
|
這裏面使用到了docker裏面的Client類,獲取到某個docker容器的當前狀態信息,而後進行運算,返回運算結果。可是容器當前信息那個dict中的network的key獲取到的信息不許確,因而我使用了docker exec命令來獲取docker容器內部的網絡流量信息。這也是我在大神的基礎上進行改進的地方,這裏的改進將python腳本的執行時間縮短了,將有助於server獲取duocker容器信息時減小長鏈接的數量,提高zabbix_server的性能。這裏的docker exec命令將會在下一個腳本中大量使用來獲取docker容器中的應用狀態信息。ide
下面是獲取容器應用狀態信息的腳本:性能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# cat docker_processmonitor.sh
#!/bin/bash
#license:GPL
#mail:a714585725@qq.com
#date:2015.09.22
processmem(){
sudo /usr/bin/docker exec $1 ps aux|grep $2|grep -v "grep"|grep -v "processstatus.sh"|awk '{sum+=$6}; END{print sum}'
}
processcpu(){
sudo /usr/bin/docker exec $1 ps aux|grep $2|grep -v "grep"|grep -v "processstatus.sh"|awk '{sum+=$3}; END{print sum}'
}
processport(){
sudo /usr/bin/docker exec $1 ss -antlp|grep $2|grep LISTEN|wc -l
}
case "$3" in
mem)
processmem $1 $2
;;
cpu)
processcpu $1 $2
;;
port)
processport $1 $2
;;
*)
echo "Usage: $0 {docker_containername}{processname}{mem|cpu|port}"
;;
esac
|
這個腳本其實沒啥說的,從我之前寫的那個腳本上面修改來的,使用了一個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命令了。)
而後就是編輯zabbix_agentd.conf文件,添加下面幾行:
1
2
3
4
|
# tail -3 /usr/local/zabbix/etc/zabbix_agentd.conf
UserParameter=docker_low_discovery[*],/bin/bash /usr/local/zabbix/scripts/docker_low_discovery.sh $1
UserParameter=docker_stats[*],sudo /usr/bin/python /usr/local/zabbix/scripts/docker_monitor.py $1 $2
UserParameter=docker_process[*],/bin/bash /usr/local/zabbix/scripts/docker_processmonitor.sh $1 $2 $3
|
保存配置並重啓zabbix_agentd服務,而後修改腳本的屬主屬組以及權限:
chown zabbix.zabbix /usr/local/zabbix/scripts/*
chmod 755 /usr/local/zabbix/scripts/*
而後能夠在zabbix_server端測試是否可以獲取到相應的數據:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[root@test1 ~]# /usr/local/zabbix-2.4.4/bin/zabbix_get -s x.x.x.x -k"docker_low_discovery[docker]"
{
"data":[
{
"{#CONTAINERNAME}":"hopeful_brown"},
{
"{#CONTAINERNAME}":"happy_einstein"}
]
}
[root@test1 ~]# /usr/local/zabbix-2.4.4/bin/zabbix_get -s x.x.x.x -k"docker_stats[happy_einstein,network_tx_bytes]"
9664252
[root@test1 ~]# /usr/local/zabbix-2.4.4/bin/zabbix_get -s x.x.x.x -k"docker_process[happy_einstein,nginx,port]"
2
|
這裏的IP地址我就用x.x.x.x代替了,這裏應該填寫客戶端的IP地址。如上所示,可以正確獲取到agentd的數據之後,而後就須要在zabbix_server這邊配置監控模版了,關於監控模版的配置我在以前的文章中說起了不少次,相信你們應該都不會陌生了,這回就不詳細描述模板的創建了,稍後我會將模板打包一塊兒上傳至附件中,這個模板目前仍是半成品,各位能夠根據模板進行修改,能夠根據大家的需求來作,下面,演示一下監控出來的效果(PS:只是在測試環境小規模的部署,項目還不錯,因而沒有作成篩選出來。)
上面這些顯示的是監控的結果,各位也能夠根據本身的需求來進行修改,總之一句話,zabbix能夠作到任何你想作的監控,嘻嘻!!!
本文出自 「檸檬」 博客,請務必保留此出處http://xianglinhu.blog.51cto.com/5787032/1697427