mirror of https://github.com/knative/docs.git
Add sample for custom routing with Kong Gateway (#4110)
* Add sample for custom routing with Kong Gateway * Remove frontmatter * Fix Markdown formatting
This commit is contained in:
parent
d45fdde421
commit
d2f9187c60
|
@ -173,6 +173,7 @@ nav:
|
|||
- Scala: serving/samples/hello-world/helloworld-scala/README.md
|
||||
- Shell: serving/samples/hello-world/helloworld-shell/README.md
|
||||
- Routing services - Go: serving/samples/knative-routing-go/README.md
|
||||
- Routing services with Kong - Go: serving/samples/kong-routing-go/README.md
|
||||
- multi-container samples: serving/samples/multi-container/README.md
|
||||
- RESTful service - Go: serving/samples/rest-api-go/README.md
|
||||
- Secrets - Go: serving/samples/secrets-go/README.md
|
||||
|
|
|
@ -14,6 +14,7 @@ Serving resources and how they can be applied across common use cases.
|
|||
| Github Webhook | A simple webhook handler that demonstrates interacting with Github. | [Go](gitwebhook-go/README.md) |
|
||||
| gRPC | A simple gRPC server. | [Go](grpc-ping-go/README.md) |
|
||||
| Knative Routing | An example of mapping multiple Knative services to different paths under a single domain name using the Istio VirtualService concept. | [Go](knative-routing-go/README.md) |
|
||||
| Kong Routing | An example of mapping multiple Knative services to different paths under a single domain name using the Kong API gateway. | [Go](kong-routing-go/README.md) |
|
||||
| Knative Secrets | A simple app that demonstrates how to use a Kubernetes secret as a Volume in Knative. | [Go](secrets-go/README.md) |
|
||||
| REST API | A simple Restful service that exposes an endpoint defined by an environment variable described in the Knative Configuration. | [Go](rest-api-go/README.md) |
|
||||
| Traffic Splitting | This samples builds off the [Creating a RESTful Service](rest-api-go) sample to illustrate applying a revision, then using that revision for manual traffic splitting. | [YAML](../../developer/serving/traffic-management.md) |
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright 2021 The Knative Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM golang AS builder
|
||||
|
||||
WORKDIR /go/src/github.com/knative/docs/
|
||||
ADD . /go/src/github.com/knative/docs/
|
||||
|
||||
RUN CGO_ENABLED=0 go build ./docs/serving/samples/kong-routing-go/
|
||||
|
||||
FROM gcr.io/distroless/base
|
||||
|
||||
EXPOSE 8080
|
||||
COPY --from=builder /go/src/github.com/knative/docs/kong-routing-go /sample
|
||||
|
||||
ENTRYPOINT ["/sample"]
|
|
@ -0,0 +1,257 @@
|
|||
# Routing across multiple Knative services with Kong
|
||||
|
||||
This example shows how to map multiple Knative services to different paths under
|
||||
a single domain name using [Kong Gateway](https://docs.konghq.com/gateway-oss/).
|
||||
Kong Gateway is a general-purpose reverse proxy and API gateway built on
|
||||
[Nginx](https://www.nginx.com/), therefore these directions can also be used to
|
||||
configure routing based on other request data such as headers, or even to map
|
||||
Knative and external resources under the same domain name.
|
||||
|
||||
In this sample, we set up two web services: _Search_ service and _Login_
|
||||
service, which simply read in an env variable `SERVICE_NAME` and print
|
||||
`"${SERVICE_NAME} is called"`. We'll then define routing rules via [Kong's
|
||||
Kubernetes Ingress
|
||||
Controller](https://docs.konghq.com/kubernetes-ingress-controller/) and [Kong's
|
||||
request transformer
|
||||
plugin](https://docs.konghq.com/hub/kong-inc/request-transformer/), so that
|
||||
`example.com/search` maps to the _Search_ service, and `example.com/login` maps
|
||||
to the _Login_ service.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. A Kubernetes cluster with [Knative Serving](../../../install/) and
|
||||
[Kong](https://docs.konghq.com/kubernetes-ingress-controller/1.3.x/guides/using-kong-with-knative/)
|
||||
installed.
|
||||
1. Install
|
||||
[Docker](https://docs.docker.com/get-started/#prepare-your-docker-environment).
|
||||
1. Acquire a domain name.
|
||||
- In this example, we use `example.com`. If you don't have a domain name,
|
||||
you can modify your hosts file (on macOS or Linux) to map `example.com` to
|
||||
your cluster's ingress IP.
|
||||
- If you have configured a custom domain for your Knative installation, we
|
||||
will refer to it as `<YOUR_DOMAIN_NAME>` in the rest of this document
|
||||
1. Check out the code:
|
||||
|
||||
```bash
|
||||
go get -d github.com/knative/docs/docs/serving/samples/kong-routing-go
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
To check the domain name, run the following command:
|
||||
|
||||
```bash
|
||||
kubectl get cm -n knative-serving config-domain -o yaml
|
||||
```
|
||||
|
||||
Then, check the value for `data`. The domain name should be in the format of
|
||||
`<YOUR_DOMAIN_NAME>: ""`, if it is available.
|
||||
|
||||
Build the application container and publish it to a container registry:
|
||||
|
||||
1. Move into the sample directory:
|
||||
|
||||
```bash
|
||||
cd $GOPATH/src/github.com/knative/docs
|
||||
```
|
||||
|
||||
1. Set your preferred container registry:
|
||||
|
||||
If you use Google Container Registry (GCR), you will need to enable the [GCR
|
||||
API](https://console.cloud.google.com/apis/library/containerregistry.googleapis.com)
|
||||
in your GCP project.
|
||||
|
||||
```bash
|
||||
export REPO="gcr.io/<YOUR_PROJECT_ID>"
|
||||
```
|
||||
|
||||
If you use Docker Hub as your Docker image registry, replace `<username>`
|
||||
with your Docker Hub username and run the following command:
|
||||
|
||||
```bash
|
||||
export REPO="docker.io/<username>"
|
||||
```
|
||||
|
||||
1. Use Docker to build your application container:
|
||||
|
||||
```bash
|
||||
docker build \
|
||||
--tag "${REPO}/kong-routing-go" \
|
||||
--file=docs/serving/samples/kong-routing-go/Dockerfile .
|
||||
```
|
||||
|
||||
1. Push your container to a container registry:
|
||||
|
||||
```bash
|
||||
docker push "${REPO}/kong-routing-go"
|
||||
```
|
||||
|
||||
1. Replace the image reference path with our published image path in the
|
||||
configuration file `docs/serving/samples/kong-routing-go/sample.yaml` in one
|
||||
of the following ways:
|
||||
|
||||
- Manually replace `image:
|
||||
github.com/knative/docs/docs/serving/samples/kong-routing-go` with `image:
|
||||
${REPO}/kong-routing-go`. If you manually changed the `.yaml` file, you
|
||||
must replace `${REPO}` with the correct path on your local machine.
|
||||
- Run this command:
|
||||
```bash
|
||||
perl -pi -e "s@github.com/knative/docs/docs/serving/samples@${REPO}@g" docs/serving/samples/kong-routing-go/sample.yaml
|
||||
```
|
||||
|
||||
## Deploy the Service
|
||||
|
||||
Deploy the Knative Serving sample:
|
||||
|
||||
```bash
|
||||
kubectl apply -f docs/serving/samples/kong-routing-go/sample.yaml
|
||||
```
|
||||
|
||||
Inspect the deployed Knative services with:
|
||||
|
||||
```bash
|
||||
kubectl get ksvc
|
||||
```
|
||||
|
||||
You should see 2 Knative services: `search-service` and `login-service`.
|
||||
|
||||
## Exploring the Routes
|
||||
|
||||
Kong Gateway serves all incoming traffic to services managed by Knative. You can
|
||||
inspect the corresponding Kubernetes service for the gateway:
|
||||
|
||||
```bash
|
||||
INGRESSGATEWAY=kong-proxy
|
||||
|
||||
kubectl get svc $INGRESSGATEWAY -n kong --output yaml
|
||||
```
|
||||
|
||||
### Access the Services
|
||||
|
||||
1. Find the gateway IP and export it as an environment variable:
|
||||
|
||||
```bash
|
||||
export GATEWAY_IP=`kubectl get svc $INGRESSGATEWAY -n kong \
|
||||
--output jsonpath="{.status.loadBalancer.ingress[*]['ip']}"`
|
||||
```
|
||||
|
||||
1. Find the _Search_ service URL:
|
||||
|
||||
```bash
|
||||
kubectl get route search-service --output=custom-columns=NAME:.metadata.name,URL:.status.url
|
||||
```
|
||||
|
||||
The output should looks like this:
|
||||
|
||||
```
|
||||
NAME URL
|
||||
search-service http://search-service.default.example.com
|
||||
```
|
||||
|
||||
1. Make a cURL request to the service:
|
||||
|
||||
```bash
|
||||
curl http://${GATEWAY_IP} --header "Host:search-service.default.example.com"
|
||||
```
|
||||
|
||||
The output should look like this:
|
||||
|
||||
```
|
||||
Search Service is called!
|
||||
```
|
||||
|
||||
1. Similarly, you can also directly access _Login_ service:
|
||||
|
||||
```bash
|
||||
curl http://${GATEWAY_IP} --header "Host:login-service.default.example.com"
|
||||
```
|
||||
|
||||
The output should look like this:
|
||||
|
||||
```
|
||||
Login Service is called!
|
||||
```
|
||||
|
||||
## Apply Custom Routing Rule
|
||||
|
||||
1. Apply the custom routing rules defined in the `routing.yaml` file:
|
||||
|
||||
```bash
|
||||
kubectl apply -f docs/serving/samples/kong-routing-go/routing.yaml
|
||||
```
|
||||
|
||||
If you have configured a custom domain name for your service, please replace
|
||||
all mentions of `example.com` in `routing.yaml` with `<YOUR_DOMAIN_NAME>`.
|
||||
|
||||
In addition, you need to verify how your domain template is defined. By
|
||||
default, we use the format of {% raw %}`{{.Name}}.{{.Namespace}}`{% endraw
|
||||
%}, like `search-service.default` and `login-service.default`. However, some
|
||||
Knative environments may use other formats like {% raw
|
||||
%}`{{.Name}}-{{.Namespace}}`{% endraw %}. You can find out the format by
|
||||
running the command:
|
||||
|
||||
```bash
|
||||
kubectl get cm config-network -n knative-serving -o yaml
|
||||
```
|
||||
|
||||
Then, look for the value for `domainTemplate`. If it is {% raw
|
||||
%}`{{.Name}}-{{.Namespace}}.{{.Domain}}`{% endraw %}, you need to change
|
||||
`search-service.default` into `search-service-default` and
|
||||
`login-service.default` into `login-service-default` as well in
|
||||
`routing.yaml`.
|
||||
|
||||
1. The `routing.yaml` file will create an ingress that forwards incoming
|
||||
requests at `example.com/search` to `search-service.default.example.com` by
|
||||
updating the "Host" header to `search-service.default.example.com` and
|
||||
stripping the request path. This modified request is then forwarded to the
|
||||
Knative ingress (Kong) and routed to the service as usual. Another ingress
|
||||
like this is also created for the _Login_ service.
|
||||
|
||||
```bash
|
||||
kubectl get ingress {search,login}-service-ingress -n kong --output yaml
|
||||
```
|
||||
|
||||
1. Send a request to the _Search_ service and the _Login_ service by using
|
||||
their corresponding URLs. You should get the same results as directly
|
||||
accessing these services.
|
||||
|
||||
- Send a request to the _Search_ service:
|
||||
```bash
|
||||
curl http://${GATEWAY_IP}/search --header "Host: example.com"
|
||||
```
|
||||
or
|
||||
```bash
|
||||
curl http://${GATEWAY_IP}/search --header "Host: <YOUR_DOMAIN_NAME>"
|
||||
```
|
||||
for the case using your own domain.
|
||||
|
||||
- Send a request to the _Login_ service:
|
||||
```bash
|
||||
curl http://${GATEWAY_IP}/login --header "Host: example.com"
|
||||
```
|
||||
or
|
||||
```bash
|
||||
curl http://${GATEWAY_IP}/login --header "Host: <YOUR_DOMAIN_NAME>"
|
||||
```
|
||||
for the case using your own domain.
|
||||
|
||||
## How It Works
|
||||
|
||||
When a request with host `example.com` or your own domain name reaches Kong
|
||||
Gateway, Kong will check if the URL path prefix is `/search` or `/login`. If the
|
||||
URL matches on of the two rules, then the "Host" header of the request will be
|
||||
rewritten into the host of the _Search_ service or _Login_ service,
|
||||
respectively, and the path will be stripped. The modified request will be
|
||||
forwarded to Kong again. Kong will check the "Host" header and forward the
|
||||
request to the _Search_ or _Login_ service according to the header value.
|
||||
|
||||

|
||||
|
||||
## Clean Up
|
||||
|
||||
To clean up the sample resources:
|
||||
|
||||
```bash
|
||||
kubectl delete --filename docs/serving/samples/kong-routing-go/sample.yaml
|
||||
kubectl delete --filename docs/serving/samples/kong-routing-go/routing.yaml
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 102 KiB |
|
@ -0,0 +1,101 @@
|
|||
# Copyright 2021 The Knative Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Create a Kong request transformer plugin to rewrite the original host header
|
||||
# to the host header of Search service in order to redirect requests to Search
|
||||
# service.
|
||||
apiVersion: configuration.konghq.com/v1
|
||||
kind: KongPlugin
|
||||
metadata:
|
||||
name: search-service-host-rewrite
|
||||
# The plugin must be created in the same namespace as the ingress.
|
||||
namespace: kong
|
||||
plugin: request-transformer
|
||||
config:
|
||||
add:
|
||||
headers:
|
||||
- "Host: search-service.default.example.com"
|
||||
replace:
|
||||
headers:
|
||||
- "Host: search-service.default.example.com"
|
||||
---
|
||||
# Create an ingress that forwards an incoming request at example.com/search to
|
||||
# "search-service.default.example.com" by updating the "Host" header to
|
||||
# "search-service.default.example.com" and stripping the request path. This
|
||||
# modified request is then forwarded to the Knative ingress (Kong) and routed
|
||||
# to the service as usual.
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: search-service-ingress
|
||||
# The ingress must be created in the same namespace as the kong-proxy service.
|
||||
namespace: kong
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: kong
|
||||
konghq.com/strip-path: "true"
|
||||
konghq.com/plugins: search-service-host-rewrite
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- host: example.com
|
||||
path: /search
|
||||
backend:
|
||||
serviceName: kong-proxy
|
||||
servicePort: 80
|
||||
|
||||
---
|
||||
|
||||
# Create a Kong request transformer plugin to rewrite the original host header
|
||||
# to the host header of Login service in order to redirect requests to Login
|
||||
# service.
|
||||
apiVersion: configuration.konghq.com/v1
|
||||
kind: KongPlugin
|
||||
metadata:
|
||||
name: login-service-host-rewrite
|
||||
# The plugin must be created in the same namespace as the ingress.
|
||||
namespace: kong
|
||||
plugin: request-transformer
|
||||
config:
|
||||
add:
|
||||
headers:
|
||||
- "Host: login-service.default.example.com"
|
||||
replace:
|
||||
headers:
|
||||
- "Host: login-service.default.example.com"
|
||||
---
|
||||
# Create an ingress that forwards an incoming request at example.com/login to
|
||||
# "login-service.default.example.com" by updating the "Host" header to
|
||||
# "login-service.default.example.com" and stripping the request path. This
|
||||
# modified request is then forwarded to the Knative ingress (Kong) and routed
|
||||
# to the service as usual.
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: login-service-ingress
|
||||
# The ingress must be created in the same namespace as the kong-proxy service.
|
||||
namespace: kong
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: kong
|
||||
konghq.com/strip-path: "true"
|
||||
konghq.com/plugins: login-service-host-rewrite
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- host: example.com
|
||||
path: /login
|
||||
backend:
|
||||
serviceName: kong-proxy
|
||||
servicePort: 80
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright 2021 The Knative Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
serviceName := os.Getenv("SERVICE_NAME")
|
||||
if serviceName == "" {
|
||||
serviceName = "NOT SPECIFIED"
|
||||
}
|
||||
log.Printf("%s received a request.", serviceName)
|
||||
fmt.Fprintf(w, "%s is called!\n", serviceName)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.Print("Sample started.")
|
||||
|
||||
http.HandleFunc("/", handler)
|
||||
http.ListenAndServe(":8080", nil)
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
# Copyright 2021 The Knative Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
apiVersion: serving.knative.dev/v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: search-service
|
||||
namespace: default
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- # This is the Go import path for the binary to containerize
|
||||
# and substitute here.
|
||||
image: github.com/knative/docs/docs/serving/samples/kong-routing-go
|
||||
env:
|
||||
- name: SERVICE_NAME
|
||||
value: Search Service
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
initialDelaySeconds: 3
|
||||
---
|
||||
apiVersion: serving.knative.dev/v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: login-service
|
||||
namespace: default
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- # This is the Go import path for the binary to containerize
|
||||
# and substitute here.
|
||||
image: github.com/knative/docs/docs/serving/samples/kong-routing-go
|
||||
env:
|
||||
- name: SERVICE_NAME
|
||||
value: Login Service
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
initialDelaySeconds: 3
|
Loading…
Reference in New Issue