Skip to content

Commit

Permalink
feat: TrafficRouting support with AWS App Mesh (#1401) (#1606)
Browse files Browse the repository at this point in the history
Signed-off-by: Kiran Meduri <[email protected]>
  • Loading branch information
kiranmeduri authored Feb 3, 2022
1 parent e79296a commit 5f0f8b4
Show file tree
Hide file tree
Showing 34 changed files with 4,516 additions and 636 deletions.
3 changes: 3 additions & 0 deletions cmd/rollouts-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func newCommand() *cobra.Command {
trafficSplitVersion string
ambassadorVersion string
ingressVersion string
appmeshCRDVersion string
albIngressClasses []string
nginxIngressClasses []string
awsVerifyTargetGroup bool
Expand Down Expand Up @@ -89,6 +90,7 @@ func newCommand() *cobra.Command {
defaults.SetIstioAPIVersion(istioVersion)
defaults.SetAmbassadorAPIVersion(ambassadorVersion)
defaults.SetSMIAPIVersion(trafficSplitVersion)
defaults.SetAppMeshCRDVersion(appmeshCRDVersion)

config, err := clientConfig.ClientConfig()
checkError(err)
Expand Down Expand Up @@ -228,6 +230,7 @@ func newCommand() *cobra.Command {
command.Flags().StringVar(&ambassadorVersion, "ambassador-api-version", defaults.DefaultAmbassadorVersion, "Set the Ambassador apiVersion that controller should look when manipulating Ambassador Mappings.")
command.Flags().StringVar(&trafficSplitVersion, "traffic-split-api-version", defaults.DefaultSMITrafficSplitVersion, "Set the default TrafficSplit apiVersion that controller uses when creating TrafficSplits.")
command.Flags().StringVar(&ingressVersion, "ingress-api-version", "", "Set the Ingress apiVersion that the controller should use.")
command.Flags().StringVar(&appmeshCRDVersion, "appmesh-crd-version", defaults.DefaultAppMeshCRDVersion, "Set the default AppMesh CRD Version that controller uses when manipulating resources.")
command.Flags().StringArrayVar(&albIngressClasses, "alb-ingress-classes", defaultALBIngressClass, "Defines all the ingress class annotations that the alb ingress controller operates on. Defaults to alb")
command.Flags().StringArrayVar(&nginxIngressClasses, "nginx-ingress-classes", defaultNGINXIngressClass, "Defines all the ingress class annotations that the nginx ingress controller operates on. Defaults to nginx")
command.Flags().BoolVar(&awsVerifyTargetGroup, "alb-verify-weight", false, "Verify ALB target group weights before progressing through steps (requires AWS privileges)")
Expand Down
11 changes: 11 additions & 0 deletions controller/metrics/rollout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,17 @@ func TestGetStrategyAndTrafficRouter(t *testing.T) {
expectedStrategy: "canary",
expectedTrafficRouter: "Nginx",
},
{
strategy: v1alpha1.RolloutStrategy{
Canary: &v1alpha1.CanaryStrategy{
TrafficRouting: &v1alpha1.RolloutTrafficRouting{
AppMesh: &v1alpha1.AppMeshTrafficRouting{},
},
},
},
expectedStrategy: "canary",
expectedTrafficRouter: "AppMesh",
},
}

for _, test := range tests {
Expand Down
3 changes: 3 additions & 0 deletions controller/metrics/rollouts.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ func getStrategyAndTrafficRouter(rollout *v1alpha1.Rollout) (string, string) {
if rollout.Spec.Strategy.Canary.TrafficRouting.SMI != nil {
trafficRouter = "SMI"
}
if rollout.Spec.Strategy.Canary.TrafficRouting.AppMesh != nil {
trafficRouter = "AppMesh"
}
}
}
return strategy, trafficRouter
Expand Down
123 changes: 123 additions & 0 deletions docs/getting-started/appmesh/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Getting Started - App Mesh

This guide covers how Argo Rollouts integrates with service-meshes managed by [AWS App Mesh](https://docs.aws.amazon.com/app-mesh/latest/userguide/what-is-app-mesh.html). This guide builds upon the concepts of the [basic getting started guide](../../getting-started.md).

## Requirements
- Kubernetes cluster with AWS App Mesh Controller for K8s installed

!!! tip

See the [App Mesh Controler Installation instructions](https://docs.aws.amazon.com/app-mesh/latest/userguide/getting-started-kubernetes.html) on how to get started using App Mesh with Kubernetes.

## 1. Deploy the Rollout, Services, App Mesh CRD

When App Mesh is used as the traffic router, the Rollout canary strategy must define the following mandatory fields:

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-rollout
spec:
strategy:
canary:
# canaryService and stableService are references to Services which the Rollout will modify
# to target the canary ReplicaSet and stable ReplicaSet respectively (required).
canaryService: my-svc-canary
stableService: my-svc-stable
trafficRouting:
appMesh:
# The referenced virtual-service will be used to determine the virtual-router that is
# manipulated to update canary weights.
virtualService:
# name of the virtual-service App Mesh CR
name: my-svc
# Optional set of routes to update. If empty, all routes associated with the virtual-service are updated.
routes:
- http-primary
# virtualNodeGroup is a structure to refer App Mesh virtual-node CR corresponding to Canary and Stable versions
virtualNodeGroup:
# canaryVirtualNodeRef refers to virtual-node corresponding to canary version. Rollouts controller will
# update the podSelector of this virtual-node to latest canary pod-hash generated by controller.
canaryVirtualNodeRef:
name: my-vn-canary
# stableVirtualNodeRef refers to virtual-node corresponding to stable version. Rollouts controller will
# update the podSelector of this virtual-node to latest stable pod-hash generated by controller.
stableVirtualNodeRef:
name: my-vn-stable
steps:
- setWeight: 25
- pause: {}
...
```

In this guide, the two services are: `my-svc-canary` and `my-svc-stable` respectively. There are two
virtual-node CRs corresponding to these services named `my-vn-canary` and `my-vn-stable`
respectively. In addition, there is a virtual-service named `rollout-demo-vsvc` that is provided by a
virtual-router CR named `rollout-demo-vrouter`. This virtual-router need have at least one route with action to forward
traffic to the canary and stable virtual-nodes. Initially weight for canary is set to 0% while for stable it is 100%.
During rollout, controller will modify the weights on route(s) based on the configuraiton defined in
`steps[N].setWeight`.

To summarize, run the following commands to deploy a service:

* Two services (stable and canary)
* One service (for VIP and DNS lookup)
* Two App Mesh virtual-nodes (stable and canary)
* One App Mesh virtual-router with routes to virtual-nodes
* One App Mesh virtual-service corresponding to VIP service
* A rollout

```shell
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/appmesh/canary-service.yaml
kubectl apply -f https://raw.githubusercontent.com/argoproj/argo-rollouts/master/docs/getting-started/appmesh/canary-rollout.yaml
```
## 2. Verify service

First make sure that rollout is stable.

```shell
kubectl argo rollouts get rollout my-rollout -n argo-examples -w
```

Then make sure the service is functional.

```shell
kubectl -n argo-examples port-forward svc/my-svc 8181:80
```

## 3. Rollout new version

Now its time to deploy new version. Update the rollout with new image.

```shell
kubectl argo rollouts set image my-rollout demo=argoproj/rollouts-demo:green -n argo-examples
```

Rollout should deploy a new canary revision and update the weights under virtual-router.

```shell
kubectl get -n argo-examples virtualrouter my-vrouter -o json | jq ".spec.routes[0].httpRoute.action.weightedTargets"
[
{
"virtualNodeRef": {
"name": "my-vn-canary"
},
"weight": 25
},
{
"virtualNodeRef": {
"name": "my-vn-stable"
},
"weight": 75
}
]
```

Now manually approve the rollout that is paused indefinitely, and continue watching the routes get updated

```shell
kubectl argo rollouts promote my-rollout -n argo-examples

watch -d 'kubectl get -n argo-examples virtualrouter my-vrouter -o json | jq ".spec.routes[0].httpRoute.action.weightedTargets"'
```
71 changes: 71 additions & 0 deletions examples/appmesh/canary-rollout.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
namespace: argo-examples
spec:
args:
- name: envoy_cluster_name
metrics:
- name: success-rate
interval: 5m
successCondition: result[0] >= 0.99
failureLimit: 3
provider:
prometheus:
address: http://appmesh-prometheus.appmesh-system:9090
query: |
sum(irate(envoy_cluster_upstream_rq_xx{app="wrk-tester",envoy_cluster_name="{{args.envoy_cluster_name}}",envoy_response_code_class!~"5.*"}[5m])) /
sum(irate(envoy_cluster_upstream_rq_xx{app="wrk-tester",envoy_cluster_name="{{args.envoy_cluster_name}}"}[5m]))
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-rollout
namespace: argo-examples
spec:
replicas: 4
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: demo
image: argoproj/rollouts-demo:blue
imagePullPolicy: Always
ports:
- name: http
containerPort: 8080
strategy:
canary:
canaryService: my-svc-canary
stableService: my-svc-stable
trafficRouting:
appMesh:
virtualService:
name: my-svc
virtualNodeGroup:
canaryVirtualNodeRef:
name: my-vn-canary
stableVirtualNodeRef:
name: my-vn-stable
steps:
- setWeight: 25
- pause: {}
- setWeight: 50
- pause: {duration: 10m}
- setWeight: 75
- pause: {duration: 10m}
# Uncomment below to enable analysis
# analysis:
# templates:
# - templateName: success-rate
# startingStep: 2
# args:
# - name: envoy_cluster_name
# value: cds_egress_argo-examples_my-vn-canary_argo-examples_http_80
Loading

0 comments on commit 5f0f8b4

Please sign in to comment.