Enterprise Java

Knative serving – using Ambassador gateway

This is a continuation of my experimentation with Knative serving, this time around building a gateway on top of a Knative serving applications. This builds on two of my previous posts – on using Knative to deploy a Spring Boot App and making a service to service call in Knative.

Why a Gateway on top of Knative application

To explain this let me touch on my previous blog post. Assuming that Knative serving is already available in a Kubernetes environment, the way to deploy an application is using a manifest which looks like this:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: sample-boot-knative-service
  namespace: default
spec:
  runLatest:
    configuration:
      revisionTemplate:
        spec:
          container:
            image: bijukunjummen/sample-boot-knative-app:0.0.3-SNAPSHOT
            env:
            - name: ASAMPLE_ENV
              value: "sample-env-val"

Now to invoke this application, I have to make the call via an ingress created by Knative serving, which can be obtained the following way in a minikube environment:

export GATEWAY_URL=$(echo $(minikube ip):$(kubectl get svc knative-ingressgateway -n istio-system -o 'jsonpath={.spec.ports[?(@.port==80)].nodePort}'))

The request now has to go through the ingress and the ingress uses a Host http header to then route the request to the app. The host header for the deployed service can be obtained using the following bash script:

export APP_DOMAIN=$(kubectl get services.serving.knative.dev sample-boot-knative-service  -o="jsonpath={.status.domain}")

and then a call via the knative ingress gateway made the following way, using CURL:

curl -X "POST" "http://${GATEWAY_URL}/messages" \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -H "Host: ${APP_DOMAIN}" \
     -d $'{
  "id": "1",
  "payload": "one",
  "delay": "300"
}'

or using httpie:

http http://${GATEWAY_URL}/messages Host:"${APP_DOMAIN}" id=1 payload=test delay=1

There are too many steps involved in making a call to the application via the knative ingress:

Ambassador gateway

My objective in this post is to simplify the users experience in making a call to the app by using a Gateway like Ambassador.

Integrating Ambassador to Knative

There is nothing special about installing Ambassador into a Knative environment, the excellent instructions provided here worked cleanly in my minikube environment.

Now my objective with the gateway is summarized in this picture:

Ambassador gateway

With Ambassador in place, all the user has to do is to send a request to Ambassador Gateway and it would take care of plugging in the Host header before making a request to the Knative Ingress.

So how does this work, fairly easily! assuming Ambassador is in place, all it needs is a configuration which piggybacks on a Kubernetes service the following way:

---
apiVersion: v1
kind: Service
metadata:
  name: sample-knative-app-gateway
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind:  Mapping
      name: sample-boot-knative-app
      prefix: /messages
      rewrite: /messages
      service: knative-ingressgateway.istio-system.svc.cluster.local 
      host_rewrite: sample-boot-knative-service.default.example.com
spec:
  type: LoadBalancer
  ports:
  - name: ambassador
    port: 80
    targetPort: 80
  selector:
    service: ambassador

Here I am providing configuration via a Service annotations, intercepting any calls to /messages uri and forwarding these request to the knative ingressgatway service (knative-ingressgateway.istio-system.svc.cluster.local) and adding the host header of “sample-boot-knative-service.default.example.com”.

Now the interaction from a user perspective is far simpler, all I have to do is to get the url for this new service and to make the api call, in a minikube environment using the following bash script:

export AMB_URL=$(echo $(minikube ip):$(kubectl get svc sample-knative-app-gateway -n default -o 'jsonpath={.spec.ports[?(@.port==80)].nodePort}'))

http http://${AMB_URL}/messages id=1 payload=test delay=1

It may be easier to try this on a real code, which is available my github repo here.

Published on Java Code Geeks with permission by Biju Kunjummen, partner at our JCG program. See the original article here: Knative serving – using Ambassador gateway

Opinions expressed by Java Code Geeks contributors are their own.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button