Canary release¶
This tutorial shows how Iter8 can be used to release a basic Kubernetes application using a canary release strategy.
In a canary release, requests that match a particular pattern, for example those that have a particular header, are directed to the candidate version of the model. The remaining requests go to the primary, or initial, version of the model.
The user declaratively describes the desired application state at any given moment. An Iter8 release
chart assists users who describe the application state at any given moment. The chart provides the configuration needed for Iter8 to automatically deploy application versions and configure the routing to implement the canary release strategy.
Before you begin
- Ensure that you have a Kubernetes cluster and the
kubectl
andhelm
CLIs. If using a local cluster (for example, Kind or Minikube), we recommend providing the cluster with at least 16GB of memory. - Install Istio. It suffices to install the demo profile, for example by using:
istioctl install --set profile=demo -y
Install the Iter8 controller¶
Iter8 can be installed and configured to watch resources either in a single namespace (namespace-scoped) or in the whole cluster (cluster-scoped).
helm install --repo https://iter8-tools.github.io/iter8 --version 1.1 iter8 controller
helm install --repo https://iter8-tools.github.io/iter8 --version 1.1 iter8 controller \
--set clusterScoped=true
For additional install options, see Iter8 Installation.
Deploy initial version¶
Deploy the initial version of the application using the Iter8 release
chart by identifying the environment into which it should be deployed, a list of the versions to be deployed (only one here), and the release strategy to be used:
cat <<EOF | helm upgrade --install httpbin --repo https://iter8-tools.github.io/iter8 release --version 1.1 -f -
environment: deployment-istio
application:
versions:
- metadata:
labels:
app.kubernetes.io/version: v0
image: kennethreitz/httpbin
strategy: canary
EOF
What happens?
Because environment
is set to deployment-istio
, a Deployment
and a Service
object are created. - The namespace default
is inherited from the Helm release namespace since it is not specified in the version or in application.metadata
. - The name httpbin-0
is derived from the Helm release name since it is not specified in the version or in application.metadata
. The name is derived by appending the index of the version in the list of versions; -0
in this case. - Alternatively, a deploymentSpecification
and/or a serviceSpecification
could have been specified.
To support routing, a Service
(of type ExternalName
) named default/httpbin
pointing at the Istio gateway, istio-ingressgateway.istio-system
, is deployed. The name is the Helm release name since it not specified in application.metadata
. Further, an Iter8 routemap is created.
Once the application components are ready, the Iter8 controller automatically configures the routing by creating an Istio VirtualService
. It is configured to route all traffic to the only deployed version, httpbin-0
.
Verify routing¶
You can verify the routing configuration by inspecting the VirtualService
:
kubectl get virtualservice httpbin -o yaml
You can also send requests from a pod within the cluster:
-
Create a
sleep
pod in the cluster from which requests can be made:curl -s https://raw.githubusercontent.com/iter8-tools/docs/v0.18.4/samples/kserve-serving/sleep.sh | sh -
-
Exec into the sleep pod:
kubectl exec --stdin --tty "$(kubectl get pod --sort-by={metadata.creationTimestamp} -l app=sleep -o jsonpath={.items..metadata.name} | rev | cut -d' ' -f 1 | rev)" -c sleep -- /bin/sh
-
Send requests:
curl httpbin.default -s -D - | grep -e '^HTTP' -e app-version
The output includes the success of the request (the HTTP return code) and the version of the application that responded (in the app-version
response header). In this example:
HTTP/1.1 200 OK
app-version: httpbin-0
To send requests from outside the cluster
To configure the release for traffic from outside the cluster, a suitable Istio Gateway
is required (for example). When using the Iter8 release
chart, set the gateway
field to the name of your Gateway
. Finally, to send traffic:
(a) In a separate terminal, port-forward the ingress gateway:
kubectl -n istio-system port-forward svc/istio-ingressgateway 8080:80
Host
header: curl -H 'Host: httpbin.default' localhost:8080 -s -D - | grep -e '^HTTP' -e app-version
Deploy candidate¶
A candidate can deployed by simply adding a second version to the list of versions comprising the application:
cat <<EOF | helm upgrade --install httpbin --repo https://iter8-tools.github.io/iter8 release --version 1.1 -f -
environment: deployment-istio
application:
versions:
- metadata:
labels:
app.kubernetes.io/version: v0
image: kennethreitz/httpbin
- metadata:
labels:
app.kubernetes.io/version: v1
image: kennethreitz/httpbin
strategy: canary
EOF
About the candidate version
In this tutorial, the candidate image is the same as the one for the primary version. In a real world example, it would be different. The version label (app.kubernetes.io/version
) can be used to distinguish between versions.
When the candidate version is ready, the Iter8 controller will Iter8 will automatically reconfigure the routing so that requests with the header traffic
set to test
will be sent to the candidate model:
HTTP/1.1 200 OK
app-version: httpbin-1
All other requests will be sent to the primary model (httpbin-0
):
HTTP/1.1 200 OK
app-version: httpbin-0
Verify routing¶
You can verify the routing configuration by inspecting the VirtualService
and/or by sending requests as described above. Those with header traffic
set to test
will be handled by the candidate model (httpbin-1
) while all others will be handled by the primary version.
Promote candidate¶
The candidate can be promoted by redefining the primary version and removing the candidate:
cat <<EOF | helm upgrade --install httpbin --repo https://iter8-tools.github.io/iter8 release --version 1.1 -f -
environment: deployment-istio
application:
versions:
- metadata:
labels:
app.kubernetes.io/version: v1
image: kennethreitz/httpbin
strategy: canary
EOF
What is different?
The version label (app.kubernetes.io/version
) of the primary version was updated. In a real world example, the image would also have been updated (with that from the candidate version).
Once the (reconfigured) primary version ready, the Iter8 controller will automatically reconfigure the routing to send all requests to it.
Verify routing¶
You can verify the routing configuration by inspecting the VirtualService
and/or by sending requests as described above. They will all be handled by the primary version. Output will be something like:
HTTP/1.1 200 OK
app-version: httpbin-0
Cleanup¶
Delete the application and its routing configuration:
helm delete httpbin
If you used the sleep
pod to generate load, remove it:
kubectl delete deploy sleep
Uninstall Iter8 controller:
helm delete iter8
For additional uninstall options, see Iter8 Uninstall.