Kubernetes Sidecar/Adapter模式导出Spring Boot Prometheus指标咨询
方案合理性判断
Sidecar/Adapter模式不是Spring Boot导出Prometheus指标的默认首选,但在特定约束下是完全合理的可选方案,不存在绝对的对错,只看是否匹配你的场景。
- 优先用原生集成的场景:如果你的Spring Boot应用处于正常迭代周期,允许修改代码和依赖、可以重新构建镜像,直接引入
io.micrometer:micrometer-registry-prometheus依赖暴露/actuator/prometheus端点是最优解。这种方式侵入性极低(只需要加依赖、改几行配置)、指标覆盖最全(内置JVM、Web请求、数据源、自定义业务指标全链路打通)、性能开销最小,完全没有额外Sidecar带来的资源损耗和运维复杂度。 - 适合用Sidecar/Adapter的场景:
- 历史遗留Spring Boot应用,已经停止功能迭代、不允许修改代码/重新构建镜像,没法直接集成Micrometer
- 集群内有统一的指标管控要求,希望所有工作负载的指标暴露、鉴权、过滤规则完全一致,不想让每个业务团队单独维护Micrometer版本、配置、指标规则
- 需要对原始指标做统一二次加工(比如加全局集群标签、脱敏高基数业务标签、丢弃无用指标降低存储成本),不想把这部分通用逻辑耦合到业务应用里
- 集群是多语言混合部署,希望所有服务的指标采集逻辑、暴露端口、鉴权方式完全统一,降低Prometheus的配置维护成本
你提到的Elasticsearch用Adapter暴露指标的示例,核心前提是Elasticsearch本身原生不支持输出Prometheus格式的指标,必须靠Adapter做协议转换,和Spring Boot本身已经支持Prometheus指标输出的场景有本质区别,不要为了套设计模式硬上Sidecar。
K8s Sidecar/Adapter模式实现逻辑
Spring Boot场景下的指标导出Sidecar主要有两种实现路径,对应不同的场景需求:
- 协议转换型Adapter:如果你的Spring Boot应用本身已经能输出其他格式的指标(比如旧版本Spring Boot Actuator默认的JSON格式
/metrics端点、Dropwizard格式指标),Sidecar只需要通过localhost拉取业务容器的原始指标,转换成Prometheus标准的文本格式,在Sidecar自己的端口暴露给Prometheus采集即可。 - 零侵入采集型Sidecar:如果应用完全没有暴露任何指标接口,可以开启Pod的进程命名空间共享,让Sidecar直接读取业务容器内JVM的MBean数据(也就是JMX指标),转换成Prometheus格式暴露,全程不需要修改应用的任何代码和配置。
通用配置注意点:
- 同一个Pod内的容器默认共享网络命名空间,Sidecar直接用
127.0.0.1就能访问业务容器的端口,不需要走Service网络 - 用JMX采集模式时必须给Pod配置
shareProcessNamespace: true,否则Sidecar没法访问业务容器的JVM进程 - Prometheus采集时直接指向Sidecar暴露的指标端口即可,不需要感知业务容器的存在
参考实现示例
下面给一个零代码侵入的JMX Exporter Sidecar配置示例,不需要修改原有Spring Boot应用的代码和镜像,只需要调整Deployment配置就能实现指标导出:
- 先创建ConfigMap存JMX Exporter的采集规则,文件命名为
jmx-exporter-config.yaml,基础配置如下:
lowercaseOutputLabelNames: true lowercaseOutputName: true rules: - pattern: "java.lang<type=(.*)><>(.*): (.*)" name: java_lang_$1_$2 type: GAUGE - pattern: "Catalina<type=(.*)><>(.*): (.*)" name: tomcat_$1_$2 type: GAUGE
执行kubectl create configmap jmx-exporter-config --from-file=jmx-exporter-config.yaml把配置存到K8s集群里。
- 调整Spring Boot应用的Deployment配置,加入Sidecar容器,核心配置片段如下:
apiVersion: apps/v1 kind: Deployment metadata: name: spring-boot-demo spec: replicas: 1 selector: matchLabels: app: spring-boot-demo template: metadata: labels: app: spring-boot-demo spec: shareProcessNamespace: true # 开启进程命名空间共享,Sidecar才能访问业务容器的JVM containers: # 原有业务容器,不需要修改原有业务镜像 - name: spring-boot-app image: 你的原有SpringBoot业务镜像地址:版本号 ports: - containerPort: 8080 # 给JVM加本地JMX访问参数,不需要对外暴露JMX端口 env: - name: JAVA_OPTS value: "-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.local.only=true" volumeMounts: - name: jmx-exporter-config mountPath: /opt/jmx-exporter # Sidecar容器:负责JMX指标采集和Prometheus格式转换 - name: prometheus-jmx-exporter image: prom/jmx-exporter:0.20.0 args: - "9404" # Sidecar对外暴露指标的端口 - "/opt/jmx-exporter/jmx-exporter-config.yaml" - "127.0.0.1:1099" # 共享网络命名空间,直接用本地地址访问JMX端口 ports: - containerPort: 9404 name: metrics volumeMounts: - name: jmx-exporter-config mountPath: /opt/jmx-exporter resources: # 给Sidecar配置合理的资源限制,避免抢占业务资源 requests: cpu: 50m memory: 128Mi limits: cpu: 200m memory: 256Mi volumes: - name: jmx-exporter-config configMap: name: jmx-exporter-config
配置完成后,Prometheus只需要采集每个Pod上9404端口的/metrics路径,就能拿到JVM内存、GC、Tomcat请求等核心运行指标。
注意:这种纯JMX采集的Sidecar模式默认拿不到Micrometer提供的自定义业务指标,如果需要采集业务维度的指标,要么在JMX Exporter配置里加对应的采集规则,要么还是优先选择应用直接集成Micrometer的原生方案。
内容的提问来源于stack exchange,提问作者Prakash

