The helloworld
Service had a spec.runLatest
field which serves all the traffic to the latest revision created form the Service’s revisionTemplate
field.
To test out the effects of a new version of your application, you will need to run multiple versions of your applications and route a portion of your traffic to the new “canary” version you are testing. This practice is called “blue-green deployment”.
Knative Serving offers the Revision
API, which tracks the changes to application configuration, and the Route
API, which lets you split the traffic to multiple revisions.
In this exercise you will:
- Deploy a “blue” Service version in
runLatest
mode. - Update Service with “green” configuration and change mode to
release
to split traffic between two revisions.
Deploying the v1 | |
To try out the a blue-green deployment, first you will need to deploy a "blue" version. | |
Services in runLatest mode will send all the traffic to the Revision specified in the Service manifest. In the earlier helloworld example, you've used a service in runLatest mode. | |
First, deploy the v1 (blue) version of the Service with runLatest mode by saving manifest to a file named v1.yaml, and apply it to the cluster: | |
v1.yaml | |
apiVersion: serving.knative.dev/v1alpha1 | |
kind: Service | |
metadata: | |
name: canary | |
spec: | |
runLatest: | |
configuration: | |
revisionTemplate: | |
spec: | |
container: | |
image: gcr.io/knative-samples/knative-route-demo:blue | |
env: | |
- name: T_VERSION | |
value: "blue" | |
$ kubectl apply -f v1.yaml | |
Query the deployed revision name (should be canary-00001): | |
$ kubectl get revisions | |
NAME CREATED AT | |
canary-00001 39s | |
Make a request and observe the blue version by replacing the IP_ADDRESS below with the gateway's IP address (the first request may take some time to complete as it starts the Pod): | |
$ curl -H "Host: canary.default.example.com" http://IP_ADDRESS | |
... | |
<div class="blue">App v1</div> | |
... | |
Deploying the v2 | |
The Knative Service API has a release mode that lets you roll out changes to new revisions with traffic splitting. | |
Make a copy of v1.yaml named v2.yaml | |
cp v1.yaml v2.yaml | |
Make the following changes to v2.yaml. | |
change runLatest mode to release | |
change blue to green in "image" and "env" fields | |
add a revisions field with the [current, current+1] revision names | |
specify a rolloutPercent field, routing 20% of traffic to the candidate ("green") revision | |
The resulting v2.yaml should look like the following snippet. Save and apply this to the cluster: | |
v2.yaml | |
apiVersion: serving.knative.dev/v1alpha1 | |
kind: Service | |
metadata: | |
name: canary | |
spec: | |
release: | |
revisions: ["canary-00001", "canary-00002"] # [current, candidate] | |
rolloutPercent: 20 # 20% to green revision | |
configuration: | |
revisionTemplate: | |
spec: | |
container: | |
image: gcr.io/knative-samples/knative-route-demo:green | |
env: | |
- name: T_VERSION | |
value: "green" | |
$ kubectl apply -f v2.yaml | |
You should now see the new revision created, while the old one is still around: | |
$ kubectl get revisions | |
NAME CREATED AT | |
canary-00001 6m | |
canary-00002 3m | |
Now, make a few requests and observe the response is served from the new "green" version roughly 20% of the time (replace IP_ADDRESS below): | |
while true; do | |
curl -s -H "Host: canary.default.example.com" http://IP_ADDRESS | grep -E 'blue|green'; | |
done | |
<div class="green">App v1</div> | |
<div class="blue">App v1</div> | |
<div class="green">App v2</div> | |
<div class="blue">App v1</div> | |
<div class="blue">App v1</div> | |
<div class="green">App v2</div> | |
<div class="green">App v2</div> | |
<div class="blue">App v1</div> | |
<div class="blue">App v1</div> | |
<div class="green">App v2</div> | |
<div class="blue">App v1</div> | |
<div class="blue">App v1</div> | |
<div class="green">App v1</div> | |
<div class="green">App v2</div> | |
<div class="blue">App v1</div> | |
The rolloutPercent determines what portion of the traffic the candidate revision gets. If you set this field to 0, the candidate revision will not get any traffic. | |
If you want to play with the percentages, you can edit the v2.yaml and re-apply it to the cluster. | |
With the Service configured in release mode, you can also connect to specific revisions through their dedicated addresses: | |
current.canary.default.example.com | |
candidate.canary.default.example.com | |
latest.canary.default.example.com (most recently deployed Revision, even if it's not specified on the revisions field.) | |
After the Service is configured with the release mode, you should see the Route object configured with the traffic splitting (20% to "candidate", 80% to "current"):+ | |
kubectl describe route canary | |
... | |
Status: | |
Traffic: | |
Name: current | |
Percent: 80 | |
Revision Name: canary-00001 | |
Name: candidate | |
Percent: 20 | |
Revision Name: canary-00002 | |
Name: latest | |
Percent: 0 | |
Revision Name: canary-00002 | |
As you roll out changes to the Service, you need to repeat finding the Revision name and specify it in the revisions field as the candidate. | |
Great job! You just used the Knative Serving API to create a blue-green deployment. | |
Recap | |
The Knative Service object has a release mode that lets you manage the lifecycle of Revisions and configure Routes to split traffic between old and new deployments. |
I’m a DevOps/SRE/DevSecOps/Cloud Expert passionate about sharing knowledge and experiences. I am working at Cotocus. I blog tech insights at DevOps School, travel stories at Holiday Landmark, stock market tips at Stocks Mantra, health and fitness guidance at My Medic Plus, product reviews at I reviewed , and SEO strategies at Wizbrand.
Please find my social handles as below;
Rajesh Kumar Personal Website
Rajesh Kumar at YOUTUBE
Rajesh Kumar at INSTAGRAM
Rajesh Kumar at X
Rajesh Kumar at FACEBOOK
Rajesh Kumar at LINKEDIN
Rajesh Kumar at PINTEREST
Rajesh Kumar at QUORA
Rajesh Kumar at WIZBRAND