mirror of
https://github.com/rustfs/rustfs.git
synced 2026-10-02 05:14:35 +08:00
fix(helm): route Gateway API traffic to the chart service (#8145)
Co-authored-by: Hauser <housemecn@gmail.com>
This commit is contained in:
+17
-2
@@ -277,7 +277,8 @@ uer. `ClusterIssuer` or `Issuer`. |
|
||||
| gatewayApi.listeners.tls.name | string | `tls` | Gateway API TLS passthrough listener name. |
|
||||
| gatewayApi.listeners.tls.port | int | `443` | Gateway API TLS passthrough listener port. |
|
||||
| gatewayApi.listeners.tls.backendPort | int | `null` | Backend service port that terminates TLS; defaults to the console port. |
|
||||
| gatewayApi.hostname | string | Hostname to access RustFS via gateway api. |
|
||||
| gatewayApi.hostname | string | `example.rustfs.com` | Console hostname for Gateway API. |
|
||||
| gatewayApi.endpointHostname | string | `""` | Optional separate S3 endpoint hostname; empty disables the S3 HTTPRoute. |
|
||||
| gatewayApi.secretName | string | Secret tls to via RustFS using HTTPS. |
|
||||
| gatewayApi.existingGateway.name | string | `""` | The existing gateway name, instead of creating a new one. |
|
||||
| gatewayApi.existingGateway.namespace | string | `""` | The namespace of the existing gateway, if not the local namespace. |
|
||||
@@ -449,7 +450,21 @@ NAME HOSTNAMES AGE
|
||||
rustfs-route ["example.rustfs.com"] 172m
|
||||
```
|
||||
|
||||
Then, via RustFS instance via `https://example.rustfs.com` or `http://example.rustfs.com`.
|
||||
Access the console at `https://example.rustfs.com`; HTTP redirects to HTTPS by default. HTTPRoutes reference the chart's Kubernetes Service directly and do not require the TraefikService CRD or Traefik's Kubernetes CRD provider. The former TraefikService cookie stickiness is no longer configured by this chart.
|
||||
|
||||
To expose the S3 endpoint alongside the console, set a different `gatewayApi.endpointHostname`:
|
||||
|
||||
```yaml
|
||||
gatewayApi:
|
||||
enabled: true
|
||||
hostname: console.example.com
|
||||
endpointHostname: s3.example.com
|
||||
existingGateway:
|
||||
name: shared-gateway
|
||||
namespace: gateway-system
|
||||
```
|
||||
|
||||
The console route uses `service.console.port` (9001 by default), and the optional S3 route uses `service.endpoint.port` (9000 by default). Both attach to the configured HTTPS listener and preserve request paths. Configure DNS and the Gateway's TLS certificate for both hostnames. When using a Gateway in another namespace, its listener must allow routes from the RustFS namespace. Leaving `endpointHostname` empty preserves the console-only behavior.
|
||||
|
||||
For end-to-end encryption, set `gatewayApi.listeners.tls.enabled` to `true`. The chart then adds a `TLS` listener with `tls.mode: Passthrough` to the `Gateway` and generates a `TLSRoute` that forwards the encrypted stream to the RustFS service, where TLS is terminated on the backend side. Note that backend TLS termination must be configured on RustFS itself (for example `RUSTFS_TLS_PATH` pointing to server certificates), and the installed Gateway API CRDs must include `TLSRoute`.
|
||||
|
||||
|
||||
@@ -1,42 +1,47 @@
|
||||
{{- if .Values.gatewayApi.enabled }}
|
||||
{{- $routes := list (dict "name" "route" "hostname" .Values.gatewayApi.hostname "port" .Values.service.console.port) }}
|
||||
{{- with .Values.gatewayApi.endpointHostname }}
|
||||
{{- if eq . $.Values.gatewayApi.hostname }}
|
||||
{{- fail "gatewayApi.endpointHostname must differ from gatewayApi.hostname" }}
|
||||
{{- end }}
|
||||
{{- $routes = append $routes (dict "name" "endpoint-route" "hostname" . "port" $.Values.service.endpoint.port) }}
|
||||
{{- end }}
|
||||
{{- range $routes }}
|
||||
{{- if eq .name "endpoint-route" }}
|
||||
---
|
||||
{{- end }}
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: {{ include "rustfs.fullname" . }}-route
|
||||
namespace: {{ .Release.Namespace }}
|
||||
name: {{ include "rustfs.fullname" $ }}-{{ .name }}
|
||||
namespace: {{ $.Release.Namespace }}
|
||||
annotations:
|
||||
{{- if eq .Values.gatewayApi.gatewayClass "contour" }}
|
||||
{{- if and (eq $.Values.gatewayApi.gatewayClass "contour") (eq .name "route") }}
|
||||
projectcontour.io/upstream-hash-policy: "cookie"
|
||||
{{- end }}
|
||||
spec:
|
||||
parentRefs:
|
||||
{{- if .Values.gatewayApi.existingGateway.name }}
|
||||
- name: {{ .Values.gatewayApi.existingGateway.name }}
|
||||
{{- if .Values.gatewayApi.existingGateway.namespace }}
|
||||
namespace: {{ .Values.gatewayApi.existingGateway.namespace }}
|
||||
{{- if $.Values.gatewayApi.existingGateway.name }}
|
||||
- name: {{ $.Values.gatewayApi.existingGateway.name }}
|
||||
{{- if $.Values.gatewayApi.existingGateway.namespace }}
|
||||
namespace: {{ $.Values.gatewayApi.existingGateway.namespace }}
|
||||
{{- end }}
|
||||
sectionName: {{ .Values.gatewayApi.listeners.https.name | default "websecure"}}
|
||||
sectionName: {{ $.Values.gatewayApi.listeners.https.name | default "websecure"}}
|
||||
{{- else }}
|
||||
- name: {{ include "rustfs.fullname" $ }}-gateway
|
||||
sectionName: {{ .Values.gatewayApi.listeners.https.name | default "websecure"}}
|
||||
sectionName: {{ $.Values.gatewayApi.listeners.https.name | default "websecure"}}
|
||||
{{- end }}
|
||||
hostnames:
|
||||
- {{ .Values.gatewayApi.hostname }}
|
||||
- {{ .hostname | quote }}
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
{{- if eq .Values.gatewayApi.gatewayClass "traefik" }}
|
||||
- name: {{ include "rustfs.fullname" . }}-sticky-svc
|
||||
port: {{ .Values.service.console.port }}
|
||||
kind: TraefikService
|
||||
group: traefik.io
|
||||
{{- else }}
|
||||
- name: {{ include "rustfs.fullname" $ }}-svc
|
||||
port: {{ .Values.service.console.port }}
|
||||
{{- end }}
|
||||
port: {{ .port }}
|
||||
{{- end }}
|
||||
{{- if .Values.gatewayApi.httpToHttpsRedirect }}
|
||||
---
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
{{- if and .Values.gatewayApi.enabled (eq .Values.gatewayApi.gatewayClass "traefik") }}
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: TraefikService
|
||||
metadata:
|
||||
name: {{ include "rustfs.fullname" . }}-sticky-svc
|
||||
namespace: {{ .Release.Namespace }}
|
||||
spec:
|
||||
weighted:
|
||||
services:
|
||||
- name: {{ include "rustfs.fullname" . }}-svc
|
||||
namespace: {{ .Release.Namespace }}
|
||||
port: {{ .Values.service.console.port }}
|
||||
weight: 1
|
||||
sticky:
|
||||
cookie:
|
||||
name: rustfs
|
||||
httpOnly: true
|
||||
secure: {{ .Values.ingress.tls.enabled | default false }}
|
||||
sameSite: {{ if .Values.ingress.tls.enabled }}none{{ else }}lax{{ end }}
|
||||
{{- end }}
|
||||
@@ -381,7 +381,8 @@ gatewayApi:
|
||||
port: 443
|
||||
# Service port that terminates TLS on the backend; defaults to the console port.
|
||||
backendPort: null
|
||||
hostname: example.rustfs.com
|
||||
hostname: example.rustfs.com # Console hostname.
|
||||
endpointHostname: "" # Optional separate hostname for the S3 endpoint.
|
||||
httpToHttpsRedirect: true
|
||||
existingGateway:
|
||||
name: ""
|
||||
|
||||
@@ -73,6 +73,84 @@ render_server_cert() {
|
||||
'
|
||||
}
|
||||
|
||||
# Gateway routes must resolve to the rendered Kubernetes Service without Traefik CRDs.
|
||||
for gateway_class in traefik contour istio; do
|
||||
for distributed in false true; do
|
||||
standalone=true
|
||||
if [[ "$distributed" == true ]]; then standalone=false; fi
|
||||
gateway_output=$(render_chart \
|
||||
--set "mode.distributed.enabled=$distributed" \
|
||||
--set "mode.standalone.enabled=$standalone" \
|
||||
--set gatewayApi.enabled=true \
|
||||
--set "gatewayApi.gatewayClass=$gateway_class" \
|
||||
--set fullnameOverride=gateway-test \
|
||||
--set service.console.port=19001 \
|
||||
--set service.endpoint.port=19000 \
|
||||
--set gatewayApi.hostname=console.example.com \
|
||||
--set gatewayApi.endpointHostname=s3.example.com \
|
||||
--set gatewayApi.existingGateway.name=shared-gateway \
|
||||
--set gatewayApi.existingGateway.namespace=gateway-system \
|
||||
--set gatewayApi.listeners.https.name=https)
|
||||
yq eval -e 'select(.kind == "Service" and .metadata.name == "gateway-test-svc") |
|
||||
.metadata.namespace == "rustfs" and
|
||||
.spec.ports[0].port == 19000 and .spec.ports[1].port == 19001' - <<<"$gateway_output" >/dev/null
|
||||
for route in route endpoint-route; do
|
||||
expected_port=19001
|
||||
expected_host=console.example.com
|
||||
if [[ "$route" == endpoint-route ]]; then
|
||||
expected_port=19000
|
||||
expected_host=s3.example.com
|
||||
fi
|
||||
ROUTE_NAME="gateway-test-$route" EXPECTED_PORT="$expected_port" EXPECTED_HOST="$expected_host" \
|
||||
yq eval -e 'select(.kind == "HTTPRoute" and .metadata.name == strenv(ROUTE_NAME)) |
|
||||
.metadata.namespace == "rustfs" and
|
||||
.spec.hostnames[0] == strenv(EXPECTED_HOST) and
|
||||
.spec.parentRefs[0].name == "shared-gateway" and
|
||||
.spec.parentRefs[0].namespace == "gateway-system" and
|
||||
.spec.parentRefs[0].sectionName == "https" and
|
||||
.spec.rules[0].matches[0].path.type == "PathPrefix" and
|
||||
.spec.rules[0].matches[0].path.value == "/" and
|
||||
(.spec.rules[0].backendRefs | length) == 1 and
|
||||
.spec.rules[0].backendRefs[0].name == "gateway-test-svc" and
|
||||
.spec.rules[0].backendRefs[0].port == env(EXPECTED_PORT) and
|
||||
(.spec.rules[0].backendRefs[0].kind // "Service") == "Service" and
|
||||
(.spec.rules[0].backendRefs[0].group // "") == ""' - <<<"$gateway_output" >/dev/null
|
||||
done
|
||||
if grep -q 'kind: TraefikService' <<<"$gateway_output"; then
|
||||
echo "Gateway API must not require a TraefikService CRD" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
gateway_default=$(render_chart --set gatewayApi.enabled=true)
|
||||
yq eval -e 'select(.kind == "HTTPRoute" and .metadata.name == "rustfs-route") |
|
||||
.spec.rules[0].backendRefs[0].name == "rustfs-svc" and
|
||||
.spec.rules[0].backendRefs[0].port == 9001 and
|
||||
.spec.parentRefs[0].name == "rustfs-gateway" and
|
||||
.spec.parentRefs[0].sectionName == "websecure"' - <<<"$gateway_default" >/dev/null
|
||||
if grep -q 'name: rustfs-endpoint-route' <<<"$gateway_default"; then
|
||||
echo "The S3 route must be opt-in" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gateway_no_redirect=$(render_chart --set gatewayApi.enabled=true --set gatewayApi.endpointHostname=s3.example.com --set gatewayApi.httpToHttpsRedirect=false)
|
||||
if grep -q 'type: RequestRedirect' <<<"$gateway_no_redirect"; then
|
||||
echo "Disabling HTTPS redirects must suppress the redirect route" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if render_chart --set gatewayApi.enabled=true --set gatewayApi.endpointHostname=example.rustfs.com >/dev/null 2>&1; then
|
||||
echo "Console and S3 routes must not share a hostname" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gateway_disabled=$(render_chart --set gatewayApi.endpointHostname=s3.example.com)
|
||||
if grep -q 'kind: HTTPRoute' <<<"$gateway_disabled"; then
|
||||
echo "Disabling Gateway API must suppress all HTTP routes" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
recreate_output=$(render_standalone_deployment --set mode.standalone.strategy.type=Recreate)
|
||||
grep -q "type: Recreate" <<<"$recreate_output"
|
||||
if grep -q "rollingUpdate:" <<<"$recreate_output"; then
|
||||
|
||||
Reference in New Issue
Block a user