Skip to content

Commit

Permalink
docs: add traffic split guide and canary rollout demo
Browse files Browse the repository at this point in the history
Adds a guide for traffic split usage and a demo to
perform canary rollouts.

Resolves openservicemesh#79
Resolves openservicemesh#88

Signed-off-by: Shashank Ram <shashr2204@gmail.com>
  • Loading branch information
shashankram committed Oct 22, 2021
1 parent 8f3e72a commit fd88c53
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 10 deletions.
170 changes: 170 additions & 0 deletions content/docs/demos/canary_rollout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
title: "Canary Rollouts using SMI Traffic Split"
description: "Managing Canary rollouts using SMI Taffic Split"
type: docs
weight: 21
---

This guide demonstrates how to perform Canary rollouts using the SMI Traffic Split configuration.


## Prerequisites

- Kubernetes cluster running Kubernetes v1.19.0 or greater.
- Have OSM installed.
- Have `kubectl` available to interact with the API server.
- Have `osm` CLI available for managing the service mesh.


## Demo

In this demo, we will deploy an HTTP application and perform a canary rollout where a new version of the application is deployed to serve a percentage of traffic directed to the service.

To split traffic to multiple service backends, the [SMI Traffic Split API](https://github.com/servicemeshinterface/smi-spec/blob/main/apis/traffic-split/v1alpha2/traffic-split.md) will be used. More about the usage of this API can be found in the [traffic split guide](/docs/guides/traffic_management/traffic_split). For client applications to transparently split traffic to multiple service backends, it is important to note that client applications must direct traffic to the FQDN of the root service referenced in a `TrafficSplit` resource. In this demo, the `curl` client will direct traffic to the `httpbin` root service, initially backed by version `v1` of the service, and then perform a canary rollout to direct a percentage of traffic to version `v2` of the service.

The following steps demonstrate the canary rollout deployment strategy.
> Note: [Permissive traffic policy mode](/docs/guides/traffic_management/permissive_mode) is enabled to avoid the need to create explicit access control policies.
1. Enable permissive mode

```bash
osm_namespace=osm-system # Replace osm-system with the namespace where OSM is installed
kubectl patch meshconfig osm-mesh-config -n "$osm_namespace" -p '{"spec":{"traffic":{"enablePermissiveTrafficPolicyMode":true}}}' --type=merge
```

1. Deploy the `curl` client into the `curl` namespace after enrolling its namespace to the mesh.

```bash
# Create the curl namespace
kubectl create namespace curl

# Add the namespace to the mesh
osm namespace add curl

# Deploy curl client in the curl namespace
kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm/main/docs/example/manifests/samples/curl/curl.yaml -n curl
```

Confirm the `curl` client pod is up and running.
```console
$ kubectl get pods -n curl
NAME READY STATUS RESTARTS AGE
curl-54ccc6954c-9rlvp 2/2 Running 0 20s
```

1. Create the root `httpbin` service that clients will direct traffic to. The service has the selector `app: httpbin`.

```bash
# Create the httpbin namespace
kubectl create namespace httpbin
# Add the namespace to the mesh
osm namespace add httpbin
# Create the httpbin root service and service account
kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm/main/docs/example/manifests/samples/canary/httpbin.yaml -n httpbin
```

1. Deploy version `v1` of the `httpbin` service. The service `httpbin-v1` has the selector `app: httpbin, version: v1`, and the deployment `httpbin-v1` has the labels `app: httpbin, version: v1` matching the selector of both the `httpbin` root service and `httpbin-v1` service.

```bash
kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm/main/docs/example/manifests/samples/canary/httpbin-v1.yaml -n httpbin
```

1. Create an SMI TrafficSplit resource that directs all traffic to the `httpbin-v1` service.

```bash
kubectl apply -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
name: http-split
namespace: httpbin
spec:
service: httpbin.httpbin.svc.cluster.local
backends:
- service: httpbin-v1
weight: 100
EOF
```
1. Confirm all traffic directed to the root service FQDN `httpbin.httpbin.svc.cluster.local` is routed to the `httpbin-v1` pod. This can be verified by inspecting the HTTP response headers and confirming that the request succeeds and the pod displayed corresponds to `httpbin-v1`.
```console
for i in {1..10}; do kubectl exec -n curl -ti "$(kubectl get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')" -c curl -- curl -sI http://httpbin.httpbin:14001/json | egrep 'HTTP|pod'; done
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
```
The above output indicates all 10 requests returned HTTP 200 OK, and were responded by the `httpbin-v1` pod.
1. Prepare the canary rollout by deploying version `v2` of the `httpbin` service. The service `httpbin-v2` has the selector `app: httpbin, version: v2`, and the deployment `httpbin-v2` has the labels `app: httpbin, version: v2` matching the selector of both the `httpbin` root service and `httpbin-v2` service.
```bash
kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm/main/docs/example/manifests/samples/canary/httpbin-v2.yaml -n httpbin
```
1. Perform the canary rollout by updating the SMI TrafficSplit resource to split traffic directed to the root service FQDN `httpbin.httpbin.svc.cluster.local` to both the `httpbin-v1` and `httpbin-v2` services, fronting the `v1` and `v2` versions of the `httpbin` service respectively. We will distribute the weight equally to demonstrate traffic splitting.
```bash
kubectl apply -f - <<EOF
apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
name: http-split
namespace: httpbin
spec:
service: httpbin.httpbin.svc.cluster.local
backends:
- service: httpbin-v1
weight: 50
- service: httpbin-v2
weight: 50
EOF
```
1. Confirm traffic is split proportional to the weights assigned to the backend services. Since we configured a weight of `50` for both `v1` and `v2`, requests should be load balanced to both the versions as seen below.
```console
$ for i in {1..10}; do kubectl exec -n curl -ti "$(kubectl get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')" -c curl -- curl -sI http://httpbin.httpbin:14001/json | egrep 'HTTP|pod'; done
HTTP/1.1 200 OK
pod: httpbin-v2-6b48697db-cdqld
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v2-6b48697db-cdqld
HTTP/1.1 200 OK
pod: httpbin-v2-6b48697db-cdqld
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
HTTP/1.1 200 OK
pod: httpbin-v2-6b48697db-cdqld
HTTP/1.1 200 OK
pod: httpbin-v2-6b48697db-cdqld
HTTP/1.1 200 OK
pod: httpbin-v1-77c99dccc9-q2gvt
```
The above output indicates all 10 requests returned an HTTP 200 OK, and both `httpbin-v1` and `httpbin-v2` pods responsed to 5 requests each based on the weight assigned to them in the `TrafficSplit` configuration.
2 changes: 1 addition & 1 deletion content/docs/demos/egress_passthrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Egress Passthrough to Unknown Destinations"
description: "Accessing external services without Egress policies"
type: docs
weight: 5
weight: 16
---

This guide demonstrates a client within the service mesh accessing destinations external to the mesh using OSM's Egress capability to passthrough traffic to unknown destinations without an Egress policy.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/demos/egress_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Egress Policy"
description: "Accessing external services using Egress policies"
type: docs
weight: 4
weight: 15
---

This guide demonstrates a client within the service mesh accessing destinations external to the mesh using OSM's Egress policy API.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/demos/ingress_contour.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Ingress with Contour"
description: "HTTP and HTTPS ingress with Contour ingress controller"
type: docs
weight: 3
weight: 10
---

OSM provides the option to use [Contour](https://projectcontour.io) ingress controller and Envoy based edge proxy to route external traffic to service mesh backends. This guide will demonstrate how to configure HTTP and HTTPS ingress to a service part of an OSM managed service mesh.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/demos/ingress_k8s_nginx.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Ingress with Kubernetes Nginx Ingress Controller"
description: "HTTP and HTTPS ingress with Kubernetes Nginx Ingress Controller"
type: docs
weight: 3
weight: 11
---

This guide will demonstrate how to configure HTTP and HTTPS ingress to a service part of an OSM managed service mesh when using [Kubernetes Nginx Ingress Controller](https://kubernetes.github.io/ingress-nginx/).
Expand Down
2 changes: 1 addition & 1 deletion content/docs/demos/outbound_ip_exclusion.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Outbound Traffic IP Range Exclusions"
description: "Excluding IP address ranges of outbound traffic from sidecar interception"
type: docs
weight: 2
weight: 5
---

This guide demonstrates how outbound IP address ranges can be excluded from being intercepted by OSM's proxy sidecar, so as to not subject them to service mesh filtering and routing policies.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/demos/prometheus_grafana.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Prometheus & Grafana"
description: "Describes basic steps to get up and running a Prometheus and Grafana stack with OSM specific configuration and Dashboards"
type: docs
weight: 7
weight: 25
---

# OSM's Prometheus and Grafana stack
Expand Down
2 changes: 1 addition & 1 deletion content/docs/demos/tcp_traffic_routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "TCP Traffic Routing"
description: "Set up TCP traffic routing"
type: docs
weight: 6
weight: 20
---

This guide demonstrates a TCP client and server application within the service mesh communicating using OSM's TCP routing capability.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/guides/traffic_management/egress.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Egress"
description: "Enable access to the Internet and services external to the service mesh."
type: docs
weight: 4
weight: 6
---

# Egress
Expand Down
2 changes: 1 addition & 1 deletion content/docs/guides/traffic_management/ingress.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Ingress"
description: "Using Ingress to manage external access to services within the cluster"
type: docs
weight: 3
weight: 5
---

# Ingress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: "Iptables Redirection"
description: "Iptables Redirection"
type: docs
weight: 1
---

# Iptables Redirection
Expand Down Expand Up @@ -66,7 +67,7 @@ OSM provides a means to specify a global list of IP ranges to exclude from outbo
## Assumes OSM is installed in the osm-system namespace
kubectl patch meshconfig osm-mesh-config -n osm-system -p '{"spec":{"traffic":{"outboundIPRangeExclusionList":["1.1.1.1/32", "2.2.2.2/24"]}}}' --type=merge
```
When IP ranges are set for exclusion post-install, make sure to restart the relevant pods in monitored namespaces for this change to take effect.
Excluded IP ranges are stored in the `osm-mesh-config` `MeshConfig` custom resource and are read at the time of sidecar injection by `osm-injector`. These dynamically configurable IP ranges are programmed by the init container along with the static rules used to intercept and redirect traffic via the Envoy proxy sidecar. Excluded IP ranges will not be intercepted for traffic redirection to the Envoy proxy sidecar. Refer to the [outbound IP range exclusion demo](/docs/demos/outbound_ip_exclusion) to learn more.
Expand Down
55 changes: 55 additions & 0 deletions content/docs/guides/traffic_management/traffic_split.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: "Traffic Splitting"
description: "Traffic splitting using SMI Traffic Split API"
type: docs
weight: 10
---

# Traffic Splitting

The [SMI Traffic Split API](https://github.com/servicemeshinterface/smi-spec/blob/main/apis/traffic-split/v1alpha2/traffic-split.md) can be used to split outgoing traffic to multiple service backends. This can be used to orchestrate canary releases for multiple versions of the software.

## What is supported

OSM implements the [SMI traffic split v1alpha2 version](https://github.com/servicemeshinterface/smi-spec/blob/main/apis/traffic-split/v1alpha2/traffic-split.md).

It supports the following:

- Traffic splitting in both SMI and Permissive traffic policy modes
- HTTP and TCP traffic splitting
- Traffic splitting for canary or blue-green deployments

## How it works

Outbound traffic destined to a Kubernetes service can be split to multiple service backends using the SMI Traffic Split API. Consider the following example where traffic to the `bookstore.default.svc.cluster.local` FQDN corresponding to the `default/bookstore` service is split to services `default/bookstore-v1` and `default/bookstore-v2`, with a weight of 90 and 10 respectively.

```yaml
apiVersion: split.smi-spec.io/v1alpha2
kind: TrafficSplit
metadata:
name: bookstore-split
namespace: default
spec:
service: bookstore.default.svc.cluster.local
backends:
- service: bookstore-v1
weight: 90
- service: bookstore-v2
weight: 10
```
For a `TrafficSplit` resource to be correctly configured, it is important to ensure the following conditions are met:

- `metadata.namespace` is a [namespace added to the mesh](/docs/guides/app_onboarding/namespaces/)
- `metadata.namespace`, `spec.service`, and `spec.backends` all belong to the same namespace
- `spec.service` specifies an [FQDN of a Kubernetes service](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#services)
- `spec.service` and `spec.backends` correspond to Kubernetes service objects
- The total weight of all backends must be greater than zero, and each backend must have a positive weight

When a `TrafficSplit` resource is created, OSM applies the configuration on client sidecars to split traffic directed to the root service (`spec.service`) to the backends (`spec.backends`) based the specified weights. For HTTP traffic, the `Host/Authority` header in the request must match the FQDNs of the root service specified in the `TrafficSplit` resource. In the above example, it implies that the `Host/Authority` header in the HTTP request originated by the client must match the Kubernetes service FQDNs of the `default/bookstore` service for traffic split to work.

> Note: OSM does not configure `Host/Authority` header rewrites for the original HTTP requests, so it is necessary that the backend services referenced in a `TrafficSplit` resource accept requests with the original HTTP `Host/Authority` header.

It is important to note that a `TrafficSplit` resource only configures traffic splitting to a service, and does not give applications permission to communicate with each other. Thus, a valid [TrafficTarget](https://github.com/servicemeshinterface/smi-spec/blob/main/apis/traffic-access/v1alpha3/traffic-access.md#traffictarget) resource must be configured in conjunction with a `TrafficSplit` configuration to achieve traffic flow between applications as desired.

Refer to a demo on [Canary rollouts using SMI Traffic Split](/docs/demos/canary_rollout.md) to learn more.

0 comments on commit fd88c53

Please sign in to comment.