Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 68 additions & 47 deletions gateway/single-cluster/regional-l7-ilb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ To achieve this, we will:
- [Deploying Gateways](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways)
- [Proxy-only subnets for internal HTTP(S) load balancers](https://cloud.google.com/load-balancing/docs/l7-internal/proxy-only-subnets)

### Gateway API v1 Migration Notes

This recipe has been updated to use the stable Gateway API v1 specification. Key changes from earlier versions:

#### API Version Updates
- **Gateway**: `networking.x-k8s.io/v1alpha1` → `gateway.networking.k8s.io/v1`
- **HTTPRoute**: `networking.x-k8s.io/v1alpha1` → `gateway.networking.k8s.io/v1`

#### HTTPRoute Field Changes
- **Backend References**: `forwardTo` → `backendRefs`
- **Service Name**: `serviceName` → `name`

#### Gateway API CRD Version
- Updated from `v0.3.0` to `v1.2.0` for stable v1 API support

If you're migrating from an older version, ensure your GKE cluster supports Gateway API v1 (available in GKE 1.24+).

## Setup

Set the project environment variable and gcloud configuration
Expand All @@ -29,14 +46,36 @@ $ gcloud services enable \
container.googleapis.com
```

Beware to [create a proxy-only subnet](https://cloud.google.com/load-balancing/docs/l7-internal/proxy-only-subnets#proxy_only_subnet_create) in the same region of the cluster you're going to create
```
gcloud compute networks subnets create SUBNET_NAME \
--purpose=INTERNAL_HTTPS_LOAD_BALANCER \
Create a [proxy-only subnet](https://cloud.google.com/load-balancing/docs/proxy-only-subnets) in the same region as your GKE cluster. This subnet is required for the internal HTTP(S) Load Balancer to function properly.

**Important**: You must create the proxy-only subnet before deploying the Gateway resources.

```bash
gcloud compute networks subnets create proxy-only-subnet \
--purpose=REGIONAL_MANAGED_PROXY \
--role=ACTIVE \
--region=REGION \
--network=VPC_NETWORK_NAME \
--range=CIDR_RANGE
--range=10.129.0.0/23
```

**Proxy-only Subnet Requirements (2024-2025 Updates)**:
- Use `--purpose=REGIONAL_MANAGED_PROXY` for regional internal load balancers
- Minimum subnet size: `/26` (64 IP addresses)
- Recommended size: `/23` (512 IP addresses) for better scalability
- Create one proxy-only subnet per region in your VPC network
- Ensure firewall rules allow traffic from the proxy-only subnet to your backend services

**Firewall Configuration**: If using a custom VPC network, create a firewall rule to allow health checks:
```bash
gcloud compute firewall-rules create allow-proxy-only-subnet \
--direction=INGRESS \
--priority=1000 \
--network=VPC_NETWORK_NAME \
--action=ALLOW \
--rules=tcp:80,tcp:443,tcp:8080 \
--source-ranges=10.129.0.0/23 \
--target-tags=gke-node
```

[Create one GKE cluster](https://github.com/GoogleCloudPlatform/gke-networking-recipes/blob/master/cluster-setup.md#single-cluster-environment) if one is not running yet.
Expand Down Expand Up @@ -147,14 +186,29 @@ $ kubectl apply -f app-v2.yaml
```

Now enable the [Gateway API Custom Resource Definitions (CRDs)](https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways#install_gateway_api_crds)

**Note**: This command has been updated to use Gateway API v1.2.0 which includes stable v1 API support:
```
kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0" | kubectl apply -f -
kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.2.0" | kubectl apply -f -
```

Check that presence of the Gateway classes, gke-l7-gxlb and gke-l7-rilb should be available and listed:

```
kubectl get gatewayclass
```
| NAME | CONTROLLER | ACCEPTED |
|---|---|---|
| gke-l7-global-external-managed | networking.gke.io/gateway | True |
| gke-l7-gxlb | networking.gke.io/gateway | True |
| gke-l7-regional-external-managed | networking.gke.io/gateway | True |
| gke-l7-rilb | networking.gke.io/gateway | True |
| gke-passthrough-lb-external-managed | networking.gke.io/persistent-ip-controller | True |
| gke-passthrough-lb-internal-managed | networking.gke.io/persistent-ip-controller | True |
| gke-persistent-fast-regional-external-managed | networking.gke.io/persistent-ip-controller | True |
| gke-persistent-fast-regional-internal-managed | networking.gke.io/persistent-ip-controller | True |
| gke-persistent-regional-external-managed | networking.gke.io/persistent-ip-controller | True |
| gke-persistent-regional-internal-managed | networking.gke.io/persistent-ip-controller | True |

## Deploy the Gateway and HTTPRoute

Expand All @@ -163,51 +217,18 @@ Once the applications have been deployed, we can then configure an internal Gate
Deploy the resources for the Single-cluster Gateway. This includes a Gateway utilizing the `gke-l7-rilb` GatewayClass and selecting on HTTPRoutes with the label `gateway: single-cluster-gateway-rilb`.

```
$ cat gateway.yaml

kind: Gateway
apiVersion: networking.x-k8s.io/v1alpha1
metadata:
name: single-cluster-gateway-rilb
namespace: store
spec:
gatewayClassName: gke-l7-rilb
listeners:
- protocol: HTTP
port: 80
routes:
kind: HTTPRoute
selector:
matchLabels:
gateway: single-cluster-gateway-rilb
kubectl apply -f gateway.yaml
```

Deploy the `store-route-ilb` HTTPRoute resource to the config cluster.
Deploy the `store` HTTPRoute resource to the config cluster.

```
$ cat route.yaml

kind: HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
metadata:
name: store-route-ilb
namespace: store
labels:
gateway: single-cluster-gateway-rilb
spec:
hostnames:
- "store.example.internal"
rules:
- forwardTo:
- serviceName: store-v1
port: 8080
weight: 50
- serviceName: store-v2
port: 8080
weight: 50
kubectl apply -f route.yaml
```

This HTTPRoute will allow users to take advantage of features in the `gke-l7-rilb ` GatewayClass like traffic weighting. In this scenario, we specify the `weight` fields in the HTTPRoute to send 50% of traffic to the application version `store-v1` and 50% of traffic to the application version `store-v2`.
This HTTPRoute will allow users to take advantage of features in the `gke-l7-rilb ` GatewayClass like traffic weighting. In this scenario, we specify the `weight` fields in the `backendRefs` to send 50% of traffic to the application version `store-v1` and 50% of traffic to the application version `store-v2`.

**Note**: This HTTPRoute uses the updated Gateway API v1 specification with `backendRefs` instead of the deprecated `forwardTo` field.

/////
## Validate successful deployment of an internal Single-cluster Gateway
Expand All @@ -222,15 +243,15 @@ $ gcloud compute instances create client-host \
--tags=allow-ssh,http-server,https-server
```

Grab the internal IP address for the Single-cluster Gateway.
Get the Internal IP address for the Single-cluster Gateway.

```
$ kubectl -n store get gateway single-cluster-gateway-rilb -o=jsonpath="{.status.addresses[0].value}"
```

SSH into the client VM.
```
$ gcloud beta compute ssh client-host --zone=europe-west2-a
$ gcloud beta compute ssh client-host --zone=$ZONE
```

Confirm that as we issue requests to the Single-cluster Regional L7 Internal Balancer with traffic weighting configured; we are seeing half traffic requests served from application `store-v1` and half requests being served from application with metadata `store-v2`.
Expand Down
16 changes: 9 additions & 7 deletions gateway/single-cluster/regional-l7-ilb/gateway.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
kind: Gateway
apiVersion: networking.x-k8s.io/v1alpha1
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: single-cluster-gateway-rilb
namespace: store
spec:
gatewayClassName: gke-l7-rilb
listeners:
- protocol: HTTP
- name: http
protocol: HTTP
port: 80
routes:
kind: HTTPRoute
selector:
matchLabels:
gateway: single-cluster-gateway-rilb
allowedRoutes:
kinds:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespaces:
from: Same
21 changes: 17 additions & 4 deletions gateway/single-cluster/regional-l7-ilb/route.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
kind: HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: store-route-ilb
namespace: store
labels:
gateway: single-cluster-gateway-rilb
spec:
# 1. Hostname is correct (matches your curl request)
hostnames:
- "store.example.internal"

# The parentRefs field is assumed to be defined by the GKE controller
# based on the Gateway's listeners, but for clarity, it should look like this:
parentRefs:
- name: single-cluster-gateway-rilb
namespace: store # Explicitly link to your Gateway
sectionName: http # Link to the specific listener (named 'http' in our previous fix)

rules:
- forwardTo:
- serviceName: store-v1
- matches:
- path:
type: PathPrefix
value: "/"
backendRefs:
- name: store-v1
port: 8080
weight: 50
- serviceName: store-v2
- name: store-v2
port: 8080
weight: 50