Problem with kubernetes dicovery client in gateway microservice

1/15/2020

I'm working on a microservices architecture just on spring and kubernetes. Right now I'm working on the gateway microservice. During the startup of the microservice I have the following error at runtime:

Blockquote

2020-01-15 11:00:57.312 ERROR 1 --- [      elastic-4] reactor.core.scheduler.Schedulers        : Scheduler worker in group main failed with an uncaught exception

reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalStateException
Caused by: java.lang.IllegalStateException: null
    at java.util.Optional.orElseThrow(Optional.java:290) ~[na:1.8.0_212]
    at org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryClient.findEndpointPort(KubernetesDiscoveryClient.java:218) ~[spring-cloud-kubernetes-discovery-1.1.1.RELEASE.jar!/:1.1.1.RELEASE]
    at org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryClient.getNamespaceServiceInstances(KubernetesDiscoveryClient.java:161) ~[spring-cloud-kubernetes-discovery-1.1.1.RELEASE.jar!/:1.1.1.RELEASE]
    at org.springframework.cloud.kubernetes.discovery.KubernetesDiscoveryClient.getInstances(KubernetesDiscoveryClient.java:118) ~[spring-cloud-kubernetes-discovery-1.1.1.RELEASE.jar!/:1.1.1.RELEASE]
    at org.springframework.cloud.kubernetes.discovery.reactive.KubernetesReactiveDiscoveryClient.lambda$getInstances$0(KubernetesReactiveDiscoveryClient.java:58) ~[spring-cloud-kubernetes-discovery-1.1.1.RELEASE.jar!/:1.1.1.RELEASE]
    at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:46) ~[reactor-core-3.3.2.RELEASE.jar!/:3.3.2.RELEASE]
    at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194) ~[reactor-core-3.3.2.RELEASE.jar!/:3.3.2.RELEASE]
    at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84) ~[reactor-core-3.3.2.RELEASE.jar!/:3.3.2.RELEASE]
    at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37) ~[reactor-core-3.3.2.RELEASE.jar!/:3.3.2.RELEASE]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_212]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_212]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_212]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_212]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_212]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_212]

2020-01-15 11:00:57.481  INFO 1 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 9080
2020-01-15 11:00:57.485  INFO 1 --- [           main] i.m.gateway.GatewayApplication           : Started GatewayApplication in 7.941 seconds (JVM running for 8.67)

Blockquote

The problem appeared with the move to kubernetes service discovery by adding the spring-cloud-starter-kubernetes dependency. By using another service discovery such as eureka or consul the gateway works correctly. Below is the pom:

<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> 
    </parent>
    <groupId>it.milionaires</groupId>
    <artifactId>gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway</name>
    <description>Gateway service</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <!--Dipendenza per gateway spring-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-core</artifactId>
            <version>3.3.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-kubernetes</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-netflix-hystrix</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.13</version>
                <executions>
                    <execution>
                        <id>tag-latest</id>
                        <goals>
                            <goal>build</goal>
                            <goal>tag</goal>
                            <goal>push</goal>
                        </goals>
                        <configuration>
                            <repository>gateway</repository>
                            <tag>latest</tag>
                        </configuration>
                    </execution>
                    <execution>
                        <id>tag-version</id>
                        <goals>
                            <goal>build</goal>
                            <goal>tag</goal>
                            <goal>push</goal>
                        </goals>
                        <configuration>
                            <repository>gateway</repository>
                            <tag>${project.version}</tag>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Has anyone encountered this problem or know how to fix it? Thanks in advance This is my deployment.yml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gateway-deployment
  labels:
    app: gateway
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gateway
  template:
    metadata:
      labels:
        app: gateway
    spec:
      containers:
        - name: gateway
          image: liviucornel/gateway
          ports:
            - containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
  name: gateway
spec:
  selector:
    app: gateway
  ports:
    - port: 9080
      targetPort: 9080
#      nodePort: 30010
  type: ClusterIP

This is the property file :

server:
  port: 9080

spring:
  application:
    name: gateway 
  profiles:
    active: zone2 
  cloud:
    loadbalancer:
      ribbon:
        enabled: false 
    config:
      uri: http://configuration-server
      failFast: false
      discovery:
        service-id: configuration-server
        enabled: true
      retry:
        maxAttempts: 20
      enabled: true
      request-connect-timeout: 500
      request-read-timeout: 500
    kubernetes:
      discovery:
        service-name: gateway
        primary-port-name: 9080
        enabled: true
        all-namespaces: true

    gateway:
      routes:
        - id : servizio1
          uri : lb://servizio1 
          predicates :
            - Path=/servizio1/**
          filters :
            - RewritePath=/servizio1/servizio1/(?<path>.*), /$\{path}
#            - name : ServiceGatewayPreFilter
#            - name : ServiceGatewayPostFilter
        - id: servizio2
          uri: lb://servizio2
          predicates:
            - Path=/servizio2/**
          filters:
            - RewritePath=/servizio2/servizio2/(?<path>.*), /$\{path}
      default-filters:
        - name : ServiceGatewayGlobalFilter
      discovery:
        locator:
          enabled: true

This is the docker file :

FROM openjdk:8-jdk-alpine

MAINTAINER Liviu <liviucornelciobanu91@gmail.com>

# Add a volume pointing to /tmp
VOLUME /tmp

# Make port 9080 available to the world outside this container
EXPOSE 9080

# The application's jar file
ARG JAR_FILE=target/gateway-0.0.1-SNAPSHOT.jar

# Add the application's jar to the container
ADD ${JAR_FILE} gateway.jar


# Run the jar file
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/gateway.jar"]
-- Liviu
kubernetes
service-discovery
spring-boot
spring-cloud-gateway
spring-cloud-kubernetes

1 Answer

1/20/2020

I have found the solution for my problem. The problem was with the DiscoveryClient Route Definition Locator on spring-cloud-gateway. I saw in the documentation that:

"The Gateway can be configured to create routes based on services registered with a DiscoveryClient compatible service registry. To enable this, set spring.cloud.gateway.discovery.locator.enabled=true and make sure a DiscoveryClient implementation is on the classpath and enabled (such as Netflix Eureka, Consul or Zookeeper)."

This properties doesn't work with Kubernate configuration Service Discovery. I have changed it to False and it worked!! Greetings

-- Liviu
Source: StackOverflow