Knative Serving 0.7

Mete Atamel
Google Cloud - Community
3 min readJul 1, 2019

As you might have heard, Knative 0.7 was out last week. One of the notable changes in this release is that Knative Serving API progressed fromv1alpha1 to v1beta1. While you can still use the old v1alpha1 API, if you want to update to v1beta, you need to rewrite your Knative service definition files. The new API also allows named revisions, silent latest deploys and a better traffic splitting configuration. In this post, I want to outline some of these changes.

More compact service definition

In previous version of Knative, if you wanted to deploy a simple Knative service and route 100% traffic to it, you had to use runLatest block as follows:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
runLatest:
configuration:
revisionTemplate:
spec:
container:
image: docker.io/meteatamel/helloworld:v1
env:
- name: TARGET
value: "v1"

In the new version, the same service definition looks like this:

apiVersion: serving.knative.dev/v1beta1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
spec:
containers:
- image: docker.io/meteatamel/helloworld:v1
env:
- name: TARGET
value: "v1"

Notice that there’s no runLatest or configuration and revisionTemplate is simply called template now. This allows a more compact service definition file.

Named revisions

In the previous version, when you deployed a change to your Knative Service, you’d get random revision numbers like this:

$ kubectl get revisionNAME                                                   
revision.serving.knative.dev/helloworld-c4pmt
revision.serving.knative.dev/helloworld-vkvjt

This is usually OK but made traffic splitting configuration a little cumbersome (more on this later).

In the new version, you still get random revision numbers by default but you can also give your revisions a predictable name. For example, take a look at this service definition file with a revision name:

apiVersion: serving.knative.dev/v1beta1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
metadata:
name: helloworld-v1
spec:
containers:
- image: docker.io/meteatamel/helloworld:v1
env:
- name: TARGET
value: "v1"
traffic:
- tag: current
revisionName: helloworld-v1
percent: 100
- tag: latest
latestRevision: true
percent: 0

When you deploy, you get the revision name you specified:

$ kubectl get revision

NAME SERVICE NAME GENERATION
helloworld-f4xvr helloworld-f4xvr 2
helloworld-ln8rv helloworld-ln8rv 3
helloworld-v1 helloworld-v1 4
helloworld-z9clz helloworld-z9clz 1

Ability to deploy latest revision silently

In the previous example, you probably noticed the latest configuration:

traffic:
- tag: current
revisionName: helloworld-v1
percent: 100
- tag: latest
latestRevision: true
percent: 0

When you deploy service, it will deploy the latest revision (under a randomly named revision id) but helloworld-v1 will be the one getting all the traffic. In other words, you silently deployed the latest revision. The main url http://helloworld.default.example.com will point to helloworld-v1 revision but you can also access the latest revision under http://latest-helloworld.default.example.com

This is useful if you want to deploy some code and test it out before rolling out to users.

More robust traffic splitting configuration

In the previous version of Knative, when you wanted to split traffic between current and candidate revisions, you had to do create a release and define a rollout percentage, something like this:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
release:
# First revision is traffic target "current"
# Second revision is traffic target "candidate"
revisions: ["helloworld-xyzss", "helloworld-zyxss"]
rolloutPercent: 20 # 20% traffic to route to "candidate"
configuration:
revisionTemplate:
spec:
container:
image: docker.io/meteatamel/helloworld:v1
env:
- name: TARGET
value: "v4"

This was problematic because the candidate revision id was not known before the initial deployment. You had to apply this configuration to get the candidate version deployed, get the random revision id for the deployed candidate revision and do another deploy again with that revision id to apply traffic splitting. Not ideal.

In the latest version of Knative, you can use named revisions in traffic splitting:

apiVersion: serving.knative.dev/v1beta1
kind: Service
metadata:
name: helloworld
namespace: default
spec:
template:
metadata:
name: helloworld-v4
spec:
containers:
- image: docker.io/meteatamel/helloworld:v1
env:
- name: TARGET
value: "v4"
traffic:
- tag: current
revisionName: helloworld-v1
percent: 50
- tag: candidate
revisionName: helloworld-v4
percent: 50
- tag: latest
latestRevision: true
percent: 0

This is definitely less cumbersome and more clear way of defining traffic splitting.

That’s all I wanted to cover with Knative Serving 0.7. If you want to try out Knative 0.7, I tested and updated my Knative Tutorial with 0.7 instructions, so check it out.

--

--

Mete Atamel
Google Cloud - Community

I'm a Developer Advocate at Google Cloud, helping developers with serverless and orchestration technologies