Basics of Traffic Splitting¶
The last super power of Knative Serving we'll go over is traffic splitting.
Splitting traffic is useful for a number of very common modern infrastructure needs, such as blue/green deployments and canary deployments. Bringing these industry standards to bear on Kubernetes is as simple as a single CLI command on Knative or YAML tweak, let's see how!
What are revisions?¶
Knative Serving splits traffic between different Revisions of a Knative Service. You can think of a Revision as a stateless, autoscaling snapshot-in-time of application code and configuration. A new Revision will get created each and every time you make changes to your Knative Service.
You may have noticed that when your Knative Service was created, Knative returned both a URL and a 'latest revision' for your Service. But what happens if we make a change to our service?
Creating a new Revision¶
Instead of "world," let's have our Knative Service "hello" greet "Knative." You can accomplish this by using the kn CLI or by editing the YAML file you made earlier.
kn service update hello --env TARGET=Knative
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: hello
spec:
template:
spec:
containers:
- image: gcr.io/knative-samples/helloworld-go
ports:
- containerPort: 8080
env:
- name: TARGET
value: "Knative"
kubectl apply -f hello.yaml
As before, Knative spits out some helpful information to the CLI:
Service hello created to latest revision <revision-name> is available at URL:
<service-url>
Notice, since we are updating an existing Knative Service, the URL doesn't change, but your Revision should have incremented by one (something like "hello-xxxxx-2").
Let's ping our Knative Service again to see the change:
curl <service-url>
The output should be:
Hello Knative!
Splitting Traffic between Revisions¶
Remember when I said that a Revision was a "stateless, autoscaling snapshot-in-time of application code and configuration?" You may at this point be wondering, "where did 'Hello world!' go?"
We can easily see a list of our existing revisions with the kn CLI:
kn get revisions
Though the following example doesn't cover it, you can peak under the hood to Kubernetes to see the revisions as Kubernetes sees them.
kubectl get revisions
The output should be:
NAME SERVICE TRAFFIC TAGS GENERATION AGE CONDITIONS READY REASON
hello-xxxxx-2 hello 100% 2 10m 3 OK / 4 True
hello-xxxxx-1 hello 1 17h 3 OK / 4 True
The column most relevant for our purposes is "TRAFFIC". It looks like 100% of traffic is going to our latest Revision (hello-xxxxx-2) "Hello Knative!" and 0% of traffic is going to the Revision we configured first (hello-xxxxx-1), "Hello world!"
By default, when Knative creates a brand new Service it directs 100% of traffic to @latest, and updates the pointer @latest with the most recent Revision when we make a change to our Service. We can change this default behavior by using specifying how much traffic we want each of our Revisions to receive.
kn service update hello \
--traffic hello-xxxxx-1=50 \
--traffic hello-xxxxx-2=50
kn service update hello \
--traffic hello-xxxxx-1=50 \
--traffic @latest=50
@latest will always point to our "latest" Revision which, at the moment, is hello-xxxxx-2.
apiVersion: serving.knative.dev/v1
kind: Route
metadata:
name: route-hello
spec:
traffic:
- revisionName: hello-xxxxx-1
- percent: 50
- revisionName: hello-xxxxx-2
percent: 50
kubectl apply -f hello.yaml
Now when we curl our Knative Service URL...
[...] curl <service-url>
Hello Knative!
[...] curl <service-url>
Hello world!
Congratulations, you've successfully split traffic between 2 different
Revisions. Up next, Knative Eventing!