【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

相关推荐
吃面不喝汤662 小时前
Flask + Swagger 完整指南:从安装到配置和注释
后端·python·flask
讓丄帝愛伱2 小时前
spring boot启动报错:so that it conforms to the canonical names requirements
java·spring boot·后端
weixin_586062022 小时前
Spring Boot 入门指南
java·spring boot·后端
凡人的AI工具箱9 小时前
AI教你学Python 第11天 : 局部变量与全局变量
开发语言·人工智能·后端·python
是店小二呀9 小时前
【C++】C++ STL探索:Priority Queue与仿函数的深入解析
开发语言·c++·后端
canonical_entropy9 小时前
金蝶云苍穹的Extension与Nop平台的Delta的区别
后端·低代码·架构
我叫啥都行10 小时前
计算机基础知识复习9.7
运维·服务器·网络·笔记·后端
无名指的等待71211 小时前
SpringBoot中使用ElasticSearch
java·spring boot·后端
.生产的驴11 小时前
SpringBoot 消息队列RabbitMQ 消费者确认机制 失败重试机制
java·spring boot·分布式·后端·rabbitmq·java-rabbitmq
AskHarries12 小时前
Spring Boot利用dag加速Spring beans初始化
java·spring boot·后端