Skip to content

Commit

Permalink
feat: Add TCPRoute support (#20)
Browse files Browse the repository at this point in the history
* feat: Add TCPRoute support

Signed-off-by: Philipp Plotnikov <[email protected]>

* refactor: split plugin.go file content to the several files

Signed-off-by: Philipp Plotnikov <[email protected]>

* test: change tests

Signed-off-by: Philipp Plotnikov <[email protected]>

* refactor: run lint

Signed-off-by: Philipp Plotnikov <[email protected]>

* test: add TCPRoute tests

Signed-off-by: Philipp Plotnikov <[email protected]>

* docs: add documentation about TCPRoute

Signed-off-by: Philipp Plotnikov <[email protected]>

* refactor: change the location of httpRoute examples

Signed-off-by: Philipp Plotnikov <[email protected]>

---------

Signed-off-by: Philipp Plotnikov <[email protected]>
  • Loading branch information
Philipp-Plotnikov authored Sep 15, 2023
1 parent 474fe43 commit d8d5410
Show file tree
Hide file tree
Showing 10 changed files with 788 additions and 348 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ release:
.PHONY: gateway-api-plugin-build
gateway-api-plugin-build:
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} go build -v -o ${DIST_DIR}/${BIN_NAME} .

.PHONY: local-build
local-build:
go build -gcflags=all="-N -l" -o gatewayapi-plugin

.PHONY: lint
lint:
golangci-lint run --fix
279 changes: 279 additions & 0 deletions examples/tcproute/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
# Using Traefik Gateway API with Argo Rollouts

This guide will describe how to use Traefik proxy an an implementation
for the Gateway API in order to do split traffic with Argo Rollouts.

Note that Argo Rollouts also [supports Traefik natively](https://argoproj.github.io/argo-rollouts/features/traffic-management/traefik/).

## Step 1 - Enable Gateway Provider and create Gateway entrypoint

Before enabling a Gateway Provider you also need to install Traefik. Follow the official [installation instructions](https://doc.traefik.io/traefik/getting-started/install-traefik/).

You should also read the documentation on how [Traefik implements the Gateway API](https://doc.traefik.io/traefik/providers/kubernetes-gateway/).

1. Register [Gateway API CRD](https://gateway-api.sigs.k8s.io/guides/#install-standard-channel)

```
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v0.6.1/standard-install.yaml
```

2. Create the same deployment resource with service account

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: traefik
spec:
replicas: 1
selector:
matchLabels:
app: argo-rollouts-traefik-lb
template:
metadata:
labels:
app: argo-rollouts-traefik-lb
spec:
serviceAccountName: traefik-controller
containers:
- name: traefik
image: traefik:v2.9
args:
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --experimental.kubernetesgateway
- --providers.kubernetesgateway
ports:
- name: web
containerPort: 80
```
3. Create the same ServiceAccount
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: traefik-controller
```
4. Create Cluster Role resource with needed permissions for Gateway API provider.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: traefik-controller-role
namespace: aws-local-runtime
rules:
- apiGroups:
- "*"
resources:
- "*"
verbs:
- "*"
```
Note that these permission are not very strict. You should lock them down according to your needs.
5. Create Cluster Role Binding
With the following role we allow Traefik to have write access to Http Routes and Gateways.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: traefik-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-controller-role
subjects:
- namespace: default
kind: ServiceAccount
name: traefik-controller
```
## Step 2 - Create GatewayClass and Gateway resources
After we enabled the Gateway API provider in our controller we can create a GatewayClass and Gateway:
- GatewayClass
```yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: argo-rollouts-gateway-class
spec:
controllerName: traefik.io/gateway-controller
```
- Gateway
```yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: argo-rollouts-gateway
spec:
gatewayClassName: argo-rollouts-gateway-class
listeners:
- protocol: TCP
name: tcp
port: 80 # one of Gateway entrypoint that we created at 1 step
```
## Step 3 - Create cluster entrypoint and map it with our Gateway entrypoint
In different controllers entry points can be created differently. For Traefik controller we can create entry point like this:
```yaml
apiVersion: v1
kind: Service
metadata:
name: argo-rollouts-traefik-lb
spec:
type: LoadBalancer
selector:
app: argo-rollouts-traefik-lb # selector of Gateway provider(step 1)
ports:
- protocol: TCP
port: 8080
targetPort: web # map with Gateway entrypoint
name: web
```
This concludes the setup that is specific to Traefik Proxy. The rest of the steps are generic to any implementation of the Gateway API.
## Step 4 - Create TCPRoute that defines a traffic split
Create TCPRoute and connect to the created Gateway resource
```yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: TCPRoute
metadata:
name: argo-rollouts-tcp-route
spec:
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: argo-rollouts-gateway
sectionName: tcp
rules:
- backendRefs:
- name: argo-rollouts-stable-service
port: 80
- name: argo-rollouts-canary-service
port: 80
```
## Step 5 - Create canary and stable services for your application
- Canary service
```yaml
apiVersion: v1
kind: Service
metadata:
name: argo-rollouts-canary-service
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: rollouts-demo
```
- Stable service
```yaml
apiVersion: v1
kind: Service
metadata:
name: argo-rollouts-stable-service
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: rollouts-demo
```
## Step 6 - Grant argo-rollouts permissions to view and modify Gateway TCPRoute resources
The argo-rollouts service account needs the ability to be able to view and mofiy TCPRoutes as well as its existing permissions. Edit the `argo-rollouts` cluster role to add the following permissions:

```yaml
rules:
- apiGroups:
- gateway.networking.k8s.io
resources:
- tcproutes
verbs:
- '*'
```

## Step 7 - Create argo-rollouts resources

We can finally create the definition of the application.

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollouts-demo
spec:
replicas: 5
strategy:
canary:
canaryService: argo-rollouts-canary-service # our created canary service
stableService: argo-rollouts-stable-service # our created stable service
trafficRouting:
plugins:
argoproj-labs/gatewayAPI:
tcpRoute: argo-rollouts-tcp-route # our created tcproute
namespace: default # namespace where this rollout resides.
steps:
- setWeight: 30
- pause: {}
- setWeight: 40
- pause: { duration: 10 }
- setWeight: 60
- pause: { duration: 10 }
- setWeight: 80
- pause: { duration: 10 }
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollouts-demo
template:
metadata:
labels:
app: rollouts-demo
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:red
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
```

Apply all the yaml files to your cluster

## Step 8 - Test the canary

Perform a deployment like any other Rollout and the Gateway plugin will split the traffic to your canary by instructing Traefik proxy via the Gateway API


74 changes: 37 additions & 37 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,69 +1,69 @@
module github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi

go 1.19
go 1.20

require (
github.com/argoproj/argo-rollouts v1.4.0-rc1.0.20230310073321-5fef78a8e47b
github.com/hashicorp/go-plugin v1.4.9
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.2
k8s.io/client-go v0.26.0
sigs.k8s.io/gateway-api v0.6.1
github.com/argoproj/argo-rollouts v1.5.1
github.com/hashicorp/go-plugin v1.4.10
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
k8s.io/client-go v0.28.0
sigs.k8s.io/gateway-api v0.7.1
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/fatih/color v1.12.0 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/hashicorp/go-hclog v0.14.1 // indirect
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oklog/run v1.0.0 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/oauth2 v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/oauth2 v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.53.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect
google.golang.org/grpc v1.57.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

require (
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/protobuf v1.29.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.26.0 // indirect
k8s.io/apimachinery v0.26.0
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
k8s.io/api v0.28.0 // indirect
k8s.io/apimachinery v0.28.0
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect
)
Loading

0 comments on commit d8d5410

Please sign in to comment.