You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让全局模式Docker Swarm服务在同一主机直接通信?

解决Docker Swarm中全局Prometheus抓取同节点Promtail指标的问题

问题根源

  1. Swarm默认服务发现(如promtail:9080)会随机路由到任意节点的Promtail实例,无法保证同节点抓取
  2. 同时使用host网络和Swarm overlay网络会触发报错,因为容器不能同时共享主机网络命名空间和连接其他网络

方案一:纯Host网络部署(最简单直接)

直接让两个服务都使用主机网络,完全避免跨节点路由:

  1. 修改Promtail部署配置,仅使用host网络:
    services:
      promtail:
        image: grafana/promtail:latest
        deploy:
          mode: global
        network_mode: host
        command: -config.file=/etc/promtail/config.yml
        volumes:
          - ./promtail-config.yml:/etc/promtail/config.yml
          - /var/log:/var/log
          - /var/lib/docker/containers:/var/lib/docker/containers:ro
        # host网络下无需单独暴露端口,直接使用主机的9080端口
    
  2. 修改Prometheus部署配置,同样使用host网络,抓取本地端口:
    services:
      prometheus:
        image: prom/prometheus:latest
        deploy:
          mode: global
        network_mode: host
        volumes:
          - ./prometheus-config.yml:/etc/prometheus/prometheus.yml
          - prometheus-data:/prometheus
    
  3. 在Prometheus配置文件中,将抓取目标设为localhost:9080/metrics
    scrape_configs:
      - job_name: 'promtail'
        static_configs:
          - targets: ['localhost:9080']
    
    这样每个节点的Prometheus只会抓取本机的Promtail实例,彻底解决跨节点路由问题。

方案二:保留Overlay网络,通过Relabeling过滤同节点目标

如果不想使用host网络,可借助Swarm服务元数据和Prometheus的relabel规则实现精准匹配:

  1. 给Promtail和Prometheus配置相同的Swarm overlay网络:
    networks:
      monitoring:
        driver: overlay
        attachable: true
    
    services:
      promtail:
        image: grafana/promtail:latest
        deploy:
          mode: global
        networks:
          - monitoring
        ports:
          - 9080:9080
        # 其他卷、命令配置...
    
      prometheus:
        image: prom/prometheus:latest
        deploy:
          mode: global
        networks:
          - monitoring
        environment:
          # 注入当前节点的主机名作为环境变量
          - POD_NODE_NAME={{.Node.Hostname}}
        volumes:
          - ./prometheus-config.yml:/etc/prometheus/prometheus.yml
    
  2. 修改Prometheus的抓取配置,通过DNS服务发现获取所有Promtail实例,再过滤同节点目标:
    scrape_configs:
      - job_name: 'promtail'
        dns_sd_configs:
          - names: ['tasks.promtail']
            type: 'A'
            port: 9080
        relabel_configs:
          # 从Swarm元数据中提取Promtail所在节点的名称
          - source_labels: [__meta_docker_swarm_node_name]
            target_label: promtail_node
          # 将Prometheus自身的节点名注入标签
          - source_labels: [__env_POD_NODE_NAME]
            target_label: prometheus_node
          # 只保留节点名匹配的目标
          - action: keep
            source_labels: [promtail_node, prometheus_node]
            regex: '(.+);\1'
    
    这个方案依赖Swarm的服务元数据传递,确保每个Prometheus实例只抓取和自己同节点的Promtail。

内容的提问来源于stack exchange,提问作者jah

火山引擎 最新活动