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:
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
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.
Spring Cloud Cloudfoundry Provides a service discovery implementation and also makes it easy to implement SSO and OAuth2 protected resources.
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.
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”.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With