Skip to content

Commit 1c9a2f9

Browse files
authored
feat(gateway): add gateway api httpRoute support (#2016)
1 parent cdfcc48 commit 1c9a2f9

File tree

5 files changed

+273
-1
lines changed

5 files changed

+273
-1
lines changed

README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ As Relay is now part of this chart, you need to make sure you enable either Ngin
290290

291291
If you are using an ingress gateway (like Istio), you have to change your inbound path from `sentry-web` to `nginx`.
292292

293-
## NGINX and/or Ingress
293+
## Traffic Routing
294294

295295
By default, NGINX is enabled to allow sending the incoming requests to [Sentry Relay](https://getsentry.github.io/relay/) or the Django backend depending on the path. When Sentry is meant to be exposed outside of the Kubernetes cluster, it is recommended to disable NGINX and let the Ingress do the same. It's recommended to go with the go-to Ingress Controller, [NGINX Ingress](https://kubernetes.github.io/ingress-nginx/), but others should work as well.
296296

@@ -311,6 +311,41 @@ nginx:
311311
tls: true
312312
```
313313

314+
### Gateway API
315+
316+
This chart supports [Kubernetes Gateway API](https://gateway-api.sigs.k8s.io/) HTTPRoute as an alternative to traditional Ingress.
317+
318+
```yaml
319+
nginx:
320+
enabled: false
321+
route:
322+
main:
323+
enabled: true
324+
hostnames:
325+
- sentry.example.com
326+
parentRefs:
327+
- name: my-gateway
328+
namespace: default
329+
```
330+
331+
With HTTP to HTTPS redirect:
332+
333+
```yaml
334+
route:
335+
main:
336+
enabled: true
337+
hostnames:
338+
- sentry.example.com
339+
parentRefs:
340+
- name: my-gateway
341+
sectionName: https
342+
httpRedirect:
343+
enabled: true
344+
parentRefs:
345+
- name: my-gateway
346+
sectionName: http
347+
```
348+
314349
## ClickHouse warning
315350

316351
Snuba only supports a UTC timezone for ClickHouse. Please keep the initial value!

charts/sentry/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,24 @@ Note: this table is incomplete, so have a look at the values.yaml in case you mi
465465
| relay.topologySpreadConstraints | list | `[]` | |
466466
| relay.volumeMounts | list | `[]` | |
467467
| relay.volumes | list | `[]` | |
468+
| route.httpRedirect.annotations | object | `{}` | Annotations for the HTTP redirect HTTPRoute |
469+
| route.httpRedirect.apiVersion | string | `"gateway.networking.k8s.io/v1"` | API version for HTTPRoute (auto-detected if not set) |
470+
| route.httpRedirect.enabled | bool | `false` | Enable HTTP to HTTPS redirect HTTPRoute |
471+
| route.httpRedirect.hostnames | list | `[]` | Hostnames (inherits from main route if empty) |
472+
| route.httpRedirect.kind | string | `"HTTPRoute"` | Route kind |
473+
| route.httpRedirect.labels | object | `{}` | Labels for the HTTP redirect HTTPRoute |
474+
| route.httpRedirect.parentRefs | list | `[]` | Parent Gateway references for HTTP listener |
475+
| route.httpRedirect.statusCode | int | `301` | HTTP redirect status code (301=permanent, 302=temporary) |
476+
| route.main.additionalRules | list | `[]` | Additional custom rules to prepend |
477+
| route.main.annotations | object | `{}` | Annotations for the HTTPRoute |
478+
| route.main.apiVersion | string | `"gateway.networking.k8s.io/v1"` | API version for HTTPRoute (auto-detected if not set) |
479+
| route.main.enabled | bool | `false` | Enable Gateway API HTTPRoute |
480+
| route.main.filters | list | `[]` | Filters applied to all backend requests |
481+
| route.main.hostnames | list | `[]` | Hostnames for the HTTPRoute |
482+
| route.main.kind | string | `"HTTPRoute"` | Route kind (HTTPRoute, GRPCRoute, etc.) |
483+
| route.main.labels | object | `{}` | Labels for the HTTPRoute |
484+
| route.main.parentRefs | list | `[]` | Parent Gateway references (required when enabled) |
485+
| route.main.path | string | `"/"` | Base path prefix for subpath deployments |
468486
| revisionHistoryLimit | int | `10` | |
469487
| sentry.billingMetricsConsumer.affinity | object | `{}` | |
470488
| sentry.billingMetricsConsumer.autoscaling.enabled | bool | `false` | |

charts/sentry/templates/_helper.tpl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,3 +1180,16 @@ app.kubernetes.io/name: {{ include "sentry.name" .ctx }}
11801180
app.kubernetes.io/instance: {{ .ctx.Release.Name }}
11811181
app.kubernetes.io/component: {{ .component }}
11821182
{{- end }}
1183+
1184+
{{/*
1185+
Return the appropriate apiVersion for Gateway API HTTPRoute.
1186+
Returns empty string if Gateway API is not available in the cluster.
1187+
Gateway API v1 is GA since Kubernetes 1.29.
1188+
*/}}
1189+
{{- define "sentry.route.apiVersion" -}}
1190+
{{- if .Capabilities.APIVersions.Has "gateway.networking.k8s.io/v1" -}}
1191+
{{- print "gateway.networking.k8s.io/v1" -}}
1192+
{{- else if .Capabilities.APIVersions.Has "gateway.networking.k8s.io/v1beta1" -}}
1193+
{{- print "gateway.networking.k8s.io/v1beta1" -}}
1194+
{{- end -}}
1195+
{{- end -}}

charts/sentry/templates/route.yaml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
{{- $mainRoute := .Values.route.main -}}
2+
{{- $redirectRoute := .Values.route.httpRedirect -}}
3+
{{- $defaultApiVersion := include "sentry.route.apiVersion" . -}}
4+
{{- if and $mainRoute.enabled $defaultApiVersion }}
5+
{{- $fullName := include "sentry.fullname" . -}}
6+
{{- $relayPort := (include "relay.port" .) | int -}}
7+
{{- $webPort := .Values.service.externalPort | int -}}
8+
{{- $nginxEnabled := .Values.nginx.enabled -}}
9+
{{- $nginxPort := .Values.nginx.service.ports.http | int -}}
10+
{{- $hostnames := $mainRoute.hostnames -}}
11+
{{- $basePath := $mainRoute.path | default "/" | trimSuffix "/" -}}
12+
{{- if $redirectRoute.enabled }}
13+
{{- $redirectHostnames := $redirectRoute.hostnames | default $hostnames -}}
14+
---
15+
apiVersion: {{ $redirectRoute.apiVersion | default $defaultApiVersion }}
16+
kind: {{ $redirectRoute.kind | default "HTTPRoute" }}
17+
metadata:
18+
name: {{ $fullName }}-http-redirect
19+
namespace: {{ .Release.Namespace }}
20+
labels:
21+
app: {{ $fullName }}
22+
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
23+
release: "{{ .Release.Name }}"
24+
heritage: "{{ .Release.Service }}"
25+
{{- include "sentry.labels" . | nindent 4 }}
26+
{{- with $redirectRoute.labels }}
27+
{{- toYaml . | nindent 4 }}
28+
{{- end }}
29+
{{- with $redirectRoute.annotations }}
30+
annotations:
31+
{{- toYaml . | nindent 4 }}
32+
{{- end }}
33+
spec:
34+
{{- with $redirectRoute.parentRefs }}
35+
parentRefs:
36+
{{- toYaml . | nindent 4 }}
37+
{{- end }}
38+
{{- with $redirectHostnames }}
39+
hostnames:
40+
{{- tpl (toYaml .) $ | nindent 4 }}
41+
{{- end }}
42+
rules:
43+
- matches:
44+
- path:
45+
type: PathPrefix
46+
value: {{ $basePath | default "/" }}
47+
filters:
48+
- type: RequestRedirect
49+
requestRedirect:
50+
scheme: https
51+
statusCode: {{ $redirectRoute.statusCode | default 301 }}
52+
{{- end }}
53+
---
54+
apiVersion: {{ $mainRoute.apiVersion | default $defaultApiVersion }}
55+
kind: {{ $mainRoute.kind | default "HTTPRoute" }}
56+
metadata:
57+
name: {{ $fullName }}
58+
namespace: {{ .Release.Namespace }}
59+
labels:
60+
app: {{ $fullName }}
61+
chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"
62+
release: "{{ .Release.Name }}"
63+
heritage: "{{ .Release.Service }}"
64+
{{- include "sentry.labels" . | nindent 4 }}
65+
{{- with $mainRoute.labels }}
66+
{{- toYaml . | nindent 4 }}
67+
{{- end }}
68+
{{- with $mainRoute.annotations }}
69+
annotations:
70+
{{- toYaml . | nindent 4 }}
71+
{{- end }}
72+
spec:
73+
{{- with $mainRoute.parentRefs }}
74+
parentRefs:
75+
{{- toYaml . | nindent 4 }}
76+
{{- end }}
77+
{{- with $hostnames }}
78+
hostnames:
79+
{{- tpl (toYaml .) $ | nindent 4 }}
80+
{{- end }}
81+
rules:
82+
{{- if $mainRoute.additionalRules }}
83+
{{- tpl (toYaml $mainRoute.additionalRules) $ | nindent 4 }}
84+
{{- end }}
85+
{{- if $nginxEnabled }}
86+
- matches:
87+
- path:
88+
type: PathPrefix
89+
value: {{ $basePath | default "/" }}
90+
{{- with $mainRoute.filters }}
91+
filters:
92+
{{- toYaml . | nindent 8 }}
93+
{{- end }}
94+
backendRefs:
95+
- name: {{ $fullName }}-nginx
96+
port: {{ $nginxPort }}
97+
{{- else }}
98+
- matches:
99+
- path:
100+
type: PathPrefix
101+
value: {{ $basePath }}/api/0
102+
{{- with $mainRoute.filters }}
103+
filters:
104+
{{- toYaml . | nindent 8 }}
105+
{{- end }}
106+
backendRefs:
107+
- name: {{ $fullName }}-web
108+
port: {{ $webPort }}
109+
- matches:
110+
- path:
111+
type: PathPrefix
112+
value: {{ $basePath }}/api
113+
{{- with $mainRoute.filters }}
114+
filters:
115+
{{- toYaml . | nindent 8 }}
116+
{{- end }}
117+
backendRefs:
118+
- name: {{ $fullName }}-relay
119+
port: {{ $relayPort }}
120+
- matches:
121+
- path:
122+
type: PathPrefix
123+
value: {{ $basePath | default "/" }}
124+
{{- with $mainRoute.filters }}
125+
filters:
126+
{{- toYaml . | nindent 8 }}
127+
{{- end }}
128+
backendRefs:
129+
- name: {{ $fullName }}-web
130+
port: {{ $webPort }}
131+
{{- end }}
132+
{{- end }}

charts/sentry/values.yaml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,6 +2348,80 @@ traefikIngressRoute:
23482348
priority: 100
23492349

23502350

2351+
# Kubernetes Gateway API HTTPRoute configuration
2352+
# Configure gateway routes for the chart here. More routes can be added by adding
2353+
# a dictionary key like the 'main' route.
2354+
# Reference: https://gateway-api.sigs.k8s.io/
2355+
route:
2356+
main:
2357+
# -- Enables or disables the route
2358+
enabled: false
2359+
2360+
# -- Set the route apiVersion
2361+
apiVersion: gateway.networking.k8s.io/v1
2362+
2363+
# -- Set the route kind
2364+
# Valid options are GRPCRoute, HTTPRoute, TCPRoute, TLSRoute, UDPRoute
2365+
kind: HTTPRoute
2366+
2367+
# -- Route annotations
2368+
annotations: {}
2369+
2370+
# -- Route labels
2371+
labels: {}
2372+
2373+
# -- Hostnames for the HTTPRoute
2374+
# Example: ["sentry.example.com", "sentry.internal.example.com"]
2375+
hostnames: []
2376+
2377+
# -- Parent Gateway references
2378+
# At least one parentRef is required when enabled
2379+
parentRefs: []
2380+
# - name: my-gateway
2381+
# namespace: default
2382+
# sectionName: https
2383+
2384+
# -- Base path prefix for all routes (for subpath deployments)
2385+
# Use this if Sentry is deployed at a subpath, e.g., "/sentry"
2386+
path: /
2387+
2388+
# -- Additional custom rules to prepend
2389+
additionalRules: []
2390+
2391+
# -- Filters applied to requests
2392+
filters: []
2393+
2394+
# -- HTTP to HTTPS redirect route
2395+
# Creates a separate HTTPRoute that redirects HTTP traffic to HTTPS
2396+
httpRedirect:
2397+
# -- Enables or disables the redirect route
2398+
enabled: false
2399+
2400+
# -- Set the route apiVersion
2401+
apiVersion: gateway.networking.k8s.io/v1
2402+
2403+
# -- Set the route kind
2404+
kind: HTTPRoute
2405+
2406+
# -- Route annotations
2407+
annotations: {}
2408+
2409+
# -- Route labels
2410+
labels: {}
2411+
2412+
# -- Hostnames (if empty, inherits from main route)
2413+
hostnames: []
2414+
2415+
# -- Parent reference for the HTTP listener
2416+
parentRefs: []
2417+
# - name: my-gateway
2418+
# namespace: default
2419+
# sectionName: http
2420+
2421+
# -- HTTP status code for redirect (301 = permanent, 302 = temporary)
2422+
statusCode: 301
2423+
2424+
23512425
filestore:
23522426
# Set to one of filesystem, gcs or s3 as supported by Sentry.
23532427
backend: filesystem

0 commit comments

Comments
 (0)