第七章:服务发现

详细介绍 Prometheus 的多种服务发现机制,包括 Kubernetes、AWS、Azure、GCE、Consul 等

最后更新: 2024-01-01
页面目录

第七章:服务发现

7.1 服务发现概述

服务发现 (Service Discovery) 是 Prometheus 自动发现监控目标的关键机制,无需手动配置即可监控动态变化的基础设施。

7.1.1 为什么需要服务发现

传统方式 服务发现
手动维护 IP 列表 自动发现目标
扩展时需要更新配置 动态感知变化
无法处理故障转移 自动更新状态
难以管理大规模集群 适合云原生环境

7.1.2 支持的服务发现类型

┌─────────────────────────────────────────────────────────────┐
│                    Prometheus Service Discovery             │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │ Kubernetes  │  │    AWS      │  │   Azure     │         │
│  │   (K8s)     │  │  (EC2/ECS)  │  │  (VM/ACS)   │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│                                                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │    GCE      │  │   Consul    │  │    DNS      │         │
│  │ (Google)    │  │  (服务网格)  │  │  (域名)     │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│                                                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │   OpenStack  │  │   Docker    │  │   Eureka    │         │
│  │   (云平台)   │  │  (容器)      │  │  (服务注册)  │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│                                                              │
└─────────────────────────────────────────────────────────────┘

7.2 Kubernetes 服务发现

7.2.1 配置 Kubernetes SD

scrape_configs:
  # 监控 API Server
  - job_name: 'kubernetes-apiservers'
    kubernetes_sd_configs:
      - role: endpoints
        api_server: https://kubernetes.default.svc:443
        namespaces:
          names:
            - default
        tls_config:
          ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    scheme: https
    relabel_configs:
      - source_labels:
          - __meta_kubernetes_namespace
          - __meta_kubernetes_service_name
          - __meta_kubernetes_endpoint_port_name
        action: keep
        regex: default;kubernetes;https
      - target_label: __address__
        replacement: kubernetes.default.svc:443

7.2.2 Node 发现

  - job_name: 'kubernetes-nodes'
    kubernetes_sd_configs:
      - role: node
        api_server: https://kubernetes.default.svc:443
        tls_config:
          ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
        bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
    relabel_configs:
      # 替换节点地址
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
        replacement: /api/v1/nodes/${1}/proxy/metrics
        target_label: __metrics_path__
      - source_labels: [__meta_kubernetes_node_address_InternalIP]
        regex: (.+)
        replacement: ${1}:10250
        target_label: __address__

7.2.3 Pod 发现

  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod
        namespaces:
          names:
            - production
            - staging
    relabel_configs:
      # 保留带有 scrape 注解的 Pod
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true

      # 从注解获取路径
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)

      # 从注解获取端口
      - source_labels:
          - __address__
          - __meta_kubernetes_pod_annotation_prometheus_io_port
        action: replace
        regex: ([^:]+)(?::\d+)?;(\d+)
        replacement: $1:$2
        target_label: __address__

      # 标签映射
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)

      # 添加 namespace 标签
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace

      # 添加 pod name 标签
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name

7.2.4 Service 发现

  - job_name: 'kubernetes-services'
    kubernetes_sd_configs:
      - role: service
    relabel_configs:
      # 只抓取带注解的服务
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true

      # 从注解配置路径
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
        action: replace
        target_label: __metrics_path__
        regex: (.+)

      # 从注解配置端口
      - source_labels:
          - __meta_kubernetes_service_name
          - __meta_kubernetes_service_annotation_prometheus_io_port
        action: replace
        regex: ([^;]+);(\d+)
        replacement: $1:$2
        target_label: __address__

7.2.5 Endpoints 发现

  - job_name: 'kubernetes-endpoints'
    kubernetes_sd_configs:
      - role: endpoints
    relabel_configs:
      # 只保留带有 scrape=true 注解的 endpoints
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
        action: keep
        regex: true

      # 添加服务标签
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace

      - source_labels: [__meta_kubernetes_service_name]
        action: replace
        target_label: service

      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: pod

7.2.6 Kubernetes 常用元标签

元标签 说明
__meta_kubernetes_namespace Pod 所属命名空间
__meta_kubernetes_pod_name Pod 名称
__meta_kubernetes_pod_ip Pod IP 地址
__meta_kubernetes_node_name Node 名称
__meta_kubernetes_service_name Service 名称
__meta_kubernetes_endpoint_port_name Endpoint 端口名

7.3 AWS EC2 服务发现

7.3.1 基本配置

scrape_configs:
  - job_name: 'aws-ec2'
    ec2_sd_configs:
      - region: us-east-1
        access_key: AKIAIOSFODNN7EXAMPLE
        secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
        # 过滤器
        filters:
          - name: tag:Environment
            values:
              - production
          - name: instance-state-name
            values:
              - running
        # 刷新间隔
        refresh_interval: 60s
    relabel_configs:
      # 使用公有 IP
      - source_labels: [__meta_ec2_public_ip]
        regex: (.+)
        replacement: '${1}:9100'
        target_label: __address__
      # 添加实例 ID
      - source_labels: [__meta_ec2_instance_id]
        target_label: instance
      # 添加可用区
      - source_labels: [__meta_ec2_availability_zone]
        target_label: availability_zone
      # 只保留运行中的实例
      - source_labels: [__meta_ec2_instance_state]
        regex: running
        action: keep

7.3.2 IAM 角色认证

scrape_configs:
  - job_name: 'aws-ec2'
    ec2_sd_configs:
      - region: us-east-1
        # 使用实例 IAM 角色认证
        # 不需要配置 access_key 和 secret_key
        filters:
          - name: tag:Role
            values:
              - prometheus

7.4 Consul 服务发现

7.4.1 基本配置

scrape_configs:
  - job_name: 'consul-services'
    consul_sd_configs:
      - server: 'consul.example.com:8500'
        datacenter: dc1
        # 服务标签过滤
        services:
          - web
          - api
        tags:
          - prometheus
        # 刷新间隔
        refresh_interval: 30s
    relabel_configs:
      # 使用 Consul 地址
      - source_labels: [__meta_consul_address]
        target_label: __address__
      # 获取服务名
      - source_labels: [__meta_consul_service]
        target_label: service
      # 获取标签
      - source_labels: [__meta_consul_tags]
        target_label: tags
      # 移除空标签
      - regex: label:consul_(.+);;
        action: labeldrop

7.4.2 Consul 常用元标签

元标签 说明
__meta_consul_namespace Consul 命名空间
__meta_consul_service 服务名称
__meta_consul_service_address 服务地址
__meta_consul_service_port 服务端口
__meta_consul_tags 服务标签
__meta_consul_dc 数据中心

7.5 DNS 服务发现

7.5.1 A/AAAA 记录发现

scrape_configs:
  - job_name: 'dns-sd'
    dns_sd_configs:
      # A 记录
      - names:
          - 'targets.example.com'
          - 'api.example.com'
        type: A
        port: 9100
        refresh_interval: 30s
      # SRV 记录
      - names:
          - '_prometheus._tcp.example.com'
        type: SRV
        refresh_interval: 30s

7.5.2 SRV 记录配置

scrape_configs:
  - job_name: 'srv-records'
    dns_sd_configs:
      - names:
          - '_metrics._tcp.my-service.prod.svc.cluster.local'
        type: SRV
    relabel_configs:
      - source_labels: [__meta_dns_name]
        target_label: service
      - source_labels: [__meta_dns_port]
        target_label: port

7.6 文件服务发现

7.6.1 JSON 格式

scrape_configs:
  - job_name: 'file-sd'
    file_sd_configs:
      - files:
          - /etc/prometheus/targets/*.json
        refresh_interval: 30s
[
  {
    "targets": ["192.168.1.10:9100", "192.168.1.11:9100"],
    "labels": {
      "env": "production",
      "service": "web"
    }
  }
]

7.6.2 YAML 格式

- targets:
    - 192.168.1.20:9100
    - 192.168.1.21:9100
  labels:
    env: staging
    service: api

7.6.3 Prometheus API 格式

{
  "targets": [
    {
      "targets": ["192.168.1.30:9100"],
      "labels": {
        "instance": "server30"
      }
    }
  ]
}

7.7 组合多个服务发现

scrape_configs:
  - job_name: 'multi-sd'
    # 多个服务发现配置
    kubernetes_sd_configs:
      - role: pod
        namespaces:
          names:
            - production
    ec2_sd_configs:
      - region: us-east-1
        filters:
          - name: tag:Environment
            values:
              - production
    # 最终通过 relabel 合并
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_name]
        regex: (.+)
        target_label: pod_name
      - source_labels: [__meta_ec2_instance_id]
        regex: (.+)
        target_label: instance_id

7.8 服务发现最佳实践

7.8.1 标签设计

relabel_configs:
  # 标准化标签
  - action: labelmap
    regex: __meta_kubernetes_pod_label_(.+)
    replacement: ${1}

  # 添加环境标签
  - source_labels: [__meta_kubernetes_namespace]
    target_label: environment
    replacement: production

  # 添加集群标签
  - target_label: cluster
    replacement: prod-us-east-1

  # 保留必要标签
  - source_labels: [__meta_kubernetes_pod_name]
    target_label: pod

  - source_labels: [__meta_kubernetes_namespace]
    target_label: namespace

7.8.2 过滤策略

relabel_configs:
  # 保留特定标签
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
    action: keep
    regex: 'true'

  # 排除特定标签
  - source_labels: [__meta_kubernetes_namespace]
    action: drop
    regex: 'kube-system|monitoring'

  # 排除已标记为不监控的 Pod
  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
    action: drop
    regex: 'false'

7.8.3 性能优化

scrape_configs:
  - job_name: 'kubernetes-pods'
    kubernetes_sd_configs:
      - role: pod
        # 只监控特定命名空间
        namespaces:
          names:
            - production
            - staging
    # 减少 relabel 数量
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: 'true'

7.9 本章小结

本章介绍了 Prometheus 多种服务发现机制:

  1. 服务发现概述 - 为什么需要和优势
  2. Kubernetes SD - Pod、Node、Service、Endpoints 发现
  3. AWS EC2 SD - EC2 实例发现
  4. Consul SD - 服务网格发现
  5. DNS SD - DNS 记录发现
  6. 文件 SD - 静态文件配置
  7. 最佳实践 - 标签设计和性能优化

📖 下一步