Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up Spring Cloud Gateway application so it can use the Service Discovery of Spring Cloud Kubernetes?

I created two Spring Boot applications which both will be deployed in a Kubernetes cluster. One of those apps will act as a gateway and therefore uses Spring Cloud Gateway as a dependency. Also I want to integrate service discovery with Spring Cloud Kubernetes and that the gateway uses the service discovery to automatically generate corresponding routes. But when I expose the gateway application, which is running in an local Minikube cluster, and invoke the second app/service I get a 503 error with following message: Unable to find instance for ...-service

Currently I have installed following:

  • Minikube
  • VirtualBox
  • Docker Toolbox

I have created a Gradle project with two subprojects (gateway and another service). All projects will be build/deployed locally. The default Service Account has permission to read the Kubernetes API. After deployment of those services I expose the gateway service externally. In the gateway service I have some endpoints implemented, which

  1. provide a list of all services in the cluster vie the DiscoveryClient.
  2. on application layer invoke the other service based on the URI provided by the DiscoveryClient.

Everything seems to work but when I invoke the other service with URI/serviceId I get the 503 error...

Following Spring Cloud versions are used: spring-cloud-starter-kubernetes 1.0.1.RELEASE spring-cloud-starter-gateway 2.1.1.RELEASE

My demo app is available at https://github.com/nmaoez/spring-cloud-gateway-kubernetes and the README.md provides steps to get both services deployed in a local Minikube cluster. Also all available endpoints are shown. But the interessing part are the application.yaml and the application class of the gateway.

application.yaml:

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
management:
  endpoints:
    web:
      exposure:
        include: '*'

GatewayApplication.java

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class GatewayApplication {

  @Autowired
  RestTemplate restTemplate;

  @Autowired
  private DiscoveryClient discoveryClient;

  @GetMapping("/")
  @ResponseBody
  public String hello() {
    return "GatewayApplication says hello!";
  }

  @GetMapping("/test")
  @ResponseBody
  public String invokeTestService() {
    List<ServiceInstance> testServiceInstances = this.discoveryClient.getInstances("test-service");
    return restTemplate.getForObject(testServiceInstances.get(0).getUri(), String.class);
  }

  @GetMapping("/services")
  public List<String> services() {
    return this.discoveryClient.getServices();
  }

  @GetMapping("/services/{serviceId}")
  public List<ServiceInstance> servicesById(@PathVariable("serviceId") String serviceId) {
    return this.discoveryClient.getInstances(serviceId);
  }

  @Bean
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

  public static void main(String[] args) {
    SpringApplication.run(GatewayApplication.class, args);
  }
}

I got it some how running after I overwrote the url-expression field in the gateway-service/application.yaml to

url-expression: "uri+'/'"

After that I got a correct response after I invoked gateway-uri/another-service/. But my wish is to not explicitly replace the default of lb://serviceid. How can I do that?

I expect that if I invoke another service in the cluster though the gateway, I get a 200 response and the correct answer based in the rest controller of the application.

like image 989
aoez Avatar asked May 16 '19 14:05

aoez


People also ask

Which module of spring Cloud is used to implement service discovery?

Spring Cloud Cloudfoundry Provides a service discovery implementation and also makes it easy to implement SSO and OAuth2 protected resources.

Can we use spring Cloud with kubernetes?

By default Spring Cloud Kubernetes will enable the kubernetes profile when it detects it is running inside a Kubernetes cluster. You can take advantage of this by creating a kubernetes-application configuration properties for anything specific to Kubernetes you might want to configure.

How would you define spring Cloud gateway routes in application properties?

Spring Cloud Gateway matches routes using the Spring WebFlux HandlerMapping infrastructure. It also includes many built-in Route Predicate Factories. All these predicates match different attributes of the HTTP request. Multiple Route Predicate Factories can be combined via the logical “and”.


1 Answers

You have to add the dependency to spring-cloud-starter-kubernetes-ribbon as well.

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
            <version>1.0.1.RELEASE</version>
        </dependency>

Then it will work without any rewrites, just with the spring.cloud.gateway.discovery.locator.enabled: true

like image 155
Jakub Kubrynski Avatar answered Nov 27 '22 11:11

Jakub Kubrynski