[toc]

Zabbix概述

什么是监控

监控系统是整个运维环节,乃至整个产品生命周期中最重要的一环,事前及时预警发现故障,事后提供翔实的数据用于追查定位问题。

为什么使用监控

  • 生活中:
    • 超市监控:防内外偷
    • 交通监控:测速,违章
  • 企业中:
    • 系统的监控:实际上是对系统不间断的实时监控
    • 实时反馈系统当前状态:我们监控某个硬件、或者某个系统,都是需要能实时看到当前系统的状态,是正常、异常、或者故障。
    • 保证服务可靠性安全性:我们监控的目的就是要保证
      系统、服务、业务正常运行
    • 保证业务持续稳定运行:如果我们的监控做得很完善,即使出现故障,能第一时间接收到故障报警,在第一时间处理解决,从而保证业务持续性的稳定运行。(往往,第一时间知道业务宕机的都是用户)

监控怎么来实现?

image-20230628220630823

1.CACTI(网络监控)

image-20230628220700125


image-20230628220711911

2.NAGIOS(系统监控)

image-20230628220724154


image-20230628220734401

3.ZABBIX(分布式监控)

image-20230628220751859


image-20230628220802122

4.open-falcon(小米监控产品)

image-20230628220813964


image-20230628220826163

5.普罗米修斯(监控docker,K8S)

image-20230628220842267


image-20230628220854809

6.lepus天兔(数据库监控)

image-20230628220909751

监控范围

硬件层面

如果说到硬件,肯定要先说物理服务器用的什么型号?

物理服务器,选型,Dell R710 720 730 …

IDRAC自带一个远程管理卡,安装上一个软件包之后,就可以监控

image-20230628220938261

如果不使用dell的idrac那就使用zabbix的IPMI接口监控硬件

  1. CPU温度
  2. 风扇转速
  3. 磁盘是否损坏
  4. CMOS电池电量
  5. 内存是否损坏

系统层面

  1. CPU:使用率、负载
  2. 内存:使用率
  3. 磁盘:使用率,IO
  4. 进程
  5. TCP状态
  6. 系统负载

网络层面

使用zabbix的snmp方式监控

  1. 网络设备:路由器,交换机
  2. 网卡入口流量
  3. 网卡出口流量
  4. 带宽的峰值

应用层面

当然了最基本的就是各个服务的进程,端口号
一些特殊程序我们还需要额外监控:

  1. MySQL:主从复制是否有延迟(zabbix监控模板)
  2. redis:主从复制是否有延迟 监控思路:zabbix没有固定模板,可以在主库中set一个key为时间戳,然后从库会同步这个时间戳(动态),写脚本时时获取这两个时间戳,做对比。
  3. NFS:磁盘挂载状况
  4. tomcat:JVM监控,老年代、新生代、永久带、full-gc、垃圾回收
  5. rsync的同步情况,MD5校验文件是否被篡改

业务层面

  1. URL的监控
  2. API的监控
  3. nginx的状态码
  4. tomcat的exception
  5. 请求时间
  6. 响应时间
  7. 加载时间
  8. 渲染时间

单机监控命令了解

CPU监控命令

  1. w

    1
    2
    3
    4
    # w
    12:30:41 up 1 day, 8:10, 1 user, load average: 0.00, 0.01, 0.05
    USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
    root pts/1 10.0.0.1 五09 1.00s 0.00s 0.00s w
  2. top

    1
    2
    3
    4
    5
    6
    # top
    top - 12:31:10 up 1 day, 8:11, 1 user, load average: 0.00, 0.01, 0.05
    Tasks: 100 total, 1 running, 99 sleeping, 0 stopped, 0 zombie
    %Cpu(s): 0.0 us, 0.3 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
    KiB Mem : 2030148 total, 1457796 free, 190464 used, 381888 buff/cache
    KiB Swap: 1048572 total, 1048572 free, 0 used. 1652944 avail Mem
  3. htop

    1
    2
    # htop
    CPU[||||||| 0.7%] Tasks: 27, 38 thr; 1 running
  4. glances

    1
    2
    3
    4
    5
    6
    7
    # glances
    web03 (CentOS Linux 7.6.1810 64bit / Linux 3.10.0-957.el7.x86_64) Uptime:18:30:18

    CPU [ 3.2%] CPU 3.2% MEM 49.8% SWAP 0.1% LOAD 1-core
    MEM [ 49.8%] user: 0.7% total: 973M total: 1024M 1 min: 0.00
    SWAP [ 0.1%] system: 0.3% used: 484M used: 776K 5 min: 0.06
    idle: 99.0% free: 488M free: 1023M 15 min: 0.10
  5. uptime

    1
    2
    # uptime
    12:33:18 up 1 day, 8:13, 1 user, load average: 0.10, 0.08, 0.07

不管用什么命令监控,查看CPU,我们都必须了解,系统的用户态和内和态。

1
2
3
4
5
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

us: 用户态 跟用户的操作有关35%
sy: 内和态 跟内核的处理有关65%
id: CPU空闲

当我们执行一个命令的时候,很快能出来结果,但是有多少人知道,这个很快,他都占用了哪些时间呢?

1
2
3
4
5
6
# time ls
backup.sh group_vars_web_group

real 0m0.002s 真实执行时间
user 0m0.001s 用户执行时间
sys 0m0.001s 系统执行时间

内存监控命令

  1. free

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # free -m
    total used free shared buff/cache available
    Mem: 1982 186 1413 9 383 1612
    Swap: 1023 0 1023

    # free -h
    total used free shared buff/cache available
    Mem: 1.9G 186M 1.4G 9.4M 383M 1.6G
    Swap: 1.0G 0B 1.0G
  2. top

  3. glances

  4. htop

后面这几个命令在看CPU的时候已经演示了。

如何查看单个进程占用内存?

1
2
3
# 进程占用内存公式
pmem = VmRSS / MemTotal * 100
process mem = 虚拟内存 / 总内存 * 100

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# cat mem.py
#!/usr/bin/env python
# _*_ coding:UTF-8 _*_
# 收集程序所占用的物理内存大小,占所有物理内存的比例
# Python: 2.7.6

import sys
import os
from subprocess import Popen,PIPE

def get_pid(program):
'获取目标程序的PID列表'
p = Popen(['pidof',program],stdout=PIPE,stderr=PIPE)
pids,stderrput = p.communicate()
# pids = p.stdout.read() #这种方法也是可以的
# 这里也可以对stderrput来进行判断
if pids:
return pids.split()
else:
raise ValueError

def mem_calc(pids):
'计算PIDs占用的内存大小'
mem_total = 0
for pid in pids:
os.chdir('/proc/%s' % pid)
with open('status') as fd:
for line in fd:
if line.startswith('VmRSS'):
mem = line.strip().split()[1]
mem_total += int(mem)
break
return mem_total


def mem_percent(mem):
'计算程序内存占用物理内存的百分比'
with open('/proc/meminfo') as fd:
for line in fd:
if line.startswith('MemTotal'):
total = line.strip().split()[1]
percent = (float(mem)/int(total)) * 100
return percent


def main():
try:
program = sys.argv[1]
pids = get_pid(program)
except IndexError as e:
sys.exit('%s need a Program name ' % __file__)
except ValueError as e:
sys.exit('%s not a Process Name or not Start' % program )
mem_total = mem_calc(pids)
percent = mem_percent(mem_total)
return program,mem_total,percent

if __name__ == '__main__':
program,mem_total,mem_percent=main()
print('进程名称:%s\n物理内存为:%s\n百分比为:%.2f%%'% (program,mem_total,mem_percent))

磁盘监控命令

  1. df

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # df -h
    文件系统 容量 已用 可用 已用% 挂载点
    /dev/sda3 18G 1.4G 17G 8% /
    devtmpfs 981M 0 981M 0% /dev
    tmpfs 992M 0 992M 0% /dev/shm
    tmpfs 992M 9.5M 982M 1% /run
    tmpfs 992M 0 992M 0% /sys/fs/cgroup
    /dev/sda1 1014M 124M 891M 13% /boot
    tmpfs 199M 0 199M 0% /run/user/0

    # df -i
    文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点
    /dev/sda3 9436672 36259 9400413 1% /
    devtmpfs 251012 393 250619 1% /dev
    tmpfs 253768 1 253767 1% /dev/shm
    tmpfs 253768 700 253068 1% /run
    tmpfs 253768 16 253752 1% /sys/fs/cgroup
    /dev/sda1 524288 326 523962 1% /boot
    tmpfs 253768 1 253767 1% /run/user/0
  2. iotop

    1
    2
    3
    # iotop
    Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
    Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
  3. iostat

    1
    2
    # 以兆为单位,每秒执行一次,执行10次
    iostat -dm 1 10
  4. dstat

    1
    2
    3
    4
    5
    6
    7
    # dstat -cdngy
    ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
    usr sys idl wai hiq siq| read writ| recv send| in out | int csw
    0 0 100 0 0 0|1729B 3483B| 0 0 | 0 0 | 47 65
    0 0 100 0 0 0| 0 0 | 66B 830B| 0 0 | 92 114
    0 0 100 0 0 0| 0 0 | 66B 350B| 0 0 | 92 106
    0 0 100 0 0 0| 0 16k| 66B 350B| 0 0 | 102 114
  5. glances

    1
    2
    3
    4
    5
    6
    7
    8
    # glances

    DISK I/O R/s W/s
    sda 0 0
    sda1 0 0
    sda2 0 0
    sda3 0 0
    sr0 0 0

网络监控命令

  1. glances

    1
    2
    3
    4
    5
    # glances
    NETWORK Rx/s Tx/s
    eth0 0b 1Kb
    eth1 0b 0b
    lo 0b 0b
  2. iftop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # iftop
    12.5Kb 25.0Kb 37.5Kb 50.0Kb 62.5Kb
    └─────────────────┴───────────────┴───────────────┴───────────────┴───────────
    web03 => 10.0.0.1 1.39Kb 1.92Kb 1.92Kb
    <= 552b 331b 331b
    web03 => public1.alidns.com 0b 162b 162b
    <= 0b 310b 310b

    # 按P键可以看到与什么服务在交互
    # Mb 与 MB的区别
    # 百兆带宽:100Mb
    # 实际:100Mbps / 8 = 12MB
  3. nethogs

    该命令可以查看某个进程所使用的流量

    1
    2
    3
    4
    5
    6
    7
    8
    # nethogs
    NetHogs version 0.8.5

    PID USER PROGRAM DEV SENT RECEIVED
    2477 root sshd: root@pts/1 eth0 0.131 0.064 KB/sec
    ? root unknown TCP 0.000 0.000 KB/sec

    TOTAL 0.131 0.064 KB/sec
  4. ifconfig

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # ifconfig
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
    inet 10.0.0.8 netmask 255.255.255.0 broadcast 10.0.0.255
    inet6 fe80::20c:29ff:fea0:7ef0 prefixlen 64 scopeid 0x20<link>
    ether 00:0c:29:a0:7e:f0 txqueuelen 1000 (Ethernet)
    RX packets 55217 bytes 64623101 (61.6 MiB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 30950 bytes 4603140 (4.3 MiB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

    lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
    inet 127.0.0.1 netmask 255.0.0.0
    inet6 ::1 prefixlen 128 scopeid 0x10<host>
    loop txqueuelen 1000 (Local Loopback)
    RX packets 27 bytes 2072 (2.0 KiB)
    RX errors 0 dropped 0 overruns 0 frame 0
    TX packets 27 bytes 2072 (2.0 KiB)
    TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  5. route

    1
    2
    3
    4
    5
    # route -n
    Kernel IP routing table
    Destination Gateway Genmask Flags Metric Ref Use Iface
    0.0.0.0 10.0.0.2 0.0.0.0 UG 100 0 0 eth0
    10.0.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0

TCP11种状态监控命令

  1. netstat

    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
    # netstat -an
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address Foreign Address State
    tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
    tcp 0 0 0.0.0.0:873 0.0.0.0:* LISTEN
    tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
    tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
    tcp 0 0 0.0.0.0:52022 0.0.0.0:* LISTEN
    tcp 0 0 172.24.156.150:59936 100.100.30.25:80 ESTABLISHED
    tcp 0 0 172.24.156.150:52022 139.226.172.217:54116 ESTABLISHED
    tcp6 0 0 :::873 :::* LISTEN
    udp 0 0 172.17.0.1:123 0.0.0.0:*
    udp 0 0 172.18.0.1:123 0.0.0.0:*
    udp 0 0 172.24.156.150:123 0.0.0.0:*
    udp 0 0 127.0.0.1:123 0.0.0.0:*
    udp 0 0 0.0.0.0:123 0.0.0.0:*
    udp6 0 0 :::123 :::*

    # netstat -an|awk '/^tcp/ {print $NF}'|sort|uniq -c
    4 ESTABLISHED
    6 LISTEN

    # netstat -an|awk '/^tcp/ {++state[$NF]} END {for(key in state) print key," \t" ,state[key]}'
    LISTEN 6
    ESTABLISHED 4
  2. ss

    1
    2
    3
    # ss -n|awk '{print $2}'|sort|uniq -c
    42 ESTAB
    1 State

实战示例

如何每1分钟监控当前系统的内存使用状态,如果可用低于100MB则发送邮件。同时打印当前还剩余多少内存

  1. 如何获取内存的状态信息 free -m
  2. 如何获取内存的可用状态 free -m|awk ‘/Mem/{print $NF}’
  3. 如何进行数字的比对,高于100MB不处理,低于100MB,发送邮件。
  4. 如何每分钟执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# vim free.sh
#!/bin/bash
while true;do
free_av=$(free -m|awk '/^Mem/{print $NF}')
Hostname=$(hostname)_$(hostname -I|awk '{print $2}')
Date=$(date +%F)

if [ $free_av -lt 100 ];then
echo "$Date: ${Hostname},内存低于100MB,还有${free_av}MB内存可用"
fi
sleep 2
done

# sh free.sh
2018-10-12: web02_,内存低于100MB,还有20MB内存可用
2018-10-12: web02_,内存低于100MB,还有6MB内存可用
2018-10-12: web02_,内存低于100MB,还有5MB内存可用

# dd < /dev/zero > /dev/null bs=2000M

系统的oom

随着时间的推移,用户不断增多,服务消耗的内存越来越多,当系统内存不足的时候,可能会导致系统产生oom(out of memory)

  1. 当系统内存不足时就会大量使用swap(虚拟内存)
  2. 当系统大量使用swap的时候,系统会特别卡

注意:有时可能内存还有剩余300M或者500M,但是swap依然被使用

1
2
3
4
5
# dd < /dev/zero > /dev/null bs=2000M

# tail -f /var/log/messages
Out of memory: Kill process 29957 (dd) score 366 or sacrifice child
Killed process 29957 (dd) total-vm:2532680kB, anon-rss:1416508kB, filers:0kB

使用脚本监控nginx

前面我们学习了使用脚本+定时任务的方法自动备份并将检查结果,发到指定邮箱,那么这里,我也可以使用脚本+定时任务的方法,进行监控,并使用邮件报警

1
2
3
4
5
#!/bin/bash
nginx_process=`ps -ef|grep -c [n]ginx`
if [ $nginx_process -lt 2 ];then
echo "目前nginx进程数是:$nginx_process"|mail -s "完犊子nginx挂了" 133411023@qq.com
fi