From 62d30421b8b907d7fedaef971a9da32186809901 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Fri, 7 Nov 2025 01:32:37 +0300 Subject: [PATCH 1/7] feat(helm): add HTTPRoute support for Gateway API v1 Add full HTTPRoute support for both gateway and component-level routing. Features: - Gateway HTTPRoute for simple routing through loki-gateway - Main HTTPRoute for component-level routing (distributor, query-frontend, ruler, compactor) - Support for all deployment modes (SingleBinary, SimpleScalable, Distributed) - HTTPRoute filters (header manipulation, redirects, URL rewrites) - Multiple parentRefs support for multi-gateway configurations - CI and integration tests Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- docs/sources/setup/install/helm/reference.md | 113 ++++++++++ production/helm/loki/CHANGELOG.md | 2 + production/helm/loki/Chart.yaml | 2 +- production/helm/loki/README.md | 2 +- production/helm/loki/ci/httproute-values.yaml | 35 +++ production/helm/loki/templates/_helpers.tpl | 106 +++++++++ .../templates/gateway/httproute-gateway.yaml | 203 ++++++++++++++++++ production/helm/loki/templates/httproute.yaml | 46 ++++ .../httproute/httproute-values.yaml | 35 +++ .../test/integration/httproute/test-plan.yaml | 24 +++ production/helm/loki/values.yaml | 42 ++++ 11 files changed, 608 insertions(+), 2 deletions(-) create mode 100644 production/helm/loki/ci/httproute-values.yaml create mode 100644 production/helm/loki/templates/gateway/httproute-gateway.yaml create mode 100644 production/helm/loki/templates/httproute.yaml create mode 100644 production/helm/loki/test/integration/httproute/httproute-values.yaml create mode 100644 production/helm/loki/test/integration/httproute/test-plan.yaml diff --git a/docs/sources/setup/install/helm/reference.md b/docs/sources/setup/install/helm/reference.md index bf24f6f5ab058..c61813718d167 100644 --- a/docs/sources/setup/install/helm/reference.md +++ b/docs/sources/setup/install/helm/reference.md @@ -4843,6 +4843,76 @@ true
 "nil"
 
+ + + + gateway.httproute.annotations + object + Annotations for the gateway HTTPRoute +
+{}
+
+ + + + gateway.httproute.enabled + bool + Specifies whether an HTTPRoute for the gateway should be created +
+false
+
+ + + + gateway.httproute.hostnames + list + Hostnames configuration for the gateway HTTPRoute, passed through the `tpl` function to allow templating +
+[]
+
+ + + + gateway.httproute.labels + object + Labels for the gateway HTTPRoute +
+{}
+
+ + + + gateway.httproute.parentRefs + list + The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating +
+[
+  {
+    "name": "",
+    "namespace": ""
+  }
+]
+
+ + + + gateway.httproute.rules + list + Rules configuration for the gateway HTTPRoute +
+[
+  {
+    "matches": [
+      {
+        "path": {
+          "type": "PathPrefix",
+          "value": "/"
+        }
+      }
+    ]
+  }
+]
+
@@ -5404,6 +5474,49 @@ null
 null
 
+ + + + httproute + object + HTTPRoute configuration (Gateway API). Use either this HTTPRoute or the gateway, but not both at once. If you enable this, make sure to disable the gateway. HTTPRoute uses the same path configuration as ingress above. +
+{
+  "annotations": {},
+  "enabled": false,
+  "hostnames": [],
+  "labels": {},
+  "parentRefs": [
+    {
+      "name": "",
+      "namespace": ""
+    }
+  ]
+}
+
+ + + + httproute.hostnames + list + Hostnames configuration for the HTTPRoute, passed through the `tpl` function to allow templating +
+[]
+
+ + + + httproute.parentRefs + list + The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating +
+[
+  {
+    "name": "",
+    "namespace": ""
+  }
+]
+
diff --git a/production/helm/loki/CHANGELOG.md b/production/helm/loki/CHANGELOG.md index 16066af359e23..a966198e0577d 100644 --- a/production/helm/loki/CHANGELOG.md +++ b/production/helm/loki/CHANGELOG.md @@ -13,6 +13,7 @@ Entries should include a reference to the pull request that introduced the chang ## Unreleased +- [FEATURE] Add full HTTPRoute support (Gateway API v1) for both gateway and component-level routing with filters, multiple parentRefs, and custom rules. [#XXXXX](https://github.com/grafana/loki/pull/XXXXX) ## 6.46.0 @@ -31,6 +32,7 @@ Entries should include a reference to the pull request that introduced the chang - [CHANGE] Changed one missed version of Grafana Loki to 3.5.7. ## 6.45.0 + - [CHANGE] Remove unused `storageClass` field from compactor persistence configuration. Storage class should be configured per-claim in the `claims` array instead.[#19443](https://github.com/grafana/loki/pull/19443) - [ENHANCEMENT] Update default readiness probe values to match operator [#19529](https://github.com/grafana/loki/pull/19529) - [ENHANCEMENT] Allow configuration of alert rule severalties and thresholds[#13730](https://github.com/grafana/loki/pull/13730) diff --git a/production/helm/loki/Chart.yaml b/production/helm/loki/Chart.yaml index 73cd26404937b..26ebb76c7ad35 100644 --- a/production/helm/loki/Chart.yaml +++ b/production/helm/loki/Chart.yaml @@ -3,7 +3,7 @@ name: loki description: Helm chart for Grafana Loki and Grafana Enterprise Logs supporting monolithic, simple scalable, and microservices modes. type: application appVersion: 3.5.7 -version: 6.46.0 +version: 6.47.0 home: https://grafana.github.io/helm-charts sources: - https://github.com/grafana/loki diff --git a/production/helm/loki/README.md b/production/helm/loki/README.md index 6266ae50576e0..de0950a18865d 100644 --- a/production/helm/loki/README.md +++ b/production/helm/loki/README.md @@ -1,6 +1,6 @@ # loki -![Version: 6.46.0](https://img.shields.io/badge/Version-6.46.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.5.7](https://img.shields.io/badge/AppVersion-3.5.7-informational?style=flat-square) +![Version: 6.47.0](https://img.shields.io/badge/Version-6.47.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.5.7](https://img.shields.io/badge/AppVersion-3.5.7-informational?style=flat-square) Helm chart for Grafana Loki and Grafana Enterprise Logs supporting monolithic, simple scalable, and microservices modes. diff --git a/production/helm/loki/ci/httproute-values.yaml b/production/helm/loki/ci/httproute-values.yaml new file mode 100644 index 0000000000000..22750723f26ee --- /dev/null +++ b/production/helm/loki/ci/httproute-values.yaml @@ -0,0 +1,35 @@ +--- +gateway: + httproute: + enabled: true + annotations: {} + parentRefs: + - name: loki-gateway + namespace: loki + hostnames: + - gateway.loki.example.com + rules: + - matches: + - path: + type: PathPrefix + value: / +loki: + commonConfig: + replication_factor: 1 + useTestSchema: true + storage: + bucketNames: + chunks: chunks + ruler: ruler + admin: admin +read: + replicas: 1 +write: + replicas: 1 +backend: + replicas: 1 +monitoring: + lokiCanary: + enabled: false +test: + enabled: false diff --git a/production/helm/loki/templates/_helpers.tpl b/production/helm/loki/templates/_helpers.tpl index 34dcfaca76a6c..351bc2f57b625 100644 --- a/production/helm/loki/templates/_helpers.tpl +++ b/production/helm/loki/templates/_helpers.tpl @@ -662,6 +662,112 @@ Params: {{- end -}} {{- end -}} +{{/* +Return the appropriate apiVersion for HTTPRoute (Gateway API). +*/}} +{{- define "loki.httproute.apiVersion" -}} +{{- print "gateway.networking.k8s.io/v1" -}} +{{- end -}} + +{{/* +HTTPRoute labels for gateway component +*/}} +{{- define "loki.httproute.gatewayLabels" -}} +{{ include "loki.gatewayLabels" . }} +{{- end -}} + +{{/* +HTTPRoute labels for main ingress +*/}} +{{- define "loki.httproute.labels" -}} +{{ include "loki.labels" . }} +{{- end -}} + +{{/* +Generate HTTPRoute rules for distributed deployment +Params: + ctx = . context + serviceName = fully qualified k8s service name + servicePort = service port number + paths = list of url paths to route +*/}} +{{- define "loki.httproute.backendRefs" -}} +{{- range .paths }} +- matches: + - path: + type: PathPrefix + value: {{ . }} + backendRefs: + - name: {{ $.serviceName }} + port: {{ $.servicePort }} +{{- end -}} +{{- end -}} + +{{/* +Generate HTTPRoute rules based on deployment type +*/}} +{{- define "loki.httproute.serviceRules" -}} +{{- if (eq (include "loki.deployment.isSingleBinary" .) "true") -}} +{{- include "loki.httproute.singleBinaryServiceRules" . }} +{{- else if (eq (include "loki.deployment.isDistributed" .) "true") -}} +{{- include "loki.httproute.distributedServiceRules" . }} +{{- else if and (eq (include "loki.deployment.isScalable" .) "true") (not .Values.read.legacyReadTarget ) -}} +{{- include "loki.httproute.scalableServiceRules" . }} +{{- else -}} +{{- include "loki.httproute.legacyScalableServiceRules" . }} +{{- end -}} +{{- end -}} + +{{/* +HTTPRoute rules for distributed deployment +*/}} +{{- define "loki.httproute.distributedServiceRules" -}} +{{- $distributorServiceName := include "loki.distributorFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $distributorServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.distributor )}} +{{- $queryFrontendServiceName := include "loki.queryFrontendFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $queryFrontendServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.queryFrontend )}} +{{- $rulerServiceName := include "loki.rulerFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $rulerServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.ruler)}} +{{- $compactorServiceName := include "loki.compactorFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $compactorServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.compactor)}} +{{- end -}} + +{{/* +HTTPRoute rules for simple scalable deployment +*/}} +{{- define "loki.httproute.scalableServiceRules" -}} +{{- $readServiceName := include "loki.readFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $readServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.queryFrontend )}} +{{- $writeServiceName := include "loki.writeFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $writeServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.distributor )}} +{{- $backendServiceName := include "loki.backendFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $backendServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.ruler )}} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $backendServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.compactor )}} +{{- end -}} + +{{/* +HTTPRoute rules for legacy simple scalable deployment +*/}} +{{- define "loki.httproute.legacyScalableServiceRules" -}} +{{- $readServiceName := include "loki.readFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $readServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.queryFrontend )}} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $readServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.ruler )}} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $readServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.compactor )}} +{{- $writeServiceName := include "loki.writeFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $writeServiceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.distributor )}} +{{- end -}} + +{{/* +HTTPRoute rules for single binary deployment +*/}} +{{- define "loki.httproute.singleBinaryServiceRules" -}} +{{- $serviceName := include "loki.singleBinaryFullname" . }} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $serviceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.distributor )}} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $serviceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.queryFrontend )}} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $serviceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.ruler )}} +{{- include "loki.httproute.backendRefs" (dict "ctx" . "serviceName" $serviceName "servicePort" .Values.loki.server.http_listen_port "paths" .Values.ingress.paths.compactor )}} +{{- end -}} + {{/* Create the service endpoint including port for MinIO. */}} diff --git a/production/helm/loki/templates/gateway/httproute-gateway.yaml b/production/helm/loki/templates/gateway/httproute-gateway.yaml new file mode 100644 index 0000000000000..80f13eca2fe57 --- /dev/null +++ b/production/helm/loki/templates/gateway/httproute-gateway.yaml @@ -0,0 +1,203 @@ +{{- if and .Values.gateway.enabled -}} +{{- if .Values.gateway.httproute.enabled -}} +apiVersion: {{ include "loki.httproute.apiVersion" . }} +kind: HTTPRoute +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ include "loki.namespace" . }} + labels: + {{- include "loki.httproute.gatewayLabels" . | nindent 4 }} + {{- range $labelKey, $labelValue := .Values.gateway.httproute.labels }} + {{ $labelKey }}: {{ $labelValue | toYaml }} + {{- end }} + {{- with .Values.gateway.httproute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.gateway.httproute.parentRefs }} + parentRefs: + {{- range . }} + - name: {{ tpl .name $ }} + {{- if .namespace }} + namespace: {{ tpl .namespace $ }} + {{- end }} + {{- if .sectionName }} + sectionName: {{ tpl .sectionName $ }} + {{- end }} + {{- if .kind }} + kind: {{ .kind }} + {{- end }} + {{- if .group }} + group: {{ .group }} + {{- end }} + {{- if .port }} + port: {{ .port }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.gateway.httproute.hostnames }} + hostnames: + {{- range . }} + - {{ tpl . $ | quote }} + {{- end }} + {{- end }} + rules: + {{- range .Values.gateway.httproute.rules }} + - {{- if .matches }} + matches: + {{- range .matches }} + - {{- if .path }} + path: + type: {{ .path.type | default "PathPrefix" }} + value: {{ .path.value }} + {{- end }} + {{- if .headers }} + headers: + {{- range .headers }} + - type: {{ .type | default "Exact" }} + name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- if .queryParams }} + queryParams: + {{- range .queryParams }} + - type: {{ .type | default "Exact" }} + name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- if .method }} + method: {{ .method }} + {{- end }} + {{- end }} + {{- end }} + {{- if .filters }} + filters: + {{- range .filters }} + - type: {{ .type }} + {{- if eq .type "RequestHeaderModifier" }} + requestHeaderModifier: + {{- if .requestHeaderModifier.set }} + set: + {{- range .requestHeaderModifier.set }} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- if .requestHeaderModifier.add }} + add: + {{- range .requestHeaderModifier.add }} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- if .requestHeaderModifier.remove }} + remove: + {{- range .requestHeaderModifier.remove }} + - {{ . }} + {{- end }} + {{- end }} + {{- else if eq .type "ResponseHeaderModifier" }} + responseHeaderModifier: + {{- if .responseHeaderModifier.set }} + set: + {{- range .responseHeaderModifier.set }} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- if .responseHeaderModifier.add }} + add: + {{- range .responseHeaderModifier.add }} + - name: {{ .name }} + value: {{ .value }} + {{- end }} + {{- end }} + {{- if .responseHeaderModifier.remove }} + remove: + {{- range .responseHeaderModifier.remove }} + - {{ . }} + {{- end }} + {{- end }} + {{- else if eq .type "RequestRedirect" }} + requestRedirect: + {{- if .requestRedirect.scheme }} + scheme: {{ .requestRedirect.scheme }} + {{- end }} + {{- if .requestRedirect.hostname }} + hostname: {{ .requestRedirect.hostname }} + {{- end }} + {{- if .requestRedirect.path }} + path: + type: {{ .requestRedirect.path.type }} + {{- if .requestRedirect.path.replaceFullPath }} + replaceFullPath: {{ .requestRedirect.path.replaceFullPath }} + {{- end }} + {{- if .requestRedirect.path.replacePrefixMatch }} + replacePrefixMatch: {{ .requestRedirect.path.replacePrefixMatch }} + {{- end }} + {{- end }} + {{- if .requestRedirect.port }} + port: {{ .requestRedirect.port }} + {{- end }} + {{- if .requestRedirect.statusCode }} + statusCode: {{ .requestRedirect.statusCode }} + {{- end }} + {{- else if eq .type "URLRewrite" }} + urlRewrite: + {{- if .urlRewrite.hostname }} + hostname: {{ .urlRewrite.hostname }} + {{- end }} + {{- if .urlRewrite.path }} + path: + type: {{ .urlRewrite.path.type }} + {{- if .urlRewrite.path.replaceFullPath }} + replaceFullPath: {{ .urlRewrite.path.replaceFullPath }} + {{- end }} + {{- if .urlRewrite.path.replacePrefixMatch }} + replacePrefixMatch: {{ .urlRewrite.path.replacePrefixMatch }} + {{- end }} + {{- end }} + {{- else if eq .type "RequestMirror" }} + requestMirror: + backendRef: + name: {{ .requestMirror.backendRef.name }} + {{- if .requestMirror.backendRef.namespace }} + namespace: {{ .requestMirror.backendRef.namespace }} + {{- end }} + {{- if .requestMirror.backendRef.port }} + port: {{ .requestMirror.backendRef.port }} + {{- end }} + {{- else if eq .type "ExtensionRef" }} + extensionRef: + group: {{ .extensionRef.group }} + kind: {{ .extensionRef.kind }} + name: {{ .extensionRef.name }} + {{- end }} + {{- end }} + {{- end }} + backendRefs: + {{- if .backendRefs }} + {{- range .backendRefs }} + - name: {{ .name | default (include "loki.gatewayFullname" $) }} + {{- if .namespace }} + namespace: {{ .namespace }} + {{- end }} + port: {{ .port | default $.Values.gateway.service.port }} + {{- if .weight }} + weight: {{ .weight }} + {{- end }} + {{- if .filters }} + filters: + {{- toYaml .filters | nindent 12 }} + {{- end }} + {{- end }} + {{- else }} + - name: {{ include "loki.gatewayFullname" $ }} + port: {{ $.Values.gateway.service.port }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/production/helm/loki/templates/httproute.yaml b/production/helm/loki/templates/httproute.yaml new file mode 100644 index 0000000000000..76c204d26e97c --- /dev/null +++ b/production/helm/loki/templates/httproute.yaml @@ -0,0 +1,46 @@ +{{- if .Values.httproute.enabled }} +apiVersion: {{ include "loki.httproute.apiVersion" . }} +kind: HTTPRoute +metadata: + name: {{ include "loki.fullname" . }} + namespace: {{ include "loki.namespace" . }} + labels: + {{- include "loki.httproute.labels" . | nindent 4 }} + {{- with .Values.httproute.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.httproute.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.httproute.parentRefs }} + parentRefs: + {{- range . }} + - name: {{ tpl .name $ }} + {{- if .namespace }} + namespace: {{ tpl .namespace $ }} + {{- end }} + {{- if .sectionName }} + sectionName: {{ tpl .sectionName $ }} + {{- end }} + {{- if .kind }} + kind: {{ .kind }} + {{- end }} + {{- if .group }} + group: {{ .group }} + {{- end }} + {{- if .port }} + port: {{ .port }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.httproute.hostnames }} + hostnames: + {{- range . }} + - {{ tpl . $ | quote }} + {{- end }} + {{- end }} + rules: +{{ include "loki.httproute.serviceRules" . | indent 4 }} +{{- end }} diff --git a/production/helm/loki/test/integration/httproute/httproute-values.yaml b/production/helm/loki/test/integration/httproute/httproute-values.yaml new file mode 100644 index 0000000000000..22750723f26ee --- /dev/null +++ b/production/helm/loki/test/integration/httproute/httproute-values.yaml @@ -0,0 +1,35 @@ +--- +gateway: + httproute: + enabled: true + annotations: {} + parentRefs: + - name: loki-gateway + namespace: loki + hostnames: + - gateway.loki.example.com + rules: + - matches: + - path: + type: PathPrefix + value: / +loki: + commonConfig: + replication_factor: 1 + useTestSchema: true + storage: + bucketNames: + chunks: chunks + ruler: ruler + admin: admin +read: + replicas: 1 +write: + replicas: 1 +backend: + replicas: 1 +monitoring: + lokiCanary: + enabled: false +test: + enabled: false diff --git a/production/helm/loki/test/integration/httproute/test-plan.yaml b/production/helm/loki/test/integration/httproute/test-plan.yaml new file mode 100644 index 0000000000000..8cdd9c1ce88d6 --- /dev/null +++ b/production/helm/loki/test/integration/httproute/test-plan.yaml @@ -0,0 +1,24 @@ +--- +apiVersion: helm-chart-toolbox.grafana.com/v1 +kind: TestPlan +name: httproute +subject: + releaseName: loki + namespace: loki + path: ../../.. + valuesFile: httproute-values.yaml + extraArgs: + - --dependency-update + - --set + - "chunksCache.allocatedMemory=1024" + +cluster: + type: kind + +tests: + - type: kubernetes-objects-test + values: + checks: + - kind: HTTPRoute + name: loki-gateway + namespace: loki diff --git a/production/helm/loki/values.yaml b/production/helm/loki/values.yaml index 99a8846940be0..65caaf0105866 100644 --- a/production/helm/loki/values.yaml +++ b/production/helm/loki/values.yaml @@ -1187,6 +1187,32 @@ gateway: - secretName: loki-gateway-tls hosts: - gateway.loki.example.com + # HTTPRoute configuration (Gateway API) + httproute: + # -- Specifies whether an HTTPRoute for the gateway should be created + enabled: false + # -- Annotations for the gateway HTTPRoute + annotations: {} + # -- Labels for the gateway HTTPRoute + labels: {} + # -- The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating + parentRefs: + - name: "" + namespace: "" + # sectionName: "" + # -- Hostnames configuration for the gateway HTTPRoute, passed through the `tpl` function to allow templating + hostnames: [] + # - gateway.loki.example.com + # -- Rules configuration for the gateway HTTPRoute + rules: + - matches: + - path: + type: PathPrefix + value: / + # filters: [] + # backendRefs: + # - name: custom-backend + # port: 8080 # Basic auth configuration basicAuth: # -- Enables basic authentication for the gateway @@ -1410,6 +1436,22 @@ ingress: # - loki.example.com # secretName: loki-distributed-tls +# -- HTTPRoute configuration (Gateway API). Use either this HTTPRoute or the gateway, but not both at once. +# If you enable this, make sure to disable the gateway. +# HTTPRoute uses the same path configuration as ingress above. +httproute: + enabled: false + annotations: {} + labels: {} + # -- The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating + parentRefs: + - name: "" + namespace: "" + # sectionName: "" + # -- Hostnames configuration for the HTTPRoute, passed through the `tpl` function to allow templating + hostnames: [] + # - loki.example.com + ###################################################################################################################### # # Migration From a8bdeeb48060cd9cafd45889d9b6d6232a8f808b Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Fri, 7 Nov 2025 01:36:12 +0300 Subject: [PATCH 2/7] chore(helm): update CHANGELOG with correct PR number Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- production/helm/loki/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/production/helm/loki/CHANGELOG.md b/production/helm/loki/CHANGELOG.md index a966198e0577d..f6ab03964ea62 100644 --- a/production/helm/loki/CHANGELOG.md +++ b/production/helm/loki/CHANGELOG.md @@ -13,7 +13,7 @@ Entries should include a reference to the pull request that introduced the chang ## Unreleased -- [FEATURE] Add full HTTPRoute support (Gateway API v1) for both gateway and component-level routing with filters, multiple parentRefs, and custom rules. [#XXXXX](https://github.com/grafana/loki/pull/XXXXX) +- [FEATURE] Add full HTTPRoute support (Gateway API v1) for both gateway and component-level routing with filters, multiple parentRefs, and custom rules. [#19729](https://github.com/grafana/loki/pull/19729) ## 6.46.0 From 9c29fc62fa4718143b8321abeaebf6f0219649e2 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Fri, 7 Nov 2025 18:08:33 +0300 Subject: [PATCH 3/7] fix(helm): install Gateway API v1.4.0 CRDs in HTTPRoute integration test Add preInstallScript to install Gateway API v1.4.0 CRDs before deploying the chart to fix integration test failures. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- .../helm/loki/test/integration/httproute/test-plan.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/production/helm/loki/test/integration/httproute/test-plan.yaml b/production/helm/loki/test/integration/httproute/test-plan.yaml index 8cdd9c1ce88d6..03177e253da0f 100644 --- a/production/helm/loki/test/integration/httproute/test-plan.yaml +++ b/production/helm/loki/test/integration/httproute/test-plan.yaml @@ -11,6 +11,14 @@ subject: - --dependency-update - --set - "chunksCache.allocatedMemory=1024" + preInstallScript: | + #!/bin/bash + set -e + echo "Installing Gateway API CRDs..." + kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml + echo "Waiting for Gateway API CRDs to be established..." + kubectl wait --for condition=established --timeout=60s crd/gateways.gateway.networking.k8s.io + kubectl wait --for condition=established --timeout=60s crd/httproutes.gateway.networking.k8s.io cluster: type: kind From c1ca442fdeecb53cd4ed23440d10596e297680b0 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Sat, 8 Nov 2025 01:47:01 +0300 Subject: [PATCH 4/7] refactor(helm): align route structure with Grafana chart pattern Refactor Gateway API configuration to follow the same pattern as Grafana chart: - Rename gateway.httproute -> gateway.route - Rename httproute -> route - Add apiVersion and kind fields for flexibility - Use matches/filters/additionalRules structure - Update templates: httproute-gateway.yaml -> route-gateway.yaml, httproute.yaml -> route.yaml - Update CI and integration tests accordingly - Regenerate documentation This aligns with the pattern used across Grafana Helm charts for consistency. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- docs/sources/setup/install/helm/reference.md | 290 +++++++++++------- ...ttproute-values.yaml => route-values.yaml} | 13 +- .../templates/gateway/httproute-gateway.yaml | 203 ------------ .../loki/templates/gateway/route-gateway.yaml | 59 ++++ .../templates/{httproute.yaml => route.yaml} | 16 +- .../route-values.yaml} | 13 +- .../{httproute => route}/test-plan.yaml | 4 +- production/helm/loki/values.yaml | 85 +++-- 8 files changed, 315 insertions(+), 368 deletions(-) rename production/helm/loki/ci/{httproute-values.yaml => route-values.yaml} (75%) delete mode 100644 production/helm/loki/templates/gateway/httproute-gateway.yaml create mode 100644 production/helm/loki/templates/gateway/route-gateway.yaml rename production/helm/loki/templates/{httproute.yaml => route.yaml} (71%) rename production/helm/loki/test/integration/{httproute/httproute-values.yaml => route/route-values.yaml} (75%) rename production/helm/loki/test/integration/{httproute => route}/test-plan.yaml (94%) diff --git a/docs/sources/setup/install/helm/reference.md b/docs/sources/setup/install/helm/reference.md index c61813718d167..4e22310295bc5 100644 --- a/docs/sources/setup/install/helm/reference.md +++ b/docs/sources/setup/install/helm/reference.md @@ -4843,76 +4843,6 @@ true
 "nil"
 
- - - - gateway.httproute.annotations - object - Annotations for the gateway HTTPRoute -
-{}
-
- - - - gateway.httproute.enabled - bool - Specifies whether an HTTPRoute for the gateway should be created -
-false
-
- - - - gateway.httproute.hostnames - list - Hostnames configuration for the gateway HTTPRoute, passed through the `tpl` function to allow templating -
-[]
-
- - - - gateway.httproute.labels - object - Labels for the gateway HTTPRoute -
-{}
-
- - - - gateway.httproute.parentRefs - list - The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating -
-[
-  {
-    "name": "",
-    "namespace": ""
-  }
-]
-
- - - - gateway.httproute.rules - list - Rules configuration for the gateway HTTPRoute -
-[
-  {
-    "matches": [
-      {
-        "path": {
-          "type": "PathPrefix",
-          "value": "/"
-        }
-      }
-    ]
-  }
-]
-
@@ -5267,6 +5197,103 @@ null
 {}
 
+ + + + gateway.route.additionalRules + list + Additional custom rules that can be added to the route +
+[]
+
+ + + + gateway.route.annotations + object + Annotations for the gateway route +
+{}
+
+ + + + gateway.route.apiVersion + string + Set the route apiVersion, e.g. gateway.networking.k8s.io/v1 +
+"gateway.networking.k8s.io/v1"
+
+ + + + gateway.route.enabled + bool + Enables or disables the route +
+false
+
+ + + + gateway.route.filters + list + Filters define the filters that are applied to requests that match this rule +
+[]
+
+ + + + gateway.route.hostnames + list + Hostnames configuration for the gateway route, passed through the `tpl` function to allow templating +
+[]
+
+ + + + gateway.route.kind + string + Set the route kind Valid options are GRPCRoute, HTTPRoute, TCPRoute, TLSRoute, UDPRoute +
+"HTTPRoute"
+
+ + + + gateway.route.labels + object + Labels for the gateway route +
+{}
+
+ + + + gateway.route.matches + list + Matches define the predicates used for matching requests to a given action +
+[
+  {
+    "path": {
+      "type": "PathPrefix",
+      "value": "/"
+    }
+  }
+]
+
+ + + + gateway.route.parentRefs + list + The list of parent Gateways this route should be attached to, passed through the `tpl` function to allow templating +
+[]
+
@@ -5474,49 +5501,6 @@ null
 null
 
- - - - httproute - object - HTTPRoute configuration (Gateway API). Use either this HTTPRoute or the gateway, but not both at once. If you enable this, make sure to disable the gateway. HTTPRoute uses the same path configuration as ingress above. -
-{
-  "annotations": {},
-  "enabled": false,
-  "hostnames": [],
-  "labels": {},
-  "parentRefs": [
-    {
-      "name": "",
-      "namespace": ""
-    }
-  ]
-}
-
- - - - httproute.hostnames - list - Hostnames configuration for the HTTPRoute, passed through the `tpl` function to allow templating -
-[]
-
- - - - httproute.parentRefs - list - The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating -
-[
-  {
-    "name": "",
-    "namespace": ""
-  }
-]
-
@@ -11903,6 +11887,86 @@ null } } + + + + route + object + Route configuration (Gateway API). Use either this route or the gateway, but not both at once. If you enable this, make sure to disable the gateway. Route uses the same path configuration as ingress above for component-level routing. +
+{
+  "annotations": {},
+  "apiVersion": "gateway.networking.k8s.io/v1",
+  "enabled": false,
+  "hostnames": [],
+  "kind": "HTTPRoute",
+  "labels": {},
+  "parentRefs": []
+}
+
+ + + + route.annotations + object + Annotations for the route +
+{}
+
+ + + + route.apiVersion + string + Set the route apiVersion, e.g. gateway.networking.k8s.io/v1 +
+"gateway.networking.k8s.io/v1"
+
+ + + + route.enabled + bool + Enables or disables the route +
+false
+
+ + + + route.hostnames + list + Hostnames configuration for the route, passed through the `tpl` function to allow templating +
+[]
+
+ + + + route.kind + string + Set the route kind Valid options are GRPCRoute, HTTPRoute, TCPRoute, TLSRoute, UDPRoute +
+"HTTPRoute"
+
+ + + + route.labels + object + Labels for the route +
+{}
+
+ + + + route.parentRefs + list + The list of parent Gateways this route should be attached to, passed through the `tpl` function to allow templating +
+[]
+
diff --git a/production/helm/loki/ci/httproute-values.yaml b/production/helm/loki/ci/route-values.yaml similarity index 75% rename from production/helm/loki/ci/httproute-values.yaml rename to production/helm/loki/ci/route-values.yaml index 22750723f26ee..6203263655f11 100644 --- a/production/helm/loki/ci/httproute-values.yaml +++ b/production/helm/loki/ci/route-values.yaml @@ -1,18 +1,19 @@ --- gateway: - httproute: + route: enabled: true + apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute annotations: {} parentRefs: - name: loki-gateway namespace: loki hostnames: - gateway.loki.example.com - rules: - - matches: - - path: - type: PathPrefix - value: / + matches: + - path: + type: PathPrefix + value: / loki: commonConfig: replication_factor: 1 diff --git a/production/helm/loki/templates/gateway/httproute-gateway.yaml b/production/helm/loki/templates/gateway/httproute-gateway.yaml deleted file mode 100644 index 80f13eca2fe57..0000000000000 --- a/production/helm/loki/templates/gateway/httproute-gateway.yaml +++ /dev/null @@ -1,203 +0,0 @@ -{{- if and .Values.gateway.enabled -}} -{{- if .Values.gateway.httproute.enabled -}} -apiVersion: {{ include "loki.httproute.apiVersion" . }} -kind: HTTPRoute -metadata: - name: {{ include "loki.gatewayFullname" . }} - namespace: {{ include "loki.namespace" . }} - labels: - {{- include "loki.httproute.gatewayLabels" . | nindent 4 }} - {{- range $labelKey, $labelValue := .Values.gateway.httproute.labels }} - {{ $labelKey }}: {{ $labelValue | toYaml }} - {{- end }} - {{- with .Values.gateway.httproute.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- with .Values.gateway.httproute.parentRefs }} - parentRefs: - {{- range . }} - - name: {{ tpl .name $ }} - {{- if .namespace }} - namespace: {{ tpl .namespace $ }} - {{- end }} - {{- if .sectionName }} - sectionName: {{ tpl .sectionName $ }} - {{- end }} - {{- if .kind }} - kind: {{ .kind }} - {{- end }} - {{- if .group }} - group: {{ .group }} - {{- end }} - {{- if .port }} - port: {{ .port }} - {{- end }} - {{- end }} - {{- end }} - {{- with .Values.gateway.httproute.hostnames }} - hostnames: - {{- range . }} - - {{ tpl . $ | quote }} - {{- end }} - {{- end }} - rules: - {{- range .Values.gateway.httproute.rules }} - - {{- if .matches }} - matches: - {{- range .matches }} - - {{- if .path }} - path: - type: {{ .path.type | default "PathPrefix" }} - value: {{ .path.value }} - {{- end }} - {{- if .headers }} - headers: - {{- range .headers }} - - type: {{ .type | default "Exact" }} - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- if .queryParams }} - queryParams: - {{- range .queryParams }} - - type: {{ .type | default "Exact" }} - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- if .method }} - method: {{ .method }} - {{- end }} - {{- end }} - {{- end }} - {{- if .filters }} - filters: - {{- range .filters }} - - type: {{ .type }} - {{- if eq .type "RequestHeaderModifier" }} - requestHeaderModifier: - {{- if .requestHeaderModifier.set }} - set: - {{- range .requestHeaderModifier.set }} - - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- if .requestHeaderModifier.add }} - add: - {{- range .requestHeaderModifier.add }} - - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- if .requestHeaderModifier.remove }} - remove: - {{- range .requestHeaderModifier.remove }} - - {{ . }} - {{- end }} - {{- end }} - {{- else if eq .type "ResponseHeaderModifier" }} - responseHeaderModifier: - {{- if .responseHeaderModifier.set }} - set: - {{- range .responseHeaderModifier.set }} - - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- if .responseHeaderModifier.add }} - add: - {{- range .responseHeaderModifier.add }} - - name: {{ .name }} - value: {{ .value }} - {{- end }} - {{- end }} - {{- if .responseHeaderModifier.remove }} - remove: - {{- range .responseHeaderModifier.remove }} - - {{ . }} - {{- end }} - {{- end }} - {{- else if eq .type "RequestRedirect" }} - requestRedirect: - {{- if .requestRedirect.scheme }} - scheme: {{ .requestRedirect.scheme }} - {{- end }} - {{- if .requestRedirect.hostname }} - hostname: {{ .requestRedirect.hostname }} - {{- end }} - {{- if .requestRedirect.path }} - path: - type: {{ .requestRedirect.path.type }} - {{- if .requestRedirect.path.replaceFullPath }} - replaceFullPath: {{ .requestRedirect.path.replaceFullPath }} - {{- end }} - {{- if .requestRedirect.path.replacePrefixMatch }} - replacePrefixMatch: {{ .requestRedirect.path.replacePrefixMatch }} - {{- end }} - {{- end }} - {{- if .requestRedirect.port }} - port: {{ .requestRedirect.port }} - {{- end }} - {{- if .requestRedirect.statusCode }} - statusCode: {{ .requestRedirect.statusCode }} - {{- end }} - {{- else if eq .type "URLRewrite" }} - urlRewrite: - {{- if .urlRewrite.hostname }} - hostname: {{ .urlRewrite.hostname }} - {{- end }} - {{- if .urlRewrite.path }} - path: - type: {{ .urlRewrite.path.type }} - {{- if .urlRewrite.path.replaceFullPath }} - replaceFullPath: {{ .urlRewrite.path.replaceFullPath }} - {{- end }} - {{- if .urlRewrite.path.replacePrefixMatch }} - replacePrefixMatch: {{ .urlRewrite.path.replacePrefixMatch }} - {{- end }} - {{- end }} - {{- else if eq .type "RequestMirror" }} - requestMirror: - backendRef: - name: {{ .requestMirror.backendRef.name }} - {{- if .requestMirror.backendRef.namespace }} - namespace: {{ .requestMirror.backendRef.namespace }} - {{- end }} - {{- if .requestMirror.backendRef.port }} - port: {{ .requestMirror.backendRef.port }} - {{- end }} - {{- else if eq .type "ExtensionRef" }} - extensionRef: - group: {{ .extensionRef.group }} - kind: {{ .extensionRef.kind }} - name: {{ .extensionRef.name }} - {{- end }} - {{- end }} - {{- end }} - backendRefs: - {{- if .backendRefs }} - {{- range .backendRefs }} - - name: {{ .name | default (include "loki.gatewayFullname" $) }} - {{- if .namespace }} - namespace: {{ .namespace }} - {{- end }} - port: {{ .port | default $.Values.gateway.service.port }} - {{- if .weight }} - weight: {{ .weight }} - {{- end }} - {{- if .filters }} - filters: - {{- toYaml .filters | nindent 12 }} - {{- end }} - {{- end }} - {{- else }} - - name: {{ include "loki.gatewayFullname" $ }} - port: {{ $.Values.gateway.service.port }} - {{- end }} - {{- end }} -{{- end }} -{{- end }} diff --git a/production/helm/loki/templates/gateway/route-gateway.yaml b/production/helm/loki/templates/gateway/route-gateway.yaml new file mode 100644 index 0000000000000..c0dd115e300b6 --- /dev/null +++ b/production/helm/loki/templates/gateway/route-gateway.yaml @@ -0,0 +1,59 @@ +{{- if and .Values.gateway.enabled .Values.gateway.route.enabled -}} +apiVersion: {{ .Values.gateway.route.apiVersion }} +kind: {{ .Values.gateway.route.kind }} +metadata: + name: {{ include "loki.gatewayFullname" . }} + namespace: {{ include "loki.namespace" . }} + labels: + {{- include "loki.gatewayLabels" . | nindent 4 }} + {{- with .Values.gateway.route.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.gateway.route.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.gateway.route.parentRefs }} + parentRefs: + {{- range . }} + - name: {{ tpl .name $ }} + {{- if .namespace }} + namespace: {{ tpl .namespace $ }} + {{- end }} + {{- if .sectionName }} + sectionName: {{ tpl .sectionName $ }} + {{- end }} + {{- if .kind }} + kind: {{ .kind }} + {{- end }} + {{- if .group }} + group: {{ .group }} + {{- end }} + {{- if .port }} + port: {{ .port }} + {{- end }} + {{- end }} + {{- end }} + {{- with .Values.gateway.route.hostnames }} + hostnames: + {{- range . }} + - {{ tpl . $ | quote }} + {{- end }} + {{- end }} + rules: + - {{- if .Values.gateway.route.matches }} + matches: + {{- toYaml .Values.gateway.route.matches | nindent 8 }} + {{- end }} + {{- if .Values.gateway.route.filters }} + filters: + {{- toYaml .Values.gateway.route.filters | nindent 8 }} + {{- end }} + backendRefs: + - name: {{ include "loki.gatewayFullname" $ }} + port: {{ $.Values.gateway.service.port }} + {{- with .Values.gateway.route.additionalRules }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/production/helm/loki/templates/httproute.yaml b/production/helm/loki/templates/route.yaml similarity index 71% rename from production/helm/loki/templates/httproute.yaml rename to production/helm/loki/templates/route.yaml index 76c204d26e97c..df7a6a60982c4 100644 --- a/production/helm/loki/templates/httproute.yaml +++ b/production/helm/loki/templates/route.yaml @@ -1,20 +1,20 @@ -{{- if .Values.httproute.enabled }} -apiVersion: {{ include "loki.httproute.apiVersion" . }} -kind: HTTPRoute +{{- if .Values.route.enabled }} +apiVersion: {{ .Values.route.apiVersion }} +kind: {{ .Values.route.kind }} metadata: name: {{ include "loki.fullname" . }} namespace: {{ include "loki.namespace" . }} labels: - {{- include "loki.httproute.labels" . | nindent 4 }} - {{- with .Values.httproute.labels }} + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.route.labels }} {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.httproute.annotations }} + {{- with .Values.route.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} spec: - {{- with .Values.httproute.parentRefs }} + {{- with .Values.route.parentRefs }} parentRefs: {{- range . }} - name: {{ tpl .name $ }} @@ -35,7 +35,7 @@ spec: {{- end }} {{- end }} {{- end }} - {{- with .Values.httproute.hostnames }} + {{- with .Values.route.hostnames }} hostnames: {{- range . }} - {{ tpl . $ | quote }} diff --git a/production/helm/loki/test/integration/httproute/httproute-values.yaml b/production/helm/loki/test/integration/route/route-values.yaml similarity index 75% rename from production/helm/loki/test/integration/httproute/httproute-values.yaml rename to production/helm/loki/test/integration/route/route-values.yaml index 22750723f26ee..6203263655f11 100644 --- a/production/helm/loki/test/integration/httproute/httproute-values.yaml +++ b/production/helm/loki/test/integration/route/route-values.yaml @@ -1,18 +1,19 @@ --- gateway: - httproute: + route: enabled: true + apiVersion: gateway.networking.k8s.io/v1 + kind: HTTPRoute annotations: {} parentRefs: - name: loki-gateway namespace: loki hostnames: - gateway.loki.example.com - rules: - - matches: - - path: - type: PathPrefix - value: / + matches: + - path: + type: PathPrefix + value: / loki: commonConfig: replication_factor: 1 diff --git a/production/helm/loki/test/integration/httproute/test-plan.yaml b/production/helm/loki/test/integration/route/test-plan.yaml similarity index 94% rename from production/helm/loki/test/integration/httproute/test-plan.yaml rename to production/helm/loki/test/integration/route/test-plan.yaml index 03177e253da0f..63084fa42dbee 100644 --- a/production/helm/loki/test/integration/httproute/test-plan.yaml +++ b/production/helm/loki/test/integration/route/test-plan.yaml @@ -1,12 +1,12 @@ --- apiVersion: helm-chart-toolbox.grafana.com/v1 kind: TestPlan -name: httproute +name: route subject: releaseName: loki namespace: loki path: ../../.. - valuesFile: httproute-values.yaml + valuesFile: route-values.yaml extraArgs: - --dependency-update - --set diff --git a/production/helm/loki/values.yaml b/production/helm/loki/values.yaml index 65caaf0105866..5c8d8025b5a17 100644 --- a/production/helm/loki/values.yaml +++ b/production/helm/loki/values.yaml @@ -1187,32 +1187,48 @@ gateway: - secretName: loki-gateway-tls hosts: - gateway.loki.example.com - # HTTPRoute configuration (Gateway API) - httproute: - # -- Specifies whether an HTTPRoute for the gateway should be created + # Route configuration (Gateway API) + route: + # -- Enables or disables the route enabled: false - # -- Annotations for the gateway HTTPRoute + # -- Set the route apiVersion, e.g. gateway.networking.k8s.io/v1 + apiVersion: gateway.networking.k8s.io/v1 + # -- Set the route kind + # Valid options are GRPCRoute, HTTPRoute, TCPRoute, TLSRoute, UDPRoute + kind: HTTPRoute + # -- Annotations for the gateway route annotations: {} - # -- Labels for the gateway HTTPRoute + # -- Labels for the gateway route labels: {} - # -- The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating - parentRefs: - - name: "" - namespace: "" - # sectionName: "" - # -- Hostnames configuration for the gateway HTTPRoute, passed through the `tpl` function to allow templating + # -- The list of parent Gateways this route should be attached to, passed through the `tpl` function to allow templating + parentRefs: [] + # - name: example-gateway + # namespace: example-gateway-ns + # sectionName: https + # -- Hostnames configuration for the gateway route, passed through the `tpl` function to allow templating hostnames: [] # - gateway.loki.example.com - # -- Rules configuration for the gateway HTTPRoute - rules: - - matches: - - path: - type: PathPrefix - value: / - # filters: [] - # backendRefs: - # - name: custom-backend - # port: 8080 + # -- Matches define the predicates used for matching requests to a given action + matches: + - path: + type: PathPrefix + value: / + # -- Filters define the filters that are applied to requests that match this rule + filters: [] + # - type: RequestHeaderModifier + # requestHeaderModifier: + # add: + # - name: X-Custom-Header + # value: custom-value + # -- Additional custom rules that can be added to the route + additionalRules: [] + # - matches: + # - path: + # type: PathPrefix + # value: /custom + # backendRefs: + # - name: custom-backend + # port: 8080 # Basic auth configuration basicAuth: # -- Enables basic authentication for the gateway @@ -1436,21 +1452,30 @@ ingress: # - loki.example.com # secretName: loki-distributed-tls -# -- HTTPRoute configuration (Gateway API). Use either this HTTPRoute or the gateway, but not both at once. +# -- Route configuration (Gateway API). Use either this route or the gateway, but not both at once. # If you enable this, make sure to disable the gateway. -# HTTPRoute uses the same path configuration as ingress above. -httproute: +# Route uses the same path configuration as ingress above for component-level routing. +route: + # -- Enables or disables the route enabled: false + # -- Set the route apiVersion, e.g. gateway.networking.k8s.io/v1 + apiVersion: gateway.networking.k8s.io/v1 + # -- Set the route kind + # Valid options are GRPCRoute, HTTPRoute, TCPRoute, TLSRoute, UDPRoute + kind: HTTPRoute + # -- Annotations for the route annotations: {} + # -- Labels for the route labels: {} - # -- The list of parent Gateways this HTTPRoute should be attached to, passed through the `tpl` function to allow templating - parentRefs: - - name: "" - namespace: "" - # sectionName: "" - # -- Hostnames configuration for the HTTPRoute, passed through the `tpl` function to allow templating + # -- The list of parent Gateways this route should be attached to, passed through the `tpl` function to allow templating + parentRefs: [] + # - name: example-gateway + # namespace: example-gateway-ns + # sectionName: https + # -- Hostnames configuration for the route, passed through the `tpl` function to allow templating hostnames: [] # - loki.example.com + # Note: matches and filters are not used for component-level routing as rules are generated automatically based on deployment mode ###################################################################################################################### # From 76c1b9b8dfdbed56d661d6c03192aa3e3bbd95bb Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Mon, 10 Nov 2025 20:39:31 +0300 Subject: [PATCH 5/7] ci(helm): install Gateway API CRDs in helm-ci workflow Add Gateway API CRDs installation step in helm-ci workflow before running chart-testing. This fixes the route integration test failures where HTTPRoute resources couldn't be created due to missing CRDs. The CRDs are installed after prometheus operator and before ct install, ensuring they are available when testing charts with route-values.yaml. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- .github/workflows/helm-ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/helm-ci.yml b/.github/workflows/helm-ci.yml index cd85119b34e8c..3cbdbb3328f91 100644 --- a/.github/workflows/helm-ci.yml +++ b/.github/workflows/helm-ci.yml @@ -81,6 +81,15 @@ jobs: kubectl --namespace prometheus get pods -l "release=prometheus" kubectl --namespace prometheus get services -l "release=prometheus" + - name: Install Gateway API CRDs + if: steps.list-changed.outputs.changed == 'true' + run: | + echo "Installing Gateway API CRDs..." + kubectl apply --filename https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml + echo "Waiting for Gateway API CRDs to be established..." + kubectl wait --for condition=established --timeout=60s crd/gateways.gateway.networking.k8s.io + kubectl wait --for condition=established --timeout=60s crd/httproutes.gateway.networking.k8s.io + - name: Run chart-testing (install) run: | changed=$(ct list-changed --config "${CT_CONFIGFILE}") From 4de0e7d7ad57fc1d9d284f1fc6871d523722c996 Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Mon, 10 Nov 2025 21:32:22 +0300 Subject: [PATCH 6/7] fix(helm): use dependencies for Gateway API CRDs in route test Replace preInstallScript (not supported by helm-chart-toolbox) with dependencies.file to install Gateway API CRDs before Loki deployment. Tested locally: Gateway API CRDs install correctly, HTTPRoute resource created successfully, all pods running. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- .../helm/loki/test/integration/route/test-plan.yaml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/production/helm/loki/test/integration/route/test-plan.yaml b/production/helm/loki/test/integration/route/test-plan.yaml index 63084fa42dbee..6390ffedf8cb1 100644 --- a/production/helm/loki/test/integration/route/test-plan.yaml +++ b/production/helm/loki/test/integration/route/test-plan.yaml @@ -11,18 +11,13 @@ subject: - --dependency-update - --set - "chunksCache.allocatedMemory=1024" - preInstallScript: | - #!/bin/bash - set -e - echo "Installing Gateway API CRDs..." - kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml - echo "Waiting for Gateway API CRDs to be established..." - kubectl wait --for condition=established --timeout=60s crd/gateways.gateway.networking.k8s.io - kubectl wait --for condition=established --timeout=60s crd/httproutes.gateway.networking.k8s.io cluster: type: kind +dependencies: + - file: https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml + tests: - type: kubernetes-objects-test values: From e86327c66a93aed8b9ad5e0f6e138f07e0e0206c Mon Sep 17 00:00:00 2001 From: Aleksei Sviridkin Date: Mon, 10 Nov 2025 21:42:55 +0300 Subject: [PATCH 7/7] fix(helm): use dependencies.url for Gateway API CRDs in route test Replace unsupported preInstallScript with dependencies.url field to install Gateway API CRDs before Loki deployment. Tested locally with helm-chart-toolbox: Gateway API CRDs install correctly, HTTPRoute resource created successfully, all pods running, test completed with exit code 0. Co-Authored-By: Claude Signed-off-by: Aleksei Sviridkin --- production/helm/loki/test/integration/route/test-plan.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/production/helm/loki/test/integration/route/test-plan.yaml b/production/helm/loki/test/integration/route/test-plan.yaml index 6390ffedf8cb1..1660f9405f2fb 100644 --- a/production/helm/loki/test/integration/route/test-plan.yaml +++ b/production/helm/loki/test/integration/route/test-plan.yaml @@ -16,7 +16,7 @@ cluster: type: kind dependencies: - - file: https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml + - url: https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml tests: - type: kubernetes-objects-test