【Monitoring】在Kubernetes中Spring Boot集成Prometheus和Grafana

【前置文章】

【参考】

使用Grafana来查看Spring Boot项目的Metrics,主要流程:

  • Spring Boot集成spring-boot-starter-actuator模块和micrometer-registry-prometheus模块暴露/actuator/prometheus端点
  • Prometheus每隔一定时间通过/actuator/prometheus端点抓取数据,存入时间序列数据库。
  • 访问Grafana Dashboard:http:localhost:3000,其背后是Grafana通过PromQL查询Prometheus时间序列数据库。

本文主要集中在如何Spring Boot如何暴露/actuator/prometheus端点,以及在Prometheus中设置Target(通过创建ServiceMonitor)。至于Prometheus和Grafana在Kubernetes中的安装,请查看前置文章。本篇基于Spring Boot 2.7.0。


1. Spring Boot暴露/actuator/prometheus端点

1.1 集成Spring Actuator模块

Spring Boot官网,关于Actuator,参考:docs.spring.io/spring-boot...

Spring Actuator模块提供了Spring Boot的生产就绪功能(Production-ready Features)。

加入依赖

xml 复制代码
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

端口号

如果没有额外声明,和项目用同一个端口号。也可以额外定义management.server.port=5050

启动Spring Boot项目后,访问:http://localhost:5050/actuator

endpoints

Spring Actuator提供了很多endpoints供查询各种信息。endpoints种类比较多,具体参考:docs.spring.io/spring-boot...

默认情况下开放的endpoints比较少,如访问以下两个端点会报404错误:

默认情况下,只提供了health相关的查询:

可以通过配置上述property进行添加,也可以用通配 * 表示开放所有endpoints。

2. 与Prometheus结合

为什么需要引入Prometheus相关的依赖?虽然Spring Boot的actuator提供了一些监控数据,但如果想要在Prometheus UI上显示或是使用Grafana图形化显示,就需要特定的格式,而项目micrometer-registry-prometheus正是帮我们做了这件事。

首先引入依赖:

xml 复制代码
    <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-registry-prometheus</artifactId>
    </dependency>

看Spring Boot Actuator官网,支持endpoints=prometheus:

第#1.1章说了默认情况下只开放了health endponts,所以需要主动加上prometheus

ini 复制代码
    management.endpoints.web.exposure.include=health,prometheus

测试项目没有配management.server.port,所以这里端口号还是8080。

访问:http://localhost:8080/actuator/prometheus,可以看到很多运行相关的信息,以下截图是jvm相关的,因为信息很多,所以一般需要通过UI进行展示:

2. 编写Dockerfile文件

这块可以参考我之前的文章:# 【k8s学习】布署Spring Boot项目到minikube上,写的很详细。

sql 复制代码
FROM openjdk:17-alpine
COPY target/spring-acturator-test.jar spring-acturator-test.jar
expose 8080
ENTRYPOINT ["java","-jar","spring-acturator-test.jar"]

3. Prometheus怎么发现新的Target?

本文假设Prometheus和Grafana已经在Kubernetes中安装好了,如没有安装,请参考文章开头的前置文章。

访问Prometheus Dashboard:http://localhost:9090

Prometheus默认集成了一些Targets,如:

通地命令查看servicemonitor,是Kubernetes定制的Kubernetes component,正是以下这些servicemonitor产生了上述Prometheus的Targets:

$ kubectl get servicemonitor -n monitoring

NAME AGE

prometheus-grafana 66m

prometheus-kube-prometheus-alertmanager 66m

prometheus-kube-prometheus-apiserver 66m

prometheus-kube-prometheus-coredns 66m

prometheus-kube-prometheus-kube-controller-manager 66m

prometheus-kube-prometheus-kube-etcd 66m

prometheus-kube-prometheus-kube-proxy 66m

prometheus-kube-prometheus-kube-scheduler 66m

prometheus-kube-prometheus-kubelet 66m

prometheus-kube-prometheus-operator 66m

prometheus-kube-prometheus-prometheus 66m

prometheus-kube-state-metrics 66m

prometheus-prometheus-node-exporter 66m

我们查看其中一个servicemonitor,以yaml形式展示:

$ kubectl get servicemonitor prometheus-grafana -n monitoring -o yaml

可以看到资源类型是ServiceMonitor,endpoints的端点是metrics,其中一个label是app.kubernetes.io/instance: prometheus,这里的label为什么是prometheus呢?其实是我们chart的name,我们在install prometheus的时候用的命令是helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring,那么这里的release-name就是prometheus,如果我们换成abc,这里的release-name也会是abc,只要和CRD中的matchLabels对应起来就可以了(下文有介绍CRD):

yaml 复制代码
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  annotations:
    meta.helm.sh/release-name: prometheus
    meta.helm.sh/release-namespace: monitoring
  creationTimestamp: "2024-04-14T06:06:21Z"
  generation: 1
  labels:
    app.kubernetes.io/instance: prometheus
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: grafana
    app.kubernetes.io/version: 10.4.0
    helm.sh/chart: grafana-7.3.7
  name: prometheus-grafana
  namespace: monitoring
  resourceVersion: "5103"
  uid: 1f009abd-37ac-4ebe-ad7b-a582b419c5ba
spec:
  endpoints:
  - honorLabels: true
    path: /metrics
    port: http-web
    scheme: http
    scrapeTimeout: 30s
  jobLabel: prometheus
  namespaceSelector:
    matchNames:
    - monitoring
  selector:
    matchLabels:
      app.kubernetes.io/instance: prometheus
      app.kubernetes.io/name: grafana

要想看具体内部是怎么关联的,我们需要再查看CRD。上述ServiceMonitor的apiVersion为:apiVersion: monitoring.coreos.com/v1,我们查看下CRD,首先列出所有CRDs:

$ kubectl get crd -n monitoring

NAME CREATED AT

prometheuses.monitoring.coreos.com 2024-04-14T05:32:50Z <其它略>

具体查看CRD=prometheuses.monitoring.coreos.com,以yaml格式展示:

$ kubectl get prometheuses.monitoring.coreos.com -n monitoring -o yaml

资源定义很长,其中一段定义,所以我们创建的ServiceMonitor,需要加上这个Label,否则就不会被关联上并发现,如果我们chart name为其它名字,如abc,那么在安装生成CRD的时候这里的release就会是abc,而不是prometheus:

yaml 复制代码
serviceMonitorSelector:
      matchLabels:
        release: prometheus

4. 编写Spring Boot的ServiceMonitor

本文参考的是上述视频2中的Git Sample: github.com/kodedge-swa...

进入Spring Boot项目目录,创建helm chart:

$ helm create ytchart

Creating ytchart

这样helm chart就创建好了,我们只需要修改其中的几个配置即可:

a. 首先要修改的是value.yaml中的image:

yaml 复制代码
image:
  repository: spring-monitoring-kube
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "latest"

还需要修改value.yaml的service定义:

yaml 复制代码
service:
  type: NodePort
  port: 8080
  serviceLabel: spring-svc
  jobName: spring-microservice-job

b. 其次修改service.yaml

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: {{ include "ytchart.fullname" . }}
  labels:
    app: {{ .Values.service.serviceLabel }}
    job: {{ .Values.service.jobName }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    {{- include "ytchart.selectorLabels" . | nindent 4 }}

c. 新建service-monitor.yaml,这边的selector.matchLabels需要和service中的labels对应起来,而这里的labels需要和CRD中的matchLabels对应起来(上一章节有介绍过)。

interval=5s表示每隔5秒来抓取一次数据。

yaml 复制代码
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: spring-boot-microservice-monitor
  labels:
    release: prometheus
spec:
  jobLabel: job
  endpoints:
    - interval: 5s
      path: /actuator/prometheus
      port: http
  namespaceSelector:
    any: true
  selector:
    matchLabels:
      app: {{ .Values.service.serviceLabel }}
      job: {{ .Values.service.jobName }}

d. 还需要把deployment.yaml中的livenessProbereadinessProbe先注释掉。

5. 开始布署

build docker image:

docker build -t spring-acturator-test .

以下这个命令是可以使minikube读取本地的docker images,这样就可以不需要让我们的docker image进行push到远程的操作了:

eval $(minikube docker-env)

安装chart:

helm install mychart ytchart

查看安装结果:

$ kubectl get pod

NAME READY STATUS RESTARTS AGE

pod/mychart-ytchart-5c686c8db8-xzm9p 1/1 Running 0 15s

查看service:

kubectl get service

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

kubernetes ClusterIP 10.96.0.1 443/TCP 3h42m

mychart-ytchart NodePort 10.110.23.68 8080:32634/TCP 96m

对service进行转发以便本地可以访问:

kubectl port-forward service/mychart-ytchart 8080:8080

访问:http://localhost:8080/actuator/prometheus,返回metrics数据。

此时访问Prometheus Dashboard的Service Discoveryhttp://localhost:9090/service-discovery,可以看到Spring Boot的Metrics了:

总结起来就是service-monitor.yaml起作用了。

6. 在Grafana中增加Spring Boot Dashboard

Prometheus并不是必须依赖Grafana,至第5章,Prometheus已经可以定期抓取运行在Kubernetes中的Spring Boot项目的Metrics了,我们可以通过Prometheus的Dashboard进行PromQL查询(如下图:在1中输入PromQL,点击2运行,3是运行结果):

但Grafana的展示更为强大。访问grafana.com/grafana/das...,查询我们想要的Grafana dashboard,输入Spring Boot查询,添加第2个结果:

点击进去,复制Dashboard ID:

回到Grafana Dashboard页面,右侧New --> Import

输入上述复制的Dashboard ID,点击Load:

Prometheus下拉框选择Prometheus,点击Import:

这样就可以展示我们Spring Boot项目Metrics了:

7. 验证抓取间隔

我们上面service-monitor.yaml配置的internal=5s,可以验证下。

在Spring Boot项目application.properties中打开DispatcherServlet类的DEBUG:

ini 复制代码
logging.level.org.springframework.web.servlet.DispatcherServlet=DEBUG

重新docker build。

helm也需要先uninstall,再install:

helm uninstall mychart
helm install mychart ytchart

查看pod日志:

kubectl logs -f mychart-ytchart-5c686c8db8-x68sv

日志结果,可以看出每隔5秒/actuator/prometheus被调用了一次:

2024-04-14 13:02:21.204 DEBUG 1 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet : GET "/actuator/prometheus", parameters={}

2024-04-14 13:02:21.211 DEBUG 1 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet : Completed 200 OK

2024-04-14 13:02:26.204 DEBUG 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/actuator/prometheus", parameters={}

2024-04-14 13:02:26.213 DEBUG 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 200 OK

2024-04-14 13:02:31.203 DEBUG 1 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : GET "/actuator/prometheus", parameters={}

2024-04-14 13:02:31.211 DEBUG 1 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed 200 OK

相关推荐
追逐时光者3 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_3 小时前
敏捷开发流程-精简版
前端·后端
苏打水com4 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧5 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧5 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧5 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧5 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧5 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng6 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6016 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring