We are currently using Spring Boot Admin for monitoring our microservices inside the OpenShift cluster.
Spring Boot Admin aplication get information about services from the Openshift's Service Discovery using spring-cloud-starter-kubernetes dependency.
Everything was fine until we deployed application with custom server.servlet.context-path.
For example, our microservice has server.servlet.context-path=/dictionary. However, Spring Boot Admin get the following information from the OpenShift's discovery:
{
"registration": {
"name": "dictionary-service",
"managementUrl": "http://10.130.1.169:8080/actuator",
"healthUrl": "http://10.130.1.169:8080/actuator/health",
"serviceUrl": "http://10.130.1.169:8080/",
"source": "discovery",
"metadata": {
"app": "dictionary-service",
...
}
}
}
So, Spring Boot Admin is expecting actuator working on "http://10.130.1.169:8080/actuator"
but it's actually working on "http://10.130.1.169:8080/dictionary/actuator"
How can we customize managementUrl and healthUrl so our Spring Boot Admin server could use correct URL for monitoring this service?
OK, so I finally solved it. Maybe it will be helpful for someone.
"registration" object from the question is generated in Spring Boot Admin itself. It's the reliability of the ServiceInstanceConverter interface. By default, DefaultServiceInstanceConverter implementation is used (you can read more about this here).
There are several metadata keys that can be used to modify your managementUrl and healthUrl (by default, "/actuator" and "/actuator/health" are used respectively).
First, I thought we can use management.context-path metadata key to append our server.servlet.context-path, but unfortunately, you can't use "/" character in metadata label value ("dictionary/actuator" is invalid), so it wasn't enough in my case.
Instead, we decided to extend DefaultServiceInstanceConverter and override convert and getManagementPath methods:
@Component
public class OpenShiftServiceInstanceConverter extends DefaultServiceInstanceConverter {
private static final String MANAGEMENT_CONTEXT_PATH = "/actuator";
private static final String MANAGEMENT_PREFIX = "management.prefix";
@Override
public Registration convert(ServiceInstance instance) {
return Registration.create(instance.getServiceId(), getHealthUrl(instance).toString())
.managementUrl(getManagementUrl(instance).toString()).serviceUrl(getServiceUrl(instance).toString())
.metadata(getMetadata(instance)).build();
}
@Override
protected String getManagementPath(ServiceInstance instance) {
String managementPath = instance.getMetadata().get(MANAGEMENT_PREFIX);
if (!isEmpty(managementPath)) {
return managementPath + MANAGEMENT_CONTEXT_PATH;
}
return MANAGEMENT_CONTEXT_PATH;
}
}
This way, we can just include server.servlet.context-path as metadata management.prefix key in service template:
kind: Template
apiVersion: v1
metadata:
name: dictionary-service
annotations:
description: Template for Dictionary Service 1.0.0
labels:
app: dictionary-service
management.prefix: dictionary
...
And now it is working like a charm.