个人网站我一般使用 Let’s Encrypt 的免费 CA 证书,当网站一多管理这些证书就显得比较麻烦,所以我非常希望有一个工具,能够将这些域名服务状态都列出来,包括证书过期时间、访问延迟、以及请求状态码等。
恰好上周看到 Grafana Labs 的一篇博客 How we eliminated service outages from ‘certificate expired’ by setting up alerts with Grafana and Prometheus 中讲到了使用 Grafana 的 表格视图来展示域名证书监控信息,觉得非常受用,惊呼这不就是我长期想要的东西吗?
迫不及待,我立马在本地搭建了一套测试环境体验了一下,下面是整个测试过程。
本地测试环境搭建
我是在 Mac 上使用 Docker 搭建的测试环境,网络拓扑如下:
因为服务之间要相互访问,为了防止重启 container 导致IP地址变化,故创建了一个叫做 mynetwork
网段为 172.18.0.0/16
的自定义网络。创建容器的时候可以通过 --ip
手动分配静态 IP,各容器分配的 IP 地址如上图。
启动 nginx 容器
启动 nginx 之前我们需要创建测试域名的证书和配置文件,本次测试涉及三个域名(www.test01~3.com)。
创建域名证书
使用 genrsa.sh
脚本批量创建自签名证书,脚本内容如下:
#!/bin/bash
#1、该脚本支持自动生成私有证书
# ,用$1,$2....表示,第1,2...个参数,分表表示域名和过期时间
if [ "$#" -ne 2 ]; then
echo "genrsa.sh www.test01.com 60"
exit 1
fi
readonly DOMAIN=$1
readonly EXPIRATION=$2
openssl genrsa -out $DOMAIN.key 2048
openssl req \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Tester/OU=Tester Software/CN=$DOMAIN/emailAddress=test@prometheus.show" \
-new \
-key $DOMAIN.key \
-out $DOMAIN.csr
openssl x509 \
-req \
-days $EXPIRATION \
-in $DOMAIN.csr \
-signkey $DOMAIN.key \
-out $DOMAIN.crt
运行效果:
创建 nginx 配置文件
# touch nginx/conf.d/www.test01.com.conf
server {
listen 443 ssl;
server_name www.test01.com;
ssl_certificate ssl/www.test01.com.crt;
ssl_certificate_key ssl/www.test01.com.key;
location / {
return 200;
}
}
# touch nginx/conf.d/www.test02.com.conf
server {
listen 443 ssl;
server_name www.test02.com;
ssl_certificate ssl/www.test02.com.crt;
ssl_certificate_key ssl/www.test02.com.key;
location / {
return 403;
}
}
# touch nginx/conf.d/www.test03.com.conf
server {
listen 443 ssl;
server_name www.test03.com;
ssl_certificate ssl/www.test03.com.crt;
ssl_certificate_key ssl/www.test03.com.key;
location / {
return 200;
}
}
- 创建了三个域名所需的证书和配置文件。
- 网站 www.test02.com 返回 403 状态码,其它返回 200。
执行容器启动命令
docker run -d --name nginx \
--net mynetwork --ip 172.18.0.2 \
-v `pwd`/nginx/ssl:/etc/nginx/ssl:ro \
-v `pwd`/nginx/conf.d:/etc/nginx/conf.d \
nginx
到此为止用于测试的 nginx 容器就启动起来了,它包了 www.test01~3.com 三个测试域名,每个域名都有自己的证书,每个证书过期时间不同。
启动 blackbox exporter
用于测试的网站已经部署完成,接下来部署 blackbox exporter。
创建 blackbox.yml
modules:
http_2xx:
prober: http
http:
preferred_ip_protocol: "ip4"
tls_config:
insecure_skip_verify: true
- 这里使用 blackbox exporter 的 http 探针。
- 当执行 http 探测的时候,指定使用 ipv4 协议,因为是自签名证书,故配置
insecure_skip_verify: true
。
执行启动命令
docker run -d -p 9115:9115 \
--name blackbox_exporter \
--net mynetwork --ip 172.18.0.3 \
--add-host www.test01.com:172.18.0.2 \
--add-host www.test02.com:172.18.0.2 \
--add-host www.test03.com:172.18.0.2 \
-v `pwd`:/config \
prom/blackbox-exporter:v0.18.0 --config.file=/config/blackbox.yml
要探测 www.test01~3.com 这三个域名,所以需要通过 --add-host
手动指定其解析的 IP 为 nginx 容器地址。
启动 Prometheus
当 blackbox exporter 部署完成后,我们需要部署 Prometheus 来抓取和存储数据。
更新 prometheus.yml 配置文件:
scrape_configs:
- job_name: 'blackbox'
metrics_path: /probe
params:
module: [http_2xx]
static_configs:
- targets:
- https://www.test01.com
- https://www.test02.com
- https://www.test03.com
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: blackbox01.com:9115
- 通过静态 static_configs 指定需要探测地址为 www.test01~03.com。
- 通过 relabel_configs 将实际的 metrics 获取地址重定向到 blackbox exporter 的地址,即我们配置的 172.18.0.3,这里使用了
blackbox01.com
域名来代替。
执行容器启动命令
docker run -d -p 9090:9090 \
--name prometheus \
--net mynetwork --ip 172.18.0.4 \
--add-host blackbox01.com:172.18.0.3 \
-v `pwd`/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus:v2.23.0
启动并配置 Grafana
经过上面的操作,已经能够在 Prometheus 的 graph 页面查看到 probe_ 开头的相关指标,我们可以更进一步,使用 Grafana 来展示。
启动 Grafana 容器
docker run -d -p 3000:3000 \
--name=grafana \
--net mynetwork --ip 172.18.0.5 \
--add-host prometheus01.com:172.18.0.4 \
grafana/grafana
这里将 promtheus 地址映射为 prometheus01.com
,这样在 grafana 可以直接使用该域名来创建数据源。
创建 Grafana 监控面板
使用 admin/admin 初始密码登录 http://localhost:3000 ,并使用 prometheus01.com:9090
创建默认 Promethues 数据源。
导入 ID 为 13230
的模板:
导入结果:
可以看到我们用于测试的这三个网站的探测信息都展示到 Grafana 图表了,展示内容包括我们想要的证书过期时间、状态码、连接各阶段耗时。
告警配置
除了可以通过 Grafana 面实时查看域名探测结果,我们可以配置 Prometheus rules 并结合 Alertmanager 实现告警监控。
告警配置如:
- name: ssl_expiry
rules:
- alert: Ssl Cert Will Expire in 7 days
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 7
for: 5m
labels:
severity: warning
annotations:
summary: "域名证书即将过期 (instance )"
description: "域名证书 7 天后过期 \n VALUE = \n LABELS: "
可能需要监控的指标:
expr: probe_ssl_earliest_cert_expiry - time() < 86400 * 7
实现域名过期检测,比如这里过期时间小于 7 天告警。expr: probe_http_status_code != 200
实现状态码不为 200的告警。expr: sum(probe_http_duration_seconds) by (instance) > 1
实现总耗时大于 1 秒的告警。
总结
今天我们在本地通过 Nginx 容器搭建了三个过期时间为 3d、60d 、365d 的测试域名,然后通过容器启动 Blackbox exporter 和 Prometheus 来探测和收集这三个域名的 metrics,最后通过 Grafana 的 13230 模板统一展示这个三个域名的探测结果。
通过测试可以看到,使用Blackbox Exporter 和 Prometheus 实现域名证书的探测和监控是非常方便的,而且 Grafana 的显示效果非常好,值得大家试试。