前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Prometheus监控实战》第4章 监控主机和容器

《Prometheus监控实战》第4章 监控主机和容器

作者头像
yeedomliu
发布2019-12-19 16:35:03
5.4K0
发布2019-12-19 16:35:03
举报
文章被收录于专栏:yeedomliu

第4章 监控主机和容器

  • 首先,我们将在每台主机上安装exporter,然后配置节点和Docker指标让Prometheus来抓取。基本主机资源监控
  1. CPU
  2. 内存
  3. 磁盘
  4. 可用性
  • 然后,我们利用收集的指标来构建一些聚合指标并保存为记录规则
  • 最后,我们会简要介绍Grafana,并对收集的数据进行基本的可视化
  • 回顾USE:
    • 使用率(Utilization)
    • 饱和度(Saturation)
    • 错误(Error)
  • USE方法可以概括为:针对每个资源,检查使用率、饱和度和错误。该方法对于监控那些受高使用率或饱和度的性能问题影响的资源来说是最有效的
    1. 资源:系统的一个组件。它是一个传统意义上的物理服务器组件,如CPU、磁盘等,但许多人也将软件资源包含在定义中
    2. 使用率:资源忙于工作的平均时间。它通常用随时间变化的百分比表示
    3. 饱和度:资源排队工作的指标,无法再处理额外的工作。通常用队列长度表示
    4. 错误:资源错误事件的计数

4.1 监控节点

  • Prometheus使用exporter工具来暴露主机和应用程序上的指标,目前有很多可用于各种目的的exporter(https://prometheus.io/docs/instrumenting/exporters/)

Exporter

  • Third-party exporters
    • Hardware related
    • Issue trackers and continuous integration
    • Messaging systems
    • Storage
    • HTTP
    • APIs
    • Logging
    • Other monitoring systems
    • Miscellaneous
    • Databases
  • Software exposing Prometheus metrics
  • [Other third-party utilities](https://prometheus.io/docs/instrumenting/exporters/#other-third-party-utilitie

  • 现在我们将专注于一个特定的exporter:Node Exporter(https://github.com/prometheus/node_exporter),它还有一个textfile收集器,允许你导出静态指标
  • 首先选择其中一台Linux主机,然后下载并安装Node Exporter。我们将选择一个Docker守护进程主机
  • 如果你不想使用exporter,那么还有很多支持Prometheus的主机监控客户端。例如,collectd也可以收集Prometheus指标(https://collectd.org/wiki/index.php/Plugin:Write_Prometheus)

4.1.1 安装Node Exporter

Mac
代码语言:javascript
复制
$ brew install node_exporter
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/cask-versions and homebrew/cask).

==> Downloading https://homebrew.bintray.com/bottles/node_exporter-0.18.1.mojave.bottle.tar.gz
==> Downloading from https://akamai.bintray.com/ff/ff7b019285ebd031d6985bb06e4300518c9e07f01536ebb5281e4970818cb8a3?__gda__=exp=1573171435~hmac=467cbe2
######################################################################## 100.0%
==> Pouring node_exporter-0.18.1.mojave.bottle.tar.gz
==> Caveats
When used with `brew services`, node_exporter's configuration is stored as command line flags in
  /usr/local/etc/node_exporter.args

Example configuration:
  echo --web.listen-address :9101 > /usr/local/etc/node_exporter.args

For the full list of options, execute
  node_exporter -h

To have launchd start node_exporter now and restart at login:
  brew services start node_exporter
Or, if you don't want/need a background service you can just run:
  node_exporter
==> Summary
?  /usr/local/Cellar/node_exporter/0.18.1: 8 files, 16MB

$ node_exporter --version
node_exporter, version  (branch: , revision: )
  build user:
  build date:
  go version:       go1.12.5
Linux
代码语言:javascript
复制
wget https://github.com/prometheus/node_exporter/releases/download/v0.18.1/node_exporter-0.18.1.linux-amd64.tar.gz && tar -zxf node_exporter-0.18.1.linux-amd64.tar.gz && cd node_exporter-0.18.1.linux-amd64/ && sudo cp node_exporter /usr/local/bin/
  • 使用配置管理工具是运行和安装exporter的最佳方式。这种方式可以轻松地管理配置,并提供自动化和服务管理

4.1.2 配置Node Exporter

  • 默认情况下,node_exporter在端口9100上运行,并在路径/metrics上暴露指标。你可以通过--web.listen-address和--web.telemetry-path参数来设置端口和路径
代码语言:javascript
复制
$ node_exporter --web.listen-address=":9600" --web.telemetry-path="/node_metrics"
INFO[0000] Starting node_exporter (version=, branch=, revision=)  source="node_exporter.go:156"
INFO[0000] Build context (go=go1.12.5, user=, date=)     source="node_exporter.go:157"
INFO[0000] Enabled collectors: source="node_exporter.go:97"
INFO[0000]  - boottime         source="node_exporter.go:104"
INFO[0000]  - cpu              source="node_exporter.go:104"
INFO[0000]  - diskstats        source="node_exporter.go:104"
INFO[0000]  - filesystem       source="node_exporter.go:104"
INFO[0000]  - loadavg          source="node_exporter.go:104"
INFO[0000]  - meminfo          source="node_exporter.go:104"
INFO[0000]  - netdev           source="node_exporter.go:104"
INFO[0000]  - textfile         source="node_exporter.go:104"
INFO[0000]  - time             source="node_exporter.go:104"
INFO[0000] Listening on :9600  source="node_exporter.go:170"
  • 查看数据
代码语言:javascript
复制
$ curl http://localhost:9600/node_metrics
# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 8
# HELP go_info Information about the Go environment.
# TYPE go_info gauge
go_info{version="go1.12.5"} 1
# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
# TYPE go_memstats_alloc_bytes gauge
  • 许多收集器默认都是启用的。它们的状态要么是启用要么是禁用,可通过使用no-前缀来修改状态。(https://github.com/prometheus/node_exporter的`Enabled by defaultDisabled by default`),如
代码语言:javascript
复制
node_exporter --no-collector.arp

Name

Description

OS

arp

Exposes ARP statistics from /proc/net/arp.

Linux

bcache

Exposes bcache statistics from /sys/fs/bcache/.

Linux

bonding

Exposes the number of configured and active slaves of Linux bonding interfaces.

Linux

boottime

Exposes system boot time derived from the kern.boottimesysctl.

Darwin, Dragonfly, FreeBSD, NetBSD, OpenBSD, Solaris

conntrack

Shows conntrack statistics (does nothing if no /proc/sys/net/netfilter/ present).

Linux

cpu

Exposes CPU statistics

Darwin, Dragonfly, FreeBSD, Linux, Solaris

cpufreq

Exposes CPU frequency statistics

Linux, Solaris

diskstats

Exposes disk I/O statistics.

Darwin, Linux, OpenBSD

edac

Exposes error detection and correction statistics.

Linux

entropy

Exposes available entropy.

Linux

exec

Exposes execution statistics.

Dragonfly, FreeBSD

filefd

Exposes file descriptor statistics from /proc/sys/fs/file-nr.

Linux

filesystem

Exposes filesystem statistics, such as disk space used.

Darwin, Dragonfly, FreeBSD, Linux, OpenBSD

hwmon

Expose hardware monitoring and sensor data from /sys/class/hwmon/.

Linux

infiniband

Exposes network statistics specific to InfiniBand and Intel OmniPath configurations.

Linux

ipvs

Exposes IPVS status from /proc/net/ip_vs and stats from /proc/net/ip_vs_stats.

Linux

loadavg

Exposes load average.

Darwin, Dragonfly, FreeBSD, Linux, NetBSD, OpenBSD, Solaris

mdadm

Exposes statistics about devices in /proc/mdstat (does nothing if no /proc/mdstat present).

Linux

meminfo

Exposes memory statistics.

Darwin, Dragonfly, FreeBSD, Linux, OpenBSD

netclass

Exposes network interface info from /sys/class/net/

Linux

netdev

Exposes network interface statistics such as bytes transferred.

Darwin, Dragonfly, FreeBSD, Linux, OpenBSD

netstat

Exposes network statistics from /proc/net/netstat. This is the same information as netstat -s.

Linux

nfs

Exposes NFS client statistics from /proc/net/rpc/nfs. This is the same information as nfsstat -c.

Linux

nfsd

Exposes NFS kernel server statistics from /proc/net/rpc/nfsd. This is the same information as nfsstat -s.

Linux

pressure

Exposes pressure stall statistics from /proc/pressure/.

Linux (kernel 4.20+ and/or CONFIG_PSI)

schedstat

Exposes task scheduler statistics from /proc/schedstat.

Linux

sockstat

Exposes various statistics from /proc/net/sockstat.

Linux

stat

Exposes various statistics from /proc/stat. This includes boot time, forks and interrupts.

Linux

textfile

Exposes statistics read from local disk. The --collector.textfile.directory flag must be set.

any

thermal_zone

Exposes thermal zone & cooling device statistics from /sys/class/thermal.

Linux

time

Exposes the current system time.

any

timex

Exposes selected adjtimex(2) system call stats.

Linux

uname

Exposes system information as provided by the uname system call.

Darwin, FreeBSD, Linux, OpenBSD

vmstat

Exposes statistics from /proc/vmstat.

Linux

xfs

Exposes XFS runtime statistics.

Linux (kernel 4.4+)

zfs

Exposes ZFS performance statistics.

Linux, Solaris

4.1.3 配置textfile收集器

  • 我们还想配置一个特定的收集器,即textfile收集器,textfile收集器非常有用,因为它允许我们暴露自定义指标。这些自定义指标可能是批处理或cron作业 等无法抓取的,可能是没有exporter的源,甚至可能是为主机提供上下文的表态指标
  • 收集器通过扫描指定目录中的文件,提取所有格式为Prometheus指标的字符串,然后暴露它们以便抓取
代码语言:javascript
复制
$ mkdir -p /var/lib/node_exporter/textfile_collector
  • 现在在这个目录中创建一个新的指标。刚创建的目录中,指标在以.prom结尾的文件内定义,并且使用Prometheus特定文本格式
  • 我们使用此格式创建一个包含有关此主机的元数据指标
代码语言:javascript
复制
metadata{role="docker_server",datacenter="NJ"} 1
  • 可以看到它包含一个指标名称(metadata)和两个标签。一个标签role定义节点的角色。在示例中,标签的植 为docker_server。另一个标签datacenter定义主机的地理位置。最后,指标的值 为1,因为它不是计数型、测量型或计时型的指标,而是提供上下文
代码语言:javascript
复制
$ echo 'metadata{role="docker_server",datacenter="NJ"} 1' | sudo tee /var/lib/node_exporter/textfile_collector/metadata.prom

Password:
metadata{role="docker_server",datacenter="NJ"} 1
  • 要启用textfile收集器,我们不需要配置参数,它默认就会被加载。但我们需要指定textfile_exporter目录,以便Node Exporter知道在哪里可以找到自定义指标。为此,我们需要指定--collector.textfile.directory参数

4.1.4 启用systemd收集器

  • 只收集以下服务指标
    • docker.service:Docker守护进程
    • ssh.service:SSH守护进程
    • rsyslog.service:RSyslog守护进程
  • 使用--collector.systemd.unit-whitelist参数配置,它会匹配systemd正则表达式

4.1.5 运行Node Exporter

  • 第一台服务器
代码语言:javascript
复制
node_exporter --collector.textfile.directory="/var/lib/node_exporter/textfile_collector/" --collector.systemd
  • 结果
代码语言:javascript
复制
[vagrant@lab1 ~]$ node_exporter
INFO[0000] Starting node_exporter (version=0.18.1, branch=HEAD, revision=3db77732e925c08f675d7404a8c46466b2ece83e)  source="node_exporter.go:156"
INFO[0000] Build context (go=go1.12.5, user=root@b50852a1acba, date=20190604-16:41:18)  source="node_exporter.go:157"
INFO[0000] Enabled collectors:       source="node_exporter.go:97"
INFO[0000]  - arp                    source="node_exporter.go:104"
INFO[0000]  - bcache                 source="node_exporter.go:104"
INFO[0000]  - bonding                source="node_exporter.go:104"
INFO[0000]  - conntrack              source="node_exporter.go:104"
INFO[0000]  - cpu                    source="node_exporter.go:104"
INFO[0000]  - cpufreq                source="node_exporter.go:104"
INFO[0000]  - diskstats              source="node_exporter.go:104"
INFO[0000]  - edac                   source="node_exporter.go:104"
INFO[0000]  - entropy                source="node_exporter.go:104"
INFO[0000]  - filefd                 source="node_exporter.go:104"
INFO[0000]  - filesystem             source="node_exporter.go:104"
INFO[0000]  - hwmon                  source="node_exporter.go:104"
INFO[0000]  - infiniband             source="node_exporter.go:104"
INFO[0000]  - ipvs                   source="node_exporter.go:104"
INFO[0000]  - loadavg                source="node_exporter.go:104"
INFO[0000]  - mdadm                  source="node_exporter.go:104"
INFO[0000]  - meminfo                source="node_exporter.go:104"
INFO[0000]  - netclass               source="node_exporter.go:104"
INFO[0000]  - netdev                 source="node_exporter.go:104"
INFO[0000]  - netstat                source="node_exporter.go:104"
INFO[0000]  - nfs                    source="node_exporter.go:104"
INFO[0000]  - nfsd                   source="node_exporter.go:104"
INFO[0000]  - pressure               source="node_exporter.go:104"
INFO[0000]  - sockstat               source="node_exporter.go:104"
INFO[0000]  - stat                   source="node_exporter.go:104"
INFO[0000]  - textfile               source="node_exporter.go:104"
INFO[0000]  - time                   source="node_exporter.go:104"
INFO[0000]  - timex                  source="node_exporter.go:104"
INFO[0000]  - uname                  source="node_exporter.go:104"
INFO[0000]  - vmstat                 source="node_exporter.go:104"
INFO[0000]  - xfs                    source="node_exporter.go:104"
INFO[0000]  - zfs                    source="node_exporter.go:104"
INFO[0000] Listening on :9100        source="node_exporter.go:170"
  • 第二台服务器
代码语言:javascript
复制
node_exporter --collector.systemd.unit-whitelist="(docker|ssh|rsyslog).service"
  • 结果
代码语言:javascript
复制
[vagrant@lab2 ~]$ node_exporter --collector.systemd.unit-whitelist="(docker|ssh|rsyslog).service"
INFO[0000] Starting node_exporter (version=0.18.1, branch=HEAD, revision=3db77732e925c08f675d7404a8c46466b2ece83e)  source="node_exporter.go:156"
INFO[0000] Build context (go=go1.12.5, user=root@b50852a1acba, date=20190604-16:41:18)  source="node_exporter.go:157"
INFO[0000] Enabled collectors:       source="node_exporter.go:97"
INFO[0000]  - arp                    source="node_exporter.go:104"
INFO[0000]  - bcache                 source="node_exporter.go:104"
INFO[0000]  - bonding                source="node_exporter.go:104"
INFO[0000]  - conntrack              source="node_exporter.go:104"
INFO[0000]  - cpu                    source="node_exporter.go:104"
INFO[0000]  - cpufreq                source="node_exporter.go:104"
INFO[0000]  - diskstats              source="node_exporter.go:104"
INFO[0000]  - edac                   source="node_exporter.go:104"
INFO[0000]  - entropy                source="node_exporter.go:104"
INFO[0000]  - filefd                 source="node_exporter.go:104"
INFO[0000]  - filesystem             source="node_exporter.go:104"
INFO[0000]  - hwmon                  source="node_exporter.go:104"
INFO[0000]  - infiniband             source="node_exporter.go:104"
INFO[0000]  - ipvs                   source="node_exporter.go:104"
INFO[0000]  - loadavg                source="node_exporter.go:104"
INFO[0000]  - mdadm                  source="node_exporter.go:104"
INFO[0000]  - meminfo                source="node_exporter.go:104"
INFO[0000]  - netclass               source="node_exporter.go:104"
INFO[0000]  - netdev                 source="node_exporter.go:104"
INFO[0000]  - netstat                source="node_exporter.go:104"
INFO[0000]  - nfs                    source="node_exporter.go:104"
INFO[0000]  - nfsd                   source="node_exporter.go:104"
INFO[0000]  - pressure               source="node_exporter.go:104"
INFO[0000]  - sockstat               source="node_exporter.go:104"
INFO[0000]  - stat                   source="node_exporter.go:104"
INFO[0000]  - textfile               source="node_exporter.go:104"
INFO[0000]  - time                   source="node_exporter.go:104"
INFO[0000]  - timex                  source="node_exporter.go:104"
INFO[0000]  - uname                  source="node_exporter.go:104"
INFO[0000]  - vmstat                 source="node_exporter.go:104"
INFO[0000]  - xfs                    source="node_exporter.go:104"
INFO[0000]  - zfs                    source="node_exporter.go:104"
INFO[0000] Listening on :9100        source="node_exporter.go:170"

4.1.6 抓取Node Exporter

  • 让我们配置一个新作业来抓取Node Exporter导出的数据。查看当前prometheus.yml文件和抓取配置文件的scrape_configs部分,Node Exporter默认抓取路径是/metrics,重启Prometheus服务器
代码语言:javascript
复制
scrape_configs:
- job_name: 'prometheus'
  static_configs:
    - targets: ['localhost:9090']

- job_name: 'node'
  static_configs:
    - targets: ['11.11.11.111:9100', '11.11.11.112:9100', '11.11.11.113:9100']
  • Prometheus假设Node Exporter具有默认路径/metrics,并且抓取的目标形式如下:
代码语言:javascript
复制
11.11.11.111:9100/metrics
  • 如果现在使用SIGHUP或重新启动Prometheus服务器,那么我们的配置将被重新加载,并且服务器也会开始抓取。我们很快就会看到时间序列数据开始流入Prometheus服务器

4.1.7过滤收集器

  • Prometheus还提供了一种方式来限制收集器从服务器端实际抓取的数据,尤其是在你无法控制正抓取的主机的配置很有用
  • 过滤惧器示例
代码语言:javascript
复制
scrape_configs:
...
- job_name: 'node'
  static_configs:
    - targets: ['11.11.11.111:9100', '11.11.11.112:9100', '11.11.11.113:9100']
  params:
    collect[]:
      - cpu
      - meminfo
      - diskstats
      - netdev
      - netstat
      - filefd
      - filesystem
      - xfs
      - systemd
  • 使用params块中collect[]列表指定,然后将它们作为URL参数传递给抓取请求。你可以使用Node Exporter实例上的curl命令来对此进行测试(只收集cpu指标,其它指标忽略)
代码语言:javascript
复制
curl -g -X GET http://11.11.11.111:9100/metrics?collect[]=cpu

4.2 监控Docker容器

  • 推荐的方法是使用Google的cAdvisor工具。在Docker守护进程上,cAdvisor作为Docker容器运行,单个cAdvisor容器返回针对Docker守护进程和所有正在运行的容器的指标。Prometheus支持通过它导出指标,并将数据传输到其他各种存储系统,如InfluxDB、Elasticsearch和Kafka

4.2.1 运行cAdvisor

  • 让我们在Docker1主机上运行一个cAdvisor容器
  • 运行cAdvisor容器
代码语言:javascript
复制
docker run --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 \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
  • 目录分为两种类型
    • 第一种是只读的,cAdvisor将从中收集数据,例如/sys目录--volume=/sys:/sys:ro
    • 第二种类型是可读写的,是Docker套接字的挂载,通常位于/var/run目录中
  • 查看web ui(http://11.11.11.112:8080/containers)

4.2.2 抓取cAdvisor

  • 我们需要告诉Prometheus cAdvisor是在Docker守护进程上运行的。为此,我们将在配置中添加第三个作业
代码语言:javascript
复制
scrape_configs:
- job_name: 'prometheus'
  static_configs:
    - targets: ['localhost:9090']

- job_name: 'node'
  static_configs:
    - targets: ['138.197.26.39:9100', '138.197.30.147:9100', '138.197.30.163:9100']

- job_name: 'docker'
  static_configs:
    - targets: ['138.197.26.39:8080']

4.3 抓取的生命周期

  • 示例都是已手动指定的静态配置的主机,以及一些其他服务发现机制,例如从文件加载目标或查询API等
  • 服务发现返回一个目标列表,其中饮食一组称为元数据的标签,这些标签以__meta_为前缀。每个服务发现机制都有不同的元数据
  • 服务发现还会根据目标的配置来设置其他标签,这些标签带有__的前缀和后缀,包括____scheme______、______address______和____metrics_path____。这些标签包含目标的模式(http或https)、目标的地址以及指标的具体路径
  • 每个标签通常都有一个默认值。例如,______metrics_path______默认为/metrics,____scheme____默认为值http。此外,如果路径中存在任何URL参数,则它们的前缀会设置为________param___*。
  • 配置标签会在抓取的生命周期中重复利用以生成其他标签。例如,指标上instance标签的默认内容是____address____标签的内容
  • 注意:为什么到现在我们都没有在界面上看到任何带____前缀和后缀的标签呢?这是因为有些标签在生命周期的后期被删除了,并且所有这些标签都被专门排除掉,不在Web UI上显示
  • 然后这些目标列表和标签会返回给Prometheus,其中一些标签可以在配置中被覆盖 ,例如,通过metrics_path参数设置的指标路径以及通过scheme参数指定的模式
  • 代码示例:覆盖标签配置
代码语言:javascript
复制
scrape_configs:
- job_name: 'node'
  scheme: https
  metrics_path: /moremetrics
  static_configs:
    - targets: ['138.197.26.39:9100', '138.197.30.147:9100', '138.197.30.163:9100']
  • Prometheus提供了可以重新标记目标的机会,并可能使用你的服务发现所添加的一些元数据。你还可以过滤目标,以删除或保留特定条目
  • 然后就是真正的数据抓取,以及指标返回。当指标被抓取时,你将拥有最后一次机会在将它们保存在服务器之前重新标记并过滤
  • 抓取的生命周期(图)

4.4 标签

  • 标签提供了时间序列的维度。它们可以定义目标,并为时间序列提供上下文。但最重要的是,结合指标名称,它们构成了时间序列的标识,如果它们改变了,那么时间序列的标识也会跟着改变。
代码语言:javascript
复制
更改或添加标签会创建新的时间序列
  • 意味着应该明知地使用标签并尽可能保持不变。如果不遵守这一规定,则可能产生新的时间序列,从而创建出一个动态的数据环境,使监控的数据源难以跟踪。想象一下,你有一个时间序列,用于跟踪服务的状态。你为该时间系列配置了一个警报,该警报依赖于指标的标签来评判。如果更改或添加标签,那么警报将变为无效

4.4.1 标签分类

  • 每个指标都天然带有两个拓扑标签:job和instance
  • 模式标签(schematic label)是url、error_code或user之类的东西,它们允许你将拓扑中同一级别的时间序列匹配在一起,例如创建数据间的比率
  • 如果你需要添加额外的标签,则可以考虑如图所示的层次结构(标签分类)

4.4.2 重新标记

  • 在一个集中的复杂监控环境中,有时你无法控制监控所有资源以及所有暴露的监控数据。通过重新票房,你可以控制、管理并标准化环境中的指标。一些最常见的用例是:
  1. 删除不必要的指标
  2. 从指标中删除敏感或不需要的标签
  3. 添加、编辑或修改指标的标签值 或标签格式
  • 请记住,我们有两个阶段可以重新标记。第一个阶段是对来自服务发现的目标进行重新标记(relabel_configs),这对于将来自服务发现的元数据标签中的信息应用于指标上的标签来说非常有用。这是在作业内的relabel_configs块中完成的
  • 第二个阶段是在抓取之后(metric_relabel_configs)且指标被保存于存储系统之前。这样,我们就可以确定哪些指标需要保存、哪些需要丢弃以及这些指标的样式。这是在我们作业 内的metric_relabel_configs块中完成的
  • 代码示例:通过重新标记来删除指标
代码语言:javascript
复制
  - job_name: 'docker'
    static_configs:
      - targets: ['138.197.26.39:8080', '138.197.30.147:8080', '138.197.30.163:8080']
    metric_relabel_configs:
      - source_labels: [__name__]
        regex: '(container_tasks_state|container_memory_failures_total)'
        action: drop
删除指标
  • 首先来看看第一种操作。我们使用source_labels参数选择要操作的指标,并且还需要一组标签名称。在示例中我们使用____name____标签,____name____标签是表示指标名称的预留标签
  • 代码示例:定义新的分隔符
代码语言:javascript
复制
  - job_name: 'docker'
    static_configs:
      - targets: ['138.197.26.39:8080', '138.197.30.147:8080', '138.197.30.163:8080']
    metric_relabel_configs:
      - source_labels: [__name__]
        separator: ','
        regex: '(container_tasks_state|container_memory_failures_total)'
        action: drop
  • 如果指定了多个源标签,那么我们将使用分隔符隔开每个正则表达式,例如
代码语言:javascript
复制
regex1;regex2;regex3
替换标签值
  • 许多cAdvisor指标都有一个id标签,其中包含正在运行的进程的名称。如果进程是一个容器,会看到如下信息
代码语言:javascript
复制
id="/docker/6f823kdj39892jd8j3jid983ujj8edjie99djc883mnbnc8833nccllddklsoow838ckkc8"
  • 然后将其放入一个新标签container_id中,通过重新标记我们可以这样做
  • 代码示例:替换标签
代码语言:javascript
复制
    metric_relabel_configs:
      - source_labels: [id]
        regex: '/docker/([a-z0-9]+)'
        replacement: '$1'
        target_label: container_id
删除标签
  • 代码示例:删除标签
代码语言:javascript
复制
    metric_relabel_configs:
      - regex: '/docker/([a-z0-9]+)'
        action: labeldrop
  • 请记住,标签是时间序列的唯一性约束。如果你删除标签并导致时间序列重复,那么系统可能会出现问题!
文档
  • relabel_configs:https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config
  • RE2正则表达式语法:https://github.com/google/re2/wiki/Syntax
  • 正则表达式测试工具:http://www.regexplanet.com/advanced/golang/index.html

4.5 Node Exporter和cAdvisor指标

  • 现在从4个主机中收集总共7组独立的指标
  1. Prometheus服务器自己的指标
  2. 来自3台主机的Node Exporter指标
  3. 来自3台主机的cAdvisor指标
  • 可通过http://localhost:9090/targets查看抓取目标列表以及每个目标的状态

4.5.1 USE方法

CPU使用率
  • 名为node_cpu_seconds_total的指标是主机上CPU使用率
  • 应该看到一个指标列表,像这样
代码语言:javascript
复制
node_cpu_seconds_total{cpu="cpu0",instance="138.197.26.39.9100",job="node",mode="user"}
  • 这里真正想要的是获得每个实例的CPU使用百分比,但要实现这一点,需要稍微处理下指标,可以通过一系列PromQL计算来实现这一结果
  • 首先计算每种CPU模式的每秒使用率。PromQL有一个名为irate的函数,用于计算范围向量中时间序列增加的每秒即时速率。让我们对node_cpu_seconds_total指标使用irate函数,在查询框中输入(表示为5分钟范围内的每秒速率)
代码语言:javascript
复制
irate(node_cpu_seconds_total{job="node"}[5m])
  • 可使用avg或average去处符介绍的by子句
代码语言:javascript
复制
avg(irate(node_cpu_seconds_total{job="node"}[5m])) by (instance)
  • 上面指标不太准确,它包括idle的值 ,并且宽没有表示成百分比形式。我们将查询每个实例的idle使用率,它已经是一个比率,将它乘以100转换为百分比
代码语言:javascript
复制
avg(irate(node_cpu_seconds_total{job="node",mode="idle"}[5m])) by (instance) * 100
  • 可用100减去这个值 ,结果就是CPU使用率的百分比
代码语言:javascript
复制
100 - avg(irate(node_cpu_seconds_total{job="node",mode="idle"}[5m])) by (instance) * 100
CPU饱和度
  • 将主机上的CPU考虑在内的一段时间内的平均运行队列长度。平均负载少于CPU的数量通常是正常的,长时间内超过该数字的平均值 则表示CPU已饱和
  • 我们需要计算主机上的CPU数量,可使用count聚合实现
代码语言:javascript
复制
count by (instance)(node_cpu_seconds_total{mode="idle"})
  • 用idle的mode计算node_cpu_seconds_total时间序列出现次数,然后使用by子句从结果向量中删除instance之外的所有标签,可以看到3个节点各有2个CPU
  • 然后将此计数与node_load1指标结合起来,如下所示
代码语言:javascript
复制
node_load1 > on (instance) 2 * count by (instance)(node_cpu_seconds_total{mode="idle"})
  • 查询的是1分钟的平均负载超过主机CPU数量的两倍的结果
  • 聚合操作符:https://prometheus.io/docs/prometheus/latest/querying/operators/#aggregation-operators
内存使用率
  • Node Exporter内存指标按内存的类型和使用率进行细分。可以在以node_memory为前缀的指标列表中找到它们
  • 重点关注node_memory指标的一个子集以获取使用率
  1. node_memory_MemTotal_bytes:主机上的总内存
  2. node_memory_MemFree_bytes:主机上的可用内存
  3. node_memory_Buffers_bytes:缓冲缓存中的内存
  4. node_memory_Cached_bytes:页面缓存中的内存
  • 所有这些指标都是以字节为单位表示的,公式为
代码语言:javascript
复制
(总内存-(可用内存+缓冲缓存中的内存+页面缓存中的内存))÷总内存×100
代码语言:javascript
复制
(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Cached_bytes + node_memory_Buffers_bytes)) /  node_memory_MemTotal_bytes * 100
内存饱和度
  • 我们还可以通过检查内存和磁盘的读写来监控内存饱和度。可以使用从/proc/vmstat收集的两个Node Exporter指标
    • node_vmstat_pswpin:系统每秒从磁盘读到内存的字节数
    • node_vmstat_pswpout:系统每秒从内存写到磁盘的字节数
  • 两者都是自上次启动以来的字节数,以KB为单位
  • 为了获得饱和度指标,我们对每个指标计算一分钟的速率,将两个速率相加,然后乘以1024以获得字节数。我们会创建一个查询来执行此操作
  • 代码清单:内存饱和度查询
代码语言:javascript
复制
1024 * sum by (instance) (
    (rate(node_vmstat_pgpgin[1m])
    + rate(node_vmstat_pgpgout[1m]))
)
磁盘使用率
  • 对于磁盘,我们只测量磁盘使用情况而不是使用率、饱和度或错误。这是因为在大多数情况下,它是对可视化和警报最有用的数据
  • node_filesystem_size_bytes显示被监控的每个文件系统挂载大小。我们可以使用与内存指标类似的查询来生成在主机上使用的磁盘空间的百分比
代码语言:javascript
复制
(node_filesystem_size_bytes{mountpoint="/"}) - node_filesystem_free_bytes{mountpoint="/") / node_filesystem_size_bytes{mountpoint="/"} * 100
  • 使用mountpoint标签文件系统"/"挂载,返回该文件系统的磁盘使用指标
  • 我们更关心的是什么时候耗尽磁盘空间?
  • 实际上Prometheus提供了一种机制,通过一个名为predict_linear的函数,可以构造一个查询来回答这个问题
代码语言:javascript
复制
predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h], 4*3600) < 0
  • 我们选择一小时的时间窗口[1h],并将此时间序列快照放在predict_linear函数中。该函数使用简单的线性回归,根据以前的增长情况来确定文件系统何时会耗尽空间。该函数参数包括一个范围向量,即一小时窗口,以及未来需要预测的时间点
  • 如果基于最后一小时的增长历史记录,文件系统将在接下来的四小时内用完空间,那么查询将返回一个负数,然后可以使用它来触发警报

4.5.2 服务状态

  • 服务的状态在node_systemd_unit_state指标中暴露出来。对于收集的每个服务和服务状态都有一个指标
  • 代码清单:指标node_systemd_unit_state
  • 可以通过添加state标签来进一步缩小搜索范围,仅返回active状态的数据
代码语言:javascript
复制
node_systemd_unit_state{name="docker.service",state="active"}
  • 看到了一个新的查询,使用比较运算符"=="。查询将返回值为1、name标签为docker.service的所有指标
  • 比较运算符:https://prometheus.io/docs/prometheus/latest/querying/operators/#comparison-binary-operators

4.5.3 可用性和up指标

  • 代码清单:up指标
代码语言:javascript
复制
up{job="<job-name>", instance="<instance-id>"}
  • 如果实例是健康的,则指标设置为1,即数据抓取成功返回。如果抓取失败,则设置为0
  • 提示:Prometheus还会填充其他一些监控指标,包括scrape_duration_seconds(抓取的持续时间)和scrape_duration_scraped(目标暴露的样本数)
  • 可以查询主机的所有up指标
  • 许多exporter都有特定的指标,旨在确定最后一次成功的数据抓取。例如,cAdvisor指标container_last_seen,它提供容器列表以及它们最近一次活动的时间。MySQL Exporter返回一个指标mysql_up
  • 注意:你不能重新票房自动填充的指标,如up指标,因为它们是在重新标记阶段之后生成的

4.5.4 metadata指标

代码语言:javascript
复制
metadata{role="docker_server",datacenter="NJ"} 1
  • 该指标提供资源的上下文信息,如角色 docker_server,主机的位置datacenter。尽管这些数据本身很有用,但为什么又要创建一个单独的指标而不是仅将作为标签添加到主机的指标中呢?我们已经知道标签提供了时间序列的维度,并且与指标名称相结合,它们构成了时间序列的标识。同时,我们也已经被警告过:
代码语言:javascript
复制
更改标签或添加新标签都会创建新的时间序列
  • 这意味着我们应该谨慎地使用标签,并且应尽可能保持不变
  • 让我们看看如何利用该指标上的标签。假设我们只想从某个特定的数据中心或一组数据中心选择指标。我们可以快速找到所有主机,例如,查询不在新泽西(NJ)的数据中心
代码语言:javascript
复制
metadata{datacenter!="NJ"}
向量匹配
  • 我们可以使用metadata指标来进行向量匹配(vector match)。向量匹配可以使用任何PromQL二元运算符。向量匹配尝试针对左侧向量中的每个元素在右侧向量中查找对应的匹配元素
  • 有两种向量匹配:一对一(one-to-one)和多对一(many-to-one,或一对多(one-to-many))
一对一匹配
  • 一对一匹配从每一侧找到唯一匹配的条目对。如果两个条目具有完全相同的标签的值 ,则它们是一对一匹配的。你可以考虑使用ignoring修饰符忽略掉特定标签,或者使用on修饰符来减少显示的标签列表
  • 代码清单:一对一向量匹配
代码语言:javascript
复制
node_system_unit_state{name="docker.service"} == 1 and on (instance, job) metadata{datacenter="SF"}
  • 将查询所有node_system_unit_state指标中name标签为docker.service并且值为1的指标。然后,我们使用on修饰符将返回的标签列表减少到metadata指标的instance和job标签,并且datacenter标签的值 为SF
  • 这将返回一个指标
代码语言:javascript
复制
node_system_unit_state{instance="138.197.30.147:9100", job="node", name="docker.service", state="active"}
多对一和一对多匹配
  • 多对一和一对多匹配是其中一侧向量中的元素与另一侧微量中的多个元素相匹配。这些匹配使用group_left或group_right修饰符显式指定,其中left或right是为了确定哪个向量具有更高的基数。Prometheus文档包含了一些这种匹配的例子,但它们通常不会被使用。大多数情况下,一对一匹配就足够了
  • 向量匹配文档:https://prometheus.io/docs/prometheus/latest/querying/operators/#vector-matching
元数据风格的指标
  • 许多现有的exporter使用这种"元数据"模式来提供额外状态的信息,例如cAdvisor的cadvisor_version指标

4.6 查询持久性

  • 可以通过以下三种方式使查询持久化
  1. 记录规则:根据查询创建新指标
  2. 警报规则:从查询生成警报
  3. 可视化:使用Grafana等仪表板可视化查询

4.6.1 记录规则

  • 记录规则是一种根据已有时间序列计算新时间序列(特别是聚合时间序列)的方法
  • 跨多个时间序列生成聚合
  • 预先计算消耗大的查询
  • 产生可用于生成警报的时间序列
  • 文档链接
    • 记录规则:https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/
    • 警报规则:https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/

4.6.2 配置记录规则

  • 规则是自动计算的,频率则由第3章介绍的prometheus.yml配置文件的global块中的evaluation_interval参数控制
  • 代码清单:evaluation_interval参数
代码语言:javascript
复制
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  • 代码清单:创建一个记录规则文件
代码语言:javascript
复制
mkdir -p rules
cd rules
touch node_rules.yml
  • 在Prometheus配置文件prometheus.yml的rule_files块中添加这个文件
  • 代码清单:添加规则文件
代码语言:javascript
复制
rule_files:
  - "rules/node_rules.yml"
  • 新的Prometheus使用2.0格式:https://www.robustperception.io/converting-rules-to-the-prometheus-2-0-format

4.6.3 添加记录规则

  • 让我们把CPU、内存和磁盘计算转换为记录规则。我们有很多要监控的主机,所以我们要对所有节点预先计算这三个指标的查询,这样就可以将这些计算作为指标,然后可以设置警报或者通过Grafana等仪表板进行可视化
  • 代码清单:一个记录规则
代码语言:javascript
复制
group:
  - name: node_rules
    rules:
      - record: instance:node_cpu:avg_rate5m
        expr: 100 - avg(irate(node_cpu_seconds_total{job="node",mode="idle"}[5m])) by (instance) * 100
  • 记录规则在规则组中定义,这里的规则组叫作node_rules。规则组名称在服务器中必须是唯一的。规则组内的规则以固定间隔顺序执行。默认情况下,这是通过全局evaluate_interval来控制的,但你可以使用interval子句在规则组中覆盖
  • 规则组内规则执行的顺序性质意味着你可以在后续规则中使用之前创建的规则。这允许你根据规则创建指标,然后在之后的规则中重用这些指标。这仅在规则组内适用,规则组是并行运行的,因此不建议跨组使用规则
  • 我们有一个名为rules的YAML块,它包含该组的记录规则。每条规则都包含一条记录,告诉Prometheus将新的时间序列命名为什么。你应该仔细命名规则,以便快速识别它们代表的内容。一般推荐的格式是:
代码语言:javascript
复制
level:metric:operations
  • 其中level表示聚合级别,以及规则输出的标签。metric是指标名称,除了使用rate()或irate()函数剥离_total计数器之外,应该保持不变。这样的命名可以帮助你更轻松地找到新指标。最后,operations是应用于指标的操作列表,一般最新的操作放在前面。
  • 所以我们的CPU查询将命名为
代码语言:javascript
复制
instance:node_cpu:avg_rate5m
  • 在Prometheus文档中有一些全名的最佳实践:https://prometheus.io/docs/practices/naming/
  • expr字段来保存生成新时间序列的查询
  • 添加labels块以向新时间序列添加新标签
  • 代码清单:一个记录规则
代码语言:javascript
复制
group:
  - name: node_rules
    rules:
      - record: instance:node_cpu:avg_rate5m
        expr: 100 - avg(irate(node_cpu_seconds_total{job="node",mode="idle"}[5m])) by (instance) * 100
        labels:
          metric_type: aggregation
  • 代码清单:一个记录规则
代码语言:javascript
复制
group:
  - name: node_rules
    rules:
      - record: instance:node_cpu:avg_rate5m
        expr: 100 - avg(irate(node_cpu_seconds_total{job="node",mode="idle"}[5m])) by (instance) * 100
      - record: instance:node_memory_usage:percentage
        expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Cached_bytes + node_memory_Buffers_bytes)) / node_memory_MemTotal_bytes * 100
      - record: instance:root:node_filesystem_usage:percentage
        expr: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_free_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} * 100
  • 通过将SIGHUP信号发送到Prometheus进程,可以在运行时重新加载规则文件。重新加载仅在规则文件格式良好时才有效。Prometheuus服务器附带一个名为promtool的实用程序,可以帮助检测规则文件
  • 如果我们现在搜索一个新的时间序列instance:node_cpu:avg_rate5m,则应该可以看到如下内容
  • 可以在web界面的/rules路径中查看当前服务器上定义的规则

4.7 可视化

  • Prometheus通常不用于长期数据保留,默认保存15天的时间序列数据。这意味着Prometheus更专注于监控问题,而不是其他可视化和仪表板系统
  • 我们也将快速安装Grafana并将Prometheus连接到上面

4.7.1 安装Grafana

  • 代码清单:在Red Hat上获取PackageCloud公钥
代码语言:javascript
复制
sudo rpm --import https://packagecloud.io/gpg.key
  • 然后将以下内容添加到grafana.repo文件内的/etc/yum.repos.d/目录中
代码语言:javascript
复制
[grafana]
name=grafana
baseurl=https://packagecloud.io/grafana/stable/el/7/$basearch
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packagecloud.io/gpg.key https://grafanarel.s3.amazonaws.com/RPM-GPG-KEY-grafana
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
  • 现在我们通过yum或者dnf命令来安装Grafana
代码语言:javascript
复制
sudo yum install grafana
在Mac OS X上安装Grafana
代码语言:javascript
复制
brew install grafana
Docker镜像
  • 链接:https://hub.docker.com/search?q=grafana&type=image

4.7.2 启动和配置Grafana

  • 代码清单:在Linux上启动Grafana
代码语言:javascript
复制
sudo service grafana-server start
  • 代码清单:在配置OS X启动时启动Grafana
代码语言:javascript
复制
brew services start grafana

4.7.3 配置Grafana Web界面

  • Grafana是一个基于Go的Web应用服务,默认在端口3000上运行。一旦运行,你就可以通过浏览器访问——例如,如果它在本地主机上运行,则可直接访问http://localhost:3000
  • 开始你会看到一个登录界面,默认用户名和密码为admin和admin,你可以通过更新Grafana配置文件的[security]部分来控制
  • 首先要将Grafana与我们的Prometheus数据关联起来,单击入门教程中的"Add data source"
  • 要添加新数据源,我们需要指定一些细节信息。首先,我们需要命名数据源,这里采用Prometheus。接下来,选中Default复选框,告诉Grafana默认搜索该数据源的数据。我们还需要确保将数据源类型设置为Prometheus
  • 需要为数据源指定HTTP设置,这是我们要查询的Prometheus服务器的URL。我们假设Grafana与Prometheus在同一台主机上运行,因此这里使用本地服务器的http://localhost:9090
  • 将Access选项设置为proxy(代理),但是这并没有为我们的连接配置HTTP代理,不过它告诉Grafana使用自己的Web服务来代理与Prometheus的连接。另一个选项direct,是从Web浏览器直接连接。proxy设置更加实用一些,因为连接部分交由Grafana服务负责
  • 单击"Add"按钮就可以完成新数据源的添加。在界面上,现在可以看到我们的数据源显示。如果保存后有横幅弹出提示"Datasource is working",则表明它正在工作!
  • 单击Grafana图标,然后单击"Dashboards->Home"返回主控制台视图

4.7.4 第一个仪表板

有大量资源和示例可供参考
  • Grafana入门:https://grafana.com/docs/guides/getting_started/
  • Grafana教程和录像:https://grafana.com/docs/tutorials/screencasts/
  • Prometheus文档中的Grafana部分:https://prometheus.io/docs/visualization/grafana/
  • Grafana预建仪表板:https://grafana.com/grafana/dashboards
  • 许多项目还包括预先构建的Grafana仪表板,以满足特定的需求,如Mysql(https://github.com/percona/grafana-dashboards)或Redis(https://grafana.com/grafana/dashboards/763)
  • 我们在本书源码中提供了可导入的完整仪表板JSON文件(https://github.com/turnbullpress/prometheusbook-code/blob/master/4/dashboard.json)

  • 《The Docker Book》https://dockerbook.com/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 yeedomliu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第4章 监控主机和容器
    • 4.1 监控节点
      • Exporter
      • 4.1.1 安装Node Exporter
      • 4.1.2 配置Node Exporter
      • 4.1.3 配置textfile收集器
      • 4.1.4 启用systemd收集器
      • 4.1.5 运行Node Exporter
      • 4.1.6 抓取Node Exporter
      • 4.1.7过滤收集器
    • 4.2 监控Docker容器
      • 4.2.1 运行cAdvisor
      • 4.2.2 抓取cAdvisor
    • 4.3 抓取的生命周期
      • 4.4 标签
        • 4.4.1 标签分类
        • 4.4.2 重新标记
      • 4.5 Node Exporter和cAdvisor指标
        • 4.5.1 USE方法
        • 4.5.2 服务状态
        • 4.5.3 可用性和up指标
        • 4.5.4 metadata指标
      • 4.6 查询持久性
        • 4.6.1 记录规则
        • 4.6.2 配置记录规则
        • 4.6.3 添加记录规则
      • 4.7 可视化
        • 4.7.1 安装Grafana
        • 4.7.2 启动和配置Grafana
        • 4.7.3 配置Grafana Web界面
        • 4.7.4 第一个仪表板
      相关产品与服务
      Prometheus 监控服务
      Prometheus 监控服务(TencentCloud Managed Service for Prometheus,TMP)是基于开源 Prometheus 构建的高可用、全托管的服务,与腾讯云容器服务(TKE)高度集成,兼容开源生态丰富多样的应用组件,结合腾讯云可观测平台-告警管理和 Prometheus Alertmanager 能力,为您提供免搭建的高效运维能力,减少开发及运维成本。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档