點選下方“民工哥技術之路”,選擇“設為星标”
回複“1024”擷取獨家整理的學習資料!

Prometheus簡介
Prometheus是由SoundCloud開發的開源監控報警系統和時序列資料庫(TSDB)。
Prometheus使用Go語言開發,是Google BorgMon監控系統的開源版本。2016年由Google發起Linux基金會旗下的原生雲基金會(Cloud Native Computing Foundation), 将Prometheus納入其下第二大開源項目。Prometheus目前在開源社群相當活躍。Prometheus和Heapster(Heapster是K8S的一個子項目,用于擷取叢集的性能資料。)相比功能更完善、更全面。Prometheus性能也足夠支撐上萬台規模的叢集。
系統架構圖
基本原理
Prometheus的基本原理是通過HTTP協定周期性抓取被監控元件的狀态,任意元件隻要提供對應的HTTP接口就可以接入監控。不需要任何SDK或者其他的內建過程。這樣做非常适合做虛拟化環境監控系統,比如VM、Docker、Kubernetes等。輸出被監控元件資訊的HTTP接口被叫做exporter 。目前網際網路公司常用的元件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系統資訊(包括磁盤、記憶體、CPU、網絡等等)。
其大概的工作流程是:
- Prometheus server 定期從配置好的 jobs 或者 exporters 中拉 metrics,或者接收來自 Pushgateway 發過來的 metrics,或者從其他的 Prometheus server 中拉 metrics。
- Prometheus server 在本地存儲收集到的 metrics,并運作已定義好的 alert.rules,記錄新的時間序列或者向 Alertmanager 推送警報。
- Alertmanager 根據配置檔案,對接收到的警報進行處理,發出告警。
- 在Grafana圖形界面中,可視化檢視采集資料。
Prometheus的特性
- 多元度資料模型。
- 靈活的查詢語言。
- 不依賴分布式存儲,單個伺服器節點是自主的。
- 通過基于HTTP的pull方式采集時序資料。
- 可以通過中間網關進行時序列資料推送。
- 通過服務發現或者靜态配置來發現目标服務對象。
- 支援多種多樣的圖表和界面展示,比如Grafana等。
Prometheus的元件
- Prometheus Server 主要負責資料采集和存儲,提供PromQL查詢語言的支援。
- Alertmanager 警告管理器,用來進行報警。
- Push Gateway 支援臨時性Job主動推送名額的中間網關。
- Exporters 輸出被監控元件資訊的HTTP接口。
- Grafana 監控資料展示Web UI。
服務發現
由于 Prometheus 是通過 Pull 的方式主動擷取監控資料,也就是每隔幾秒鐘去各個target采集一次metric。是以需要手工指定監控節點的清單,當監控的節點增多之後,每次增加節點都需要更改配置檔案,盡管可以使用接口去熱更新配置檔案,但仍然非常麻煩,這個時候就需要通過服務發現(service discovery,SD)機制去解決。
Prometheus 支援多種服務發現機制,可以自動擷取要收集的 targets,包含的服務發現機制包括:azure、consul、dns、ec2、openstack、file、gce、kubernetes、marathon、triton、zookeeper(nerve、serverset),配置方法可以參考手冊的配置頁面。可以說 SD 機制是非常豐富的,但目前由于開發資源有限,已經不再開發新的 SD 機制,隻對基于檔案的 SD 機制進行維護。針對我們現有的系統情況,我們選擇了靜态配置方式。
部署PrometheusServer
使用官方鏡像運作
由于Prometheus官方鏡像沒有開啟熱加載功能,而且時區相差八小時,是以我們選擇了自己制作鏡像,當然你也可以使用官方的鏡像,提前建立Prometheus配置檔案prometheus.yml和Prometheus規則檔案rules.yml,然後通過如下指令挂載到官方鏡像中運作:
$ docker run -d -p 9090:9090 --name=prometheus \
-v /root/prometheus/conf/:/etc/prometheus/ \
prom/prometheus
制作鏡像
現在我們建立自己的Prometheus鏡像,當然你也可以直接使用我制作的鏡像
$ docker pull zhanganmin2017/prometheus:v2.9.0
首先去Prometheus下載下傳二進制檔案安裝包解壓到package目錄下,我的Dockerfile目錄結構如下:
$ tree prometheus-2.9.0/
prometheus-2.9.0/
├── conf
│ ├── CentOS7-Base-163.repo
│ ├── container-entrypoint
│ ├── epel-7.repo
│ ├── prometheus-start.conf
│ ├── prometheus-start.sh
│ ├── prometheus.yml
│ ├── rules
│ │ └── service_down.yml
│ └── supervisord.conf
├── Dockerfile
└── package
├── console_libraries
├── consoles
├── LICENSE
├── NOTICE
├── prometheus
├── prometheus.yml
└── promtool
5 directories, 26 files
分别建立圖中的目錄,可以看到conf目錄中有一些名為supervisord的檔案,這是因為在容器中的程序我們選擇使用supervisor進行管理,當然如果不想使用的化可以進行相應的修改。
制作prometheus-start.sh啟動腳本,Supervisor啟動Prometheus會調用該腳本
#!/bin/bash
/bin/prometheus \
--config.file=/data/prometheus/prometheus.yml \
--storage.tsdb.path=/data/prometheus/data \
--web.console.libraries=/data/prometheus/console_libraries \
--web.enable-lifecycle \
--web.console.templates=/data/prometheus/consoles
制作Prometheus-start.conf啟動檔案,Supervisord的配置檔案
[program:prometheus]
command=sh /etc/supervisord.d/prometheus-start.sh ; 程式啟動指令
autostart=false ; 在supervisord啟動的時候不自動啟動
startsecs=10 ; 啟動10秒後沒有異常退出,就表示程序正常啟動了,預設1秒
autorestart=false ; 關閉程式退出後自動重新開機,可選值:[unexpected,true,false],預設為unexpected,表示程序意外殺死才重新開機
startretries=0 ; 啟動失敗自動重試次數,預設是3
user=root ; 用哪個使用者啟動程序,預設是root
redirect_stderr=true ; 把stderr重定向到stdout,預設false
stdout_logfile_maxbytes=20MB ; stdout 日志檔案大小,預設是50MB
stdout_logfile_backups=30 ; stdout 日志檔案備份數,預設是10;
# stdout 日志檔案,需要注意當指定目錄不存在時無法正常啟動,是以需要手動建立目錄(supervisord 會自動建立日志檔案)
stdout_logfile=/data/prometheus/prometheus.log
stopasgroup=true
killasgroup=tru
制作supervisord.conf啟動檔案
[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
chmod=0700 ; sockef file mode (default 0700)
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
user=root
minfds=10240
minprocs=200
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
[program:sshd]
command=/usr/sbin/sshd -D
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/ssh_out.log
stderr_logfile=/var/log/supervisor/ssh_err.log
[include]
files = /etc/supervisord.d/*.conf
制作container-entrypoint守護檔案,容器啟動後執行的腳本
#!/bin/sh
set -x
if [ ! -d "/data/prometheus" ];then
mkdir -p /data/prometheus/data
fi
mv /usr/local/src/* /data/prometheus/
exec /usr/bin/supervisord -n
exit
在conf目錄下建立Prometheus.yml配置檔案,這個是Prometheus配置監控主機的檔案
global:
scrape_interval: 60s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 60s # Evaluate rules every 15 seconds. The default is every 1 minute.
alerting:
alertmanagers:
- static_configs:
- targets: [ '192.168.133.110:9093']
rule_files:
- "rules/host_sys.yml"
scrape_configs:
- job_name: 'Host'
static_configs:
- targets: ['10.1.250.36:9100']
labels:
appname: 'DEV01_250.36'
- job_name: 'prometheus'
static_configs:
- targets: [ '10.1.133.210:9090']
labels:
appname: 'Prometheus'
在conf目錄下建立rules目錄,編寫service_down.yml規則檔案,這個也可以等到容器建立後再編寫,這裡我們就直接寫好添加到鏡像中
groups:
- name: servicedown
rules:
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
name: instance
severity: Critical
annotations:
summary: " {{ $labels.appname }}"
description: " 服務停止運作 "
value: "{{ $value }}"
制作dockerfile 鏡像檔案
FROM docker.io/centos:7
MAINTAINER from [email protected]
# install repo
RUN rm -rf /etc/yum.repos.d/*.repo
ADD conf/CentOS7-Base-163.repo /etc/yum.repos.d/
ADD conf/epel-7.repo /etc/yum.repos.d/
# yum install
RUN yum install -q -y openssh-server openssh-clients net-tools \
vim supervisor && yum clean all
# install sshd
RUN ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key \
&& ssh-keygen -q -N "" -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key \
&& ssh-keygen -q -N "" -t ed25519 -f /etc/ssh/ssh_host_ed25519_key \
&& sed -i 's/#UseDNS yes/UseDNS no/g' /etc/ssh/sshd_config
# UTF-8 and CST +0800
ENV LANG=zh_CN.UTF-8
RUN echo "export LANG=zh_CN.UTF-8" >> /etc/profile.d/lang.sh \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& localedef -c -f UTF-8 -i zh_CN zh_CN.utf8
# install Prometheus
COPY package/prometheus /bin/prometheus
COPY package/promtool /bin/promtool
COPY package/console_libraries/ /usr/local/src/console_libraries/
COPY package/consoles/ /usr/local/src/consoles/
COPY conf/prometheus.yml /usr/local/src/prometheus.yml
COPY conf/rules/ /usr/local/src/rules/
# create user
RUN echo "root:123456" | chpasswd
# supervisord
ADD conf/supervisord.conf /etc/supervisord.conf
ADD conf/prometheus-start.conf /etc/supervisord.d/prometheus-start.conf
ADD conf/container-entrypoint /container-entrypoint
ADD conf/prometheus-start.sh /etc/supervisord.d/prometheus-start.sh
RUN chmod +x /container-entrypoint
# cmd
CMD ["/container-entrypoint"]
Dockerfile中安裝了supervisor程序管理工具和SSH服務,指定了字元集和時區。
生成鏡像并運作容器服務
$ docker build -t zhanganmin2017/prometheus:v2.9.0 .
$ docker run -itd -h prometheus139-210 -m 8g --cpuset-cpus=28-31 --name=prometheus139-210 --network trust139 --ip=10.1.133.28 -v /data/works/prometheus139-210:/data 192.168.166.229/1an/prometheus:v2.9.0
$ docker exec -it prometheus139-210 /bin/bash
$ supervisorctl start prometheus
通路prometheus Web頁面 IP:9090
部署監控元件Exporter
Prometheus 是使用 Pull 的方式來擷取名額資料的,要讓 Prometheus 從目标處獲得資料,首先必須在目标上安裝名額收集的程式,并暴露出 HTTP 接口供 Prometheus 查詢,這個名額收集程式被稱為 Exporter ,不同的名額需要不同的 Exporter 來收集,目前已經有大量的 Exporter 可供使用,幾乎囊括了我們常用的各種系統和軟體,官網列出了一份常用Exporter的清單 ,各個 Exporter 都遵循一份端口約定,避免端口沖突,即從 9100 開始依次遞增,這裡是完整的 Exporter端口清單 。另外值得注意的是,有些軟體和系統無需安裝 Exporter,這是因為他們本身就提供了暴露 Prometheus 格式的名額資料的功能,比如 Kubernetes、Grafana、Etcd、Ceph 等。
部署主機監控元件
各節點主機使用主機網絡模式部署主機監控元件node-exporter,官方不建議将其部署為Docker容器,因為該node_exporter設計用于監控主機系統。需要通路主機系統,而且通過容器的方式部署發現磁盤資料不太準确。二進制部署就去看項目文檔吧
$ docker run -d \
--net="host" \
--pid="host" \
-v "/:/host:ro,rslave" \
quay.io/prometheus/node-exporter \
--path.rootfs=/host
容器正常運作後,進入Prometheus容器,在Prometheus.yml 檔案中添加node-exporter元件位址
$ docker exec -it prometheus-133-210 /bin/bash
$ vim /data/prometheus/prometheus.yml
global:
scrape_interval: 60s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 60s # Evaluate rules every 15 seconds. The default is every 1 minute.
rule_files:
- "rules/service_down.yml"
scrape_configs:
- job_name: 'Host'
static_configs:
- targets: ['10.1.250.36:9100'] #node-exporter位址
labels:
appname: 'DEV01_250.36' #添加的标簽
- job_name: 'prometheus'
static_configs:
- targets: [ '10.2.139.210:9090']
labels:
appname: 'prometheus'
熱加載更新Prometheus
$ curl -X POST http://10.1.133.210:9090/-/reload
檢視Prometheus的web頁面已經可以看到node-exporter,然後我們就可以定義報警規則和展示看闆了,這部分内容在後面配置Alertmanager和Grafana上會詳細介紹。
部署容器監控元件
各節點主機部署容器監控元件cadvisor-exporter,我這邊Docker網絡使用的macvlan方式,是以直接給容器配置設定了IP位址。
# docker run -d -h cadvisor139-216 --name=cadvisor139-216 --net=none -m 8g --cpus=4 --ip=10.1.139.216 --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --volume=/dev/disk/:/dev/disk:ro google/cadvisor:latest
同樣的,容器正常運作後,我們通路Cadvisor的Web頁面 IP+8080 端口
現在我們進入Prometheus容器,在prometheus.yml主機檔案中添加cadvisor元件
-----------
- job_name: 'Cadvisor'
static_configs:
- targets: [ '10.1.139.216:8080']
labels:
appname: 'DEV_Cadvisor01'
$ curl -X POST http://10.1.133.210:9090/-/reload
可以看到,Prometheus添加的cadvisor狀态為UP,說明正常接收資料。
部署Redis監控元件
容器部署Redis服務監控元件redis_exporter,--redis.passwd指定認證密碼,如果你的redis通路沒有密碼那麼就無需指定後面參數。
$ docker run -d -h redis_exporter139-218 --name redis_exporter139-218 --network trust139 --ip=10.1.139.218 -m 8g --cpus=4 oliver006/redis_exporter --redis.passwd 123456
在prometheus.yml 添加redis-exporter
---------
- job_name: 'Redis-exporter' #exporter位址
static_configs:
- targets: ['10.2.139.218:9121'']
labels:
appname: 'redis-exporter'
- job_name: 'RedisProxy' #需要監控的redis位址
static_configs:
- targets:
- redis://10.2.139.70:6379
- redis://10.2.139.71:6379
labels:
appname: RedisProxy
metrics_path: /scrape
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 10.2.139.218:9121
然後熱加載更新,步驟同上。
部署應用監控元件
中間件部署JVM監控元件jmx_exporter, 這種方式是适用于代碼中沒有暴露應用metrics資訊的服務,無需進行代碼改動,在應用啟動時調用該jar包暴露jmx資訊,然後在Prometheus分别指定應用的位址即可。
首先下載下傳jar :https://github.com/prometheus/jmx_exporter(jmx_prometheus_javaagent-0.11.0.jar )
下載下傳配置檔案,有tomcat和weblogic注意區分:https://github.com/prometheus/jmx_exporter/tree/master/example_configs
然後在中間件啟動參數添加以下内容,指定配置檔案和jar包的路徑:
CATALINA_OPTS="-javaagent:/app/tomcat-8.5.23/lib/jmx_prometheus_javaagent-0.11.0.jar=12345:/app/tomcat-8.5.23/conf/config.yaml"
上面我指定暴露metrics資訊的端口為12345,是以我們在prometheus.yml檔案中添加即可:
---------
- job_name: 'MIDL'
static_configs:
- targets: ['192.168.166.18:12345','192.168.166.19:12345']
labels:
appname: 'ORDER'
- targets: ['10.2.139.111:12345','10.2.139.112:12345']
labels:
appname: 'WEB'
其他步驟同上,Prometheus熱加載更新即可。
部署程序監控元件
因為我們容器是使用單獨的網絡部署的,相當于胖容器的方式,是以需要在監控的容器中部署process-exporter程序監控元件來監控容器的程序,
軟體包下載下傳:
wget https://github.com/ncabatoff/process-exporter/releases/download/v0.5.0/process-exporter-0.5.0.linux-amd64.tar.gz
配置檔案:process-name.yaml
process_names:
- name: "{{.Matches}}"
cmdline:
- 'redis-shake' #比對程序,支援正則
啟動參數:
$ nohup ./process-exporter -config.path process-name.yaml &
在Prometheus.yml 添加該容器的IP位址,端口号為9256
-----------
- job_name: 'process'
static_configs:
- targets: [ '10.2.139.186:9256']
labels:
appname: 'Redis-shake'
ok,現在我們熱加載更新Prometheus的主機檔案
$ curl -X POSThttp://10.2.139.210:9090/-/reload
部署Alertmanager報警元件
Alertmanager 概述
Alertmanager處理用戶端應用程式(如Prometheus伺服器)發送的告警。它負責對它們進行重複資料删除,分組和路由,以及正确的接收器內建,例如電子郵件,PagerDuty或OpsGenie。它還負責警報的靜默和抑制。
以下描述了Alertmanager實作的核心概念。請參閱配置文檔以了解如何更詳細地使用它們。
- 分組(Grouping)
-
- 分組将類似性質的告警分類為單個通知。這在大型中斷期間尤其有用,因為許多系統一次失敗,并且可能同時發射數百到數千個警報。
- 示例:發生網絡分區時,群集中正在運作數十或數百個服務執行個體。一半的服務執行個體無法再通路資料庫。Prometheus中的告警規則配置為在每個服務執行個體無法與資料庫通信時發送告警。結果,數百個告警被發送到Alertmanager。
- 作為使用者,隻能想要獲得單個頁面,同時仍能夠确切地看到哪些服務執行個體受到影響。是以,可以将Alertmanager配置為按群集和alertname對警報進行分組,以便發送單個緊湊通知。
- 這些通知的接收器通過配置檔案中的路由樹配置告警的分組,定時的進行分組通知。
- 抑制(Inhibition)
-
- 如果某些特定的告警已經觸發,則某些告警需要被抑制。
- 示例:如果某個告警觸發,通知無法通路整個叢集。Alertmanager可以配置為在該特定告警觸發時将與該叢集有關的所有其他告警靜音。這可以防止通知數百或數千個與實際問題無關的告警觸發。
- 靜默(SILENCES)
-
- 靜默是在給定時間内簡單地靜音告警的方法。基于比對器配置靜默,就像路由樹一樣。檢查告警是否比對或者正規表達式比對靜默。如果比對,則不會發送該告警的通知。在Alertmanager的Web界面中可以配置靜默。
- 用戶端行為(Client behavior)
-
- Alertmanager對其客戶的行為有特殊要求。這些僅适用于不使用Prometheus發送警報的進階用例。#制作鏡像方式和Prometheus類似,稍作更改即可,此步省略。
設定警報和通知的主要步驟如下:
- 設定并配置Alertmanager;
- 配置Prometheus對Alertmanager通路;
- 在普羅米修斯建立警報規則;
部署Alertmanager元件
首先需要建立Alertmanager的報警通知檔案,我這裡使用企業微信報警,其中企業微信需要申請賬号認證,方式如下:
- 通路網站注冊企業微信賬号(不需要企業認證)。
- 通路apps建立第三方應用,點選建立應用按鈕 -> 填寫應用資訊:
- 建立報警組,擷取組ID:
建立alertmanager.yml報警通知檔案
global:
resolve_timeout: 2m
smtp_smarthost: smtp.163.com:25
smtp_from: [email protected]
smtp_auth_username: [email protected]
smtp_auth_password: zxxx
templates:
- '/data/alertmanager/conf/template/wechat.tmpl'
route:
group_by: ['alertname_wechat']
group_wait: 1s
group_interval: 1s
receiver: 'wechat'
repeat_interval: 1h
routes:
- receiver: wechat
match_re:
serverity: wechat
receivers:
- name: 'email'
email_configs:
- to: '[email protected]'
send_resolved: true
- name: 'wechat'
wechat_configs:
- corp_id: 'wwd402ce40b4720f24'
to_party: '2'
agent_id: '1000002'
api_secret: '9nmYa4p12OkToCbh_oNc'
send_resolved: true ## 發送已解決通知
參數說明:
corp_id: #企業微信賬号唯一 ID, 可以在我的企業中檢視。
to_party: #需要發送的組。
agent_id: #第三方企業應用的 ID,可以在自己建立的第三方企業應用詳情頁面檢視。
api_secret: #第三方企業應用的密鑰,可以在自己建立的第三方企業應用詳情頁面檢視。
然後我們建立企業微信的消息模闆,template/wechat.tmpl
{{ define "wechat.default.message" }}
{{ range $i, $alert :=.Alerts }}
【系統報警】
告警狀态:{{ .Status }}
告警級别:{{ $alert.Labels.severity }}
告警應用:{{ $alert.Annotations.summary }}
告警詳情:{{ $alert.Annotations.description }}
觸發閥值:{{ $alert.Annotations.value }}
告警主機:{{ $alert.Labels.instance }}
告警時間:{{ $alert.StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
{{ end }}
這個報警的模闆其中的值是在Prometheus觸發的報警資訊中提取的,是以你可以根據自己的定義進行修改。
運作Alertmanager容器
$ docker run -d -p 9093:9093 --name alertmanager -m 8g --cpus=4 -v /opt/alertmanager.yml:/etc/alertmanager/alertmanager.yml -v /opt/template:/etc/alertmanager/template docker.io/prom/alertmanager:latest
容器運作完成後檢視web頁面 IP:9093
配置報警規則
Prometheus的報警規則通過PromQL語句編寫
進入Prometheus容器的rules目錄,上面我們制作鏡像的時候已經建立好并挂載到了容器中,現在我們編寫其他的規則檔案
編寫主機監控規則檔案,rules/host_sys.yml
cat host_sys.yml
groups:
- name: Host
rules:
- alert: HostMemory Usage
expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 90
for: 1m
labels:
name: Memory
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: "主控端記憶體使用率超過90%."
value: "{{ $value }}"
- alert: HostCPU Usage
expr: sum(avg without (cpu)(irate(node_cpu_seconds_total{mode!='idle'}[5m]))) by (instance,appname) > 0.8
for: 1m
labels:
name: CPU
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: "主控端CPU使用率超過80%."
value: "{{ $value }}"
- alert: HostLoad
expr: node_load5 > 20
for: 1m
labels:
name: Load
severity: Warning
annotations:
summary: "{{ $labels.appname }} "
description: " 主機負載5分鐘超過20."
value: "{{ $value }}"
- alert: HostFilesystem Usage
expr: (node_filesystem_size_bytes-node_filesystem_free_bytes)/node_filesystem_size_bytes*100>80
for: 1m
labels:
name: Disk
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 主控端 [ {{ $labels.mountpoint }} ]分區使用超過80%."
value: "{{ $value }}%"
- alert: HostDiskio writes
expr: irate(node_disk_writes_completed_total{job=~"Host"}[1m]) > 10
for: 1m
labels:
name: Diskio
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 主控端 [{{ $labels.device }}]磁盤1分鐘平均寫入IO負載較高."
value: "{{ $value }}iops"
- alert: HostDiskio reads
expr: irate(node_disk_reads_completed_total{job=~"Host"}[1m]) > 10
for: 1m
labels:
name: Diskio
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 宿機 [{{ $labels.device }}]磁盤1分鐘平均讀取IO負載較高."
value: "{{ $value }}iops"
- alert: HostNetwork_receive
expr: irate(node_network_receive_bytes_total{device!~"lo|bond[0-9]|cbr[0-9]|veth.*|virbr.*|ovs-system"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_receive
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 主控端 [{{ $labels.device }}] 網卡5分鐘平均接收流量超過10Mbps."
value: "{{ $value }}3Mbps"
- alert: hostNetwork_transmit
expr: irate(node_network_transmit_bytes_total{device!~"lo|bond[0-9]|cbr[0-9]|veth.*|virbr.*|ovs-system"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_transmit
severity: Warning
annotations:
summary: " {{ $labels.appname }} "
description: " 主控端 [{{ $labels.device }}] 網卡5分鐘内平均發送流量超過10Mbps."
value: "{{ $value }}3Mbps"
編寫容器監控規則檔案,rules/container_sys.yml
groups:
- name: Container
rules:
- alert: ContainerCPU
expr: (sum by(name,instance) (rate(container_cpu_usage_seconds_total{image!=""}[5m]))*100) > 200
for: 1m
labels:
name: CPU_Usage
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: " 容器CPU使用超200%."
value: "{{ $value }}%"
- alert: Memory Usage
expr: (container_memory_usage_bytes{name=~".+"} - container_memory_cache{name=~".+"}) / container_spec_memory_limit_bytes{name=~".+"} * 100 > 200
for: 1m
labels:
name: Memory
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: " 容器記憶體使用超過200%."
value: "{{ $value }}%"
- alert: Network_receive
expr: irate(container_network_receive_bytes_total{name=~".+",interface=~"eth.+"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_receive
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: "容器 [{{ $labels.device }}] 網卡5分鐘平均接收流量超過10Mbps."
value: "{{ $value }}Mbps"
- alert: Network_transmit
expr: irate(container_network_transmit_bytes_total{name=~".+",interface=~"eth.+"}[5m]) / 1048576 > 10
for: 1m
labels:
name: Network_transmit
severity: Warning
annotations:
summary: "{{ $labels.name }} "
description: "容器 [{{ $labels.device }}] 網卡5分鐘平均發送流量超過10Mbps."
value: "{{ $value }}Mbps"
編寫redis監控規則檔案,redis_check.yml
groups:
- name: redisdown
rules:
- alert: RedisDown
expr: redis_up == 0
for: 1m
labels:
name: instance
severity: Critical
annotations:
summary: " {{ $labels.alias }}"
description: " 服務停止運作 "
value: "{{ $value }}"
- alert: Redis linked too many clients
expr: redis_connected_clients / redis_config_maxclients * 100 > 80
for: 1m
labels:
name: instance
severity: Warning
annotations:
summary: " {{ $labels.alias }}"
description: " Redis連接配接數超過最大連接配接數的80%. "
value: "{{ $value }}"
- alert: Redis linked
expr: redis_connected_clients / redis_config_maxclients * 100 > 80
for: 1m
labels:
name: instance
severity: Warning
annotations:
summary: " {{ $labels.alias }}"
description: " Redis連接配接數超過最大連接配接數的80%. "
value: "{{ $value }}"
編寫服務停止監控規則,rules/service_down.yml
- alert: ProcessDown
expr: namedprocess_namegroup_num_procs == 0
for: 1m
labels:
name: instance
severity: Critical
annotations:
summary: " {{ $labels.appname }}"
description: " 程序停止運作 "
value: "{{ $value }}"
- alert: Grafana down
expr: absent(container_last_seen{name=~"grafana.+"} ) == 1
for: 1m
labels:
name: grafana
severity: Critical
annotations:
summary: "Grafana"
description: "Grafana容器停止運作"
value: "{{ $value }}"
編寫報警規則可以參考後面Grafana展示看闆後的資料展示語句,需要注意的是,我們容器使用的是胖容器的方式,即當作虛拟機來使用,是以需要添加應用和服務停止的Exporter,如果你的容器守護程序直接就是應用的話,隻需要監控容器的啟停就可以了。
測試微信報警
Grafana展示元件
雖然 Prometheus 提供的 Web UI 也可以很好的檢視不同名額的視圖,但是這個功能非常簡單,隻适合用來調試。要實作一個強大的監控系統,還需要一個能定制展示不同名額的面闆,能支援不同類型的展現方式(曲線圖、餅狀圖、熱點圖、TopN 等),這就是儀表盤(Dashboard)功能。
Prometheus 開發了一套儀表盤系統PromDash,不過很快這套系統就被廢棄了,官方開始推薦使用 Grafana 來對 Prometheus 的名額資料進行可視化,這不僅是因為 Grafana 的功能非常強大,而且它和 Prometheus 可以完美的無縫融合。
Grafana是一個用于可視化大型測量資料的開源系統,它的功能非常強大,界面也非常漂亮,使用它可以建立自定義的控制台,你可以在面闆中配置要顯示的資料和顯示方式,它支援很多不同的資料源,比如:Graphite、InfluxDB、OpenTSDB、Elasticsearch、Prometheus 等,而且它也支援衆多的插件 。
部署Grafana服務容器
$ docker run -d -h grafana139-211 -m 8g --network trust139 --ip=10.2.139.211 --cpus=4 --name=grafana139-211 -e "GF_SERVER_ROOT_URL=http://10.2.139.211" -e "GF_SECURITY_ADMIN_PASSWORD=passwd" grafana/grafana
運作後通路IP:3000,user:admin pass:passwd
添加Prometheus資料源
導入監控模闆
使用編号導入模闆,Grafana服務需要聯網,否則需要到Grafana模闆下載下傳JSON檔案導入。
下面是我使用的幾個模闆,導入後可以根據自己的情況定義變量值
主機監控展示看闆Node-exporter導入 8919 模闆
容器監控展示看闆cadvisor-exporter導入193 模闆
應用監控展示看闆jmx-exporter導入8563 模闆
Redis監控展示看闆Redis-exporter導入2751 模闆
程序監控展示看闆Process-exporter導入249 模闆
使用Concul HTTP注冊方式實作服務發現
一般是用服務發現需要應用需要服務注冊,我們這邊因為微服務改造還沒完成,還有一些tomcat和weblogic中間件,而且選用的注冊中心是Eurka,是以為了在代碼不改動的情況下使用服務發現,選擇了concul 作為注冊中心,因為是consul是可以通過http方式注冊的。
consul 内部原理
Consul分為Client和Server兩種節點(所有的節點也被稱為Agent),Server節點儲存資料,Client負責健康檢查及轉發資料請求到Server;Server節點有一個Leader和多個Follower,Leader節點會将資料同步到Follower,Server的數量推薦是3個或者5個,在Leader挂掉的時候會啟動選舉機制産生一個新的Leader。
叢集内的Consul節點通過gossip協定(流言協定)維護成員關系,也就是說某個節點了解叢集内現在還有哪些節點,這些節點是Client還是Server。單個資料中心的流言協定同時使用TCP和UDP通信,并且都使用8301端口。跨資料中心的流言協定也同時使用TCP和UDP通信,端口使用8302。
叢集内資料的讀寫請求既可以直接發到Server,也可以通過Client使用RPC轉發到Server,請求最終會到達Leader節點,在允許資料輕微陳舊的情況下,讀請求也可以在普通的Server節點完成,叢集内資料的讀寫和複制都是通過TCP的8300端口完成。
具體consul的原理及架構請通路:http://blog.didispace.com/consul-service-discovery-exp/
使用docker部署consul 叢集
#啟動第1個Server節點,叢集要求要有3個Server,将容器8500端口映射到主機8900端口,同時開啟管理界面
docker run -d --name=consul1 -p 8900:8500 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --bootstrap-expect=3 --client=0.0.0.0 -ui
#啟動第2個Server節點,并加入叢集
docker run -d --name=consul2 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.1
#啟動第3個Server節點,并加入叢集
docker run -d --name=consul3 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=true --client=0.0.0.0 --join 172.17.0.2
#啟動第4個Client節點,并加入叢集
docker run -d --name=consul4 -e CONSUL_BIND_INTERFACE=eth0 consul agent --server=false --client=0.0.0.0 --join 172.17.0.2
浏覽器通路容器映射的8900端口:
服務注冊到Consul
使用HTTP API 方式注冊node-exporter服務到Consul
curl -X PUT -d '{"id": "192.168.16.173","name": "node-exporter","address": "192.168.16.173","port": ''9100,"tags": ["DEV"], "checks": [{"http": "http://192.168.16.173:9100/","interval": "5s"}]}' http://172.17.0.4:8500/v1/agent/service/register
解注冊:
curl --request PUT http://172.17.0.4:8500/v1/agent/service/deregister/192.168.166.14
注冊多個服務到consul,使用腳本:
#!/bin/bash
all_IP=`cat /opt/ip`
name=cadvisor
port=9100
for I in $all_IP
do
curl -X PUT -d '{"id": "'$I'","name": "'$name'","address": "'$I'","port": '$port',"tags": ["cadvisor"], "checks": [{"http": "http://'$I':'$port'/","interval": "5s"}]}' http://172.17.0.4:8500/v1/agent/service/register
done
Prometheus 配置consul 服務發現
consul 可以使用的元标簽:
__meta_consul_address:目标的位址
__meta_consul_dc:目标的資料中心名稱
__meta_consul_tagged_address_<key>:每個節點标記目标的位址鍵值
__meta_consul_metadata_<key>:目标的每個節點中繼資料鍵值
__meta_consul_node:為目标定義的節點名稱
__meta_consul_service_address:目标的服務位址
__meta_consul_service_id:目标的服務ID
__meta_consul_service_metadata_<key>:目标的每個服務中繼資料鍵值
__meta_consul_service_port:目标的服務端口
__meta_consul_service:目标所屬服務的名稱
__meta_consul_tags:标記分隔符連接配接的目标的标記清單
修改Prometheus.yml 檔案,使用relabel将consul的元标簽重寫便于檢視
- job_name: 'consul'
consul_sd_configs:
- server: '192.168.16.173:8900'
services: [] #比對所有service
relabel_configs:
- source_labels: [__meta_consul_service] #service 源标簽
regex: "consul" #比對為"consul" 的service
action: drop # 執行的動作
- source_labels: [__meta_consul_service] # 将service 的label重寫為appname
target_label: appname
- source_labels: [__meta_consul_service_address]
target_label: instance
- source_labels: [__meta_consul_tags]
target_label: job
Prometheus 熱加載更新
curl -X POST http://192.168.16.173:9090/-/reload
通路Prometheus web頁面
應用注冊到consul
在不需要開發修改代碼的前提下,我們可以使用Prometheus的jmx-exporter收集應用的相關名額,在應用中間件tomcat/weblogic等調用jmx-exporter,具體方式檢視https://www.jianshu.com/p/dfd6ba5206dc
啟動應用後會啟動12345端口暴露jvm資料,現在我們要做的就是将這個端口注冊到Consul上,然後Prometheus會從consul 拉取應用主機。
使用腳本實作
$ cat ip
TEST 192.168.166.10 192.168.166.11
UNMIN 192.168.166.12 192.168.166.13
---------------
$ cat consul.sh
#!/bin/bash
port=12345
while read app
do
echo ${app}
app_tmp=(${app})
echo ${app_tmp[0]}
length=${#app_tmp[@]}
echo ${length}
for((k=1;k<${length};k++));
do
echo ${app_tmp[k]}
curl -X PUT -d '{"id": "'${app_tmp[k]}'","name": "'${app_tmp[0]}'","address": "'${app_tmp[k]}'","port": '$port',"tags": ["MIDL"],"checks": [{"http": "http://'${app_tmp[k]}':'$port'/","interval": "5s"}]}' http://172.17.0.4:8500/v1/agent/service/register
done
done < ip
執行腳本注冊到consul
配置Grafana JVM 監控模闆
Load 8563模闆
來源:https://www.jianshu.com/p/dde0dc1761ec
推薦閱讀 點選标題可跳轉
牛逼!用 GitLab 做 CI/CD 是什麼感覺,太強了
徹夜怒肝!Docker 疑難雜症解決方案已撸完,快要裂開了
螞蟻金服 CEO 突然辭職!去向很意外
再見 FTP/SFTP!下一代檔案傳輸利器 Croc 來了!
MongoDB 日常運維實踐總結
這 5 種常用運維監控工具都不會?你算啥運維人
超詳細講解!10 種常見的軟體架構模式