Quarkus Serverless with Knative
Knative Client is the command line utility aimed at enhancing the developer experience when doing Knative Serving and Eventing tasks.
At the end of this chapter you will be able to :
-
Install Knative Client
-
Create, update, list and delete Knative service
-
Create, update, list and delete Knative service revisions
-
List Knative service routes
Install kn
by using the command line section in RedHat Sandbox:
Download it, unzip it, and put in an accessible directory.
Verify installation by running the command:
kn version
The above command will return a response like
Version: {kn-client-version}
Build Date: 2021-12-14T12:31:50Z
Git Revision: 530841f1
Supported APIs:
* Serving
- serving.knative.dev/v1 (knative-serving )
* Eventing
- sources.knative.dev/v1 (knative-eventing )
- eventing.knative.dev/v1 (knative-eventing )
Intro to Knative
Create Service
To create the greeter
service using kn
run the following command:
kn service create greeter \
--image quay.io/rhdevelopers/knative-tutorial-greeter:quarkus
A successful creation of the greeter
service should show a response like
Creating service 'greeter' in namespace 'knativetutorial':
0.028s The Configuration is still working to reflect the latest desired specification.
0.097s The Route is still working to reflect the latest desired specification.
0.120s Configuration "greeter" is waiting for a Revision to become ready.
12.075s ...
12.128s Ingress has not yet been reconciled.
12.223s unsuccessfully observed a new generation
12.378s Ready to serve.
Service 'greeter' created to latest revision 'greeter-zyjrq-1' is available at URL:
http://greeter-asotobue-dev.apps.sandbox.x8i5.p1.openshiftapps.com
List Knative Services
You can list the created services using the command:
kn service list
NAME URL LATEST AGE CONDITIONS READY REASON
greeter http://greeter-asotobue-dev.apps.sandbox.x8i5.p1.openshiftapps.com greeter-sxnzq-1 10m 3 OK / 3 True
Hi greeter => '9861675f8845' : 1
List the Pods:
kubectl get pods
NAME READY STATUS RESTARTS AGE
greeter-stdvk-1-deployment-5cbd996d7f-mbmjq 2/2 Running 0 49s
The greeter Pod is deployed, now wait for 60 seconds and list the Pods again:
kubectl get pods
No greeter-stdvk-1-deployment-5cbd996d7f-mbmjq
Pod is shown as it has been automatically scaled to 0.
Hi greeter => '9861675f8845' : 1
Automatically a new instance is scaled up when the request comes to the cluster.
Delete Knative Service
You can also use kn
to delete the service that we created, to delete the service named greeter
run the following command:
kn service delete greeter
Service 'greeter' successfully deleted in namespace ''.
Traffic Distribution
To explore the goals of this chapter, we will be using a colors service called blue-green-canary
, and we’ll deploy using YAML files instead of using kn
.
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: blue-green-canary
spec:
template:
spec:
containers:
- image: quay.io/rhdevelopers/blue-green-canary
env:
- name: BLUE_GREEN_CANARY_COLOR
value: "#6bbded"
- name: BLUE_GREEN_CANARY_MESSAGE
value: "Hello"
kubectl apply -f colors-service-blue.yaml
Deploy a New Revision of a Service
Let us now change the configuration of the service by updating the service environment variable BLUE_GREEN_CANARY_COLOR to make the browser display green color with greeting text as Namaste.
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: blue-green-canary
spec:
template:
spec:
containers:
- image: quay.io/rhdevelopers/blue-green-canary
env:
- name: BLUE_GREEN_CANARY_COLOR
value: "#5bbf45"
- name: BLUE_GREEN_CANARY_MESSAGE
value: "Namaste"
kubectl apply -f colors-service-green.yaml
Now invoking the service again using the service URL will show a green color browser page with greeting Namaste.
Tag Revisions
As you had observed that the Knative service blue-green-canary
now has two revisions namely blue-green-canary-00001 and blue-green-canary-00002. As the Revision names are autogenerated it is hard to comprehend to which code/configuration set it corresponds to. To overcome this problem Knative provides tagging of revision names that allows one to tag a revision name to a logical human understandable names called tags.
As our colors service shows different colors on the browser let us tag the revisions with color,
List the existing revisions,
kn revision list -s blue-green-canary
NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON
blue-green-canary-00002 blue-green-canary 100% 2 23m 3 OK / 4 True
blue-green-canary-00001 blue-green-canary 1 51m 3 OK / 4 True
When Knative rolls out a new revision, it increments the GENERATION
by 1 and then routes 100% of the TRAFFIC
to it, hence we can use the GENERATION
or TRAFFIC
to identify the latest revision.
Tag Blue
Let us tag blue-green-canary-00001
which shows blue browser page with tag name blue
.
kn service update blue-green-canary --tag=blue-green-canary-00001=blue
Updating Service 'blue-green-canary' in namespace 'knativetutorial':
0.037s The Route is still working to reflect the latest desired specification.
0.126s Ingress has not yet been reconciled.
0.162s Waiting for load balancer to be ready
0.303s Ready to serve.
Service 'blue-green-canary' with latest revision 'blue-green-canary-00002' (unchanged) is available at URL:
http://blue-green-canary.knativetutorial.192.168.64.13.nip.io
Tag Green
Let us tag blue-green-canary-00002
which shows green browser page with tag name green
.
kn service update blue-green-canary --tag=blue-green-canary-00002=green
Updating Service 'blue-green-canary' in namespace 'knativetutorial':
0.037s The Route is still working to reflect the latest desired specification.
0.126s Ingress has not yet been reconciled.
0.162s Waiting for load balancer to be ready
0.303s Ready to serve.
Service 'blue-green-canary' with latest revision 'blue-green-canary-00002' (unchanged) is available at URL:
http://blue-green-canary.knativetutorial.192.168.64.13.nip.io
Tag Latest
Lets tag whatever revision that is latest to be tagged as latest.
kn service update blue-green-canary --tag=@latest=latest
Updating Service 'blue-green-canary' in namespace 'knativetutorial':
0.037s The Route is still working to reflect the latest desired specification.
0.126s Ingress has not yet been reconciled.
0.162s Waiting for load balancer to be ready
0.303s Ready to serve.
Service 'blue-green-canary' with latest revision 'blue-green-canary-00002' (unchanged) is available at URL:
http://blue-green-canary.knativetutorial.192.168.64.13.nip.io
Let us query the Service Revisions again,
kn revision list -s blue-green-canary
NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON
blue-green-canary-00002 blue-green-canary 100% latest,green 2 29m 3 OK / 4 True
blue-green-canary-00001 blue-green-canary blue 1 57m 3 OK / 4 True
As green happened to be latest revision it has been tagged with name lastest
in addition to green
.
Let us use the tag names for easier identification of the revision and perform traffic distribution amongst them.
Applying Blue-Green Deployment Pattern
Knative offers a simple way of switching 100% of the traffic from one Knative service revision (blue) to another newly rolled out revision (green). If the new revision (e.g. green) has erroneous behavior then it is easy to rollback the change.
In this exercise you will applying the Blue/Green deployment pattern with the Knative Service called greeter. You have already deployed two revisions of blue-green-canary identified using the tags blue
and green
.
With the deployment of green revison you noticed that Knative automatically started to routing 100% of the traffic to blue-green-canary-00002
.
Now let us assume, due to a critical bug we need to roll back green
to blue
.
The following Knative Service YAML is identical to the previously deployed green
except that we have added the traffic section to indicate that 100% of the traffic should be routed to blue
.
Before you rollback the revision, refresh the browser window where you have opened the blue-green-canary service, to make sure it is still showing green browser page with greeting Namaste.
Now apply the update Knative service configuration using the command as shown in following listing:
Rollback to blue
Route all the traffic of service blue-green-canary
to blue revision of the service:
kn service update blue-green-canary --traffic blue=100,green=0,latest=0
We use the tag names to identify the revisions |
Let us list all revisions with tags:
kn revision list
Based on the revision tags that we created earlier, the output should be like:
NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON
blue-green-canary-00002 blue-green-canary latest,green 2 56m 4 OK / 4 True
blue-green-canary-00001 blue-green-canary 100% blue 1 83m 4 OK / 4 True
Let us list the available sub-routes:
kubectl get ksvc blue-green-canary -oyaml \
| yq r - 'status.traffic[*].url'
The above command should return you three sub-routes for the main greeter
route:
1 | the sub route for the traffic tag latest |
2 | the sub route for the traffic tag blue |
3 | the sub route for the traffic tag green |
You will notice that the command does not create any new configuration/revision/deployment as there was no application update (e.g. image tag, env var, etc), but when you call the service, Knative scales up the blue
that shows blue browser page with greeting Hello.
kubectl get pods
NAME READY STATUS RESTARTS AGE
blue-green-canary-00001-deployment-54597d94b9-25x4r# 2/2 Running 0 12s
blue-green-canary-00002-deployment-6cb545df65-ktqc2 0/2 Terminating 0 2m
Since blue
is the active revision now, the existing green
pod is getting terminated as no future requests will be served by it.
As an exercise, flip all the traffic back to |
Applying Canary Release Pattern
A Canary release is more effective when you want to reduce the risk of introducing a new feature. It allows you a more effective feature-feedback loop before rolling out the change to your entire user base.
Knative allows you to split the traffic between revisions in increments as small as 1%.
To see this in action, apply the following Knative service definition that will split the traffic 80% to 20% between blue
and green
.
To roll out the greeter canary deployment use the following command:
kn service update blue-green-canary \
--traffic="blue=80" \
--traffic="green=20"
As in the previous section on [blue-green] deployments, the command will not create any new configuration/revision/deployment. To observe the traffic distribution, open the Service Route URL in your browser window.
You will notice the browser alternating between green and blue color, with a majority of the time staying with blue.
You should also notice that two pods are running representing both blue
and green
:
kubectl get pods
NAME READY STATUS RESTARTS AGE
blue-green-canary-00001-deployment-54597d94b9-q8c57 2/2 Running 0 79s
blue-green-canary-00002-deployment-8564bf5b5b-gtvh4 2/2 Running 0 14s
Serverlessing Todo Service
One of the key aspects of services running under serverless architecture, is the startup time. This application might take around 6 seconds to start in the RedHat Sandbox machines.
This is fine for long-running services, but in serverless where the cluster might start and stop the service pretty often, the startup time becomes important.
Quarkus integrates with GraalVM to compile the Java application into native binary file speeding up the start up times and the usage memory.
Compile to native
Start your local Docker/Podman/CRI-O instance, and run the following command in the terminal to compile to native, create a container image and push it:
./mvnw clean package -DskipTests -Pnative -Dquarkus.native.container-build=true -Dquarkus.container-image.push=true -Dquarkus.container-image.tag=1.0.0-SNAPSHOT-native
We override the tag value to 1.0.0-SNAPSHOT-native
to have both JVM and native containers correctly tagged.
Deploy
To deploy the application as a KNative service, create a new file with name service.yaml
with the following content:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: quarkus-app-workshop
spec:
template:
spec:
containers:
- image: quay.io/rhdevelopers/quarkus-app-workshop:1.0.0-SNAPSHOT-native (1)
livenessProbe:
httpGet:
path: /q/health/live
readinessProbe:
httpGet:
path: /q/health/ready
1 | Change this value for your image |
Finally apply this resource:
kubectl apply -f service.yaml
List the KNative services to validate the instantiation of the service and get the URL:
kn service list
NAME URL LATEST AGE CONDITIONS READY REASON
quarkus-app-workshop https://quarkus-app-workshop-asotobue-dev.apps.sandbox.x8i5.p1.openshiftapps.com quarkus-app-workshop-00001 59m 3 OK / 3 True