https://www.weixueyuan.net/nginx/log/
名称 | 访问日志指令 |
---|---|
指令 | access_log |
作用域 | http、stream、server、location、if in location、limit except |
默认值 | logs/access.log combined; |
指令值格式 | off 或 path[format[buffer=size][gzip[=level]][flush=time][if=condition]]; |
指令说明 | 设置访问日志输出方式及引用的日志格式 |
access_log off;
access_log logs/access.log combined;
access_log logs/log.gz combined gzip flush=5m;
map $status $loggable {
~^[23] 0;
default 1;
}
access_log logs/access.log combined if=$loggable;
名称 | 日志格式指令 |
---|---|
指令 | log_format |
作用域 | http、stream |
默认值 | combined"..."; |
指令值格式 | name[escape=default 或 json 或 none]string...; |
指令说明 | 设置访问日志输出方式及输出日志格式 |
变量名 | 变量说明 |
---|---|
$time_iso8601 | ISO 8601 时间格式 |
$time_local | 用户请求的时间和时区 |
$msec | 毫秒级别的日志记录时间 |
$remote_addr | 发起与 Nginx 建立连接的网络客户端的 IP,有时会是上层代理服务器的 IP |
$http_x_forwarded_for | 可以记录客户端 IP,通过代理服务器来记录客户端的 IP |
$remote_user | 用于记录远程客户端的用户名称 |
$http_user_agent | 用户客户端浏览器标识 |
$connection | 网络连接编号 |
$connection_requests | 当前连接的请求数 |
$request | 用户请求的 URI 及请求方法 |
$request_method | 用户请求方法 |
$request_uri | 用户请求的 URI 及请求方法 |
$server_protocol | 请求协议 |
$request_time | 请求时间 |
$request_length | 请求数据大小 |
$status | 用户请求响应状态码 |
$bytes_sent | 发送到客户端响应数据的大小 |
$body_bytes_sent | 用户请求返回的响应体字节数 |
$http_referer | HTTP 请求头中属性字段 referer |
# 普通格式日志 log_format main '$remote_addr - $connection - $remote_user [$time_local] "$request" - $upstream_addr' '$status - $body_bytes_sent - $request_time - "$http_referer" ' '"$http_user_agent" - "$http_x_forwarded_for" - '; # JSON格式日志 log_format json '{"@timestamp": "$time_iso8601", ' '"connection": "$connection", ' '"remote_addr": "$remote_addr", ' '"remote_user": "$remote_user", ' '"request_method": "$request_method", ' '"request_uri": "$request_uri", ' '"server_protocol": "$server_protocol", ' '"status": "$status", ' '"body_bytes_sent": "$body_bytes_sent", ' '"http_referer": "$http_referer", ' '"http_user_agent": "$http_user_agent", ' '"http_x_forwarded_for": "$http_x_forwarded_for", ' '"request_time": "$request_time"}';Nginx TCP/UDP 的访问日志的变量与 HTTP 的访问日志的变量是不同的,TCP/UDP 常见日志变量如下表所示。
变量名 | 变量说明 |
---|---|
$time_iso8601 | ISO 8601 时间格式 |
$time_local | 用户请求的时间和时区 |
$connection | 网络连接编号 |
$remote_addr | 发起与 Nginx 建立连接的网络客户端的 IP,有时会是上层代理服务器的 IP |
$server_addr | Nginx 服务器地址 |
$server_port | Nginx 服务器端口 |
$status | 用户请求响应状态码 |
$upstream_addr | 被代理服务器地址 |
$bytes_received | 接收字节数 |
$bytes_sent | 发送字节数 |
$session_time | 连接会话时间 |
$proxy_protocol_addr | 代理协议地址 |
$proxy_protocol_port | 代理协议端口 |
# 普通格式日志 log_format tcp '$remote_addr - $connection - [$time_local] $server_addr: $server_port ' '- $status - $upstream_addr - $bytes_received - $bytes_sent - $session_time ' '- $proxy_protocol_addr:$proxy_protocol_port '; # JSON格式日志 log_format json '{"@timestamp": "$time_iso8601", ' '"connection": "$connection", ' '"remote_addr": "$remote_addr", ' '"server_addr": "$server_addr:$server_port" ' '"status": "$status" ' '"upstream_addr": "$upstream_addr" ' '"bytes_received": "$bytes_received" ' '"bytes_sent": "$bytes_sent" ' '"session_time": "$session_time" ' '"proxy_protocol_addr": "$proxy_protocol_addr:$proxy_protocol_port" '}'打开日志缓存指令见下表。
名称 | 打开日志缓存指令 |
---|---|
指令 | open_log_file_cache |
作用域 | http、stream、server、location |
默认值 | off |
指令值格式 | off 或 max=N [inactive=time][min_uses=N][valid=time]; |
指令说明 | 设置存储日志文件描述符(文件句柄)的缓存 |
open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
logs/access.log combined;
说明 | 错误日志指令组成 |
---|---|
主指令 | error_log |
作用域 | main、http、mail、stream、server、location |
默认值 | logs/error.log error; |
指令说明 | 设置错误日志输出方式及输出日志级别 |
error_log syslog:server=192.168.2.109 error;
error_log memory:32m debug;
error_log /dev/null;
# 访问文件不存在时,记入错误日志
log_not_found on;
级别 | 级别值 | 级别说明 |
---|---|---|
debug | 8 | 代码中标记为 NGX_LOG_DEBUG 的输出,输出最为详细,配合调试使用 |
info | 7 | 代码中标记为 NGX_LOG_INFO 的输出,因包括除 debug 级别的所有输出,故同样会消耗大量磁盘 IO 资源 |
notice | 6 | 代码中标记为 NGX_LOG_NOTICE 的输出 |
warn | 5 | 代码中标记为 NGX_LOG_WARN 的输出 |
error | 4 | 代码中标记为 NGX_LOG_ERROR 的输出,实际生产环境中常用的输出级别 |
crit | 3 | 代码中标记为 NGX_LOG_CRIT 的输出 |
alert | 2 | 代码中标记为 NGX_LOG_ALERT 的输出 |
emerg | 1 | 代码中标记为 NGX_LOG_EMERG 的输出 |
yum -y install logrotate
/etc/logrotate.conf # logrotate主配置文件 /usr/sbin/logrotate # logrotate二进制文件 /etc/logrotate.d/ # 自定义logrotate配置文件 /var/lib/logrotate/logrotate.status # logrotate管理日志执行记录的状态文件
-d, --debug # 测试归档配置文件 -f, --force # 立即执行归档操作 -m, --mail=command # 指定发送邮件的命令(默认为'/bin/mail') -s, --state=statefile # 设置logrotate.status文件路径,可用于区分在同 # 一系统下以不同用户身份运行的logrotate任务 -v, --verbose # 显示配置详细信息 -l, --log=STRING # 将Logrotate执行的详情输出到指定的文件 logrotate -v /etc/logrotate.conf # 显示配置文件详细信息 logrotate -d /etc/logrotate.d/syslog -l /var/log/logrotate.log # 配置文件,执行测试 logrotate -f /etc/logrotate.d/syslog # 立即执行当前配置文件
指令 | 指令说明 |
---|---|
归档执行周期 | |
hourly | 日志归档周期为 1 小时,默认 Logrotate 的最小周期为 1 天,需额外调整该参数才可生效 |
daily | 日志归档周期为 1 天 |
weekly | 日志归档周期为 1 周 |
monthly | 日志归档周期为 1 月,通常为每月的第一天 |
归档执行条件 | |
include | 读取外部参数文件 |
missingok | 如果日志文件不存在,则不显示错误信息 |
nomissingok | 如果日志文件不存在,则显示错误信息。默认配置 |
size | 日志文件可被归档的最小值 |
minsize | 日志文件可被归档的最小值,没到归档周期执行时间,不会执行归档操作 |
maxsize | 日志文件超过设定值时,即使没到归档周期执行时间,也会执行归档操作 |
ifempty | 即使日志文件为空,也执行归档操作 |
notifempty | 如果日志文件为空,则不进行归档。默认设置 |
tabooext | 不对设置扩展名的日志文件执行归档操作 |
归档文件命名 | |
start count | 使用日志文件归档次数作为归档文件扩展名,count 默认值为 1,默认配置 |
dateext | 为归档文件名添加日期,默认追加到扩展名后 |
dateformat | 设置归档文件名中的日期格式,使用“%Y%m%d%H”作为说明符,默认为-%Y%m%d |
dateyesterday | 使用前一天的日期而非创建归档文件时的日期作为归档文件的文件名中的日期 |
extension | 指定日志的扩展名,并将其设置为归档文件的扩展名,启用压缩时,压缩的扩展名在最后 |
compressext | 启用压缩时,自定义归档文件扩展名,如将“.gz”改为“.ddd” |
归档文件保存方式 | |
compress | 对归档文件启用压缩,默认为 gzip 压缩 |
nocompress | 不压缩归档文件。默认设置 |
compresscmd | 指定压缩归档文件的命令,默认为 gzip 压缩 |
uncompresscmd | 指定解压归档文件的命令,默认为 gunzip 解压 |
compressoptions | 启用压缩时,设置压缩工具的命令选项 |
delaycompress | 在下一个归档周期再对当前归档文件进行压缩 |
nodelaycompress | 不延迟压缩。默认设置 |
归档执行方式 | |
copy | 为日志文件复制一个副本后再进行归档 |
nocopy | 不复制源日志文件。默认配置 |
copytruncate | 复制日志文件后清空日志文件的内容 |
nocopytruncate | 复制源日志文件后,不清空源文件。默认设置 |
create mode owner group, create owner group | 重命名日志文件,创建与日志文件同名的文件,默认 mode=0644 uid=0 gid=0,与 copy 指令不能同时使用 |
nocreate | 不创建与日志文件同名的文件。默认设置 |
olddir | 设置归档文件保存目录 |
noolddir | 归档文件与源文件在同一目录。默认设置 |
createolddir mode owner group | 如果 olddir 参数指定的目录不存在,则创建目录并指定属组,默认 mode = 0777 uid = 0 gid = 0 |
nocreateolddir | 当 olddir 参数设定目录不存在时,不创建目录。默认设置 |
prerotate ... endscript | 归档执行之前执行脚本,日志文件名为传入的第一个参数 |
postrotate ... endscript | 归档执行之后执行脚本,日志文件名为传入的第一个参数 |
firstaction ... endscript | prerotate 脚本之前,仅当第一个日志文件被开始执行归档操作时才执行脚本,日志文件名为传入的第一个参数 |
lastaction ... endscript | postrotate 脚本之后,仅当最后一个日志文件执行归档操作结束时才执行脚本,日志文件名为传入的第一个参数 |
preremove ... endscript | 删除日志文件之前执行脚本,日志文件名为传入的第一个参数 |
sharedscripts | 当匹配的日志文件为多个时,prerotate 和 postrotate 脚本会在每个日志文件执行归档操作时都执行一次,启用共享模式会让 prerotate 和 postrotate 脚本在全局只运行一次 |
nosharedscripts | 当匹配的日志文件为多个时,prerotate 和 postrotate 脚本会在每个日志文件执行归档操作时都执行一次。默认设置 |
su user group | 指定操作源文件执行归档操作的用户及属组 |
归档文件清理 | |
设置接收归档文件的邮件地址 | |
nomail | 不将归档文件发送到任何邮件地址 |
mailfirst | 将刚生成的归档文件发送到设置的邮箱 |
maillast | 将要超过 maxage 设置时间的归档文件发送到设置的邮箱 |
mахage | 设置过期归档文件的天数 |
rotate | 保留归档文件数,默认为 0 |
shred | 彻底删除 |
shredcycles count | 彻底删除时,覆盖文件的次数,默认为 3 |
noshred | 不彻底删除 |
vi /etc/logrotate.d/nginx /usr/local/nginx/logs/*.log { daily # 日志归档周期为1天 size 1 # 日志文件最小为1字节时才执行归档 minsize 1 # 日志文件最小为1字节时才执行归档 notifempty # 日志文件不为空时才执行归档 dateext # 归档文件名添加时间字符串 dateformat -%Y%m%d%H # 归档文件名时间字符串格式为-%Y%m%d%H dateyesterday # 归档文件名时间字符串以归档操作的前一天为时间戳 extension .log # 归档文件名中保留日志的扩展名 compress # 归档文件执行压缩 delaycompress # 在归档执行的下个周期再进行压缩 create # 以创建新文件方式实现日志归档 olddir /data/backup/nginx_logs # 归档文件存储目录 createolddir # 归档文件存储目录不存在时自动创建 postrotate # 归档执行后执行脚本 /usr/local/nginx/sbin/nginx -s reopen -g "pid /run/nginx.pid;" # 通知Nginx重新打开日志文件 endscript sharedscripts # 启用脚本共享模式 maxage 7 # 归档文件最多保留7天 rotate 7 # 归档文件最多保留7份 }
关键词 | 名称 | 关键词说明 |
---|---|---|
cluster | 集群 | 集群由一个主节点和多个从节点组成,主节点是通过内部选举产生的。Elastic-search 集群是一个去中心化的分布式架构,对于外部用户来讲,Elasticsearch 集群是个整体,与其中任何一个节点通信获取内容都是一致的 |
index | 索引 | Elasticsearch 是面向文档的数据库,一条数据就是一个文档,文档内容为包含多个 key,value 格式字段数据。Elasticsearch 集群可以包括多个索引,每个索引下包含多个类型,每个类型下包含多个文档。索引相当于关系型数据库中的库,类型相当于关系型数据库中的表 |
shards | 索引分片 | Elasticsearch 可以把一个完整的索引分成多个分片,该方式可以把一个大的索引拆分成多个,并分布到不同的节点,实现分布式搜索 |
replicas | 索引副本 | Elasticsearch 可以为索引设置多个副本,当集群中某个节点或某个索引的分片损坏或丢失时,可以通过副本进行恢复,同时可以为搜索请求提供负载均衡,以提高查询效率 |
recovery | 数据分配与恢复 | Elasticsearch 集群在有节点加入或退出时,会根据节点的数量变化对索引分片进行重新分配,当挂掉的节点重启后也会进行数据分配与恢复 |
gateway | 存储方式 | Elasticsearch 存储方式,Elasticsearch 会先把索引存放到内存中,当内存满了时再持久化到 gateway 配置的目标存储中。默认 gateway 配置为本地硬盘,也支持其他分布式文件系统,如 Hadoop 的 HDFS 和 Amazon 的 s3 云存储服务等 |
# 安装yum工具 yum install -y yum-utils # 安装Docker官方yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 安装docker及docker-compose应用 yum install -y docker-ce docker-compose # 设置docker服务开机自启动 systemctl enable docker # 启动docker服务 systemctl start docker # 优化内核参数,设置一个进程拥有VMA(虚拟内存区域)的最大数量为262144 sysctl -w vm.max_map_count=262144
cat elk.yaml version: '2' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.0.1 container_name: elasticsearch701 environment: - discovery.type=single-node - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 hostname: elasticsearch restart: always ports: - "9200:9200" - "9300:9300" kibana: image: docker.elastic.co/kibana/kibana:7.0.1 container_name: kibana701 hostname: kibana depends_on: - elasticsearch restart: always ports: - "5601:5601" logstash: image: docker.elastic.co/logstash/logstash:7.0.1 container_name: logstash701 hostname: logstash restart: always depends_on: - elasticsearch ports: - "5044:5044" # 运行ELK容器 docker-compose -felk.yaml up -ddocker-compose 是功能非常强的容器运行编排工具,内部含有很多配置指令可以完成容器的资源配置、运行、服务依赖、网络配置等运行时的编排配置,具体指令说明可参照 docker-compose 的官方文档。
cd /opt/data/apps # 创建容器外挂卷目录及数据存储目录 mkdir -p {elasticsearch/data,elasticsearch/config,elasticsearch/modules,elastic-search/plugins,kibana/config,logstash/pipeline,logstash/config} # 复制容器数据到数据存储目录 docker cp elasticsearch701:/usr/share/elasticsearch/data elasticsearch docker cp elasticsearch701:/usr/share/elasticsearch/config elasticsearch docker cp elasticsearch701:/usr/share/elasticsearch/modules elasticsearch docker cp elasticsearch701:/usr/share/elasticsearch/plugins elasticsearch docker cp logstash701:/usr/share/logstash/config logstash docker cp logstash701:/usr/share/logstash/pipeline logstash docker cp kibana701:/usr/share/kibana/config kibana # Logstash配置 cat>logstash/pipeline/logstash.conf<<EOF input { beats { port => 5044 codec =>"json" } } output { elasticsearch { hosts => ["http://10.10.4.37:9200"] index => "logstash-nginx-%{[@metadata][version]}-%{+YYYY.MM.dd}" } } EOF # 配置目录权限 chown -R 1000:1000 elasticsearch/* chown -R 1000:1000 logstash/* # 配置docker-compose脚本,挂载数据存储目录 cat elk.yaml version: '2' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.0.1 container_name: elasticsearch701 environment: - discovery.type=single-node - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - /opt/data/apps/elasticsearch/modules:/usr/share/elasticsearch/modules - /opt/data/apps/elasticsearch/plugins:/usr/share/elasticsearch/plugins - /opt/data/apps/elasticsearch/data:/usr/share/elasticsearch/data - /opt/data/apps/elasticsearch/config:/usr/share/elasticsearch/config hostname: elasticsearch restart: always ports: - "9200:9200" - "9300:9300" kibana: image: docker.elastic.co/kibana/kibana:7.0.1 container_name: kibana701 hostname: kibana volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - /opt/data/apps/kibana/config:/usr/share/kibana/config depends_on: - elasticsearch restart: always ports: - "5601:5601" logstash: image: docker.elastic.co/logstash/logstash:7.0.1 container_name: logstash701 hostname: logstash volumes: - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - /opt/data/apps/logstash/pipeline:/usr/share/logstash/pipeline - /opt/data/apps/logstash/config:/usr/share/logstash/config restart: always depends_on: - elasticsearch ports: - "5044:5044" # 运行ELK容器 docker-compose -f elk.yaml up -d
log_format json '{"@timestamp": "$time_iso8601", ' '"connection": "$connection", ' '"remote_addr": "$remote_addr", ' '"remote_user": "$remote_user", ' '"request_method": "$request_method", ' '"request_uri": "$request_uri", ' '"server_protocol": "$server_protocol", ' '"status": "$status", ' '"body_bytes_sent": "$body_bytes_sent", ' '"http_referer": "$http_referer", ' '"http_user_agent": "$http_user_agent", ' '"http_x_forwarded_for": "$http_x_forwarded_for", ' '"request_time": "$request_time"}';
# 安装Filebeat rpm -ivh https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.0.1 -x86_64.rpm # 设置输出数据到Logstash及Logstash地址 sed -i "s/#output.logstash:/output.logstash:/g" /etc/filebeat/filebeat.yml sed -i "s/#hosts: \[\"localhost:5044\"\]/ hosts: \[\"10\.10\.4\.37:5044\"\]/g" /etc/filebeat/filebeat.yml # 关闭直接输出数据到Elasticsearch sed -i "s/output.elasticsearch/#output.elasticsearch/g" /etc/filebeat/filebeat.yml sed -i "s/hosts: \[\"localhost:9200\"\]/#hosts: \[\"localhost:9200\"\]/g" /etc/filebeat/filebeat.yml # 安装Filebeat Nginx模块 filebeat modules enable nginx # 配置Filebeat Nginx模块 cat >/etc/filebeat/modules.d/nginx.yml<<EOF - module: nginx access: enabled: true var.paths: ["/usr/local/nginx/logs/*access.log"] error: enabled: true var.paths: ["/usr/local/nginx/logs/*error.log"] EOF # 检查配置 filebeat test config filebeat test output # 启动Filebeat systemctl restart filebeat # 设置为自启动 systemctl enable filebeat
cat>prometheus.yaml<<EOF version: '3.5' services: prometheus: hostname: prometheus container_name: prometheus restart: always image: prom/prometheus ports: - "9090:9090" stop_grace_period: 1m grafana: hostname: grafana container_name: grafana restart: always image: grafana/grafana ports: - "3000:3000" stop_grace_period: 1m EOF # 启动镜像 docker-compose -f prometheus.yaml up -d
cd /opt/data/apps mkdir -p {prometheus,grafana} # 复制配置文件 docker cp prometheus:/etc/prometheus prometheus/prometheus # 复制监控数据文件 docker cp prometheus:/prometheus prometheus/prometheus_data # 配置Alertmanager服务器地址 sed -i "s/# - alertmanager:9093/ - 10.10.4.39:9093/g" prometheus/prometheus/prometheus.yml # 配置告警规则文件目录 sed -i "/rule_files:/a\ - /etc/prometheus/*.rules" prometheus/prometheus/prometheus.yml # 配置PushGateway地址 cat>>prometheus/prometheus/prometheus.yml<<EOF - job_name: pushgateway # 监控job名称,全局唯一 static_configs: - targets: ['10.10.4.39:9091'] # 被监控主机的IP及Exporter的端口 labels: instance: pushgateway # 被监控主机的标识,多为主机名或docker实例名称 EOF # 设置目录权限 chown -R 65534:65534 prometheus/* # 复制Grafana配置文件 docker cp grafana:/etc/grafana grafana/config # 复制Grafana数据文件 docker cp grafana:/var/lib/grafana grafana/data # 设置目录权限 chown -R 472:472 grafana/* # 修改docker-compose脚本 cat>prometheus.yaml<<EOF version: '3.5' services: prometheus: hostname: prometheus container_name: prometheus restart: always image: prom/prometheus ports: - "9090:9090" volumes: - /etc/localtime:/etc/localtime:ro - /opt/data/apps/prometheus/prometheus:/etc/prometheus - /opt/data/apps/prometheus/prometheus_data:/prometheus stop_grace_period: 1m grafana: hostname: grafana container_name: grafana restart: always image: grafana/grafana ports: - "3000:3000" volumes: - /etc/localtime:/etc/localtime:ro - /opt/data/apps/grafana/config:/etc/grafana - /opt/data/apps/grafana/data:/var/lib/grafana stop_grace_period: 1m EOF # 重建并运行镜像 docker-compose -f prometheus.yaml up -d通过浏览器访问 http://10.10.4.38:9090/targets,就可以看到 Prometheus 和 PushGateway 这两个 Endpoint。然后通过浏览器访问 Grafana Web 管理页面 http://10.10.4.38:3000,初始用户名和密码都是 admin。
cat>prometheus.yaml<<EOF version: '3.5' services: alertmanager: hostname: alertmanager container_name: alertmanager restart: always image: prom/alertmanager ports: - "9093:9093" stop_grace_period: 1m pushgateway: hostname: pushgateway container_name: pushgateway restart: always image: prom/pushgateway ports: - "9091:9091" stop_grace_period: 1m EOF # 运行镜像 docker-compose -f prometheus.yaml up -d
cd /opt/data/apps mkdir -p prometheus # 复制Alertmanager配置文件 docker cp alertmanager:/etc/alertmanager prometheus/alertmanager # 复制Alertmanager数据文件 docker cp alertmanager:/alertmanager prometheus/alertmanager_data # 配置目录权限 chown -R 65534:65534 prometheus/alertmanager chown -R 65534:65534 prometheus/alertmanager_data # 配置prometheus.yaml cat>prometheus.yaml<<EOF version: '3.5' services: alertmanager: hostname: alertmanager container_name: alertmanager restart: always image: prom/alertmanager ports: - "9093:9093" volumes: - /etc/localtime:/etc/localtime:ro - /opt/data/apps/prometheus/alertmanager:/etc/alertmanager - /opt/data/apps/prometheus/alertmanager_data:/alertmanager stop_grace_period: 1m pushgateway: hostname: pushgateway container_name: pushgateway restart: always image: prom/pushgateway ports: - "9091:9091" volumes: - /etc/localtime:/etc/localtime:ro EOF # 重建并运行镜像 docker-compose -f prometheus.yaml up -d通过浏览器访问 http://10.10.4.39:9093,可以查看 Alertmanager 的告警信息及配置;通过浏览器访问 http://10.10.4.39:9091,可以查看 PushGateway 的相关信息。
# 获取nginx-vts-exporter二进制文件 wget https://github.com/hnlq715/nginx-vts-exporter/releases/download/v0.10.3/nginx-vts-exporter-0.10.3.linux-amd64.tar.gz tar zxmf nginx-vts-exporter-0.10.3.linux-amd64.tar.gz cp nginx-vts-exporter-0.10.3.linux-amd64/nginx-vts-exporter /usr/local/nginx/sbin/ # 运行测试 nginx-vts-exporter -nginx.scrape_timeout 10 -nginx.scrape_uri http://127.0.0.1: 8080/vts/format/json curl http://127.0.0.1:9913/metrics
# 安装supervisor yum install supervisor # 配置nginx-vts-exporter服务管理配置 cat>/etc/supervisord.d/nginx-vts-exporter.ini<<EOF [program:nginx-vts-exporter] ;配置进程运行命令 command=/usr/local/nginx/sbin/nginx-vts-exporter -nginx.scrape_timeout 10 -nginx.scrape_uri http://127.0.0.1:8080/vts/format/json directory=/usr/local/nginx/sbin ;进程运行目录 startsecs=5 ;启动5秒后没有异常退出表示进程正常启动,默认为1秒 autostart=true ;在supervisord启动的时候也自动启动 autorestart=true ;程序退出后自动重启 EOF # 启动supervisord并配置为开机运行 systemctl start supervisord systemctl enable supervisord # nginx-vts-exporter进程服务管理 # 查看nginx-vts-exporter进程服务状态 supervisorctl status nginx-vts-exporter # 重启nginx-vts-exporter进程服务 supervisorctl restart nginx-vts-exporter # 启动nginx-vts-exporter进程服务 supervisorctl start nginx-vts-exporter # 停止nginx-vts-exporter进程服务 supervisorctl stop nginx-vts-exporter # 访问测试 curl http://10.10.4.8:9913/metrics
cd /opt/data/apps cat>>prometheus/prometheus/prometheus.yml<<EOF # nginx-vts-exporter job - job_name: nginx_exporter static_configs: - targets: ['10.10.4.8:9913'] labels: instance: nginx-1 EOF docker restart prometheus
import prometheus_client from prometheus_client import Counter,Gauge import requests import sys import json import time from flask import Response, Flask # 初始化监控项 nginx_info = Gauge("nginx_info", "nginx_info nginx info",['hostName','nginxVersion']) nginx_server_info = Gauge("nginx_server_info", "nginx_server_info nginx server info",['host','port','protocol']) nginx_server_connections = Gauge("nginx_server_connections", "nginx connections", ['status']) nginx_server_bytes = Counter("nginx_server_bytes","request/response bytes", ['direction','host']) nginx_upstream_responses = Counter("nginx_upstream_requests","requests counter", ['backend','code','upstream']) app = Flask(__name__) @app.route("/metrics") def requests_metrics(): metrics="" url = "http://127.0.0.1:8080/sts/format/json" res = requests.get(url) all_data = json.loads(json.dumps(res.json())) # server_info nginx_info.labels(hostName=all_data["hostName"],nginxVersion=all_data["nginx-Version"]).set(time.time()) metrics+=prometheus_client.generate_latest(nginx_info) # connections connections=["accepted","active","handled","reading","requests","waiting", "writing"] for con in connections: nginx_server_connections.labels(status=con).set(all_data["connections"][con]) metrics+=prometheus_client.generate_latest(nginx_server_connections) # streamServerZones for k,streamServer in all_data["streamServerZones"].items(): nginx_server_bytes.labels(direction="in",host=k).inc(streamServer["inBytes"]) nginx_server_bytes.labels(direction="out",host=k).inc(streamServer["outBytes"]) nginx_server_info.labels(host=k,port=streamServer["port"],protocol=stream-Server["protocol"]).set(1) metrics+=prometheus_client.generate_latest(nginx_server_bytes) metrics+=prometheus_client.generate_latest(nginx_server_info) # streamUpstreamZones status_code=["1xx","2xx","3xx","4xx","5xx"] for ups,stream in all_data["streamUpstreamZones"].items(): for v in stream: for code in status_code: nginx_upstream_responses.labels(backend=v["server"],code=code,up-stream=ups).inc(v["responses"][code]) metrics+=prometheus_client.generate_latest(nginx_upstream_responses) return Response(metrics,mimetype="text/plain") @app.route('/') def index(): html='''<html> <head><title>Nginx sts Exporter</title></head> <body> <h1>Nginx sts Exporter</h1> <p><a href="/metrics">Metrics</a></p> </body> </html>''' return html if __name__ == "__main__": app.run( host="0.0.0.0", port= 9912, debug=True )在此处只选了几个监控项做样例,感兴趣的读者可继续补充完整。
将 Exporter 脚本保存为 /usr/local/nginx/sbin/nginx-sts-exporter.py。 # 配置运行环境 yum install python2-pip pip install prometheus_client requests flask # 运行Exporter python /usr/local/nginx/sbin/nginx-sts-exporter.py # 测试 curl http://127.0.0.1:9912/metrics
cd /opt/data/apps cat>>prometheus/prometheus/prometheus.yml<<EOF # nginx-vts-exporter && nginx-sts-exporter job - job_name: nginx_exporter_8 static_configs: - targets: ['10.10.4.8:9913','10.10.4.8:9912'] labels: instance: nginx-8 EOF # 重启Prometheus,使配置生效 docker restart prometheus
ALERT <alert name> # 告警标识符,可以不唯一 IF <expression> # 触发告警阈值规则 [ FOR <duration> ] # 触发告警通知的持续时间 [ LABELS <label set> ] # 分组标签,用以Alertmanager进行分拣路由 [ ANNOTATIONS <label set> ] # 告警描述信息
cat>prometheus/prometheus/nginx.rules<<EOF groups: - name: NginxAlert # 规则组名称 rules: - alert: ResponseTimeAlert # 规则的名称 # 告警阈值计算规则为响应时间大于1000ms并持续10s的发送告警 expr: (nginx_upstream_responseMsec > 1000) for: 10s # 持续时间为10s labels: # 定义告警路由标签 severity: critical service: nginx annotations: # 告警信息 summary: “Nginx响应大于1000ms” description: “Nginx {{ $labels.instance }}后端集群{{ $labels.upstream }} 中{{ $labels.backend }}的响应时间大于1000ms。当前值为:{{ $value }} ms” EOF # 重启Prometheus docker restart prometheus其中,$labels 是 Metric 行数据的 labels 内容。labels 的内容可用对象数据类型方法引用;$value 是 Metric 行的 value;$labels 是多条时,会自动遍历内容,每条记录生成一个 annotations 信息。
cd /opt/data/apps # 配置Alertmanager cat>prometheus/alertmanager/alertmanager.yml<<EOF # 全局配置,配置smtp信息 global: resolve_timeout: 5m # 处理超时时间,默认为5min smtp_smarthost: 'smtp.exmail.qq.com:465' # 邮箱smtp服务器代理,请替换自己的smtp # 服务器地址 smtp_from: 'monitor@nginxbar.org' # 发送告警信息的邮箱地址,请替换自己的 # 邮箱地址 smtp_auth_username: 'monitor@nginxbar.org' # 邮箱账号,请替换自己的邮箱账号 smtp_auth_password: '12345678' # 邮箱密码,请替换自己的邮箱密码 smtp_require_tls: false # 定义发送邮件的模板信息 templates: - 'template/*.tmpl' # 定义发送告警邮件的路由信息,这个路由不仅可以接收所有的告警,还可以配置多个路由 route: group_by: ['alertname'] # 告警信息分组依据,按照同类alertname # 进行分组 group_wait: 10s # 最初等待10s发送告警通知 group_interval: 60s # 在发送新告警前的等待时间 repeat_interval: 1h # 发送重复告警的等待周期为1小时,避免产 # 生邮件风暴 receiver: 'email' # 全局默认告警接收者的名称,与receivers # 的name对应 routes: - match: # 匹配labels存在如下标签的告警信息 severity: critical service: nginx receiver: nginx_email #Nginx服务器警报接收者的名称 # 定义默认警报接收者信息 receivers: - name: 'email' # 路由中对应的receiver名称 email_configs: # 告警接收者邮箱配置 - to: 'xiaodong.wang@freemud.com' # 告警接收者的邮箱配置 - name: 'nginx_email' # 路由中对应的receiver名称 email_configs: # 告警接收者邮箱配置 - to: 'xiaodong.wang@freemud.com' # 告警接收者的邮箱配置 EOF # 重启alertmanager docker restart alertmanagerNginx 监控项的阈值触发设置的告警规则时,Prometheus 就会自动发送告警到目标邮箱。