背景
公司內部的API接口一般會分爲兩大類,一類是直接暴露在公網可以訪問的,一類是隻能在局域網內訪問的。
暴露在公網的一般就是業務網關以及一些和第三方公司有着某些合作,從而進行數據交互的接口。
檢查API接口是否存活,第一反應應該就是健康檢查了。
在局域網環境內搭配 nginx 或註冊中心之類的健康檢查機制,一定程度的保證了只有健康的實例纔會進行服務。
把這一塊放到公網環境,判斷一個API接口是否存活,情況就複雜很多了。
- 域名解析
- SSL證書
- 響應情況
- ...
舉個老黃待過的兩個公司的實際例子,這兩個公司遇到的都是SSL證書過期,沒有及時更換的問題,直接就是最高級故障。
在這種情況下,其實接口在局域網內是能正常訪問,可以理解成它是存活的,但是放到公網環境,用戶就是不能訪問到,這個時候對用戶來說就是故障的。
所以涉及到對外服務API存活的檢查,光一個簡單的健康檢查還是不夠的,還需要站在用戶的層面去考慮。
或許大家會說,這種事情不是運維負責的嗎?怎麼還要我們開發去操心?
這個很大程度是看團隊的,有的團隊都不一定有運維這個角色,都是開發搞定的。
另外,多豐富一點自己的技術棧和技術廣度並不是什麼壞事哈。
下面就簡單介紹一下老黃的處理方案吧。
處理方案
老黃這邊選擇的處理方案是 【Prometheus + Blackbox + Grafana + Alertmanager + PrometheusAlert】
Prometheus,Grafana 和 Alertmanager 這三個就不過多的介紹了。
下面主要介紹一下 Blackbox 和 PrometheusAlert:
Blackbox 是 Prometheus 官方提供的一種黑盒監測方案,也是本文一個最關鍵的點。
下面是一些常見的應用場景
- HTTP 測試,定義 Request Header 信息,判斷 Http status / Http Respones Header / Http Body 內容
- TCP 測試, 業務組件端口狀態監聽,應用層協議定義與監聽
- ICMP 測試,主機探活機制
- POST 測試,接口聯通性
- SSL 證書過期時間
PrometheusAlert 是開源的運維告警中心消息轉發系統,支持主流的監控系統Prometheus、Zabbix,日誌系統Graylog2,Graylog3、數據可視化系統Grafana、SonarQube等支持WebHook接口的系統發出的預警消息,支持將收到的這些消息發送到釘釘,微信,飛書,騰訊短信,騰訊電話,阿里雲短信,阿里雲電話,華爲短信,容聯雲電話等。
換句話就是說,把告警消息通過 PrometheusAlert 發送個體企業微信機器人或釘釘機器人。
整個鏈路大概是這樣的:
- BlackBox 負責探測
- Prometheus 主動 pull 探測的結果並進行存儲
- Prometheus 根據告警規則進行評估,將告警仍到 AlertManager
- AlertManager 收到 Prometheus 的消息後,通知給 PrometheusAlert
- PrometheusAlert 收到 AlertManager 的消息後,通知到對應的端
實戰
下面先用 docker 啓動一個 blackbox-exporter 實例
docker run -d \
-p 13002:9115 \
--name=blackbox \
--restart=always \
prom/blackbox-exporter:v0.19.0
運行後看到的大概就是這個樣子。
這一塊的配置基本不用變更,用默認的即可,主要的配置還是在 Prometheus 那邊。
可以點擊上圖的 Configuration 去看默認的配置。
下面就去調整 Prometheus 的配置。
這裏只以 http 檢測爲例來說明。
global:
scrape_interval: 30s
evaluation_interval: 30s
alerting:
alertmanagers:
- static_configs:
- targets:
- xxx.xxx.xxx.xxx:13005
rule_files:
- "/prometheus/blackbox_rules/*.yml"
scrape_configs:
- job_name: 'outer'
metrics_path: "/probe"
params:
module: [http_2xx] # 模塊對應 blackbox.yml
file_sd_configs:
- files: ['/prometheus/blackbox_configs/outer/*.yml']
refresh_interval: 10s
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: xxx.xxx.xxx.xxx:13002 # blackbox安裝在哪臺機器
其中 scrape_configs
裏面是最爲重要的,一個是 params ,一個是 relabel_configs, 一個是 file_sd_configs。
剩下的就是一些常規配置了。
然後是 file_sd_configs 裏面一堆可以變化的 yml 文件,也就是那些對外的域名要進行 http 檢測的。
- targets: [ 'https://xxx.xxxxx.com' ]
labels:
domain: xxxxxxxx
env: xx雲-公網
service: 網關
ip: xxxxxxxx
配置裏面的 labels 是一些輔助信息,可以按需添加,可以在 grafana 裏面進行展示的。
到這裏,關於 blackbox 的配置基本就差不多了。
接下來是在 grafana 裏面展示,看一下結果。
PS: 這裏用的是 【9965】 這個模板。
面板雖然好看,但是我們不能每時每刻都在盯着這個面板的,所以還是離不開告警這一監控領域的大頭。
下面是告警規則的配置
groups:
- name: 服務探測
rules:
- alert: BlackboxProbeFailed
expr: probe_success == 0
for: 0m
labels:
severity: critical
team: node
annotations:
summary: Blackbox probe failed (instance {{ $labels.instance }})
description: "服務在線檢查失敗\n當前值= {{ $value }}\nIp = {{ $labels.ip }}\nDomain= {{ $labels.domain }}\nEnv= {{ $labels.env }}\n服務名= {{ $labels.service }}"
- alert: BlackboxProbeHttpFailure
expr: probe_http_status_code <= 199 OR probe_http_status_code >= 400
for: 0m
labels:
severity: critical
team: node
annotations:
summary: Blackbox probe HTTP failure (instance {{ $labels.instance }})
description: "HTTP狀態碼不在200-399\n當前值= {{ $value }}\nIp = {{ $labels.ip }}\nDomain= {{ $labels.domain }}\nEnv= {{ $labels.env }}\n服務名= {{ $labels.service }}"
- alert: BlackboxSslCertificateWillExpireSoon
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 30
for: 0m
labels:
severity: warning
annotations:
summary: Blackbox SSL certificate will expire soon (instance {{ $labels.instance }})
description: "SSL certificate expires in 30 days\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
上面這個主要是3個告警規則,看描述就知道它的作用的,也不用過多的說明了,這些告警表達式是參考 Awesome Prometheus alerts 調整的。
再下一步就到告警消息的配置了。
先用 docker 啓動一個 prometheus-alert 的實例
docker run -d -p 13006:8080 \
-v /data/prom-alert/conf:/app/conf \
-v /data/prom-alert/db:/app/db \
-v /data/prom-alert/logs:/app/logs \
--name prom-alert \
-e TZ=Asia/Shanghai \
--restart=always \
feiyu563/prometheus-alert:v-4.4.3
這裏默認帶了很多模板
這裏選擇自己定義一個告警模板
{{ $var := .externalURL}}{{ range $k,$v:=.alerts }}
{{if eq $v.status "resolved"}}
#### [Prometheus恢復信息]({{$v.generatorURL}})
> <font color="info">告警名稱</font>:[{{$v.labels.alertname}}]({{$var}})
> <font color="info">告警級別</font>:{{$v.labels.severity}}
> <font color="info">開始時間</font>:{{GetCSTtime $v.startsAt}}
> <font color="info">結束時間</font>:{{GetCSTtime $v.endsAt}}
> <font color="info">實例地址</font>:{{$v.labels.instance}}
> <font color="info">主機名稱</font>:{{$v.labels.hostname}}
**{{$v.annotations.description}}**
{{else}}
#### [Prometheus告警信息]({{$v.generatorURL}})
> <font color="#FF0000">告警名稱</font>:[{{$v.labels.alertname}}]({{$var}})
> <font color="#FF0000">告警級別</font>:{{$v.labels.severity}}
> <font color="#FF0000">開始時間</font>:{{GetCSTtime $v.startsAt}}
> <font color="#FF0000">結束時間</font>:{{GetCSTtime $v.endsAt}}
> <font color="#FF0000">實例地址</font>:{{$v.labels.instance}}
> <font color="#FF0000">主機名稱</font>:{{$v.labels.hostname}}
**{{$v.annotations.description}}**
{{end}}
{{ end }}
這裏的模板是做了一個顏色的區分,告警的用紅色,恢復的用綠色,由於 Prometheus 和 AlertManager 用的都是 UTC 時間,所以這裏用 GetCSTtime 轉化成北京時間。
最後是回到 alertmanager 裏面去配置
global:
resolve_timeout: 5m
route:
receiver: 'default-receiver'
group_wait: 30s
group_interval: 1m
repeat_interval: 5m
group_by: [alertname]
routes:
- receiver: 'blackbox-webhook-outer'
group_wait: 10s
continue: false
match_re:
job: outer
receivers:
- name: 'default-receiver'
webhook_configs:
- url: 'http://xxxxxx:13006/prometheusalert?type=wx&tpl=prometheus-wx&wxurl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxx'
- name: 'blackbox-webhook-outer'
webhook_configs:
# 這裏的url 是配置的 PrometheusAlert 自定義模板管理裏面的路徑
- url: 'http://xxxxxx:13006/prometheusalert?type=wx&tpl=blackbox_alert&wxurl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxx'
最後來看一些實際告警和恢復的例子
其他
如果不想考慮自己搭建的話,不少雲產商也有提供類似的功能,好比阿里雲有一個叫站點監控的產品也可以幫我們搞定這個問題,不過只能免費一個月,超過還是需要購買的。
小結
API接口存活的檢查其實也是一門不小的學問,考慮的內容還是不少的。經歷過生產事故,所以對這一塊會特別看重。
目前中小團隊的監控體系應該是離不開事實標準的 Prometheus,所以在其基礎上去拓展會有比較多成熟的可以借鑑的經驗來落地。