一、需求場景
在某些docker容器中運行着java,容器提供API供監控調用。需要監控服務運行是否正常和容器內JVM使用情況。
二、想法
編寫監控腳本,使用自定義key的方式添加到Zabbix中。
三、實踐
1、編寫服務監控腳本
#!/bin/bash
interval_time=600
service_port_file=/script/tmp/service_port.txt
#Gener_service_port
tee > ${service_port_file} << EOF
apigate=8603
config=8602
eureka=8601
file=8606
schedule=8677
service=8605
EOF
#Accept input
container_id=$($(which docker) ps|grep "$1"|awk '{print $1}')
service_name=$(echo $1 | awk -F '.' '{print $1}'|awk -F '-' '{print $NF}')
service_port=$(grep ${service_name} ${service_port_file}|awk -F '=' '{print $NF}')
#Get created
created_time=$(docker inspect ${container_id} --format '{{.Created}}')
created_timestamp=$(date +%s -d ${created_time})
system_timestamp=$(date +%s)
interval=$((system_timestamp-created_timestamp))
#Get container version
container_version=$(docker exec ${container_id} [ -f "/etc/redhat-release" ] && grep -oE "[0-9.]+" /etc/redhat-release|awk -F . '{print $1}' || echo 0)
#Get ip
docker_gwbridge=$(ifconfig docker_gwbridge|awk 'NR==2'|awk '{print $2}'|awk -F . '{print $1"."$2"."$3}')
if [ ${container_version} -eq 7 ];then
service_ip=$($(which docker) exec ${container_id} hostname -I | grep -o ${docker_gwbridge}.*|sed s/[[:space:]]//g)
else
service_ip=$($(which docker) exec ${container_id} ifconfig | grep ${docker_gwbridge}|awk '{print $2}'|awk -F ':' '{print $2}')
fi
#Get status_code
status_code=$(curl -I -m 10 -o /dev/null -s -w %{http_code} ${service_ip}:${service_port}/info)
#Return value
if [ ${status_code} -eq 200 ];then
echo "1"
else
if [ ${interval} -gt ${interval_time} ];then
echo "0"
else
awk 'BEGIN{printf "%.2f\n",(1-'${interval}'/'${interval_time}')}'
fi
fi
說明:腳本接受容器名字作爲參數,訪問預先商議好對應服務的API。返回200則表示正常,將輸出1。若返回0,則判斷容器的創建時間,如果是創建時間小於約定的時間,說明容器是新生成的,返回對應代表進度的數值,否則返回0。
2、編寫監控JVM的腳本
#!/bin/bash
pid=1
container_id=$($(which docker) ps|grep "$1"|awk '{print $1}')
function Survivor0 {
$(which docker) exec ${container_id} jstat -gcutil ${pid} | awk 'NR==2 {print $1}'
}
function Survivor1 {
$(which docker) exec ${container_id} jstat -gcutil ${pid} | awk 'NR==2 {print $2}'
}
function Eden {
$(which docker) exec ${container_id} jstat -gcutil ${pid} | awk 'NR==2 {print $3}'
}
function Old {
$(which docker) exec ${container_id} jstat -gcutil ${pid} | awk 'NR==2 {print $4}'
}
function Perm {
$(which docker) exec ${container_id} jstat -gcutil ${pid} | awk 'NR==2 {print $5}'
}
function Metaspace {
$(which docker) exec ${container_id} jstat -gcutil ${pid} | awk 'NR==2 {print $5}'
}
"$2"
說明:腳本接受2個參數。第一個參數爲容器名,第二個參數爲監控項目名。
3、編寫自動發現腳本
#!/bin/bash
key=cloud
#Get app_name
array=($($(which docker) ps |awk '{print $NF}'|grep ${key}|awk -F '[_.]' '{print $2 "." $3}'))
printf '['
for ((i=0;i<${#array[@]};i++))
do
printf '{'
num=$(echo $((${#array[@]}-1)))
if [ "$i" == ${num} ];
then
printf "\"{#APP_NAME}\":\"${array[$i]}\"}"
else
printf "\"{#APP_NAME}\":\"${array[$i]}\"},"
fi
done
printf "]"
說明:以特定的關鍵字過濾需要監控的容器名字,按照規則輸出json格式的字串。
4、在Agent的配置文件中加入自定義key
UserParameter=app.status[*],sudo /usr/bin/bash /script/appstatus.sh $1
UserParameter=docker.java[*],sudo /usr/bin/bash /script/dockerjava.sh $1 $2
UserParameter=app.discovery,sudo /usr/bin/bash /script/appdiscovery.sh
5、在Zabbix創建自動發現規則
(1)填寫鍵值
(2)創建監控原型
(3)創建觸發器
(4)創建圖形原型
四、效果展示
1、服務監控腳本
(1)Zabbix
(2)Grafana
(3)說明
(1)在14:45分之前,服務正常運行(值爲1)
(2)在14:46分時,關閉2個服務(值爲0,觸發報警),重啓其他服務
(3)在14:47分左右,重啓所有服務(隨着時間的推移,數值逐漸減少)
(4)在14:53分左右,服務逐漸恢復。
2、JVM監控腳本