We usually use gRPC for internal service communication, but sometime we need to expose the connection for 3rd party or another client to connect. The architecture is almost same as the image below.

We have several gRPC service listen port diference port, we placed Kong Gateway in the front of them. gRPC client will connect to Kong though HTTP/2 and use ALTS.

I will use a widecard certificate for Kong Gateway, the FQDN is *.dongnguyen.link
.
So let start.
Deploy Kong Gateway
I will deploy Kong
using docker-compose
for testing purpose. The docker-compose.yml
content is below.
version: "3.9"
networks:
default:
name: kong-db-less
driver: bridge
configs:
kong:
file: kong.yaml
cert:
file: kong.crt
key:
file: kong.pem
x-kong-env:
&kong-env
KONG_DATABASE: "off"
KONG_DECLARATIVE_CONFIG: /home/kong/kong.yaml
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001
KONG_PROXY_LISTEN: 0.0.0.0:443 http2 ssl
KONG_SSL_CERT: /etc/ssl/kong.crt
KONG_SSL_CERT_KEY: /etc/ssl/kong.pem
services:
kong:
image: kong
environment: *kong-env
configs:
- source: kong
target: /home/kong/kong.yaml
- source: cert
target: /etc/ssl/kong.crt
- source: key
target: /etc/ssl/kong.pem
privileged: true
restart: always
ports:
- 443:443
- 8001:8001
In this directory we also have
- kong.crt
is the fullchain CA certification that kong
use for https
listener
- kong.pem
is the private key
for tls
- kong.yaml
is the kong declartive
file, our kong
will run in db less
mode, so the kong admin api
is read only
.
The current directory
❯ tree
.
├── docker-compose.yml
├── kong.crt
├── kong.pem
├── kong.yaml
1 directory, 4 files
The kong.yaml
define all service and also route to the service.
_format_version: "3.0"
_transform: true
services:
- name: order
host: 192.168.1.115
port: 9000
protocol: grpc
tags:
- order
routes:
- name: order
preserve_host: true
snis:
- order.dongnguyen.link
strip_path: false
protocols:
- grpcs
- name: noti
host: 192.168.1.115
port: 10000
protocol: grpc
tags:
- noti
routes:
- name: noti
preserve_host: true
snis:
- noti.dongnguyen.link
strip_path: false
protocols:
- grpcs
As you can see, in this kong.yaml
file above, i defined two services order
and api
.
Kong will proxy traffic to order
service if they recieved request with SNI
equal to order.dongnguyen.link
, the order
service is listening on 192.168.1.115:9000
behind kong
.
Kong will proxy traffic to noti
service if they recieved request with SNI
equal to noti.dongnguyen.link
, the noti
service is listening on 192.168.1.115:1000
behind kong
.
Now deploy kong
using docker compose
cli.
docker compose up

View Kong Service Route by KongA
Kong Inc did not provide us the management UI for community version, but luckily we have https://github.com/pantsel/konga, please checkout this site to deploy a konga
server.
For me i already deployed on my host machine. So i can access kong admin api
though port 8001
on host machine.

Go to Services
tab, you will see that we have 2 defined services.

Go to Routes
tab, you will see that we have 2 defined routes.

Deploy Dummy gRPC Server
We will use https://github.com/moul/grpcbin to deployed 2 fake gRPC server that listen on port 9000
and also 10000
.
Order
service listen on port 9000
docker run -it --rm -p 9000:9000 -p 9001:9001 moul/grpcbin

Noti
service listen on port 10000
docker run -it --rm -p 10000:9000 -p 10001:9001 moul/grpcbin

Send Test Request
I will use https://github.com/fullstorydev/grpcurl to send traffic to two servers above.
- Call
order.dongnguyen.link
docker run fullstorydev/grpcurl -v -d \
'{"greeting": "Kong gRPC"}' \
order.dongnguyen.link:443 hello.HelloService.SayHello

From stdout
you can see that kong proxied traffic to order
service.
2. Call order.dongnguyen.link
docker run fullstorydev/grpcurl -v -d \
'{"greeting": "Kong gRPC"}' \
order.dongnguyen.link:443 hello.HelloService.SayHello
The result is same as above.

3. Call whatever.dongnguyen.link

It failed because there is no route with SNI
equal to whatever.dongnguyen.link
That is, this approch is easy to implement, thank for reading the post.