如何使用 Blackbox Exporter 監控 URL?

東風微鳴發表於2022-12-31

前言

監控域名和 URL 是可觀察性的一個重要方面,主要用於診斷可用性問題。接下來會詳細介紹如何使用 Blackbox Exporter 和 Prometheus 在 Kubernetes 中實現 URL 監控。

Blackbox Exporter 簡介

Blackbox Exporter 是 Prometheus 的一個可選元件,像其他 Exporter 一樣, 主要用於將監控資料轉換為 Prometheus 可理解的指標格式,即 Prometheus exposition format

Endpoint 監控

Endpoint 監控是指監控內部和外部 Endpoint(HTTP/S、DNS、TCP、ICMP 和 grpc)的各種引數,包括 HTTP 響應時間、DNS 查詢延遲、SSL 證書過期資訊、TLS 版本等等。

在 Kubernetes 中,不僅僅是外部 Endpoint 需要被監控,內部 Endpoint 也需要被監控響應時間和其他引數。這些指標是基礎設施的一個重要部分,以確保服務的連續性、可用性和符合一些安全認證。

白盒(WhiteBox)與黑盒(Blackbox)監控

白盒監控是指對系統內部的監控,包括應用 logging、handlers、tracing 和 metrics。與之相對,黑盒監控主要從外部發起探測,探測影響使用者的行為,如伺服器停機、頁面不工作或網站效能下降。

Blackbox Exporter

Blackbox Exporter 用於探測 HTTPS、HTTP、TCP、DNS、ICMP 和 grpc 等 Endpoint。在你定義 Endpoint 後,Blackbox Exporter 會生成指標,可以使用 Grafana 等工具進行視覺化。Blackbox Exporter 最重要的功能之一是測量 Endpoint 的可用性。

下圖顯示了 Blackbox Exporter 監控一個 Endpoint 的流程:

blackbox exporter 流程圖

Blackbox Exporter 安裝和配置

使用 Helm 安裝 Blackbox Exporter

Blackbox Exporter 的安裝很簡單,可以透過 Helm Chart 安裝:

# 新增 repo
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# Install chart
helm install [RELEASE_NAME] prometheus-community/prometheus-blackbox-exporter

?

Blackbox 基本配置

下面是 Blackbox Exporter 配置中定義的一個預設模組:

blackbox.yaml:

modules:
  http_2xx:
    prober: http
    timeout: 15s  
    http:
      fail_if_not_ssl: true
      ip_protocol_fallback: false
      method: GET
      follow_redirects: true
      preferred_ip_protocol: ip4
      valid_http_versions:
        - HTTP/1.1
        - HTTP/2.0
      valid_status_codes:
        - 200
        - 204

你可以相應地配置你自己的blackbox.yml,使探針 (probe) 根據你的配置返回成功/失敗。以上面配置為例,詳細說明下 modulehttp probe 的配置:

  • prober: 探測的協議(可以是:http, tcp, dns, icmp, grpc)。
  • timeout: 探測超時時間。
  • http: http probe

接下來是 http probe 的配置:

  • valid_status_codes: <int>, ... | default = 2xx: 該 Probe 可接受的狀態碼。預設為 2xx。建議使用預設值。
  • valid_http_versions: 該 Probe 接受的 http 版本。可選值:HTTP/1.1 HTTP/2.0
  • method: <string> | default = "GET": probe 使用的 http method
  • headers: probe 使用的 header, 比如可以加一些 user-agent 之類的 header 避免被 WAF 攔截
  • body_size_limit: <size> | default = 0 將被處理的最大未壓縮的主體長度(位元組)。值為 0 意味著沒有限制。
  • compression: 用於解壓響應的壓縮演算法(gzip、br、deflate、ident)。
  • follow_redirects: <boolean> | default = true: 是否 follow 重定向
  • fail_if_ssl: 如果存在 SSL,則探測失敗
  • fail_if_not_ssl: 如果不存在 SSL, 則探測失敗
  • fail_if_body_matches_regexp: 如果返回的 body 匹配該正則則失敗
  • fail_if_body_not_matches_regexp: 如果返回的 body 不匹配該正則則失敗
  • fail_if_header_matches: 如果返回的 header 匹配該正則,則失敗。對於有多個值的 header,如果至少有一個符合,則失敗。
  • fail_if_header_not_matches: 如果返回的 header 不匹配該正則,則失敗。
  • tls_config: HTTP probe 的 TLS 協議配置,常用於私人證書。
  • basic_auth: 目標的 HTTP basic auth 憑證。
  • bearer_token: <secret>: 模板的 bearer token.
  • proxy_url 用於連線到目標的 proxy server 的配置
  • skip_resolve_phase_with_proxy 當設定了 HTTP 代理(proxy_url)時,跳過 DNS 解析和 URL 變更。
  • oauth2 用於連線到模板的 OAuth 2.0 配置
  • enable_http2 是否啟用 http2
  • preferred_ip_protocol HTTP probe 的 IP 協議 (ip4, ip6)
  • ip_protocol_fallback
  • body probe 中使用的 HTTP 請求的主體。

你可以檢視這個 example.yml 中的詳細例子,瞭解更多情況。另外還需要在 Prometheus 做一些配置上的改變,Blackbox Exporter 才會傳送與應用的配置相關的指標。

Prometheus 中的配置

需要在 Prometheus 裡配置 scrape 的配置,以及 Blackbox 相關的 Alert Rules.

Blackbox 的 Prometheus Scrape 配置

示例如下:

scrape_configs:
  - job_name: blackbox-exporter
    params:
      module:
        - http_2xx
    scrape_interval: 1m
    scrape_timeout: 10s
    metrics_path: /probe
    scheme: http
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: prometheus-blackbox-exporter.monitoring:9115
        action: replace
    static_configs:
      - targets:
          - https://ewhisper.cn
          - https://www.ewhisper.cn
          - https://rancher.ewhisper.cn
        labels:
          domain: ewhisper
          environment: test
          cluster: home-k3s

這樣直接改 Prometheus 的配置是比較容易出錯的,如果你已經安裝了 Prometheus Operator, 則可以直接透過 probe CRD 來配置,非常方便:

apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
  name: ewhisper
  namespace: monitoring
spec:
  jobName: http-get
  interval: 60s
  module: http_2xx
  prober:
    url: prometheus-blackbox-exporter.monitoring:9115
    scheme: http
    path: /probe
  targets:
    staticConfig:
      static:
      - targets:
          - https://ewhisper.cn
          - https://www.ewhisper.cn
          - https://rancher.ewhisper.cn
        labels:
          domain: ewhisper
          environment: test
          cluster: home-k3s

Blackbox Exporter 探測場景

單論 URL, 總結起來,Blackbox Exporter 有以下探測場景:

  1. 探測外部 URL
  2. 探測 K8S 叢集內部 service
  3. 探測 K8S 叢集內部 Ingress
  4. 探測 K8S 叢集內部 Pod

場景一:探測外部 URL

配置 上面 已經提過,這裡就不在贅述。

場景二:探測 K8S 叢集內部 service

在 Kubernetes 系統中,資源和 Endpoint 會隨著時間的推移而出現和消失,可以非常有用的探測是對資源的動態探測,包括 pods、service 和 ingress。

在 Prometheus 中使用 Kubernetes 服務發現配置,我們可以實現 Endpoint 的動態探測。Kubernetes 服務發現配置允許從 Kubernetes 的 API 中獲取刮削目標,並始終與叢集狀態保持同步。你可以在文件的 kubernetes_sd_config 部分找到可以配置為發現目標的可用角色列表。

kubernetes_sd_configs:
  - role: service
    metrics_path: /probe
    params:
      module:
      - http_2xx
    relabel_configs:
    - action: keep
      regex: true
      source_labels:
      - __meta_kubernetes_service_annotation_prometheus_io_probe
    - source_labels:
      - __address__
      target_label: __param_target
    - replacement: prometheus-blackbox-exporter.monitoring:9115
      target_label: __address__
    - source_labels:
      - __param_target
      target_label: instance
    - action: labelmap
      regex: __meta_kubernetes_service_label_(.+)
    - source_labels:
      - __meta_kubernetes_namespace
      target_label: kubernetes_namespace
    - source_labels:
      - __meta_kubernetes_service_name
      target_label: kubernetes_name

這裡我們可以使用[__meta_kubernetes_service_annotation_prometheus_io_probe]來只檢查那些有prometheus.io/probe = true註釋的服務,示例如下:

➜ kubectl describe svc nginx
...
Annotations:              prometheus.io/probe: true
...

場景三:探測 K8S 叢集內部 Ingress

    - job_name: "blackbox-kubernetes-ingresses"
      metrics_path: /probe
      params:
        module: [http_2xx]
      kubernetes_sd_configs:
      - role: ingress
      relabel_configs:
      # 示例重新標記,只探測有 "prometheus.io/probe = true"註釋的一些接入點。
      #  - source_labels: [__meta_kubernetes_ingess_annotation_prometheus_io_probe]
      #    action: keep
      #    regex: true
        - source_labels:
            [
              __meta_kubernetes_ingress_scheme,
              __address__,
              __meta_kubernetes_ingress_path,
            ]
          regex: (.+);(.+);(.+)
          replacement: ${1}://${2}${3}
          target_label: __param_target
        - target_label: __address__
          replacement: prometheus-blackbox-exporter.monitoring:9115
        - source_labels: [__param_target]
          target_label: instance
        - action: labelmap
          regex: __meta_kubernetes_ingress_label_(.+)
        - source_labels: [__meta_kubernetes_namespace]
          target_label: kubernetes_namespace
        - source_labels: [__meta_kubernetes_ingress_name]
          target_label: ingress_name

場景四:探測 K8S 叢集內部 Pod

    - job_name: "blackbox-kubernetes-pods"
      metrics_path: /probe    
      params:
        module: [http_2xx]
      kubernetes_sd_configs:
      - role: pod        
      relabel_configs:
      # 示例重新標記,只探測有
      # "prometheus.io/probe = true"註釋的 pod。
      #  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_probe]
      #    action: keep
      #    regex: true
        - source_labels: [__address__]
          target_label: __param_target
        - target_label: __address__
          replacement:  prometheus-blackbox-exporter.monitoring:9115
        - source_labels: [__param_target]
          replacement: ${1}/health
          target_label: instance          
        - action: labelmap
          regex: __meta_kubernetes_pod_label_(.+)
        - source_labels: [__meta_kubernetes_namespace]
          target_label: kubernetes_namespace
        - source_labels: [__meta_kubernetes_pod_name]
          target_label: kubernetes_pod_name     

在 Prometheus 驗證生成的指標

Blackbox Alert

一旦更改被 apply,Blackbox Exporter 的資源被部署,我們可以在 Prometheus 中驗證目標的狀態。我們可以透過跳轉到狀態選項卡,然後在 Prometheus UI 中選擇 targets,來檢查 Blackbox Exporter 是否與註冊的目標一起啟動。

在這裡你可以看到我們使用https://rancher.ewhisper.cn作為外部目標來參考,其狀態是 404。我們還可以透過尋找以probe_開頭的指標來檢查指標是否被收集。

Prometheus probe metrics

在這裡你可以看到一些生成的probe_ 的指標列表。

指標名 功能
probe_duration_seconds 返回探針完成的時間(秒)。
probe_http_status_code 響應 HTTP 狀態程式碼
probe_http_version 返回探針響應的 HTTP 版本
probe_success 顯示探測是否成功
probe_dns_lookup_time_seconds 返回探測 DNS 的時間,單位是秒。
probe_ip_protocol 指定探針 IP 協議是 IP4 還是 IP6
probe_ssl_earliest_cert_expiry metric 返回以 unixtime 為單位的最早的 SSL 證書到期時間
probe_tls_version_info 包含所使用的 TLS 版本
probe_failed_due_to_regex 表示探測是否因 regex 匹配而失敗
probe_http_content_length HTTP 內容響應的長度

使用 Grafana 監控配置的 URL

可以直接複用 Grafana 上的一些 Dashboard, 檢視 URL 的指標:

dashboard

dashboard

點這裡?Blackbox Grafana 搜尋和下載對應的 Grafana Dashboard.

Blackbox 的優勢梳理

  1. 開源免費的 Blackbox Endpoint 監控工具;
  2. 除了 HTTP/S, 還支援 DNS、TCP、ICMP 和** grpc**
  3. 豐富的 HTTP 黑盒監控配置,如 Header、認證、代理、正則匹配等。
  4. 利用 Prometheus + Kubernetes 的 kubernetes_sd_config 功能動態地產生指標,並可用於動態 Endpoint 監控。
  5. 可以監控證書過期時間。

Blackbox Exporter 的行業應用場景

為什麼需要 Blackbox Exporter?

以我所熟悉的保險行業為例,大中型保險公司,都是採用類似:

  • 總部
  • 省級分公司
  • 中心支公司
  • 中公司
  • 營業部

這樣的組織形式。分支機構往往是透過專線和總部連線,並使用總部提供的各類保險業務系統。

雖然國內外有各種工具和服務可用於監控域名和 URL, 如 聽雲、Dynatrace 等。但是

  • 一方面,服務是按探測次數收費的,如果探測頻率、探測 URL 過多,價格不低的;
  • 另一方面,這些商業化服務可能無法覆蓋保險行業這種近乎內網的網路架構。

在這種情況下,Blackbox Exporter 是現有解決方案的一個開源替代品,由 Prometheus 社群維護。

而且,Prometheus + Blackbox Exporter + Kubernetes 動態發現,可以大大減少人工配置大量 URL 探測的工作。

另外,針對上面提到的情況, 也可以使用 Prometheus + Blackbox Exporter + 輕量級 K8s 解決方案如 K3s, 將 probe 節點部署到各個分支機構,實現和分支機構員工完全相同的訪問路徑。分支-總部各系統網路可用性一目瞭然,及時發現分支-總部各系統網路問題。

總結

透過本文,我們討論了:

  • 什麼是 Blackbox Exporter
  • 如何安裝和配置它
  • 幾種典型的配置場景,特別是利用 Prometheus + Blackbox Exporter + Kubernetes 動態發現
  • Blackbox Exporter 優勢
  • Blackbox Exporter 的行業應用場景

希望對各位讀者有所幫助。

???

?️ Reference

相關文章