Prometheus安全加固实战:Nginx反向代理与内置认证配置详解
1. 项目概述:为什么我们需要给Prometheus“上锁”?
在监控领域,Prometheus 以其强大的数据抓取能力和灵活的查询语言(PromQL)成为了事实上的标准。但很多朋友在初次部署时,往往会忽略一个关键环节:安全。默认情况下,Prometheus 的 Web UI 和 API 是直接暴露的,没有任何访问控制。想象一下,你的服务器性能指标、业务运行状态,甚至是一些包含敏感信息的标签(比如数据库连接串、内部服务地址),就这么“裸奔”在网络上,任何人只要知道 IP 和端口就能一览无余。这无异于把自家大门的钥匙插在锁上。
我见过不止一个团队,在内部测试环境部署了 Prometheus,因为觉得是内网就跳过了认证,结果某次端口意外暴露到公网,差点酿成数据泄露的风险。所以,给 Prometheus 加上“锁”——也就是加密配置和登录认证,绝不是可有可无的“高级功能”,而是生产环境部署的必备步骤。这不仅仅是防止未授权访问,更是满足各类安全审计和合规性要求的基础。
本次分享,我将结合自己多次在生产环境落地的经验,详细拆解两种主流的 Prometheus 安全加固方式:基于 Web 服务器(如 Nginx/Apache)的反向代理认证,以及 Prometheus 自身集成的 Web 配置文件和基础认证。我会把配置的每一步、背后的原理,以及我踩过的那些“坑”都摊开来讲清楚。无论你是运维工程师、SRE,还是正在搭建自己监控体系的开发者,这篇内容都能帮你构建一个既安全又可靠的 Prometheus 监控栈。
2. 安全加固的两种核心路径解析
在开始动手之前,我们得先理清思路。Prometheus 本身在设计上遵循“只做一件事并做好”的 Unix 哲学,其核心是抓取和存储时间序列数据,因此原生不提供复杂的用户认证和授权系统。要实现安全访问,我们需要借助外部组件或其有限的内置功能。主流方案可以归结为以下两条路径,它们各有优劣,适用场景也不同。
2.1 路径一:反向代理网关模式
这是目前生产环境中最主流、最推荐的方式。其核心思想是:不直接暴露 Prometheus 服务,而是在其前面部署一个成熟的 Web 服务器(如 Nginx、Apache、Caddy)或 API 网关(如 Traefik、Envoy)作为反向代理和认证网关。
工作原理:
- 用户或客户端(如 Grafana)的所有请求首先到达反向代理服务器。
- 代理服务器负责完成 TLS/SSL 加密(HTTPS)、用户认证(如 Basic Auth、OAuth2、LDAP)等所有安全相关的工作。
- 认证通过后,代理服务器将请求转发给后端的 Prometheus 服务(通常监听在 localhost 或内部网络)。
- Prometheus 本身无需任何修改,它只接收来自可信代理的“干净”请求。
为什么这是首选方案?
- 功能强大且成熟:Nginx 等 Web 服务器经过多年实战检验,其 TLS 实现、认证模块非常稳定和全面。你可以轻松集成多种认证方式,这是 Prometheus 自身无法比拟的。
- 职责分离:安全(认证、加密)与业务(监控数据抓取、查询)解耦。Prometheus 可以专注于其核心任务,安全策略的变更和升级不影响监控服务本身。
- 统一入口:在实际架构中,你很可能不止有 Prometheus 需要保护,还有 Alertmanager、Grafana 等其他组件。使用同一个反向代理作为统一的安全网关,可以简化证书管理和认证策略配置。
- 灵活性高:你可以轻松添加 IP 白名单、限流、访问日志审计等更多安全层。
2.2 路径二:Prometheus 内置 Web 配置文件认证
从 Prometheus 2.24 版本开始,引入了通过web.config.yml文件配置 TLS 和基础认证(Basic Authentication)的支持。这种方式将安全配置直接内嵌到 Prometheus 进程中。
工作原理:
- 你需要准备一个
web.config.yml配置文件,其中定义了 TLS 证书路径和 HTTP 基础认证的用户密码哈希。 - 在启动 Prometheus 时,通过
--web.config.file参数指定该配置文件。 - Prometheus 的 Web 服务器将直接使用该配置,提供 HTTPS 服务和基础认证。
它的适用场景与局限:
- 优点:部署简单,无需引入额外组件,适合小型环境或快速原型验证。所有配置集中在一个 Prometheus 实例上。
- 缺点:
- 功能单一:仅支持静态配置的基础认证,无法集成 OAuth、LDAP 等复杂认证系统。
- 管理不便:用户密码以哈希形式写在配置文件中,添加或修改用户需要更新配置文件并重启 Prometheus。
- 耦合性高:安全与业务耦合,证书轮换等操作需要重启服务。
- 版本依赖:需要较新版本的 Prometheus(>=2.24)。
我的经验选择:对于任何严肃的生产环境,我毫无保留地推荐路径一(反向代理模式)。它更符合现代云原生架构的理念,扩展性和可维护性要好得多。路径二可以作为一个轻量级的备选方案,或者在开发测试环境中临时使用。接下来,我将以最常用的 Nginx 作为反向代理为例,展开详细配置。
3. 实战:基于 Nginx 反向代理的完整配置流程
我们将搭建一个标准的架构:用户 -> HTTPS (Nginx with Basic Auth) -> HTTP (Prometheus)。目标是让 Prometheus 在http://localhost:9090安全地运行,而外部通过https://your-domain.com/prometheus来访问。
3.1 环境准备与组件安装
首先,确保你的服务器上已经安装了 Prometheus。如果还没安装,可以通过以下步骤快速完成(以 Linux 为例):
# 下载最新版本的 Prometheus (请从官网替换为最新版本号) wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz # 解压 tar xvf prometheus-*.tar.gz cd prometheus-* # 将可执行文件移动到系统路径 sudo cp prometheus promtool /usr/local/bin/ # 创建配置和数据目录 sudo mkdir -p /etc/prometheus /var/lib/prometheus sudo cp prometheus.yml /etc/prometheus/接下来,安装 Nginx。大多数 Linux 发行版都可以通过包管理器安装:
# Ubuntu/Debian sudo apt update && sudo apt install nginx apache2-utils -y # CentOS/RHEL sudo yum install nginx httpd-tools -y这里我们同时安装了apache2-utils(或httpd-tools),因为它包含了htpasswd工具,用于生成基础认证的密码文件。
3.2 生成密码文件与配置基础认证
安全的第一步是创建授权用户。我们将用户名和密码哈希存储在一个文件中。
# 创建密码文件,首次添加用户使用 -c 参数,后续添加不要用 -c,否则会覆盖! sudo htpasswd -c /etc/nginx/.htpasswd prometheus_admin执行命令后,会提示你输入并确认密码。prometheus_admin是你指定的用户名。请务必将生成的/etc/nginx/.htpasswd文件权限设置为仅 root 可读,以保护密码哈希。
sudo chmod 600 /etc/nginx/.htpasswd3.3 获取与配置 SSL/TLS 证书
没有 HTTPS 的认证是“纸糊的墙”,因为密码在网络上明文传输。我们必须启用 HTTPS。
对于生产环境:你应该使用来自 Let‘s Encrypt(免费)或其他商业 CA 签发的可信证书。使用 Certbot 可以自动化这个过程:
# 安装 Certbot (以 Nginx on Ubuntu 为例) sudo apt install certbot python3-certbot-nginx -y # 获取并自动配置证书,your-domain.com 替换为你的域名 sudo certbot --nginx -d your-domain.comCertbot 会自动修改你的 Nginx 配置,启用 HTTPS。
对于测试或内部环境:你可以使用自签名证书。虽然浏览器会警告,但用于内部服务或配合 Grafana(可配置跳过证书验证)是可行的。
# 生成自签名证书 (有效期365天) sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout /etc/ssl/private/nginx-selfsigned.key \ -out /etc/ssl/certs/nginx-selfsigned.crt你需要填写一些证书信息,其中Common Name最好填写你的服务器 IP 或域名。
3.4 编写核心的 Nginx 服务器配置
这是最关键的一步。我们将在/etc/nginx/sites-available/prometheus创建一个新的服务器块配置。假设你的域名是monitor.yourcompany.com。
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name monitor.yourcompany.com; # 你的域名 # SSL 证书路径 (使用 Certbot 的路径通常如下,自签名证书需调整) ssl_certificate /etc/letsencrypt/live/monitor.yourcompany.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/monitor.yourcompany.com/privkey.pem; # 启用 SSL 会话复用,提升性能 ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; # 安全地转发到 Prometheus location /prometheus/ { # 1. 启用基础认证 auth_basic "Prometheus Server Authentication"; auth_basic_user_file /etc/nginx/.htpasswd; # 2. 反向代理到本地的 Prometheus proxy_pass http://localhost:9090/; # 注意结尾的斜杠,它很重要! # 3. 传递必要的头部信息 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 4. 设置 WebSocket 支持 (Grafana Live 特性可能需要) proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 5. 适当调大超时时间,应对大量查询 proxy_read_timeout 300; proxy_connect_timeout 300; } # 可选:重定向 HTTP 到 HTTPS # server { # listen 80; # server_name monitor.yourcompany.com; # return 301 https://$server_name$request_uri; # } }配置要点解析:
auth_basic和auth_basic_user_file指令启用了基础认证,并指定了密码文件。proxy_pass将匹配/prometheus/路径的请求转发给本地 9090 端口的 Prometheus。结尾的斜杠/至关重要,它会将/prometheus/api/v1/query这样的请求正确地重写为http://localhost:9090/api/v1/query。如果没有这个斜杠,路径会错乱,这是最常见的配置错误之一。proxy_set_header系列指令确保了原始请求的客户端信息(如真实 IP)能传递给 Prometheus,这对于日志记录和审计很有帮助。- WebSocket 头部的设置是为了兼容 Grafana 的“实时预览”等高级功能。
- 超时时间的调整是因为 Prometheus 的查询,尤其是范围查询,可能耗时较长,需要避免代理层过早断开连接。
3.5 启用配置并启动服务
创建符号链接启用站点配置,并测试 Nginx 配置语法。
sudo ln -s /etc/nginx/sites-available/prometheus /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置,必须看到 “syntax is ok” 和 “test is successful”如果测试成功,重启 Nginx 使配置生效。
sudo systemctl restart nginx现在,确保你的 Prometheus 服务正在运行(默认监听localhost:9090)。然后,你就可以通过浏览器访问https://monitor.yourcompany.com/prometheus,会弹出一个登录框,输入之前设置的prometheus_admin和密码即可访问。
4. 另一种选择:配置 Prometheus 内置的 Web 认证
如果你坚持使用内置方案,以下是具体步骤。再次强调,这更适合轻量级、非核心的场景。
4.1 创建 Web 配置文件
在 Prometheus 配置目录(如/etc/prometheus)下创建web-config.yml:
tls_server_config: cert_file: /etc/prometheus/ssl/prometheus.crt key_file: /etc/prometheus/ssl/prometheus.key basic_auth_users: prometheus_admin: $2y$12$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxtls_server_config:指定你的 TLS 证书和私钥路径。证书生成方式同上。basic_auth_users:定义用户名和密码的 bcrypt 哈希。密码不是明文!
4.2 生成密码哈希
使用htpasswd或其他工具生成 bcrypt 哈希。这里用openssl:
# 生成 bcrypt 哈希 (rounds 是成本因子,默认12,越高越安全但也越慢) openssl passwd -6 -stdin输入你的密码后,会输出一个以$2b$或$2y$开头的哈希字符串,将其复制到web-config.yml中。
4.3 修改 Prometheus 启动命令
你需要修改 systemd 服务文件(通常是/etc/systemd/system/prometheus.service)或直接修改启动命令,添加--web.config.file参数:
ExecStart=/usr/local/bin/prometheus \ --config.file=/etc/prometheus/prometheus.yml \ --storage.tsdb.path=/var/lib/prometheus/ \ --web.console.templates=/etc/prometheus/consoles \ --web.console.libraries=/etc/prometheus/console_libraries \ --web.config.file=/etc/prometheus/web-config.yml \ # 新增这行 --web.listen-address=0.0.0.0:9090重启 Prometheus 服务后,它将在 9090 端口提供 HTTPS 服务,并需要基础认证。
5. 关键踩坑点与疑难问题排查实录
理论配置看起来简单,但实操中陷阱不少。下面是我总结的几个典型“坑”及其解决方案。
5.1 路径代理的“斜杠”陷阱
这是 Nginxproxy_pass指令最经典的坑。
- 错误配置:
location /prometheus { proxy_pass http://localhost:9090; } - 现象:访问
https://domain/prometheus可能正常,但访问https://domain/prometheus/api/v1/targets时,Nginx 会将请求转发给http://localhost:9090/api/v1/targets,丢失了/prometheus前缀。这会导致 Prometheus 返回 404,因为它的 API 根路径是/,而不是/prometheus。 - 正确配置:
- 方案A(推荐):在
location和proxy_pass的 URL 后都加上斜杠。location /prometheus/ { proxy_pass http://localhost:9090/; }。这样 Nginx 会将/prometheus/前缀从请求路径中剥离后再转发。 - 方案B:使用
rewrite指令重写路径。location /prometheus { rewrite ^/prometheus/(.*) /$1 break; proxy_pass http://localhost:9090; }。
- 方案A(推荐):在
5.2 Grafana 数据源配置认证
当 Prometheus 开启基础认证后,Grafana 数据源必须配置对应的凭据。
- 在 Grafana 中,进入Configuration -> Data Sources -> Prometheus。
- 在HTTP部分:
- URL:填写完整的代理地址,如
https://monitor.yourcompany.com/prometheus。 - Auth:开启Basic Auth。
- User和Password:填写你在
.htpasswd中设置的用户名和密码。
- URL:填写完整的代理地址,如
- 点击Save & Test。如果成功,会显示 “Data source is working”。
常见问题:
- 证书错误:如果使用自签名证书,Grafana 会报 SSL 错误。需要在数据源配置的TLS/SSL Auth部分,开启Skip TLS Verify(仅限测试环境)。生产环境请务必使用可信证书。
- 路径错误:确保 Grafana 中配置的 URL 包含了 Nginx 中设置的路径前缀(如
/prometheus)。
5.3 Prometheus 抓取配置(scrape_configs)的认证
如果你的 Prometheus 需要从同样需要认证的 exporter(如 Node Exporter with HTTPS)抓取数据,需要在prometheus.yml的scrape_configs中配置认证。
scrape_configs: - job_name: 'node' basic_auth: username: 'exporter_user' password: 'your_secure_password' tls_config: insecure_skip_verify: true # 谨慎使用,仅用于测试或内部自签名证书 static_configs: - targets: ['node-exporter-host:9100']这里配置的是Prometheus(客户端)去访问exporter(服务端)时使用的认证,与前面讲的保护 Prometheus 自身(服务端)的认证是两回事,不要混淆。
5.4 性能与超时问题
当配置了反向代理和认证后,链路过长可能引入性能开销和超时风险。
- 问题:在 Grafana 中加载一个跨度较大的仪表盘时,可能遇到 “504 Gateway Time-out” 错误。
- 排查:
- 检查 Nginx 错误日志:
sudo tail -f /var/log/nginx/error.log。 - 通常能看到
upstream timed out相关记录。
- 检查 Nginx 错误日志:
- 解决:在 Nginx 的
location块中增加超时设置,如前面配置示例中的proxy_read_timeout 300;。这个值需要根据你的查询复杂度和数据量进行调整。同时,也可以考虑优化 PromQL 查询,避免全时间范围扫描。
5.5 系统服务与权限问题
- SELinux/AppArmor:在开启了强制安全模块的系统上,Nginx 可能被禁止访问密码文件
.htpasswd或代理到本地端口。可以通过审计日志排查,或临时设置为宽容模式测试。 - 防火墙:确保 Nginx 的 443 端口对外部开放,同时确保 Prometheus 的 9090 端口仅对本地(127.0.0.1)或内部网络开放,不要暴露到公网。
6. 进阶考量与最佳实践建议
完成基础配置只是第一步,要让这套安全体系更健壮,还需要考虑以下几点。
6.1 认证方式的升级:从 Basic Auth 到 OAuth2
基础认证简单,但不够安全(密码每次请求都传输)也不便于管理(多服务需重复配置)。在生产环境中,更推荐使用 OAuth2 代理(如oauth2-proxy)或直接使用支持 OAuth2 的入口网关(如ingress-nginx的注解配置)。
其工作流程变为:用户访问 -> 网关重定向到身份提供商(如 Google, GitHub, 企业内部 SSO)登录 -> 登录成功后携带令牌访问 -> 网关验证令牌并转发请求给 Prometheus。这种方式用户体验更好,也更安全。
6.2 细粒度授权(RBAC)
基础认证或简单的 OAuth2 只解决了“你是谁”的问题,没有解决“你能做什么”。Prometheus 本身不支持基于角色的访问控制(RBAC)。如果你需要限制不同用户只能查看特定的监控数据(例如,开发团队只能看应用指标,运维团队才能看主机和数据库指标),目前需要借助更外层的方案:
- 使用 Grafana 的数据源权限:在 Grafana 中可以为不同团队创建不同的数据源,每个数据源连接到一个经过过滤的 Prometheus 查询代理(如
promxy或自建代理服务),该代理根据用户身份对 PromQL 查询进行改写或过滤。 - 专门的监控门户:开发一个轻量级前端,集成认证,后端调用 Prometheus API 时根据用户角色注入不同的标签过滤条件。
6.3 配置管理与自动化
当你有成百上千个监控目标时,手动管理认证凭据是不现实的。
- 密码/密钥管理:使用诸如 HashiCorp Vault、AWS Secrets Manager 等工具动态管理密码和 TLS 证书,并通过 sidecar 或 init container 注入到 Nginx 或 Prometheus 的容器中。
- 配置即代码:将 Nginx 配置、Prometheus 的
web-config.yml纳入 Git 版本控制,结合 CI/CD 流水线进行自动化部署和检查。 - 在 Kubernetes 中的实践:在 K8s 中部署时,通常使用 Ingress 资源来配置反向代理和 TLS。认证可以通过 Ingress Annotations 集成
oauth2-proxy或使用 Service Mesh(如 Istio)的授权策略来实现,管理起来更加云原生。
安全是一个持续的过程,而不是一次性的配置。给 Prometheus 加上认证和加密,是构建可靠监控体系的坚实第一步。从简单的 Nginx 反向代理开始,随着业务复杂度的提升,再逐步演进到更完善的统一认证授权体系,这是一个稳妥且实用的路径。