Let’s discover how to monitor Spring Boot apps using Prometheus on Kubernetes clusters. Prometheus and the app will be deployed to different Kubernetes namespaces. So we’ll also see how using ExternalName Kubernetes service enables Prometheus to get metrics of Spring Boot Java app deployed to a different namespace.
If you later find this article useful take a look at the disclaimer for information on how to thank me.
This post assumes familiarity with all the mentioned technologies. Let’s jump straight to the demo.
Demo
Demo Prerequisites
As both Spring Boot Java app and Prometheus will be installed in a Kubernetes cluster, we’ll need such a cluster.
I’ll use Linode’s managed Kubernetes cluster for the demo and will create the Kubernetes cluster on Linode using linode-cli. If you prefer a UI you can create Kubernetes Cluster on Linode using its Cloud Manager UI. Linode is a cloud service provider recently purchased by Akamai. With this purchase, Akamai became a competitor in the cloud providers market. You can repeat this demo on your own Linode account. Create one and get 100$ credit using this link.
In addition to the Kubernetes cluster, you’ll need kubectl
and helm
installed on your local machine.
Below demo assumes you downloaded kubeconfig
of the cluster and set it as kubectl
config context.
Create Spring Boot Java App
I’ll use a sample java Spring Boot app from my GitHub for the demo. It’s a fork of this project. As I’ve built and pushed the app image to DockerHub, we can deploy it to the Kubernetes cluster as a pod.
kubectl run --image=warrior7089/java-spring-boot-metrics jsbm -n default
Let’s expose it as a Kubernetes service. We’ll use the below manifest for this and run kubectl create -f templates/service.yaml
to create the service.
apiVersion: v1
kind: Service
metadata:
labels:
app: jsbm
name: jsbm
namespace: default
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: jsbm
type: ClusterIP
To make sure the app was deployed successfully and is exposing Prometheus metrics let’s first use port forwarding to expose it to the outside world:
kubectl port-forward svc/jsbm 8080:8080
Next access http://localhost:8080/actuator/prometheus
to see the metrics. Next access http://localhost:8080/greeting
endpoint and access http://localhost:8080/actuator/prometheus
again. Pay attention to greeting
endpoints related metrics, such as greetings_counter_total
and greeting_time_seconds
.
Inspect src/main/java/com/tutorialworks/demos/springbootwithmetrics/GreetingController.java
and the app config file for understanding how the app metrics were exposed as in Prometheus format.
Install Prometheus using Helm
Prometheus will scrape the metrics of Java Spring Boot app. Let’s install it in the same Kubernetes cluster, but in a different namespace.
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/prometheus -f prometheus-config/values.yaml -n prometheus --create-namespace
Let’s go over important parts in Prometheus chart values.yaml
I modified:
As I used Linode cloud, I set Prometheus service type to LoadBalancer
to be able to access it on the internet. Alternatively you may expose Prometheus using Ingres. Next I’ve disabled persistence just for the demo. If you want, you can take advantage of Linode CSI Volumes which will be dynamically provisioned for Prometheus to use.
Next, comes the most important part, scrape config:
extraScrapeConfigs: |
- job_name: 'spring boot metrics'
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
static_configs:
- targets:
- jsbm:8080
We put a java app service name as the scrape target. Will it work? No, as jsbm
service name is reachable only within its own namespace, default
in our case. So how will it work? Let’s see how ExternalName
Kubernetes service will help to expose the service to Prometheus.
Create ExternalName Kubernetes service
Let’s create in Prometheus namespace ExternalName service:
kind: Service
apiVersion: v1
metadata:
name: jsbm
namespace: prometheus
spec:
type: ExternalName
externalName: jsbm.default.svc.cluster.local
ports:
- port: 8080
jsbm.default.svc.cluster.local
is the DNS name of jsbm
service from a default
namespace registered at the Kubernetes cluster DNS Service. By mapping service jsbm
in prometheus
namespace to the DNS name using this ExternalName
we enabled the scraping of Spring Boot app’s metrics by Prometheus.
Double check that you can see the app metrics in Prometheus.
Summary
We discovered how to monitor Spring Boot apps using Prometheus on Kubernetes clusters. As always, feel free to share.
If you found this article useful, take a look at the disclaimer for information on how to thank me.
You may find interesting below articles I wrote:
and other ways to enrich your knowledge:
- Become a Certified Kubernetes Administrator (CKA)!
- Become a Certified Kubernetes Application Developer (CKAD)!
- BUNDLE KUBERNETES FUNDAMENTALS & CKA CERTIFICATION (COURSE & CERTIFICATION) FOR THE BEST DEAL! $499 ONLY!
Recommended Kubernetes
courses on Pluralsight:
- Deploying Stateful Applications in Kubernetes
- Configuring and Managing Kubernetes Storage and Scheduling
Sign up using this link to get exclusive discounts like 50% off your first month or 15% off an annual subscription)
Recommended Kubernetes books on Amazon.