Search code examples
spring-bootnetflix-eurekaservice-discoverykong

How to configure kong api gateway with service discovery?


I am working on a microservice architecture. I want to have a kong API gateway implemented at the front. I don't want to go into kong admin API and manually add all the exposed API. Can I take the help of any service discovery implementation like eureka to autoconfigure my APIs to Kong?


Solution

  • You can use a combination of OpenAPI spec generation using springdoc-openapi and a transformation to Kong's Declarative Configuration using Insomnia's Inso CLI. This approach frees you from the need to manually use Kong's admin API to add Spring Boot services (which I don't like to do):

    enter image description here

    This process is even automatable inside your (e.g. Maven) build - and would be updated automatically after every build or push (if configured inside your CI/CD pipeline).

    I created a fully comprehensible blog post for this scenario, but here are the brief steps:

    1. Generating the OpenAPI spec with the springdoc-openapi-maven-plugin

    Add springdoc-openapi-ui to your pom.xml:

    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
        <version>1.4.8</version>
    </dependency>
    

    Then add springdoc-openapi-maven-plugin and configure your spring-boot-maven-plugin to run it inside the pre-integration-test phase:

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
            <execution>
                <id>pre-integration-test</id>
                <goals>
                    <goal>start</goal>
                </goals>
            </execution>
            <execution>
                <id>post-integration-test</id>
                <goals>
                    <goal>stop</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-maven-plugin</artifactId>
        <version>1.1</version>
        <executions>
            <execution>
                <phase>integration-test</phase>
                <goals>
                    <goal>generate</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    Now a mvn verify already generates an openapi.json inside your target directory.

    2. Generating Kong Declarative Configuration from OpenAPI spec

    Install Insomnia Inso CLI via npm:

    npm i -g insomnia-inso
    

    Now use Insomnica Inso CLI to generate Kong Declarative Configuration from the OpenAPI json:

    inso generate config weatherbackend/target/openapi.json --output kong/kong.yml --type declarative --verbose
    

    This will generate a kong/kong.yml like this:

    _format_version: "1.1"
    services:
      - name: weatherbackend
        url: http://weatherbackend:8080
        plugins: []
        routes:
          - tags:
              - OAS3_import
            name: weatherbackend-path-get
            methods:
              - GET
            paths:
              - /weather/general/outlook
            strip_path: false
          - tags:
              - OAS3_import
            name: weatherbackend-path_1-post
            methods:
              - POST
            paths:
              - /weather/general/outlook
            strip_path: false
          - tags:
              - OAS3_import
            name: weatherbackend-path_2-get
            methods:
              - GET
            paths:
              - /weather/(?<name>\S+)$
            strip_path: false
        tags:
          - OAS3_import
    upstreams:
      - name: weatherbackend
        targets:
          - target: weatherbackend:8080
        tags:
          - OAS3_import
    

    3. Running Kong in DB-less Declarative Configuration Mode based on the generated kong.yml

    You can use this file directly as Kong's configuration! See this Docker Compose deployment as an example on how to do that:

    version: '3.7'
    
    services:
      kong:
        image: kong:2.2.0
        environment:
          KONG_ADMIN_ACCESS_LOG: /dev/stdout
          KONG_ADMIN_ERROR_LOG: /dev/stderr
          KONG_ADMIN_LISTEN: '0.0.0.0:8001'
          KONG_DATABASE: "off"
          KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong.yml
          KONG_PROXY_ACCESS_LOG: /dev/stdout
          KONG_PROXY_ERROR_LOG: /dev/stderr
        volumes:
          - ./kong/:/usr/local/kong/declarative
        networks:
          - kong-net
        ports:
          - "8000:8000/tcp"
          - "127.0.0.1:8001:8001/tcp"
          - "8443:8443/tcp"
          - "127.0.0.1:8444:8444/tcp"
        healthcheck:
          test: ["CMD", "kong", "health"]
          interval: 10s
          timeout: 10s
          retries: 10
        restart: on-failure
        deploy:
          restart_policy:
            condition: on-failure
     
      # no portbinding here - the actual services should be accessible through Kong
      weatherbackend:
        build: ./weatherbackend
        ports:
          - "8080"
        networks:
          - kong-net
        tty:
          true
        restart:
          unless-stopped
    
    networks:
      kong-net:
        external: false
    

    The whole process is automatable (e.g. using the exec-maven-plugin as described in my post).

    If you're in doubt how this all works together you may also check out this example project which leverages every step mentioned here (incl. the CI/CD automation of every step): https://github.com/jonashackt/spring-boot-openapi-kong