Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs for Gateway API #1813

Merged
merged 10 commits into from
Dec 20, 2024
325 changes: 325 additions & 0 deletions calico-enterprise/networking/gateway-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
---
description: Enable support for the Kubernetes Gateway API.
---

# Gateway API

## Big picture

Enable support for the Kubernetes Gateway API.

## Value

{{prodname}} includes support for the Kubernetes Gateway API, which allows advanced routing to services in a cluster, including weighted or blue-green load balancing.

## Concepts

### Gateway API

The Gateway API is an official Kubernetes API for advanced routing to services in a cluster. To read about its use cases, structure and design, please see [the official docs](https://gateway-api.sigs.k8s.io/).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we specify which (minimum) gateway api version(s) we support? I imagine that there may be conflicts with api versions, for example the grant is at v1beta1 now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've added a table to show this.


### Envoy Gateway

Several implementations of the Gateway API are available, one of which is the [Envoy Gateway](https://gateway.envoyproxy.io/). {{prodname}} integrates the Envoy Gateway implementation in order to provide support for the Gateway API.

### Access into a cluster from outside

The Gateway API only provides access into a cluster from outside when the cluster is _also_ provisioned to support Kubernetes Services with `type: LoadBalancer`. When a Gateway is configured, {{prodname}} creates a Deployment that does the actual work of routing and load balancing, etc., and a Service with `type: LoadBalancer` that fronts that Deployment. If the cluster has a `type: LoadBalancer` provider, it will then allocate an IP outside the cluster and arrange for requests to that IP to be forwarded to the Gateway Service.

Managed Kubernetes services like AKS, EKS and GKE include a `type: LoadBalancer` provider that automatically integrates with Azure, AWS and GCP respectively. On-prem clusters and non-managed clusters in the cloud need to set up their own `type: LoadBalancer` support.

## Before you begin

**Unsupported**

- Windows

## How to

- [Enable Gateway API support](#enable-gateway-api-support)
- [Use the Gateway API](#use-the-gateway-api)
- [Disable Gateway API support](#disable-gateway-api-support)

### Enable Gateway API support

To enable Gateway API support, create a `GatewayAPI` resource with name `tigera-secure`:

```bash
kubectl apply -f - <<EOF
apiVersion: operator.tigera.io/v1
kind: GatewayAPI
metadata:
name: tigera-secure
EOF
```

Shortly after this you will see that Gateway API resources are now available:

```bash
kubectl api-resources | grep gateway.networking.k8s.io
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be relying on the new tigerastatus instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point I'm more interested in showing that the CRDs have been installed. But certainly we could mention the "gatewayapi" tigerastatus object as well - would you like me to add that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think tigerastatus is a more useful thing to use. If it succeeds, then we know CRDs are installed. If not, it provides you useful troubleshooting information.

```

And also that there is a GatewayClass resource corresponding to the Envoy Gateway implementation included in {{prodname}}:

```bash
kubectl get gatewayclass -o yaml
```

### Use the Gateway API

Now you can use the Gateway API in any way that the API supports. When configuring a Gateway resource, be sure to specify `gatewayClassName: tigera-gateway-class`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be calling it tigera-gateway? -class is redundant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do. But in this case I think the -class is helpful, on balance. There are so many things that are called "gateway": the API, the controller, the Gateway objects, and the GatewayClass. So here I think it's helpful to be more explicit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't add suffixes to any resource we create in the operator, like storage classes, deployments, services, ... I think we should be consistent in naming things.


By way of a simple example:

- Create echo servers in namespaces `ns1` and `ns2`:

```bash
kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
name: ns1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
namespace: ns1
spec:
replicas: 1
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- image: ealen/echo-server:latest
imagePullPolicy: IfNotPresent
name: echoserver
ports:
- containerPort: 80
env:
- name: PORT
value: "80"
---
apiVersion: v1
kind: Service
metadata:
name: echoserver
namespace: ns1
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: ClusterIP
selector:
app: echoserver
---
apiVersion: v1
kind: Namespace
metadata:
name: ns2
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echoserver
namespace: ns2
spec:
replicas: 1
selector:
matchLabels:
app: echoserver
template:
metadata:
labels:
app: echoserver
spec:
containers:
- image: ealen/echo-server:latest
imagePullPolicy: IfNotPresent
name: echoserver
ports:
- containerPort: 80
env:
- name: PORT
value: "80"
---
apiVersion: v1
kind: Service
metadata:
name: echoserver
namespace: ns2
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: ClusterIP
selector:
app: echoserver
EOF
```

- Create a client pod that we can test from:

```bash
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test-client
spec:
containers:
- args:
- "3600"
command:
- /bin/sleep
image: ubuntu
imagePullPolicy: Always
name: c1
terminationGracePeriodSeconds: 0
EOF
```

- Once that pod is running, install `curl` in it:

```bash
kubectl exec -it test-client -- apt-get -y update
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we combine the lines and remote -it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a need to do that. I agree it's slightly annoying that everyone puts -it everywhere even when not needed, but it does no harm. (And I remember cases where -i is surprisingly needed. Not sure if this could be one of those.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confident that these don't need it.

Copy link
Member

@rene-dekker rene-dekker Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use https://hub.docker.com/r/alpine/curl image for this page to avoid apt update and installing curl.

-- update --
Never mind, I see you need jq

kubectl exec -it test-client -- apt-get -y install curl
```

- Configure a Gateway:

```bash
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: tigera-gateway-class
listeners:
- name: http
protocol: HTTP
port: 80
EOF
```

- Configure routes to the two echo servers:

```bash
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ns1-2-echo
spec:
parentRefs:
- name: eg
rules:
- backendRefs:
- group: ""
kind: Service
name: echoserver
namespace: ns1
port: 80
weight: 1
matches:
- path:
type: PathPrefix
value: /ns1
- backendRefs:
- group: ""
kind: Service
name: echoserver
namespace: ns2
port: 80
weight: 1
matches:
- path:
type: PathPrefix
value: /ns2
EOF
```

- Configure the ReferenceGrants that are needed to allow the Gateway to reference services in other namespaces:

```bash
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: echo
namespace: ns1
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: default
to:
- group: ""
kind: Service
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: echo
namespace: ns2
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: default
to:
- group: ""
kind: Service
EOF
```

- Find the cluster IP of the Gateway Service:

```bash
kubectl get services -n tigera-gateway-system -o wide
```

- Curl from the test client pod to a URL that should be handled by the echo server in namespace `ns1`, via the Gateway:

```bash
curl http://<cluster IP>/ns1/subpath?query=demo | jq
```

- The output confirms that the request was handled by the echo server in namespace `ns1`:

```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be empty? Maybe if we expect an empty output, we can put it in text, rather than an empty code block? (I'm not even sure something will be rendered, the deploy preview didn't build unfortunately.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this was work-in-progress. It's filled in now.

```

- Curl from the test client pod to a URL that should be handled by the echo server in namespace `ns2`, via the Gateway:

```bash
curl http://<cluster IP>/ns2/subpath?query=demo | jq
```

- The output confirms that the request was handled by the echo server in namespace `ns2`:

```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be empty as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this was work-in-progress. It's filled in now.

```

### Disable Gateway API support

To disable Gateway API support, delete the `GatewayAPI` resource with name `tigera-secure`:

```bash
kubectl delete -f - <<EOF
apiVersion: operator.tigera.io/v1
kind: GatewayAPI
metadata:
name: tigera-secure
EOF
```

Please note that the Gateway API CRDs will be left in place. This is to allow for the possibility of using other Gateway API implementations in addition to the one provided by {{prodname}}.

Check failure on line 325 in calico-enterprise/networking/gateway-api.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'CRDs'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'CRDs'?", "location": {"path": "calico-enterprise/networking/gateway-api.mdx", "range": {"start": {"line": 325, "column": 34}}}, "severity": "ERROR"}
1 change: 1 addition & 0 deletions sidebars-calico-enterprise.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ module.exports = {
link: { type: 'doc', id: 'networking/index' },
items: [
'networking/determine-best-networking',
'networking/gateway-api',
{
type: 'category',
label: 'Networking basics',
Expand Down
Loading