Cloud run and Knative : What is the relationship between the two
Cloud Run is a service particularly suited to stateless web applications, APIs, serverless functions, microservices backends, data processing tasks, and more generally any use case requiring code execution in isolated containers.
Cloud Run is based on Knative open source technology, which enables it to benefit from the advantages of Kubernetes containers, such as portability, flexibility and container orchestration. One of the great advantages of Cloud run is also its ability to manage “scale from zero to X”, or to have an active container at all times, so as to be able to respond instantly to requests if required.
What if we were to compare 2/3 features of our two friends Cloud run and Knative?Knative et Cloud Run first tests
Dans cet exemple nous allons déployer un service Knative avec une application complexe hello-world ;) puis tenter de déployer une nouvelle version de celle-ci et voir comment on peux splitter le traffic simplement.
Creation of its first Knative opensource service:
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
spec:
containers:
- image: gcr.io/knative-samples/helloworld-go
env:
- name: TARGET
value: "Go Sample v1"
and here is the command to deploy on knative
kubectl apply -f service.yaml
You can see that no pods are currently executing
% kubectl get pods
No resources found in default namespace.
Let’s retrieve the URL of my service and do a little test
% kubectl get ksvc
NAME URL LATESTCREATED LATESTREADY READY REASON
helloworld-go http://helloworld-go.default.127.0.0.1.sslip.io helloworld-go-00001 helloworld-go-00001 True
% curl http://helloworld-go.default.127.0.0.1.sslip.io
Hello Go Sample v1!
If you look at the pods as soon as the URL is called, you can see pods executing and then terminating.
v.ledan@MFR-FVFJT0HR1WG7 knative % kubectl get pods
NAME READY STATUS RESTARTS AGE
helloworld-go-00001-deployment-d5d85785f-vkd2r 2/2 Running 0 61s
v.ledan@MFR-FVFJT0HR1WG7 knative % kubectl get pods
NAME READY STATUS RESTARTS AGE
helloworld-go-00001-deployment-d5d85785f-vkd2r 2/2 Terminating 0 78s
the default timeout is 30 seconds of inactivity before terminating, but this behavior can be easily modified at cluster level or by service.
per revision :
annotations:
autoscaling.knative.dev/scale-to-zero-pod-retention-period: "1m5s"
Per cluster
apiVersion: v1
kind: ConfigMap
metadata:
name: config-autoscaler
namespace: knative-serving
data:
scale-to-zero-pod-retention-period: "42s"
Create your first cloud run service
Let’s imagine that we want to deploy the same service on cloud run, in which case we simply need to execute the following command:
gcloud beta run deploy hello --image gcr.io/knative-samples/helloworld-go \
--platform managed --region europe-west1 --timeout 30s --set-env-vars TARGET="Go Sample v1"
v.ledan@MFR-FVFJT0HR1WG7 knative % gcloud beta run deploy hello --image gcr.io/knative-samples/helloworld-go --platform managed --region europe-west1 --timeout 30s --min-instances=0
Allow unauthenticated invocations to [hello] (y/N)? y
Deploying container to Cloud Run service [hello] in project [vincent-ledan-378413] region [europe-west1]
✓ Deploying new service... Done.
✓ Creating Revision... Creating Service.
✓ Routing traffic...
✓ Setting IAM Policy...
Done.
Service [hello] revision [hello-00001-wek] has been deployed and is serving 100 percent of traffic.
Service URL: https://hello-y6wbxjtiyq-ew.a.run.app
Now let’s do the same test:
% curl https://hello-y6wbxjtiyq-ew.a.run.app
Hello World!
A quick look at the deployed configuration on google clearly shows the Knative configuration
New revision and how to split traffic 50/50 with Knative and Cloud run
Knative
We will apply the second revision by changing only the value: “Go Sample v2” :
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: helloworld-go
namespace: default
spec:
template:
spec:
containers:
- image: gcr.io/knative-samples/helloworld-go
env:
- name: TARGET
value: "Go Sample v2"
traffic:
- latestRevision: true
percent: 50
- latestRevision: false
percent: 50
revisionName: helloworld-go-00001
kubectl get revisions
NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON ACTUAL REPLICAS DESIRED REPLICAS
helloworld-go-00001 helloworld-go 1 True 0 0
helloworld-go-00002 helloworld-go 2 True 1 1
% kn revisions list
NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON
helloworld-go-00002 helloworld-go 50% 2 2m4s 3 OK / 4 True
helloworld-go-00001 helloworld-go 50% 1 87m 3 OK / 4 True
and let’s check that the traffic is loabalanced:
% for i in {1..10}; do curl http://helloworld-go.default.127.0.0.1.sslip.io; done
Hello Go Sample v2!
Hello Go Sample v2!
Hello Go Sample v2!
Hello Go Sample v1!
Hello Go Sample v1!
Hello Go Sample v2!
Hello Go Sample v2!
Hello Go Sample v2!
Hello Go Sample v1!
Hello Go Sample v2!
Cloud run
For example, you can deploy a new v2 version without redirecting traffic to it.
gcloud beta run deploy hello \
--image gcr.io/knative-samples/helloworld-go \
--platform managed --set-env-vars TARGET="Go Sample v2" --no-traffic
Service [hello] revision [hello-00002-hew] has been deployed and is serving 0 percent of traffic.
and split traffic between the two revisions
% gcloud beta run services update-traffic hello \
--region=europe-west1 --to-revisions hello-00002-hew=50
✓ Updating traffic... Done.
✓ Routing traffic...
Done.
URL: https://hello-y6wbxjtiyq-ew.a.run.app
Traffic:
50% hello-00001-qet
50% hello-00002-hew
and now a small test
% for i in {1..10}; do curl https://hello-y6wbxjtiyq-ew.a.run.app; done
Hello Go Sample v1!
Hello Go Sample v2!
Hello Go Sample v1!
Hello Go Sample v1!
Hello Go Sample v1!
Hello Go Sample v2!
Hello Go Sample v2!
Hello Go Sample v2!
Hello Go Sample v2!
Hello Go Sample v1!
Conclusion
This is of course a simplistic comparison, but it simply shows why the behavior is very similar.
In my next article, we’ll take a look at the Knative everywhere vision with Cloud Run for Anthos.