docker swarm 部署 prometheus 监控

使用 prometheus 同时监控 docker swarm 集群的多个 stock
news
prometheus
docker swarm
Author

lastnumber

Published

April 8, 2024

docker swarm 使用 prometheus 监控集群状态

背景

想要使用 prometheus 监控 docker swarm 的集群以及集群中的容器,按照 prometheus 官方的文档实现的话,需要将所有容器的端口都暴露出来,出于安全和维护得考虑我并不想把所有的容器端口都暴露到容器集群之外,而是只使用一个代理服务暴露出来。通过服务名称在集群内通信。关于这部分网络通信可以查看 docker swarm 网络相关文档。这里引用一段关于 overlay 网络的说明。

overlay: Overlay networks connect multiple Docker daemons together and enable Swarm services and containers to communicate across nodes. This strategy removes the need to do OS-level routing. See Overlay network driver.

overlay: 覆盖网络将多个 Docker 守护进程连接在一起,并使 Swarm 服务和容器能够跨节点通信。此策略消除了进行操作系统级路由的需要。

由于网络的限制,prometheus 不能从外部访问 docker swarmoverlay 网络,prometheus 无法在外部访问应用端口,所以需要将 prometheus 部署对应的 stack 环境并加入到 ingress 网络,这样就能在内部通过 vip 或者 service name 访问容器。

prometheus 官方并没有提供关于这个的最佳解决方案,所以才有了本篇文章。

打开 docker 采集端口

以下是我在官方关于 docker swarm 服务发现的配置基础上做了部分改进。建议先查看 prometheus 官方文档再看以下部分,可以帮助理解。

  1. 修改 /etc/docker/daemon.json 添加配置:
{
  "metrics-addr": "0.0.0.0:9323",
  "experimental": true
}

也可以配置 ip 地址而不是 0.0.0.0

  1. 重启 docker 守护进程
$ systemctl restart docker
注意
  • 需要集群中所有 docker 节点打开 9323 端口
  • 需要打开服务器防火墙

在 docker swarm 创建 configs

我们需要将 prometheus 的配置挂载到容器外的宿主机上,这里有两种方式可以使用:

  1. 只读方式挂载到宿主机本地磁盘
  2. 使用 docker config 方式配置到容器的配置列表。

这里采用里的 2 的方式,这样便于从容器相关可视化页面查看,例如: portainer

docker swarm manager节点 创建 prometheus.yml 文件:

# my global config
global:
  scrape_interval: 1m # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 1m # Evaluate rules every 15 seconds. The default is every 1 minute.
  scrape_timeout: 10s # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093
          
scrape_configs:
1  - job_name: "dockerswarm"
2    dockerswarm_sd_configs:
      - host: unix:///var/run/docker.sock
        role: nodes
    relabel_configs:
3      - source_labels: [__meta_dockerswarm_node_address]
        target_label: __address__
        replacement: $1:9323
4      - source_labels: [__meta_dockerswarm_node_hostname]
        target_label: instance

5  - job_name: 'dockertasks'
    metrics_path: /actuator/prometheus
    dockerswarm_sd_configs:
      - host: unix:///var/run/docker.sock
        role: tasks
    relabel_configs:
      # Only keep containers that should be running.
6      - source_labels: [__meta_dockerswarm_task_desired_state]
        regex: running
        action: keep
7      - source_labels: [__meta_dockerswarm_container_label_com_docker_stack_namespace]
        regex: dev
        action: keep
8      - source_labels: [__meta_dockerswarm_container_label_external_metrics_enable]
        regex: true
        action: keep
9      - source_labels: [__address__]
        target_label: __address__
        regex: '(.+):.*'
        replacement: $1:8080
10      - source_labels: [__meta_dockerswarm_service_label_com_docker_stack_namespace]
        target_label: namespace
11      - source_labels: [__meta_dockerswarm_service_name]
        target_label: serviceName
12      - source_labels: [__meta_dockerswarm_service_name]
        target_label: application
13      - source_labels: [__meta_dockerswarm_task_id]
        target_label: instance
1
job_name:"dockerswarm": docker swarm 节点监控
2
dockerswarm_sd_configs: 使用 prometheus 内置支持的 dockerswarm 服务发现配置 ;host: 配置 unix:///var/run/docker.sock 访问 docker 的守护进程 ;role: 配置为 node 用于访问表示监控 docker swarm 节点
3
__meta_dockerswarm_node_address: 使用 docker swarm 节点地址替换 __address label
4
__meta_dockerswarm_node_hostname: 使用 docker swarm hostname 替换 instance label
5
job_name: 'dockertasks': docker task 监控, 监控容器
6
dockerswarm_sd_configs: 同样使用 docker swarm 服务发现配置 ;host: 配置 unix:///var/run/docker.sock 访问 docker 的守护进程 ;role: 配置为 tasks 用于访问表示监控 docker swarm 运行的容器
7
__meta_dockerswarm_task_desired_state: 过滤容器运行状态要保持容器状态微 running
8
__meta_dockerswarm_container_label_com_docker_stack_namespace: 容器运行的命名空间, 对应的是 docker swarm 中的 stock , namespacek8s 中不同环境之间隔离的划分名称, 这里过滤掉 stockdev
9
__meta_dockerswarm_container_label_external_metrics_enable: 过滤开启了监控的容器
10
__address__: 替换默认监控容器的端口, 我习惯上使用容器内的 8080 端口作为服务的默认访问端口, 可以根据跟人习惯修改
11
__meta_dockerswarm_service_label_com_docker_stack_namespace: 使用 stack 替换 namespace
12
__meta_dockerswarm_service_name: 使用docker swarm的服务名称替换掉 applicationserviceName label
13
__meta_dockerswarm_task_id: 使用 task_id 替换掉 instance

docker_compose.yml 配置

创建 docker_compose.yml 文件:

$ vim docker_compose.yml

写入以下配置:

version: "3.5"

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
1    user: root
    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
2          - node.role == manager
    networks:
      - overlay
    configs:
3      - source: prometheus_config
        target: /etc/prometheus/prometheus.yml
    command:
4      - '--config.file=/etc/prometheus/prometheus.yml'
    volumes:
5      - /var/run/docker.sock:/var/run/docker.sock:ro

configs:
  prometheus_config:
6    file: ./prometheus.yml

networks:
  overlay:
1
user:root: 使用 root 用户创建容器,因为需要监听 docker.sock
2
node.role == manager: 设置角色为 manager, 因为需要将 prometheus 容器运行在 docker swarm 的主节点上
3
prometheus_config: 是上一步设置的 docker config 名称
4
config.file=/etc/prometheus/prometheus.yml: 设置 prometheus 启动时使用的命令
5
/var/run/docker.sock:/var/run/docker.sock:ro: 挂载 docker 的守护进程
6
configs: 对应 <3> 的配置设置, 指定使用当前启动 docker_compose.yml 文件的相对路径下的 prometheus.yml

在 docker swarm 集群部署

在目标 stack 环境部署 prometheus

$ docker stack deploy -c docker_compose.yml {stack}
注意

如果是多套 stock 环境则必须每个 stock 中都要部署 prometheus 用于监控, 这是因为 docker swarm 默认的 overlay 网络之间不能互相通信. 同时每个容器只能配置唯一的 overlay 网络