Categories
Monitoring Orchestration

Monitor Spring Boot Apps using Prometheus on Kubernetes

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:

Recommended Kubernetes courses on Pluralsight:

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.