- 测试
- 云原生
- 质量保障
【免费下载链接】origin
Conformance test suite for OpenShift
导读
本文基于 OpenShift Origin(openshift/origin)仓库中的官方提案文档 instrumentation-of-services.md,系统讲解 OpenShift 集群中所有基础设施组件(路由器、API Server、OAuth 服务器、监控组件等)必须遵循的服务插桩(instrumentation)规范:如何通过统一的/healthz、/metrics、/healthz/ready与/debug/pprof/*端点暴露存活状态、就绪状态、业务指标与性能画像,并给出 Prometheus 指标命名、安全认证与异常豁免的完整要求。读完本文,你将掌握为 OpenShift 组件接入健康检查、监控指标与性能剖析的标准接口约定,并能在本仓库的 e2e 测试与监控测试源码中找到对应的可验证实现。
一、统一端点约定:所有 OpenShift 组件必须暴露的接口
提案文档首先给出了一个硬性要求:所有 OpenShift 组件 MUST 在其公共 HTTPS 端口(若无 HTTPS 端口则用公共 HTTP 端口)上暴露以下两个端点:
| 端点 | 响应约定 | 语义 |
|---|---|---|
/healthz | 返回 HTTP 200 与文本ok | 表示实例进程存活(liveness) |
/metrics | 以 Prometheus 文本格式返回一组合理的指标 | 用于刻画该服务器的健康与性能状态 |
通过 Service 或 Route 暴露的组件,MUST 额外暴露以下端点:
| 端点 | 响应约定 | 语义 |
|---|---|---|
/healthz/ready | 返回 HTTP 200 与文本ok | 表示实例已就绪,可以开始接收网络流量(readiness) |
此外还有两条补充规则:
- 仅提供 TCP 端点的组件:应监听一个独立的端口,并在该端口上暴露上述对应的检查端点(即把 HTTP 健康检查挂在独立端口上,避免与业务 TCP 端口冲突)。
- 已有社区等价端点的组件:若组件从上游社区原样(as-is)采用了与上述端点等价的现有端点(例如 kube-apiserver 的
/readyz),则 MAY 直接沿用,不必重复实现一套。
从本仓库的测试代码可以印证这些约定在真实组件中的落地情况。以集群路由器(HAProxy router)为例,test/extended/router/metrics.go 中的 e2e 测试明确断言:路由器必须在 metrics 端口上暴露健康检查,测试通过http://<host>:<metricsPort>/healthz期望返回 200。测试在BeforeEach中从openshift-ingress命名空间的router-internal-defaultEndpoints 里按端口名metrics提取 metrics 端口号:
// 从 Endpoints 中按名称提取 metrics 端口 for _, port := range subset.Ports { if port.Name == "metrics" { metricsPort = port.Port break } } o.Expect(metricsPort).NotTo(o.BeZero())而test/extended/router/certs.go、test/extended/router/scoped.go、test/extended/router/stress.go等多处 e2e 测试(如 certs.go)则将Path: "/healthz/ready"配置为后端 Pod 的 HTTP 就绪探针(readinessProbe),这正是“通过 Service/Route 暴露的组件必须提供/healthz/ready”这一规则在探针场景中的直接应用。
对于“社区等价端点”的例外条款,kube-apiserver 是最典型的例子:上游 Kubernetes 的 apiserver 提供的是/readyz(而非/healthz/ready),本仓库的 test/extended/apiserver/health_endpoints.go 即通过readyz?verbose=true来验证 apiserver 各子检查项的就绪状态,并配合 test/extended/apiserver/graceful_termination.go 断言 API 负载均衡器会跟随/readyz停止/恢复向 apiserver 发送请求。
二、Metrics 指标:为什么选 Prometheus 格式
文档明确说明选用 Prometheus 格式的两点理由:
- 与上游 Kubernetes 社区保持一致;
- 它是 Go 生态系统的天然契合格式(Go 官方指标库即输出 Prometheus 文本格式)。
因此,对于不原生提供 Prometheus 端点的 COTS(商用现货)软件,规范要求使用适配器(adapter)来暴露 Prometheus 指标——适配器既可以打进其进程内,也可以作为sidecar 容器伴随运行;Java 组件虽然可以使用 JMX,但仍然推荐适配到 Prometheus 格式。
指标内容:度量业务而非进程琐碎
文档强调,要暴露的指标应代表服务本身的业务度量(business measurements),并引用了 Prometheus 官方 instrumentation 实践指南:
- 如果组件的职责是处理请求,就捕获请求的计数(count)、耗时(duration)与类型(types);
- 如果组件内部有队列,就报告队列深度(queue depth)与队列吞吐(throughput);
- 标签与命名遵循 Prometheus 官方 naming 实践(如
_total后缀用于计数器、单位嵌入名称等)。
若指标值或标签包含敏感信息,应考虑匿名化(anonymizing)或归类(categorizing);若信息本质上是多租户(multi-tenant)的,则继续阅读下文安全一节。
Go 程序的落地路径
- Go 程序应通过现有 Prometheus 客户端库轻松集成(例如
github.com/prometheus/client_golang/prometheus); - 优先使用现成的 Prometheus exporter;只有在特定框架下适配指标成本过高、或无法合入上游时,才考虑自行适配。
本仓库 e2e 测试对路由器 metrics 端点的断言可以作为“业务度量”的极佳范例:test/extended/router/metrics.go 验证了以下指标族:
- 路由/后端维度:
haproxy_backend_connections_total、haproxy_server_http_responses_total(带code标签区分 2xx/5xx)、haproxy_server_connections_total、haproxy_server_bytes_in_total/haproxy_server_bytes_out_total; - 通用 exporter 指标:
haproxy_up、haproxy_exporter_scrape_interval、haproxy_exporter_total_scrapes、haproxy_exporter_csv_parse_failures; - 进程维度:
haproxy_process_resident_memory_bytes、haproxy_process_max_fds; - 路由器自身模板渲染耗时:
template_router_reload_seconds、template_router_write_config_seconds。
测试还使用 Prometheus 官方expfmt解析器(p.TextToMetricFamilies)将抓取到的文本转换为 MetricFamily 结构再逐项断言,这正是文档“用 Prometheus 格式暴露业务指标”约定的端到端验证——从端点抓取、格式解析到语义断言一条链路全部覆盖。
三、Profiling 性能剖析:/debug/pprof/*的使用边界
对于高流量(high traffic)或已知性能瓶颈且使用 Go 编写的组件,文档要求(SHOULD)暴露/debug/pprof/*系列端点。
同时有一个不可妥协的前提:这些端点 MUST 通过认证与授权保护,因为性能剖析数据可能导致信息泄露(information disclosure)——例如 goroutine 栈中的变量、堆内存中的字符串等都可能泄漏内部状态。
路由器再次提供了完整实现样板:test/extended/router/metrics.go 中的 e2e 测试断言:
- 未提供用户名密码访问
http://<host>:<metricsPort>/debug/pprof/heap必须返回401 或 403; - 使用认证凭据访问
/debug/pprof/heap?debug=1时,响应内容必须包含# runtime.MemStats标记(即 Go 运行时堆剖析输出的标准头)。
g.By("preventing access without a username and password") err := expectURLStatusCodeExec(ns, execPodName, fmt.Sprintf("http://%s/debug/pprof/heap", net.JoinHostPort(host, strconv.Itoa(int(metricsPort)))), 401, 403) o.Expect(err).NotTo(o.HaveOccurred()) g.By("at /debug/pprof") results, err := getAuthenticatedURLViaPod(ns, execPodName, fmt.Sprintf("http://%s/debug/pprof/heap?debug=1", net.JoinHostPort(host, strconv.Itoa(int(metricsPort)))), username, password) o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(results).To(o.ContainSubstring("# runtime.MemStats"))这一测试完整落地了“pprof 必须认证 + 认证后可读取剖析数据”的双重要求。
四、安全:健康检查与指标端点的访问控制
文档在安全一节给出了三条明确原则:
1. 健康检查:本地可达即可
健康检查(/healthz、/healthz/ready)必须能在 Pod 或本地网络上被访问,这样远端探针代理(如 kubelet、监控 Agent)才能访问它们。对于更复杂、可能泄露密码、磁盘路径、用户身份信息等敏感数据的检查,则 MAY 引入认证与授权。
2. Metrics 端点:泄露租户信息时 MUST 认证
如果 metrics 端点会泄露租户信息(pod 名、service 名、namespace 名或用户身份信息),则SHOULD 使用认证保护。文档给出的推荐做法是:
- 使用BASIC 认证,密码通过环境变量或 Secret提供——并明确点名“参考路由器的实现”;
- 对于系统级组件(如 controller manager、scheduler、kubelet、router),可以可选地利用集群内生的授权能力(如 kubelet 的 authn/authz、apiserver 的 RBAC)。
路由器的实现恰好是本仓库中可以直接引用的范例:test/extended/router/metrics.go 展示了凭据的来源——从openshift-ingress命名空间读取名为router-stats-default的 Secret,其中包含statsUsername与statsPassword两个字段;同时测试还创建一个prometheus-k8sServiceAccount 的 bearer token 用于抓取。随后测试断言:
- 未认证访问
/metrics返回401 或 403(见 metrics.go); - 用
router-stats-default提供的用户名密码认证后可以读取指标(metrics.go)。
OAuth 服务器同样验证了这一安全模型:test/extended/oauth/requestheaders.go 断言/metrics端点“匿名不可见”“未认证用户不应能访问”,而 requestheaders.go 进一步验证/metrics需要“有权访问该端点的用户”的 token。
3. 泄露租户信息的 metrics 必须走 TLS
文档特别强调:暴露租户信息并使用认证的组件,MUST 使用 HTTPS 提供 metrics——这是一条通用基础设施要求:所有用户信息都必须经 TLS 传输。
本仓库中与之呼应的佐证:监控系统对路由器 metrics 的抓取目标 URL 即为https://.*/metrics(test/extended/router/metrics.go),由router-internal-default这个 Prometheus job 以 HTTPS 抓取;同时 test/extended/apiserverauth/apiserver_util.go 中 apiserver 的/healthz也是通过https://地址访问的。
五、Push Metrics:为什么应作为最后手段
部分组件可能需要向远端 Agent推送较大量的指标。文档对此的态度非常明确:这在技术上是允许的,但 SHOULD 作为最后手段(last resort)。
理由如下:
- 设计良好的 Prometheus 端点应能干净地扩展到约 1k–10k 个租户,这已经覆盖当前集群规模的边界("within our cluster size bounds today");
- **推送指标需要申请例外(exception)**才能实施。
也就是说,Pull 模型(Prometheus 主动抓取)是默认且推荐的方式,Push 模型只有在 Pull 确实无法满足(例如指标量极大、组件生命周期过短等)时才允许,并且必须走例外审批流程。
本仓库对“Pull 抓取”的验证同样充分:should enable openshift-monitoring to pull metrics测试(test/extended/router/metrics.go)调用 Prometheus 的/api/v1/targets?state=active接口,断言router-internal-default这个 job 存在一个 health 为up、抓取 URL 匹配^https://.*/metrics$的活动 target——即集群监控系统确实通过 Pull 方式从路由器拉取指标。
六、Exceptions 例外:可被豁免,但缺失即 Bug
最后,文档给出了一个务实而强硬的收尾条款:
可以对这些要求授予例外(exceptions),但无法暴露这些信息的组件就无法被监控。请把这类信息的缺失视为一个 Bug。
这意味着:
- 例外申请是存在且允许的(尤其针对 Push Metrics 场景);
- 但任何无法提供健康检查、就绪检查或指标端点的组件,本质上都会变成监控盲区;
- 因此团队应当把“组件缺少可观测信息”当作缺陷来处理,而不是长期接受。
七、规范落地全景:从提案到测试的印证路径
为了帮助读者在本仓库中继续深挖,下表汇总了本文所有关键规则对应的源码/测试证据位置:
| 规范条款 | 仓库中的验证/实现位置 |
|---|---|
组件须暴露/healthz | test/extended/router/metrics.go(路由器 metrics 端口/healthz返回 200);test/extended/apiserverauth/apiserver_util.go(apiserver HTTPS/healthz) |
Service/Route 暴露组件须有/healthz/ready | test/extended/router/certs.go、scoped.go、stress.go(作为后端 readinessProbe 路径) |
社区等价端点可直接沿用(/readyz) | test/extended/apiserver/health_endpoints.go、graceful_termination.go |
/metrics业务度量 + Prometheus 格式 | test/extended/router/metrics.go(haproxy_*、template_router_*等指标族断言) |
/debug/pprof/*必须认证 | test/extended/router/metrics.go(未认证 401/403,认证后返回# runtime.MemStats) |
| metrics 泄露租户信息须 BASIC 认证(Secret 提供密码) | test/extended/router/metrics.go(router-stats-defaultSecret 的statsUsername/statsPassword) |
未认证访问/metrics被拒绝 | test/extended/router/metrics.go;test/extended/oauth/requestheaders.go |
| 监控系统 Pull 抓取 HTTPS metrics | test/extended/router/metrics.go(target URL 匹配^https://.*/metrics$) |
| 组件健康端点的持续监控(disruption 场景) | pkg/monitortests/network/disruptioningress/monitortest.go(对 oauth/console 等 route 的/healthz做可用性监控) |
结语:给组件开发者的检查清单
把提案文档浓缩成一份可直接对照的验收清单:
- 组件是否在公共 HTTPS(或 HTTP)端口上暴露了
/healthz(返回 200 +ok)与/metrics(Prometheus 格式)? - 若组件通过 Service/Route 暴露,是否额外提供了
/healthz/ready? - 仅 TCP 端点的组件,是否在独立端口上挂出了上述 HTTP 检查?
- 指标是否刻画了业务度量(请求计数/耗时/类型、队列深度/吞吐),而非仅仅进程琐碎?
- 指标或标签中是否含敏感信息?是否已匿名化/归类?
- 指标是否泄露租户信息?若是,是否已用 BASIC 认证(密码来自环境变量或 Secret)保护,且通过 HTTPS 提供服务?
- Go 高流量/瓶颈组件是否暴露了经认证的
/debug/pprof/*? - 若无法满足上述任何一项,是否已申请例外?——如果既无法暴露信息也没有例外,请把它当作 Bug 修复,因为无法被监控的组件等于运行在黑盒里。
遵循这套插桩规范,OpenShift 中的每一个基础设施组件都能被 kubelet 探针、Prometheus 抓取与集群监控链路完整覆盖,这也是整个 OpenShift 集群可观测性体系能够运转的地基。
- 测试
- 云原生
- 质量保障
【免费下载链接】origin
Conformance test suite for OpenShift
相关推荐
如何在5分钟内上手Lawnchair:从安装到数据持久化的快速入门教程
如何在5分钟内上手Lawnchair:从安装到数据持久化的快速入门教程 Lawnchair是一款轻量级客户端JSON文档存储工具,专为HTML5移动应用设计,提
Dante Cloud设施Starter:基础设施切换依赖的最佳实践
Dante Cloud设施Starter:基础设施切换依赖的最佳实践 引言:微服务架构中的基础设施挑战 在微服务架构演进过程中,基础设施组件的选择和切换往往成为
Lecture_Notes:微服务监控:Metrics与Logging最佳实践
Lecture_Notes:微服务监控:Metrics与Logging最佳实践 在微服务架构中,服务数量的激增使得监控成为保障系统稳定性的核心环节。本文将结合
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考