The Nginx Ingress Controller 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. You can read more about these canary annotations on the official canary annotations documentation page. The canary Ingress ignores any other non-canary nginx annotations. Instead, it leverages the annotation settings from the primary Ingress.
The Rollout controller will always set the following two annotations on the canary Ingress (using your configured or the default
canary: trueto indicate that this is the canary Ingress
canary-weight: <num>to indicate what percentage of traffic to send to the canary. If all traffic is routed to the stable Service, this is set to
You can provide additional annotations to add to the canary Ingress via the
additionalIngressAnnotations field to enable features like routing by header or cookie.
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:
apiVersion: argoproj.io/v1alpha1 kind: Rollout spec: ... strategy: canary: canaryService: canary-service # required stableService: stable-service # required trafficRouting: nginx: # Either stableIngress or stableIngresses must be configured, but not both. stableIngress: primary-ingress stableIngresses: - primary-ingress - secondary-ingress - tertiary-ingress annotationPrefix: customingress.nginx.ingress.kubernetes.io # optional additionalIngressAnnotations: # optional canary-by-header: X-Canary canary-by-header-value: iwantsit
The stable 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 Service. 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 Service 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
annotationPrefix field. The canary Ingress uses that prefix instead of the default
nginx.ingress.kubernetes.io if the field set.
Using Argo Rollouts with multiple NGINX ingress controllers per service¶
Starting with v1.5, argo rollouts supports multiple Nginx ingress controllers pointing at one service with canary deployments. If only one ingress controller is needed, utilize the existing key
stableIngress. If multiple ingress controllers are needed (e.g., separating internal vs external traffic), use the key
stableIngresses instead. It takes an array of string values that are the names of the ingress controllers. Canary steps are applied identically across all ingress controllers.
Using Argo Rollouts with custom NGINX ingress controller names¶
As a default, the Argo Rollouts controller only operates on ingresses with the
kubernetes.io/ingress.class annotation or
spec.ingressClassName set to
nginx. A user can configure the controller to operate on Ingresses with different class name by specifying the
--nginx-ingress-classes flag. A user can list the
--nginx-ingress-classes flag multiple times if the Argo Rollouts controller should operate on multiple values. This solves the case where a cluster has multiple Ingress controllers operating on different class values.
If the user would like the controller to operate on any Ingress without the
kubernetes.io/ingress.class annotation or
spec.ingressClassName, a user should add the following