本文最后更新于45 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
Prometheus 架构
1. 什么是 Prometheus
Prometheus 是一个开源系统监控和警报工具包,最初由 SoundCloud 构建。自 2012 年成立以来,许多公司和组织都采用了 Prometheus,该项目拥有非常活跃的开发人员和用户社区。它现在是一个独立的开源项目,独立于任何公司进行维护。为了强调这一点,并澄清该项目的治理结构,Prometheus 于 2016 年加入云原生计算基金会(CNCF),成为继 Kubernetes 之后的第二个托管项目。
- 官网地址:https://prometheus.io/
- CNCF 地址:https://landscape.cncf.io/
2. Prometheus 架构
- Prometheus Server:时间数据存储,监控指标管理。
- 可视化:
- Prometheus Web UI:集群状态管理,PromQL。
- Grafana:非常全面的可视化套件。
- 数据采集:
- Exporter:为客户端暴露出符合 Prometheus 规则的数据指标。Exporter 以守护进程模式运行并采集数据,本身是一个 HTTP 服务器,可以响应 HTTP 请求并返回数据(K/V 形式的 metrics)。
- 监控目标:
- 服务发现:通过 file、DNS、Kubernetes、Consul 等动态发现监控目标。
- 告警:
- Alertmanager:接收 Prometheus Server 的告警,进行去重、分组,并路由到对应的接收方式(如电子邮件、PagerDuty、Webhook 等)。
Prometheus 组件
- Prometheus Server:独立运行,依赖本地存储,负责抓取时序数据、规则处理和告警。
- Client Library:为监控的服务生成 metrics 并暴露给 Prometheus Server。当 Prometheus Server 拉取时,返回实时状态的 metrics。
- Push Gateway:用于短期任务,支持自定义监控数据,允许任务直接向 Prometheus Server 推送 metrics。
- Exporters:部署在第三方软件主机上,暴露第三方服务的 metrics 给 Prometheus。
- Data Visualization:
- Prometheus Web UI(内置界面)
- Grafana(第三方可视化组件,需单独部署)
- Server Discovery:动态发现待监控的 Target,适用于容器化环境。
上述组件大多用 Go 编写,易于构建和部署为二进制文件。
参考地址
二进制部署 Prometheus
1. 下载 Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.53.3/prometheus-2.53.3.linux-amd64.tar.gz
2. 解压软件包
tar xf prometheus-2.53.3.linux-amd64.tar.gz
3. 运行 Prometheus
cd prometheus-2.53.3.linux-amd64/
./prometheus
基于脚本一键部署 Prometheus
1. 下载部署脚本(软件包资源需要手动下载参考上一步)
#!/bin/bash
# auther: zhangdada
VERSION=2.53.3
ARCH=amd64
SOFTWARE=prometheus-${VERSION}.linux-${ARCH}.tar.gz
URL=https://github.com/prometheus/prometheus/releases/download/v${VERSION}/${SOFTWARE}
DOWNLOAD=./download
INSTALLDIR=/zhangdada/softwares
BASEDIR=${INSTALLDIR}/prometheus-${VERSION}.linux-amd64
DATADIR=/zhangdada/data/prometheus
LOGDIR=/zhangdada/logs/prometheus
HOSTIP=0.0.0.0
PORT=9090
HOSTNAME=`hostname`
function prepare() {
# 判断目录是否存在,若不存在则创建
[ -d $INSTALLDIR ] || install -d ${INSTALLDIR}
[ -d $DOWNLOAD ] || install -d ${DOWNLOAD}
[ -d $DATADIR ] || install -d ${DATADIR}
[ -d $LOGDIR ] || install -d ${LOGDIR}
. /etc/os-release
if [ "$ID" == "centos" ];then
# 判断系统是否安装wget
[ -f /usr/bin/wget ] || yum -y install wget
fi
# 判断文件是否存在,若不存在则下载
[ -s ${DOWNLOAD}/${SOFTWARE} ] || wget $URL -O ${DOWNLOAD}/${SOFTWARE}
}
function deploy() {
# 检查环境
prepare
# 解压文件软件包
tar xf ${DOWNLOAD}/${SOFTWARE} -C ${INSTALLDIR}
# 生成启动脚本
cat > /etc/systemd/system/prometheus-server.service <<EOF
[Unit]
Description=Oldboyedu Linux Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
After=network.target
[Service]
Restart=on-failure
ExecStart=/bin/bash -c "${BASEDIR}/prometheus \
--config.file=${BASEDIR}/prometheus.yml \
--web.enable-lifecycle \
--storage.tsdb.path=${DATADIR} \
--storage.tsdb.retention.time=60d \
--web.listen-address=${HOSTIP}:${PORT} \
--web.max-connections=65535 \
--storage.tsdb.retention.size=512MB \
--query.timeout=10s \
--query.max-concurrency=20 \
--log.level=info \
--log.format=json \
--web.read-timeout=5m &>> ${LOGDIR}/prometheus-server.log"
ExecReload=/bin/kill -HUP \$MAINPID
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
# 将服务设置为开机自启动
systemctl daemon-reload
systemctl enable --now prometheus-server
systemctl status prometheus-server
sleep 0.3
ss -ntl | grep ${PORT}
}
function delete(){
systemctl disable --now prometheus-server.service
rm -rf /etc/systemd/system/node-exporter.service $BASEDIR $DATADIR $LOGDIR
}
function main() {
case $1 in
deploy|i)
deploy
echo "${HOSTNAME} 的prometheus-server 已经部署成功![successfully]"
;;
delete|r)
delete
echo " ${HOSTNAME} 的prometheus-server 已经卸载成功,期待下次使用~"
;;
*)
echo "Usage: $0 deploy[i]|delete[r]"
;;
esac
}
main $1
2. 解压软件包
tar xf oldboyedu-install-prometheus-server-v2.53.3.tar.gz
3. 安装 Prometheus 服务
./install-prometheus-server.sh i
4. 访问 Web UI
http://10.0.0.31:9090/
5. 卸载 Prometheus 服务
./install-prometheus-server.sh r
Node-Exporter 部署
1. 下载脚本
#!/bin/bash
# auther: zhangdada
VERSION=1.8.2
SOFTWARE=node_exporter-${VERSION}.linux-amd64.tar.gz
URL=https://github.com/prometheus/node_exporter/releases/download/v${VERSION}/${SOFTWARE}
DOWNLOAD=./download
INSTALLDIR=/zhangdada/softwares
BASEDIR=${INSTALLDIR}/node_exporter-${VERSION}.linux-amd64
HOST="0.0.0.0"
PORT=9100
hostname=`hostname`
function prepare() {
# 判断目录是否存在,若不存在则创建
[ -d $INSTALLDIR ] || mkdir -pv ${INSTALLDIR}
[ -d $DOWNLOAD ] || mkdir -pv ${DOWNLOAD}
if [ "$ID" == "centos" ];then
# 判断系统是否安装curl
[ -f /usr/bin/wget ] || yum -y install wget
fi
# 判断文件是否存在,若不存在则下载
[ -s ${DOWNLOAD}/${SOFTWARE} ] || wget $URL -O ${DOWNLOAD}/${SOFTWARE}
}
function install() {
# 检查环境
prepare
# 解压文件软件包
tar xf ${DOWNLOAD}/${SOFTWARE} -C ${INSTALLDIR}
# 生成启动脚本
cat > /etc/systemd/system/node-exporter.service <<EOF
[Unit]
Description=Oldboyedu Linux Node Exporter
Documentation=https://prometheus.io/docs/introduction/overview/
After=network.target
[Service]
ExecStart=${BASEDIR}/node_exporter --web.telemetry-path="/metrics" \
--web.listen-address=${HOST}:${PORT}
[Install]
WantedBy=multi-user.target
EOF
# 将服务设置为开机自启动
systemctl daemon-reload
systemctl enable --now node-exporter.service
systemctl status node-exporter.service
ss -ntl | grep 9100
}
function remove(){
systemctl disable --now node-exporter.service
rm -rf /etc/systemd/system/node-exporter.service $BASEDIR
}
function main() {
case $1 in
install|i)
install
echo "${hostname} 的node-exporter 已经部署成功![successfully]"
;;
remove|r)
remove
echo "${hostname} 的node-exporter 已经卸载成功,期待下次使用~"
;;
*)
echo "Usage: $0 install[i]|remove[r]"
;;
esac
}
main $1
2. 解压软件包
3. 安装 Node-Exporter
./install-node-exporter.sh i
4. 访问 Node-Exporter Web UI
http://10.0.0.41:9100/metrics
5. 其他节点部署 Node-Exporter
5.1 拷贝脚本到其他服务器
scp oldboyedu-install-node-exporter-v1.8.2.tar.gz 10.0.0.42:~
scp oldboyedu-install-node-exporter-v1.8.2.tar.gz 10.0.0.43:~
5.2 其他节点部署 Node-Exporter
tar xf oldboyedu-install-node-exporter-v1.8.2.tar.gz
./install-node-exporter.sh i
Prometheus 监控 Node-Exporter 实战
1. 修改 Prometheus 配置文件
global:
scrape_interval: 3s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: "oldboyedu-node-exporter"
static_configs:
- targets: ["10.0.0.41:9100", "10.0.0.42:9100", "10.0.0.43:9100", "10.0.0.44:9100"]
2. 热加载配置
curl -X POST 10.0.0.31:9090/-/reload
3. 检查 Web UI
http://10.0.0.31:9090/targets
Prometheus Metrics Type
Prometheus 支持以下几种数据类型:
- Gauge:简单的返回值,表示瞬时状态(如硬盘、内存使用情况)。
- Counter:从 0 开始累积计算的计数器,通常只增不减(如用户访问量)。
- Histogram:统计分布情况(如最小值、最大值、中位数等)。
- Summary:Histogram 的扩展类型,用于弥补 Histogram 的不足。
PromQL 初体验
1. 查看某个特定的 key
node_cpu_seconds_total
2. 查看某个节点的指标
node_cpu_seconds_total{instance="10.0.0.41:9100"}
3. 查看某个节点的某刻 CPU 的某种状态
node_cpu_seconds_total{instance="10.0.0.41:9100", cpu="0", mode="idle"}
4. 查询最近 10s 内某个节点 CPU 的某种状态时间
node_cpu_seconds_total{instance="10.0.0.41:9100", cpu="0", mode="idle"}[10s]
5. 统计 1 分钟内,使用标签过滤器查看 “10.0.0.42:9100” 节点的第 0 颗 CPU,非空闲状态使用的总时间
node_cpu_seconds_total{mode!="idle", cpu="0", instance="10.0.0.42:9100"}[1m]
6. 统计 1 分钟内,使用标签过滤器查看 “10.0.0.42:9100” 节点的第 0 颗 CPU,mode 名称以字母 “i” 开头的所有 CPU 核心
node_cpu_seconds_total{mode=~"i.*", cpu="0", instance="10.0.0.42:9100"}[1m]
7. 统计 1 分钟内,使用标签过滤器查看 “10.0.0.42:9100” 节点的第 0 颗 CPU,mode 名称不是以字母 “i” 开头的所有 CPU 核心
node_cpu_seconds_total{mode!~"i.*", cpu="0", instance="10.0.0.42:9100"}[1m]
Prometheus 常用函数
1. increase
increase(node_cpu_seconds_total{mode="idle", cpu="0", instance="10.0.0.42:9100"}[1m])
2. sum
sum(increase(node_cpu_seconds_total{mode="idle"}[1m]))
3. by
sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by (instance)
4. rate
rate(node_cpu_seconds_total{mode="idle", cpu="0", instance="10.0.0.42:9100"}[1m])
5. topk
topk(3, rate(node_cpu_seconds_total{mode="idle"}[1m]))
6. count
count(rate(node_cpu_seconds_total{cpu="0", mode="idle"}[1m]))
监控 CPU 使用情况案例
1. 统计各个节点 CPU 的使用率
1.1 找到 CPU 相关的 key
node_cpu_seconds_total
1.2 过滤出 CPU 的空闲时间
node_cpu_seconds_total{mode='idle'}
1.3 统计 1 分钟内 CPU 的增量时间
increase(node_cpu_seconds_total{mode='idle'}[1m])
1.4 将结果进行加和统计
sum(increase(node_cpu_seconds_total{mode='idle'}[1m]))
1.5 按照不同节点进行分组
sum(increase(node_cpu_seconds_total{mode='idle'}[1m])) by (instance)
1.6 计算 1 分钟内 CPU 空闲时间的百分比
sum(increase(node_cpu_seconds_total{mode='idle'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)
1.7 统计 1 分钟内 CPU 的使用率
(1 - sum(increase(node_cpu_seconds_total{mode='idle'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100
1.8 统计 1 小时内 CPU 的使用率
(1 - sum(increase(node_cpu_seconds_total{mode='idle'}[1h])) by (instance) / sum(increase(node_cpu_seconds_total[1h])) by (instance)) * 100
2. 计算 CPU 用户态的 1 分钟内百分比
sum(increase(node_cpu_seconds_total{mode='user'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance) * 100
3. 计算 CPU 内核态的 1 分钟内百分比
(sum(increase(node_cpu_seconds_total{mode='system'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100
4. 计算 CPU IO 等待时间的 1 分钟内百分比
(sum(increase(node_cpu_seconds_total{mode='iowait'}[1m])) by (instance) / sum(increase(node_cpu_seconds_total[1m])) by (instance)) * 100
Grafana 基于 MySQL 作为数据存储实战案例
1. 安装 Grafana 的依赖包
apt-get -y install adduser libfontconfig1 musl
2. 下载 Grafana 的软件包
wget https://dl.grafana.com/enterprise/release/grafana-enterprise_9.5.21_amd64.deb
3. 安装 Grafana
dpkg -i grafana-enterprise_9.5.21_amd64.deb
4. 安装 MySQL 数据库
4.1 安装 Docker 环境
wget
tar xf yinzhengjie-autoinstall-docker-docker-compose.tar.gz
./install-docker.sh i
4.2 导入 MySQL 镜像
wget http://192.168.15.253/Resources/Docker/images/WordPress/oldboyedu-mysql-v8.0.36-oracle.tar.gz
docker load < oldboyedu-mysql-v8.0.36-oracle.tar.gz
4.3 启动 MySQL 服务
docker run -d --name mysql-server --restart always --network host -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -e MYSQL_DATABASE=prometheus -e MYSQL_USER=linux95 -e MYSQL_PASSWORD=oldboyedu mysql:8.0.36-oracle --character-set-server=utf8 --collation-server=utf8_bin --default-authentication-plugin=mysql_native_password
5. 修改 Grafana 的配置文件
vim /etc/grafana/grafana.ini
配置内容:ini复制
[database]
type = mysql
host = 10.0.0.43:3306
name = prometheus
user = linux95
password = oldboyedu
6. 启动 Grafana
systemctl restart grafana-server.service
7. 登录 Grafana Web UI
http://10.0.0.31:3000/
初始用户名和密码:admin