从 v2.20.0 开始,Prometheus 可以发现 Docker Swarm 集群中的目标。本指南演示如何使用该服务发现机制。
Docker Swarm 服务发现架构
Docker Swarm 服务发现包含 3 种不同的角色:nodes、services 和 tasks。
第一种角色 nodes 代表属于 Swarm 的主机。它可以用于自动监控运行在 Swarm 主机上的 Docker 守护进程或 Node Exporter。
第二种角色 tasks 代表在 Swarm 中部署的任何单独容器。每个 task 都会获得其关联的 service 标签。一个 service 可以由一个或多个 task 支撑。
第三种角色 services 将发现部署在 Swarm 中的服务。它会发现服务暴露的端口。通常你会更希望使用 tasks 角色而不是这个角色。
Prometheus 只会发现暴露端口的 tasks 和 services。
NOTE: 本文的其余部分假设你已经有一个正在运行的 Swarm。
设置 Prometheus
对于本指南,你需要设置 Prometheus。我们假设 Prometheus 运行在 Docker Swarm 管理节点上,并且可以通过 /var/run/docker.sock 访问 Docker socket。
监控 Docker 守护进程
让我们深入了解服务发现本身。
Docker 本身作为守护进程,暴露了可以被 Prometheus 服务器采集的指标。
你可以通过编辑 /etc/docker/daemon.json 并设置以下属性来启用它们:
{
"metrics-addr" : "0.0.0.0:9323",
"experimental" : true
}
你可以将 0.0.0.0 替换为 Docker Swarm 节点的 IP。
需要重启守护进程以使新配置生效。
Docker 文档包含了更多相关信息。
然后,你可以通过提供以下 prometheus.yml 文件来配置 Prometheus 抓取 Docker 守护进程:
scrape_configs:
# Make Prometheus scrape itself for metrics.
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# Create a job for Docker daemons.
- job_name: 'docker'
dockerswarm_sd_configs:
- host: unix:///var/run/docker.sock
role: nodes
relabel_configs:
# Fetch metrics on port 9323.
- source_labels: [__meta_dockerswarm_node_address]
target_label: __address__
replacement: $1:9323
# Set hostname as instance label
- source_labels: [__meta_dockerswarm_node_hostname]
target_label: instance
对于 nodes 角色,你也可以使用 dockerswarm_sd_configs 的 port 参数。不过,推荐使用 relabel_configs,因为它使 Prometheus 能够在相同的 Docker Swarm 配置之间复用相同的 API 调用。
监控容器
现在让我们在 Swarm 中部署一个服务。我们将部署 cadvisor,它暴露容器资源指标:
docker service create --name cadvisor -l prometheus-job=cadvisor \
--mode=global --publish target=8080,mode=host \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock,ro \
--mount type=bind,src=/,dst=/rootfs,ro \
--mount type=bind,src=/var/run,dst=/var/run \
--mount type=bind,src=/sys,dst=/sys,ro \
--mount type=bind,src=/var/lib/docker,dst=/var/lib/docker,ro \
google/cadvisor -docker_only
以下是用于监控它的最小 prometheus.yml 文件:
scrape_configs:
# Make Prometheus scrape itself for metrics.
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# Create a job for Docker Swarm containers.
- job_name: 'dockerswarm'
dockerswarm_sd_configs:
- host: unix:///var/run/docker.sock
role: tasks
relabel_configs:
# Only keep containers that should be running.
- source_labels: [__meta_dockerswarm_task_desired_state]
regex: running
action: keep
# Only keep containers that have a `prometheus-job` label.
- source_labels: [__meta_dockerswarm_service_label_prometheus_job]
regex: .+
action: keep
# Use the prometheus-job Swarm label as Prometheus job label.
- source_labels: [__meta_dockerswarm_service_label_prometheus_job]
target_label: job
让我们分析重新标记配置的每个部分。
- source_labels: [__meta_dockerswarm_task_desired_state]
regex: running
action: keep
Docker Swarm 通过 API 暴露 task 的期望状态。在我们的示例中,我们只保留应该正在运行的目标。这可以避免监控那些应该被关闭的 task。
- source_labels: [__meta_dockerswarm_service_label_prometheus_job]
regex: .+
action: keep
当我们部署 cadvisor 时,添加了一个标签 prometheus-job=cadvisor。由于 Prometheus 会获取 task 的标签,我们可以指示它只保留具有 prometheus-job 标签的目标。
- source_labels: [__meta_dockerswarm_service_label_prometheus_job]
target_label: job
最后一部分获取 task 的 prometheus-job 标签,并将其转换为目标标签,覆盖来自 scrape 配置的默认 dockerswarm job 标签。
已发现的标签
Prometheus 文档包含了完整的标签列表,以下是一些你可能会觉得有用的其他重新标记配置。
仅通过特定网络抓取指标
- source_labels: [__meta_dockerswarm_network_name]
regex: ingress
action: keep
仅抓取全局 task
全局 task 运行在每个守护进程上。
- source_labels: [__meta_dockerswarm_service_mode]
regex: global
action: keep
- source_labels: [__meta_dockerswarm_task_port_publish_mode]
regex: host
action: keep
为目标添加 docker_node 标签
- source_labels: [__meta_dockerswarm_node_hostname]
target_label: docker_node
连接到 Docker Swarm
上面的 dockerswarm_sd_configs 条目有一个 host 字段:
host: unix:///var/run/docker.sock
这使用的是 Docker socket。如果你更喜欢通过 HTTP 和 HTTPS 连接到 Swarm,Prometheus 提供了额外的配置选项。
结论
有许多发现标签可以帮助你更好地确定要监控哪些目标以及如何监控。对于 tasks,有超过 25 个可用标签。请查看 Prometheus 服务器上的 "Service Discovery" 页面(在 "Status" 菜单下)以查看所有已发现的标签。
服务发现不会对你的 Swarm 技术栈做任何假设,因此只要配置得当,它应该可以插入任何现有的技术栈。