Skip to content

Commit e55b781

Browse files
Merge pull request #2438 from MAIF/feature/k8s-gateway-api
Experimental support for k8s gateway api
2 parents 3e745c8 + 5cf5cfa commit e55b781

41 files changed

Lines changed: 5582 additions & 22 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ otoroshi/javascript/stats.json
3131
.scala-build
3232
*.iml
3333
CLAUDE.md
34-
_doc-research
34+
_doc-research
35+
gateway-api-conformance-suite
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
apiVersion: apiextensions.k8s.io/v1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: plugins.proxy.otoroshi.io
5+
spec:
6+
group: proxy.otoroshi.io
7+
names:
8+
kind: Plugin
9+
plural: plugins
10+
singular: plugin
11+
scope: Namespaced
12+
versions:
13+
- name: v1alpha1
14+
served: false
15+
storage: false
16+
deprecated: true
17+
schema:
18+
openAPIV3Schema:
19+
x-kubernetes-preserve-unknown-fields: true
20+
type: object
21+
- name: v1
22+
served: true
23+
storage: true
24+
deprecated: false
25+
schema:
26+
openAPIV3Schema:
27+
x-kubernetes-preserve-unknown-fields: true
28+
type: object

kubernetes/helm/otoroshi/crds/crds.yaml

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,4 +707,32 @@ spec:
707707
openAPIV3Schema:
708708
x-kubernetes-preserve-unknown-fields: true
709709
type: "object"
710-
710+
---
711+
apiVersion: "apiextensions.k8s.io/v1"
712+
kind: "CustomResourceDefinition"
713+
metadata:
714+
name: "plugins.proxy.otoroshi.io"
715+
spec:
716+
group: "proxy.otoroshi.io"
717+
names:
718+
kind: "Plugin"
719+
plural: "plugins"
720+
singular: "plugin"
721+
scope: "Namespaced"
722+
versions:
723+
- name: "v1alpha1"
724+
served: false
725+
storage: false
726+
deprecated: true
727+
schema:
728+
openAPIV3Schema:
729+
x-kubernetes-preserve-unknown-fields: true
730+
type: "object"
731+
- name: "v1"
732+
served: true
733+
storage: true
734+
deprecated: false
735+
schema:
736+
openAPIV3Schema:
737+
x-kubernetes-preserve-unknown-fields: true
738+
type: "object"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRole
3+
metadata:
4+
name: otoroshi-admin-user
5+
rules:
6+
# Core resources (existing Otoroshi needs)
7+
- apiGroups: [""]
8+
resources: [services, endpoints, secrets, configmaps, namespaces, pods]
9+
verbs: [get, list, watch]
10+
- apiGroups: ["apps"]
11+
resources: [deployments]
12+
verbs: [get, list, watch]
13+
# EndpointSlices for pod-level target resolution
14+
- apiGroups: [discovery.k8s.io]
15+
resources: [endpointslices]
16+
verbs: [get, list, watch]
17+
- apiGroups: [""]
18+
resources: [secrets, configmaps]
19+
verbs: [update, create, delete]
20+
# Ingress
21+
- apiGroups: [extensions, networking.k8s.io]
22+
resources: [ingresses, ingressclasses]
23+
verbs: [get, list, watch]
24+
- apiGroups: [extensions, networking.k8s.io]
25+
resources: [ingresses/status]
26+
verbs: [update]
27+
# Otoroshi CRDs
28+
- apiGroups: [proxy.otoroshi.io]
29+
resources: ["*"]
30+
verbs: [get, list, watch]
31+
# Gateway API — read resources
32+
- apiGroups: [gateway.networking.k8s.io]
33+
resources: [gatewayclasses, gateways, httproutes, grpcroutes, referencegrants, backendtlspolicies]
34+
verbs: [get, list, watch]
35+
# Gateway API — update status subresources
36+
- apiGroups: [gateway.networking.k8s.io]
37+
resources: [gatewayclasses/status, gateways/status, httproutes/status, grpcroutes/status]
38+
verbs: [get, update, patch]

kubernetes/helm/otoroshi/templates/rbac.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ rules:
5656
- get
5757
- list
5858
- watch
59+
- apiGroups:
60+
- discovery.k8s.io
61+
resources:
62+
- endpointslices
63+
verbs:
64+
- get
65+
- list
66+
- watch
5967
- apiGroups:
6068
- ""
6169
resources:
@@ -68,6 +76,7 @@ rules:
6876
- delete
6977
- apiGroups:
7078
- extensions
79+
- networking.k8s.io
7180
resources:
7281
- ingresses
7382
- ingressclasses
@@ -77,6 +86,7 @@ rules:
7786
- watch
7887
- apiGroups:
7988
- extensions
89+
- networking.k8s.io
8090
resources:
8191
- ingresses/status
8292
verbs:
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
apiVersion: apiextensions.k8s.io/v1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: plugins.proxy.otoroshi.io
5+
spec:
6+
group: proxy.otoroshi.io
7+
names:
8+
kind: Plugin
9+
plural: plugins
10+
singular: plugin
11+
scope: Namespaced
12+
versions:
13+
- name: v1
14+
served: true
15+
storage: true
16+
deprecated: false
17+
schema:
18+
openAPIV3Schema:
19+
x-kubernetes-preserve-unknown-fields: true
20+
type: object

kubernetes/kustomize/base/crds.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,35 @@ spec:
699699
singular: "simple-admin-user"
700700
scope: "Namespaced"
701701
versions:
702+
- name: "v1"
703+
served: true
704+
storage: true
705+
deprecated: false
706+
schema:
707+
openAPIV3Schema:
708+
x-kubernetes-preserve-unknown-fields: true
709+
type: "object"
710+
---
711+
apiVersion: "apiextensions.k8s.io/v1"
712+
kind: "CustomResourceDefinition"
713+
metadata:
714+
name: "plugins.proxy.otoroshi.io"
715+
spec:
716+
group: "proxy.otoroshi.io"
717+
names:
718+
kind: "Plugin"
719+
plural: "plugins"
720+
singular: "plugin"
721+
scope: "Namespaced"
722+
versions:
723+
- name: "v1alpha1"
724+
served: false
725+
storage: false
726+
deprecated: true
727+
schema:
728+
openAPIV3Schema:
729+
x-kubernetes-preserve-unknown-fields: true
730+
type: "object"
702731
- name: "v1"
703732
served: true
704733
storage: true
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: ClusterRole
3+
metadata:
4+
name: otoroshi-admin-user
5+
rules:
6+
# Core resources (existing Otoroshi needs)
7+
- apiGroups: [""]
8+
resources: [services, endpoints, secrets, configmaps, namespaces, pods]
9+
verbs: [get, list, watch]
10+
- apiGroups: ["apps"]
11+
resources: [deployments]
12+
verbs: [get, list, watch]
13+
# EndpointSlices for pod-level target resolution
14+
- apiGroups: [discovery.k8s.io]
15+
resources: [endpointslices]
16+
verbs: [get, list, watch]
17+
- apiGroups: [""]
18+
resources: [secrets, configmaps]
19+
verbs: [update, create, delete]
20+
# Ingress
21+
- apiGroups: [extensions, networking.k8s.io]
22+
resources: [ingresses, ingressclasses]
23+
verbs: [get, list, watch]
24+
- apiGroups: [extensions, networking.k8s.io]
25+
resources: [ingresses/status]
26+
verbs: [update]
27+
# Otoroshi CRDs
28+
- apiGroups: [proxy.otoroshi.io]
29+
resources: ["*"]
30+
verbs: [get, list, watch]
31+
# Gateway API — read resources
32+
- apiGroups: [gateway.networking.k8s.io]
33+
resources: [gatewayclasses, gateways, httproutes, grpcroutes, referencegrants, backendtlspolicies]
34+
verbs: [get, list, watch]
35+
# Gateway API — update status subresources
36+
- apiGroups: [gateway.networking.k8s.io]
37+
resources: [gatewayclasses/status, gateways/status, httproutes/status, grpcroutes/status]
38+
verbs: [get, update, patch]

kubernetes/kustomize/base/rbac.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ rules:
4444
- get
4545
- list
4646
- watch
47+
- apiGroups:
48+
- discovery.k8s.io
49+
resources:
50+
- endpointslices
51+
verbs:
52+
- get
53+
- list
54+
- watch
4755
- apiGroups:
4856
- ""
4957
resources:

manual/src/main/paradox/deploy/kubernetes.md

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1353,8 +1353,103 @@ kind: ApiKey
13531353
metadata:
13541354
name: http-app-2-apikey-3
13551355
spec:
1356-
exportSecret: true
1356+
exportSecret: true
13571357
secretName: secret-3
13581358
daikokuToken: RShQrvINByiuieiaCBwIZfGFgdPu7tIJEN5gdV8N8YeH4RI9ErPYJzkuFyAkZ2xy
13591359
```
13601360

1361+
## Kubernetes Gateway API
1362+
1363+
Starting from version 17.13.0, Otoroshi supports the [Kubernetes Gateway API](https://gateway-api.sigs.k8s.io/) specification (v1.4). This is the standard Kubernetes API for managing ingress traffic, designed as the successor to the Ingress resource.
1364+
1365+
With Gateway API support enabled, you can define `GatewayClass`, `Gateway`, `HTTPRoute`, and `GRPCRoute` resources in your cluster and Otoroshi will automatically convert them into native `NgRoute` entities. This allows you to use standard, portable Kubernetes manifests while benefiting from Otoroshi's full feature set. GRPCRoute backends are automatically called using HTTP/2.
1366+
1367+
### Quick setup
1368+
1369+
First, install the Gateway API CRDs on your cluster:
1370+
1371+
```sh
1372+
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml
1373+
```
1374+
1375+
Make sure the Otoroshi ServiceAccount has RBAC permissions for Gateway API resources (`gatewayclasses`, `gateways`, `httproutes`, `grpcroutes`, `referencegrants`, `backendtlspolicies` and their status subresources).
1376+
1377+
Then enable the Gateway API controller job in your Otoroshi deployment configuration:
1378+
1379+
```json
1380+
{
1381+
"config": {
1382+
"scripts": {
1383+
"enabled": true,
1384+
"jobRefs": [
1385+
"cp:otoroshi.plugins.jobs.kubernetes.KubernetesGatewayApiControllerJob"
1386+
],
1387+
"jobConfig": {
1388+
"KubernetesConfig": {
1389+
"namespaces": ["*"],
1390+
"gatewayApi": true,
1391+
"gatewayApiControllerName": "otoroshi.io/gateway-controller",
1392+
"gatewayApiHttpListenerPort": 8080,
1393+
"gatewayApiHttpsListenerPort": 8443,
1394+
"gatewayApiSyncIntervalSeconds": 30
1395+
}
1396+
}
1397+
}
1398+
}
1399+
}
1400+
```
1401+
1402+
Once configured, you can create Gateway API resources:
1403+
1404+
```yaml
1405+
apiVersion: gateway.networking.k8s.io/v1
1406+
kind: GatewayClass
1407+
metadata:
1408+
name: otoroshi
1409+
spec:
1410+
controllerName: otoroshi.io/gateway-controller
1411+
---
1412+
apiVersion: gateway.networking.k8s.io/v1
1413+
kind: Gateway
1414+
metadata:
1415+
name: my-gateway
1416+
namespace: default
1417+
spec:
1418+
gatewayClassName: otoroshi
1419+
listeners:
1420+
- name: http
1421+
protocol: HTTP
1422+
port: 8080
1423+
hostname: "*.my.domain"
1424+
allowedRoutes:
1425+
namespaces:
1426+
from: Same
1427+
---
1428+
apiVersion: gateway.networking.k8s.io/v1
1429+
kind: HTTPRoute
1430+
metadata:
1431+
name: my-route
1432+
namespace: default
1433+
spec:
1434+
parentRefs:
1435+
- name: my-gateway
1436+
sectionName: http
1437+
hostnames:
1438+
- "api.my.domain"
1439+
rules:
1440+
- matches:
1441+
- path:
1442+
type: PathPrefix
1443+
value: /
1444+
backendRefs:
1445+
- name: my-service
1446+
port: 80
1447+
```
1448+
1449+
Otoroshi will automatically create an `NgRoute` that forwards traffic for `api.my.domain` to `my-service:80`.
1450+
1451+
@@@ note
1452+
The Gateway API controller can run alongside the existing CRDs controller. Both share the same `KubernetesConfig` configuration block.
1453+
@@@
1454+
1455+
For the full documentation — including supported filters, configuration reference, current limitations, and troubleshooting — see @ref:[Kubernetes Gateway API support](../topics/kubernetes-gateway-api.md).

0 commit comments

Comments
 (0)