Skip to content

Commit

Permalink
Add Nginx docs for traffic management
Browse files Browse the repository at this point in the history
  • Loading branch information
dthomson25 committed Dec 16, 2019
1 parent 032eaf4 commit abb0a57
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 0 deletions.
47 changes: 47 additions & 0 deletions docs/features/traffic-management/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Traffic management

NOTE: This is being implemented for the v0.7 version and everything described below is subject to change.

Traffic management is controlling the data plane to have intelligent routing rules for an application. These routing rules can manipulate the flow of traffic to different versions of an application enabling Progressive Delivery. These controls limit the blast radius of a new release by ensuring a small percentage of users receive a new version while it is verified.

There are various techniques to achieve traffic management:

- Raw percentages (i.e., 5% of traffic should go to the new version while the rest goes to the stable version)
- Header-based routing (i.e., send requests with a specific header to the new version)
- Mirrored traffic where all the traffic is copied and send to the new version in parallel (but the response is ignored)

## Traffic Management tools in Kubernetes

The core Kubernetes objects do not have fine-grained tools needed to fulfill all the requirements of traffic management. At most, Kubernetes offers naïve load balancing capabilities through the Service object by offering an endpoint that routes traffic to a grouping of pods based on that Service's selector. Functionality like traffic mirroring or routing by headers is not possible with the default core Service object, and the only way to control the percentage of traffic to different versions of an application is by manipulating replica counts of those versions.

Service Meshes fill this missing functionality in Kubernetes. They introduce new concepts and functionality to control the data plane through the use of CRDs and other core Kubernetes resources.

## How does Argo Rollouts enable traffic management?

Argo Rollouts enables traffic management by manipulating the Service Mesh resources to match the intent of the Rollout. Argo Rollouts currently supports the following service meshes:

- [Istio](istio.md)
- [Nginx Ingress Controller](nginx.md)
- File a ticket [here](https://github.com/argoproj/argo-rollouts/issues) if you would like another implementation (or thumbs up it if that issue already exists)

Regardless of the Service Mesh used, the Rollout object has to set a canary Service and a stable Service in its spec. Here is an example with those fields set:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
...
strategy:
canary:
canaryService: canary-service
stableService: stable-service
networking:
...
```
The controller modifies these Services to route traffic to the appropriate canary and stable ReplicaSets as the Rollout progresses. These Services are used by the Service Mesh to define what group of pods should receive the canary and stable traffic.
Additionally, the Argo Rollouts controller needs to treat the Rollout object differently when using traffic management. In particular, the Stable ReplicaSet owned by the Rollout remains fully scaled up as the Rollout progresses through the Canary steps.
Since the traffic is controlled independently by the Service Mesh resources, the controller needs to make a best effort to ensure that the Stable and New ReplicaSets are not overwhelmed by the traffic sent to them. By leaving the Stable ReplicaSet scaled up, the controller is ensuring that the Stable ReplicaSet can handle 100% of the traffic at any time*. The New ReplicaSet follows the same behavior as without traffic management. The new ReplicaSet's replica count is equal to the latest SetWeight step percentage multiple by the total replica count of the Rollout. This calculation ensures that the canary version does not receive more traffic than it can handle.
*The Rollout has to assume that the application can handle 100% of traffic if it is fully scaled up. It should outsource to the HPA to detect if the Rollout needs to more replicas if 100% isn't enough.
3 changes: 3 additions & 0 deletions docs/features/traffic-management/istio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Istio

TBD
35 changes: 35 additions & 0 deletions docs/features/traffic-management/nginx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Nginx

NOTE: This is being implemented for the v0.7 version and everything described below is subject to change.

The [Nginx Ingress Controller](https://kubernetes.github.io/ingress-nginx/) enables traffic management through one or more Ingress objects to configure an Nginx deployment that routes traffic directly to pods. Each Nginx Ingress contains multiple annotations that modify the behavior of the Nginx Deployment. For traffic management between different versions of an application, the Nginx Ingress controller provides the capability to split traffic by introducing a second Ingress object (referred to as the canary Ingress) with some special annotations. Here are the canary specific annotations:

- `nginx.ingress.kubernetes.io/canary` indicates that this Ingress is serving canary traffic
- `nginx.ingress.kubernetes.io/canary-weight` indicates what percentage of traffic to send to the canary.
- Other canary-specific annotations deal with routing traffic via headers or cookies. A future version of Argo Rollouts will contain this functionality.

You can read more about these canary annotations on the official [documenentation page](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary). The canary Ingress ignores any other non-canary nginx annotations. Instead, it leverages the annotation settings from the primary Ingress.

## Integration with Argo Rollouts
There are a couple of required fields in a Rollout to send split traffic between versions using Nginx. Below is an example of a Rollout with those fields:

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
spec:
...
strategy:
canary:
canaryService: canary-service # required
stableService: stable-service # required
networking:
nginx:
primaryIngress: primary-ingress # required
annotationPrefix: example.nginx.com/ # optional
```
The primary Ingress field is a reference to an Ingress in the same namespace of the Rollout. The Rollout requires the primary Ingress routes traffic to the stable ReplicaSet. The Rollout checks that condition by confirming the Ingress has a backend that matches the Rollout's stableService.
The controller routes traffic to the canary ReplicaSet by creating a second Ingress with the canary annotations. As the Rollout progresses through the Canary steps, the controller updates the canary Ingress's canary annotations to reflect the desired state of the Rollout enabling traffic splitting between two different versions.
Since the Nginx Ingress controller allows users to configure the annotation prefix used by the Ingress controller, Rollouts can specify the optional `annonationPrefix` field. The canary Ingress uses that prefix instead of the default `nginx.ingress.kubernetes.io` if the field set.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ nav:
- features/index.md
- BlueGreen: features/bluegreen.md
- Canary: features/canary.md
- Traffic Management: features/traffic-management/index.md
- Kubectl Plugin: features/kubectl-plugin.md
- HPA Support: features/hpa-support.md
- Kustomize Support: features/kustomize.md
Expand Down

0 comments on commit abb0a57

Please sign in to comment.