0

I have Spring Cloud gateway setup to route traffic to various backend services. I also have a fallback route that forwards any unmatched routes to some static content. It works great.

Now I need to expose the gateway's local /actuator/prometheus endpoint for monitoring. By default, this routes to my fallback route, resulting in hitting the actuator endpoint of the fallback service. I need the gateway to serve /actuator/prometheus locally, but I'm not sure how to define this. If I use a URI pointing to the gateway itself, I'll simply wind up in an infinite loop.

  cloud:
    gateway:
      routes:

      # Other routes defined...

      - id: actuator
        uri: http://localhost:8080  # Won't work; infinite loop
        predicates:
        - Path=/actuator/**

        # Fallback route:
      - id: web-interface
        uri: lb://fallback
        predicates:
        - Path=/**

How can I configure Spring Cloud Gateway to serve certain routes locally, like /actuator/**, but still have a fallback route for anything else that is not matched? I could replace my fallback route with "/web/**" or something, but I'd like to avoid changing a lot of front-end code.

Adding key detail: The conundrum listed above is specific to the spring-cloud-starter-gateway reactive version of Spring Cloud Gateway. If I use spring-cloud-starter-gateway-mvc, the /actuator/** endpoints are resolved to the gateway itself, without lifting a finger.

1 Answer 1

0

I had a similar issue, and I solved setting the management port for the actuator endpoints, using this property (e.g. setting 18080 or whatever you need):

management.server.port=18080

As documented in https://docs.spring.io/spring-boot/reference/actuator/monitoring.html and https://docs.spring.io/spring-boot/how-to/actuator.html. You can use this also in the yml format, of course:

management:
  server:
    port: 18080

This makes the actuator run an additional netty server that is used for management only and does not fall under routing rules.

You can also try to customize the prefix for the management endpoints (see in https://docs.spring.io/spring-boot/reference/actuator/monitoring.html) but you can use this only under precise conditions, that are explained in documentation.

Using this setting however, you might have to specify the new port that has to be used for interacting with the Spring Actuator API endpoints.

In the case of a microservice that is deployed on a K8S cluster, for the Deployment, there is the port setting for the probes, e.g.:

readinessProbe:
  httpGet:
    path: /actuator/health/readiness
    port: 18080
  initialDelaySeconds: 5
  periodSeconds: 10

To let service discovery (or other management systems for the microservices cluster, such as Spring Boot Admin) know that management is exposed under a specific port, I found that this approach is useful: for the Service, specify a management.port annotation and expose the customized port with management name. This is an example:

apiVersion: v1
kind: Service
metadata:
  name: my-microservice
  labels:
    app: my-microservice
  annotations:
    management.port: "18080"
spec:
  type: ClusterIP
  selector:
    app: my-microservice
  ports:
    - name: http-default
      protocol: TCP
      port: 8080
      targetPort: 8080
    - name: management
      protocol: TCP
      port: 18080
      targetPort: 18080

I also found an (old) reference of something that seems like this situation: https://github.com/codecentric/spring-boot-admin/issues/437, perhaps it may help.

Sign up to request clarification or add additional context in comments.

3 Comments

Very clever. Of course now I'd need to explain to prometheus that this eureka-discovered instance must be reached by a different port / path than the others, or convert everything over to a different port (which I don't know if I can do with the spring web mvc based services), but it is definitely a thought.
I remember that it is possible to specify, in the k8s Service description, the management port in a way that can be used by clients (i.e. prometheous and others). I don't have right now an example, but I think I can try to find something useful in the next few hours.
@KenKrueger I updated the answer with some hints to try to make the Eureka discover understand correctly which is the customized management port. Hope it helps!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.