1 docker监控方式
Docker的监控,可以使⽤Docker⾃带的stats命令来获取当前主机上运⾏中的容器的资源使⽤情况。例如:容器的CPU使⽤率、内存占⽤、⽹络IO以及磁盘IO等指标。
# CONTAINER ID: 容器的唯⼀标识符。
# NAME: 容器的名称。
# CPU %: 容器使⽤的CPU百分⽐。
# MEM USAGE / LIMIT: 容器当前的内存使⽤量和它所能使⽤的最⼤内存量。
# MEM %: 容器使⽤的内存占总分配内存的百分⽐。
# NET I/O: 容器的⽹络输⼊/输出量,分别显示了接收和发送的总数据量。
# BLOCK I/O: 容器的磁盘输⼊/输出量,分别显示了读取和写⼊的总数据量。
# PIDS: 容器内的进程数。
另外,Google开源的CAdvisor⼯具就是专⻔针对容器的性能进⾏监测和分析。它提供了⼀个直观的UI界⾯,⽤于展示容器的实时或历史资源使⽤情况。
最为重要的是,CAdvisor能够导出与Prometheus兼容的监控指标,这使得Prometheus可以抓取这些指标,从⽽对容器的资源使⽤进⾏监控和分析。 Cadvisor项⽬地址:(https://github.com/google/cadvisor/releases)
2 Cadvisor
2.1 运行docker容器
运行两个容器应用
docker run -d --memory=100m -p 8081:80 --name nginx1 hub.atomgit.com/amd64/nginx:latest
docker run -d --memory=50m -p 8082:80 --name nginx2 hub.atomgit.com/amd64/nginx:latest
2.2 运⾏Cadvisor
1、启动Cadvisor容器
docker run -d --name=cadvisor \
-p 8083:8080 \
-v /:/rootfs:ro \
-v /var/run:/var/run:ro \
-v /sys:/sys:ro \
-v /dev/disk/:/dev/disk:ro \
-v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-v /data/docker/:/var/lib/docker:ro \
--privileged \
gcr.io/cadvisor/cadvisor:v0.47.2
2、Cadvisor提供的metrics地址为
http://192.168.137.128:8083/metrics
3、访问Cadvisor提供的webUI
http://192.168.137.128:8083/containers/
2.3 配置Prometheus
1、修改Prometheus配置
- job_name: "docker"
metrics_path: "/metrics"
static_configs:
- targets: ["192.168.137.128:8083"]
2、重新加载Prometheus配置⽂件
curl -X POST http://192.168.137.131:9090/-/reload
2.4 Docker常⽤指标与示例
2.4.1 Docker CPU相关指标
指标名称 | 指标类型 | 指标含义 |
container_cpu_usage_seconds_total | counter | 容器在所有CPU核⼼上累积使⽤的时间,以秒为单位。 |
container_cpu_user_seconds_total | counter | 容器在所有CPU核⼼user模式下累积使⽤的时间,以秒为单位。 |
container_cpu_system_seconds_total | counter | 容器在所有CPU核⼼system模式下累积使⽤的时间,以秒为单位。 |
案例:计算每个容器的CPU利⽤率。
1、列出所有容器使⽤CPU的累积时间;
2、使⽤rate将最近1分钟的使⽤时间专为平均速率;
3、使⽤sum聚合,⽽后进⾏实例和容器名称的分组,最后乘以100将利⽤率专为百分⽐。
sum(rate(container_cpu_usage_seconds_total{name!=""}[1m])) by(instance,name) * 100
2.4.2 Docker 内存相关指标
指标名称 | 指标类型 | 指标含义 |
container_memory_usage_bytes | gauge | 容器当前正在使⽤的内存。包括常驻内存,缓存、交换(swap)等类型的内存使⽤情况。 |
container_memory_working_set_bytes | gauge | 容器当前实际使⽤的内存量。仅包括常驻内存,不包括缓存,以及可被回收的内存,因此更它准确。 |
container_spec_memory_limit_bytes | gauge | 容器的内存使⽤上限。如果容器没有设置内存限制,则可能会显示0,或者宿主机的内存。 |
machine_memory_bytes | gauge | 代表当前主机(宿主机)的总内存量(以字节为单位) |
案例1:获取每个容器的内存的实际使⽤量,以MB单位展示
sum(container_memory_working_set_bytes{name!=""}) by(instance,name) /1024 /1024
案例2:计算每个容器的实际内存使⽤,占其配置的内存最⼤限制⽐率。
计算公式:( 容器实际的使⽤内存 / ( 容器限制最⼤能使⽤的内存 > 0 ) * 100 )
sum(container_memory_working_set_bytes{name!=""}) by(instance,name) /
sum(container_spec_memory_limit_bytes{name!=""} > 0) by(instance,name) * 100
案例3:计算所有容器实际使⽤的内存的和,占物理内存的⽐率。
计算公式:( 所有容器内存使⽤的和 / 物理内存 * 100 )
sum(container_memory_working_set_bytes{name!=""}) / sum(machine_memory_bytes)
2.4.3 Docker磁盘相关指标
指标名称 | 指标类型 | 指标含义 |
container_fs_writes_b ytes_total | counter | 容器写⼊的总⼤⼩。 |
container_fs_reads_bytes_total | counter | 容器读取的总⼤⼩。 |
container_fs_writes_t otal | counter | 容器⾃启动以来的⽂件系统IO写操作的总次数。(IOPS) |
container_fs_reads_to tal | counter | 容器⾃启动以来的⽂件系统IO读操作的总次数。(IOPS) |
案例1:计算每个容器每秒的磁盘写⼊吞吐量。以MB为单位
# 进⼊nginx1容器执⾏:dd if=/dev/zero of=/bigdata bs=1M count=5000
sum(rate(container_fs_writes_bytes_total{name!=""}[1m])) by(instance,job,name) /1024 /1024
案例2:计算每个容器每秒的磁盘读取吞吐量。以MB为单位
# 进⼊nginx1容器执⾏:dd if=/bigdata of=/dev/null
sum(rate(container_fs_reads_bytes_total{name!=""}[1m])) by(instance,job,name) /1024 /1024
案例3:计算每个容器的每秒的读次数、写次数,也就是每秒的IOPS
sum(rate(container_fs_reads_total{name!=""}[1m])) by(instance,name)
sum(rate(container_fs_writes_total{name!=""}[1m])) by(instance,name)
2.4.4 Docker inode相关指标
指标名称 | 指标类型 | 指标含义 |
container_fs_inodes_free | gauge | 容器的空闲inode数量。 |
container_fs_inodes_total | gauge | 容器的inode总数。 |
案例1:计算inode已使⽤率,
计算公式:( (总的inode - 空闲的Inode ) / 总的inode ) * 100 )
(container_fs_inodes_total{name!=""} - container_fs_inodes_free{name!=""})/container_fs_inodes_total{name!=""} * 100
2.4.5 Docker⽹络相关指标
指标名称 | 指标类型 | 指标含义 |
container_network_transmit_bytes_total | counter | 容器⾃启动以来发送的⽹络流量的总量,以字节为单位 |
container_network_receive_bytes_total | counter | 容器⾃启动以来接收的⽹络流量的总量,以字节为单位。 |
案例1:查询每个容器“接收”的总流量⼤⼩,以MB为单位。(如果值太⼩,可以考虑使⽤ab模拟流量)
sum(container_network_receive_bytes_total{name!=""}) by(instance,name) /1024 /1024
案例2:查询每个容器⽹络“发送”的总流量⼤⼩,以MB为单位。(如果值太⼩,可以考虑使⽤ab模拟流量)
sum(container_network_transmit_bytes_total{name!=""}) by(instance,name) /1024 /1024
# 环⽐10分钟前的接收流量总⼤⼩⽐率 (当前流量-10分钟前流量) / 10分钟前流量 * 100
(sum(container_network_receive_bytes_total{name!=""}) - sum(container_network_receive_bytes_total{name!=""} offset 10m))
/ sum(container_network_receive_bytes_total{name!=""} offset 10m) * 100
案例3:查询每个容器⽹络每秒“接收”的⼤⼩除以1024,单位为KB/s(如果需要专为带宽兆⽐特Mbps,则需要 *8 /1024/1024)
sum(rate(container_network_receive_bytes_total{name!=""}[1m])) by (instance,job,name) / 1024
案例4:查询每个容器⽹络每秒“发送”的⼤⼩除以1024,单位为KB/s(如果需要专为带宽兆⽐特Mbps,则需要 *8 /1024/1024)
sum(rate(container_network_transmit_bytes_total{name!=""}[1m])) by (instance,job,name) / 1024
2.4.6 Docker其他相关指标
指标名称 | 指标类型 | 指标含义 |
container_tasks_state | gauge | 跟踪不同状态下的容器状态的数量,例如:(running、sleeping、stopped)等 |
container_start_time_seconds | gauge | 容器启动的时间戳,可以⽤来确定容器的运⾏时⻓。 |
container_last_seen | gauge | 容器最后⼀次被探测到的时间戳。 |
案例1:查询正在运⾏的容器数量
count(container_tasks_state{name!="",state="running"})
案例2:查询每个容器所运⾏的时⻓。
计算公式:( 当前时间减去 - 容器运⾏时⻓ / 3600 = 容器运⾏的⼩时 )
sum (time() - container_start_time_seconds{name!=""}) by (instance,name) / 3600
案例3:查询是否有容器被删除了、或停⽌运⾏了。
计算公式:(当前时间戳 - 容器上⼀次观测到的时间戳 > 60s 则表明容器可能被停⽌或删除)
sum (time() - container_last_seen{name!=""}) by (instance,name) > 60
2.5 Docker告警规则⽂件
2.5.1 告警规则⽂件
vim /app/module/prometheus/rules/docker_rules.yml
groups:
- name: Docker的告警规则
rules:
- alert: 容器CPU利用率高
expr: sum(rate(container_cpu_usage_seconds_total{name!=""}[1m])) by (instance,name) * 100 > 80
for: 1m
labels:
severity: warning
annotations:
summary: "实例{{ $labels.instance }}的容器{{ $labels.name }}CPU利用率高"
description: "容器{{ $labels.name }}的CPU利用率当前为{{ $value }}%,超过了80%的阈值。"
- alert: 容器内存利用率高
expr: |
sum(container_memory_working_set_bytes{name!=""}) by (instance,name) /
sum(container_spec_memory_limit_bytes{name!=""} > 0) by (instance,name) * 100 > 80
for: 1m
labels:
severity: warning
annotations:
summary: "实例{{ $labels.instance }}的容器{{ $labels.name }}内存利用率高"
description: 容器{{ $labels.name }}的内存最大限制是{{ printf `sum(container_spec_memory_limit_bytes{instance="%s",name="%s"}) /1024 /1024` $labels.instance $labels.name | query | first | value }}MB , 目前利用率已达{{ $value }}%,超过限制的80%。
- alert: 容器整体内存利用率高
expr: sum(container_memory_working_set_bytes{name!=""}) / sum(machine_memory_bytes) * 100 > 80
for: 1m
labels:
severity: warning
annotations:
summary: "所有容器的总内存利用率高"
description: "当前所有容器占用物理内存的总量为{{ $value }}%,超过了物理内存的80%阈值。"
- alert: 容器网络发送速率过高
expr: sum(rate(container_network_transmit_bytes_total{name!=""}[1m])) by (instance,job,name) * 8 / 1024 / 1024 > 50
for: 1m
labels:
severity: warning
annotations:
summary: "实例{{ $labels.instance }}的容器{{ $labels.name }}网络发送速率过高"
description: "容器{{ $labels.name }}的网络发送速率达到{{ $value }}Mbps,超过了50Mbps的阈值。"
- alert: 容器网络接收速率过高
expr: sum(rate(container_network_receive_bytes_total{name!=""}[1m])) by (instance,job,name) * 8 / 1024 / 1024 > 50
for: 1m
labels:
severity: warning
annotations:
summary: "实例{{ $labels.instance }}的容器{{ $labels.name }}网络接收速率过高"
description: "容器{{ $labels.name }}的网络接收速率达到{{ $value }}Mbps,超过了50Mbps的阈值。"
- alert: 容器停止时间过长
expr: sum(time() - container_last_seen{name!=""}) by (instance,name) > 60
for: 1m
labels:
severity: critical
annotations:
summary: "实例{{ $labels.instance }}的容器{{ $labels.name }}已停止"
description: "容器{{ $labels.name }}已停止运行超过60秒。当前停止时长 {{$value }}s"
2.5.2 检查rules语法
/app/module/prometheus/promtool check rules /app/module/prometheus/rules/docker_rules.yml
2.5.3 重新加载Prometheus
curl -X POST http://192.168.137.131:9090/-/reload
2.5.4 验证告警规则
2.5.5 模拟告警测试
# 启动容器,模拟内存满、然后退出容器模拟容器停⽌时间过⻓
docker stop nginx2
docker exec -it nginx1 /bin/bash
dd if=/dev/zero of=/dev/null bs=100M count=50000
2.6 导⼊Docker图形
导⼊⼀个Docker Container的Grafana模板。Dashboard ID为 11600