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 filesThe 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.
