diff --git a/.changes/unreleased/charts-redpanda-Added-20260414-gateway-api.yaml b/.changes/unreleased/charts-redpanda-Added-20260414-gateway-api.yaml new file mode 100644 index 000000000..45d88115e --- /dev/null +++ b/.changes/unreleased/charts-redpanda-Added-20260414-gateway-api.yaml @@ -0,0 +1,8 @@ +project: charts/redpanda +kind: Added +body: |- + Added Gateway API TLSRoute support for external access. Individual external + listeners can opt into TLSRoute mode via `gateway: true`, enabling SNI-based + routing through a user-managed Gateway. This supports per-listener domains + and gradual migration from NodePort/LoadBalancer to Gateway API. +time: 2026-04-14T20:00:00.000000-04:00 diff --git a/charts/redpanda/chart.go b/charts/redpanda/chart.go index f640527c9..a4edd911e 100644 --- a/charts/redpanda/chart.go +++ b/charts/redpanda/chart.go @@ -24,6 +24,7 @@ import ( policyv1 "k8s.io/api/policy/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes/scheme" consolechart "github.com/redpanda-data/redpanda-operator/charts/console/v3/chart" @@ -56,6 +57,7 @@ func Types() []kube.Object { &corev1.Secret{}, &corev1.ServiceAccount{}, &corev1.Service{}, + &TLSRoute{}, &monitoringv1.PodMonitor{}, &monitoringv1.ServiceMonitor{}, &networkingv1.Ingress{}, @@ -72,6 +74,15 @@ func init() { must(scheme.AddToScheme(Scheme)) must(certmanagerv1.AddToScheme(Scheme)) must(monitoringv1.AddToScheme(Scheme)) + addTLSRouteToScheme(Scheme) +} + +// addTLSRouteToScheme registers our lightweight TLSRoute type with a +// runtime.Scheme so the test harness can decode it. +// +gotohelm:ignore=true +func addTLSRouteToScheme(s *runtime.Scheme) { + gv := schema.GroupVersion{Group: "gateway.networking.k8s.io", Version: "v1alpha2"} + s.AddKnownTypeWithName(gv.WithKind("TLSRoute"), &TLSRoute{}) } // +gotohelm:ignore=true @@ -167,6 +178,14 @@ func renderResources(state *RenderState) []kube.Object { manifests = append(manifests, obj) } + for _, obj := range GatewayServices(state) { + manifests = append(manifests, obj) + } + + for _, obj := range TLSRoutes(state) { + manifests = append(manifests, obj) + } + for _, obj := range Secrets(state) { manifests = append(manifests, obj) } diff --git a/charts/redpanda/chart/templates/_chart.go.tpl b/charts/redpanda/chart/templates/_chart.go.tpl index eb8c9ecc3..0c80abf3c 100644 --- a/charts/redpanda/chart/templates/_chart.go.tpl +++ b/charts/redpanda/chart/templates/_chart.go.tpl @@ -81,6 +81,18 @@ {{- if $_is_returning -}} {{- break -}} {{- end -}} +{{- range $_, $obj := (get (fromJson (include "redpanda.GatewayServices" (dict "a" (list $state)))) "r") -}} +{{- $manifests = (concat (default (list) $manifests) (list $obj)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $_, $obj := (get (fromJson (include "redpanda.TLSRoutes" (dict "a" (list $state)))) "r") -}} +{{- $manifests = (concat (default (list) $manifests) (list $obj)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} {{- range $_, $obj := (get (fromJson (include "redpanda.Secrets" (dict "a" (list $state)))) "r") -}} {{- $manifests = (concat (default (list) $manifests) (list $obj)) -}} {{- end -}} diff --git a/charts/redpanda/chart/templates/_secrets.go.tpl b/charts/redpanda/chart/templates/_secrets.go.tpl index b04d7098a..530e91351 100644 --- a/charts/redpanda/chart/templates/_secrets.go.tpl +++ b/charts/redpanda/chart/templates/_secrets.go.tpl @@ -230,7 +230,8 @@ echo "passed"`) -}} {{- $port = (index $externalVals.advertisedPorts $replicaIndex) -}} {{- end -}} {{- end -}} -{{- $host := (get (fromJson (include "redpanda.advertisedHostJSON" (dict "a" (list $state $externalName $port $replicaIndex)))) "r") -}} +{{- $host := (get (fromJson (include "redpanda.advertisedHostJSON" (dict "a" (list $state $port $replicaIndex (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $externalVals.host "")))) "r") (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $externalVals.hostTemplate "")))) "r") (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $externalVals)))) "r"))))) "r") -}} +{{- $_ := (set $host "name" $externalName) -}} {{- $address := (toJson $host) -}} {{- $prefixTemplate := (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $externalVals.prefixTemplate "")))) "r") -}} {{- if (eq $prefixTemplate "") -}} @@ -278,7 +279,8 @@ echo "passed"`) -}} {{- $port = (index $externalVals.advertisedPorts $replicaIndex) -}} {{- end -}} {{- end -}} -{{- $host := (get (fromJson (include "redpanda.advertisedHostJSON" (dict "a" (list $state $externalName $port $replicaIndex)))) "r") -}} +{{- $host := (get (fromJson (include "redpanda.advertisedHostJSON" (dict "a" (list $state $port $replicaIndex (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $externalVals.host "")))) "r") (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $externalVals.hostTemplate "")))) "r") (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $externalVals)))) "r"))))) "r") -}} +{{- $_ := (set $host "name" $externalName) -}} {{- $address := (toJson $host) -}} {{- $prefixTemplate := (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $externalVals.prefixTemplate "")))) "r") -}} {{- if (eq $prefixTemplate "") -}} @@ -341,12 +343,19 @@ echo "passed"`) -}} {{- define "redpanda.advertisedHostJSON" -}} {{- $state := (index .a 0) -}} -{{- $externalName := (index .a 1) -}} -{{- $port := (index .a 2) -}} -{{- $replicaIndex := (index .a 3) -}} +{{- $port := (index .a 1) -}} +{{- $replicaIndex := (index .a 2) -}} +{{- $host := (index .a 3) -}} +{{- $hostTemplate := (index .a 4) -}} +{{- $isGateway := (index .a 5) -}} {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} -{{- $host := (dict "name" $externalName "address" (get (fromJson (include "redpanda.externalAdvertiseAddress" (dict "a" (list $state)))) "r") "port" $port) -}} +{{- if (and (get (fromJson (include "redpanda.ExternalConfig.IsGatewayEnabled" (dict "a" (list $state.Values.external)))) "r") $isGateway) -}} +{{- $_is_returning = true -}} +{{- (dict "r" (get (fromJson (include "redpanda.advertisedHostJSONGateway" (dict "a" (list $state $replicaIndex $host $hostTemplate)))) "r")) | toJson -}} +{{- break -}} +{{- end -}} +{{- $hostMap := (dict "name" "" "address" (get (fromJson (include "redpanda.externalAdvertiseAddress" (dict "a" (list $state)))) "r") "port" $port) -}} {{- if (gt ((get (fromJson (include "_shims.len" (dict "a" (list $state.Values.external.addresses)))) "r") | int) (0 | int)) -}} {{- $address := "" -}} {{- if (gt ((get (fromJson (include "_shims.len" (dict "a" (list $state.Values.external.addresses)))) "r") | int) (1 | int)) -}} @@ -356,13 +365,43 @@ echo "passed"`) -}} {{- end -}} {{- $domain_5 := (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $state.Values.external.domain "")))) "r") -}} {{- if (ne $domain_5 "") -}} -{{- $host = (dict "name" $externalName "address" (printf "%s.%s" $address (tpl $domain_5 $state.Dot)) "port" $port) -}} +{{- $hostMap = (dict "name" "" "address" (printf "%s.%s" $address (tpl $domain_5 $state.Dot)) "port" $port) -}} {{- else -}} -{{- $host = (dict "name" $externalName "address" $address "port" $port) -}} +{{- $hostMap = (dict "name" "" "address" $address "port" $port) -}} +{{- end -}} +{{- end -}} +{{- $_is_returning = true -}} +{{- (dict "r" $hostMap) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + +{{- define "redpanda.advertisedHostJSONGateway" -}} +{{- $state := (index .a 0) -}} +{{- $replicaIndex := (index .a 1) -}} +{{- $host := (index .a 2) -}} +{{- $hostTemplate := (index .a 3) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $gw := $state.Values.external.gateway -}} +{{- $port := ((get (fromJson (include "redpanda.GatewayConfig.GatewayAdvertisedPort" (dict "a" (list $gw)))) "r") | int) -}} +{{- if (eq $hostTemplate "") -}} +{{- $hostTemplate = $host -}} +{{- end -}} +{{- $pods := (get (fromJson (include "redpanda.PodNames" (dict "a" (list $state (mustMergeOverwrite (dict "Name" "" "Generation" "" "Statefulset" (dict "additionalSelectorLabels" (coalesce nil) "replicas" 0 "updateStrategy" (dict) "additionalRedpandaCmdFlags" (coalesce nil) "podTemplate" (dict) "budget" (dict "maxUnavailable" 0) "podAntiAffinity" (dict "topologyKey" "" "type" "" "weight" 0 "custom" (coalesce nil)) "sideCars" (dict "image" (dict "repository" "" "tag" "") "args" (coalesce nil) "pvcUnbinder" (dict "enabled" false "unbindAfter" "") "brokerDecommissioner" (dict "enabled" false "decommissionAfter" "" "decommissionRequeueTimeout" "") "configWatcher" (dict "enabled" false) "controllers" (dict "image" (coalesce nil) "enabled" false "createRBAC" false "healthProbeAddress" "" "metricsAddress" "" "pprofAddress" "" "run" (coalesce nil))) "initContainers" (dict "fsValidator" (dict "enabled" false "expectedFS" "") "setDataDirOwnership" (dict "enabled" false) "configurator" (dict)) "initContainerImage" (dict "repository" "" "tag" "")) "ServiceAnnotations" (coalesce nil)) (dict "Statefulset" $state.Values.statefulset)))))) "r") -}} +{{- range $_, $set := $state.Pools -}} +{{- $pods = (concat (default (list) $pods) (default (list) (get (fromJson (include "redpanda.PodNames" (dict "a" (list $state $set)))) "r"))) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} {{- end -}} +{{- $podName := "" -}} +{{- if (lt $replicaIndex ((get (fromJson (include "_shims.len" (dict "a" (list $pods)))) "r") | int)) -}} +{{- $podName = (index $pods $replicaIndex) -}} {{- end -}} +{{- $address := (get (fromJson (include "redpanda.renderBrokerHost" (dict "a" (list $hostTemplate $replicaIndex $podName)))) "r") -}} {{- $_is_returning = true -}} -{{- (dict "r" $host) | toJson -}} +{{- (dict "r" (dict "name" "" "address" $address "port" $port)) | toJson -}} {{- break -}} {{- end -}} {{- end -}} diff --git a/charts/redpanda/chart/templates/_service.gateway.go.tpl b/charts/redpanda/chart/templates/_service.gateway.go.tpl new file mode 100644 index 000000000..7690aa070 --- /dev/null +++ b/charts/redpanda/chart/templates/_service.gateway.go.tpl @@ -0,0 +1,98 @@ +{{- /* GENERATED FILE DO NOT EDIT */ -}} +{{- /* Transpiled by gotohelm from "github.com/redpanda-data/redpanda-operator/charts/redpanda/v25/service.gateway.go" */ -}} + +{{- define "redpanda.GatewayServices" -}} +{{- $state := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- if (not (get (fromJson (include "redpanda.ExternalConfig.IsGatewayEnabled" (dict "a" (list $state.Values.external)))) "r")) -}} +{{- $_is_returning = true -}} +{{- (dict "r" (coalesce nil)) | toJson -}} +{{- break -}} +{{- end -}} +{{- $labels := (get (fromJson (include "redpanda.FullLabels" (dict "a" (list $state)))) "r") -}} +{{- $selector := (get (fromJson (include "redpanda.ClusterPodLabelsSelector" (dict "a" (list $state)))) "r") -}} +{{- $ports := (get (fromJson (include "redpanda.gatewayServicePorts" (dict "a" (list $state)))) "r") -}} +{{- if (eq ((get (fromJson (include "_shims.len" (dict "a" (list $ports)))) "r") | int) (0 | int)) -}} +{{- $_is_returning = true -}} +{{- (dict "r" (coalesce nil)) | toJson -}} +{{- break -}} +{{- end -}} +{{- $services := (coalesce nil) -}} +{{- $bootstrap := (mustMergeOverwrite (dict "metadata" (dict) "spec" (dict) "status" (dict "loadBalancer" (dict))) (mustMergeOverwrite (dict) (dict "apiVersion" "v1" "kind" "Service")) (dict "metadata" (mustMergeOverwrite (dict) (dict "name" (printf "%s-gateway-bootstrap" (get (fromJson (include "redpanda.Fullname" (dict "a" (list $state)))) "r")) "namespace" $state.Release.Namespace "labels" $labels)) "spec" (mustMergeOverwrite (dict) (dict "ports" $ports "publishNotReadyAddresses" true "selector" $selector "sessionAffinity" "None" "type" "ClusterIP")))) -}} +{{- $services = (concat (default (list) $services) (list $bootstrap)) -}} +{{- $pods := (get (fromJson (include "redpanda.PodNames" (dict "a" (list $state (mustMergeOverwrite (dict "Name" "" "Generation" "" "Statefulset" (dict "additionalSelectorLabels" (coalesce nil) "replicas" 0 "updateStrategy" (dict) "additionalRedpandaCmdFlags" (coalesce nil) "podTemplate" (dict) "budget" (dict "maxUnavailable" 0) "podAntiAffinity" (dict "topologyKey" "" "type" "" "weight" 0 "custom" (coalesce nil)) "sideCars" (dict "image" (dict "repository" "" "tag" "") "args" (coalesce nil) "pvcUnbinder" (dict "enabled" false "unbindAfter" "") "brokerDecommissioner" (dict "enabled" false "decommissionAfter" "" "decommissionRequeueTimeout" "") "configWatcher" (dict "enabled" false) "controllers" (dict "image" (coalesce nil) "enabled" false "createRBAC" false "healthProbeAddress" "" "metricsAddress" "" "pprofAddress" "" "run" (coalesce nil))) "initContainers" (dict "fsValidator" (dict "enabled" false "expectedFS" "") "setDataDirOwnership" (dict "enabled" false) "configurator" (dict)) "initContainerImage" (dict "repository" "" "tag" "")) "ServiceAnnotations" (coalesce nil)) (dict "Statefulset" $state.Values.statefulset)))))) "r") -}} +{{- range $_, $set := $state.Pools -}} +{{- $pods = (concat (default (list) $pods) (default (list) (get (fromJson (include "redpanda.PodNames" (dict "a" (list $state $set)))) "r"))) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $_, $podname := $pods -}} +{{- $podSelector := (dict) -}} +{{- range $k, $v := $selector -}} +{{- $_ := (set $podSelector $k $v) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- $_ := (set $podSelector "statefulset.kubernetes.io/pod-name" $podname) -}} +{{- $svc := (mustMergeOverwrite (dict "metadata" (dict) "spec" (dict) "status" (dict "loadBalancer" (dict))) (mustMergeOverwrite (dict) (dict "apiVersion" "v1" "kind" "Service")) (dict "metadata" (mustMergeOverwrite (dict) (dict "name" (printf "gw-%s" $podname) "namespace" $state.Release.Namespace "labels" $labels)) "spec" (mustMergeOverwrite (dict) (dict "ports" $ports "publishNotReadyAddresses" true "selector" $podSelector "sessionAffinity" "None" "type" "ClusterIP")))) -}} +{{- $services = (concat (default (list) $services) (list $svc)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- $_is_returning = true -}} +{{- (dict "r" $services) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + +{{- define "redpanda.gatewayServicePorts" -}} +{{- $state := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $ports := (coalesce nil) -}} +{{- range $name, $listener := $state.Values.listeners.admin.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $ports = (concat (default (list) $ports) (list (mustMergeOverwrite (dict "port" 0 "targetPort" 0) (dict "name" (printf "admin-%s" $name) "protocol" "TCP" "port" ($listener.port | int))))) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $name, $listener := $state.Values.listeners.kafka.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $ports = (concat (default (list) $ports) (list (mustMergeOverwrite (dict "port" 0 "targetPort" 0) (dict "name" (printf "kafka-%s" $name) "protocol" "TCP" "port" ($listener.port | int))))) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $name, $listener := $state.Values.listeners.http.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $ports = (concat (default (list) $ports) (list (mustMergeOverwrite (dict "port" 0 "targetPort" 0) (dict "name" (printf "http-%s" $name) "protocol" "TCP" "port" ($listener.port | int))))) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $name, $listener := $state.Values.listeners.schemaRegistry.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $ports = (concat (default (list) $ports) (list (mustMergeOverwrite (dict "port" 0 "targetPort" 0) (dict "name" (printf "schema-%s" $name) "protocol" "TCP" "port" ($listener.port | int))))) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- $_is_returning = true -}} +{{- (dict "r" $ports) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + diff --git a/charts/redpanda/chart/templates/_service.nodeport.go.tpl b/charts/redpanda/chart/templates/_service.nodeport.go.tpl index c32c971bd..33e055614 100644 --- a/charts/redpanda/chart/templates/_service.nodeport.go.tpl +++ b/charts/redpanda/chart/templates/_service.nodeport.go.tpl @@ -15,11 +15,15 @@ {{- (dict "r" (coalesce nil)) | toJson -}} {{- break -}} {{- end -}} +{{- $gwEnabled := (get (fromJson (include "redpanda.ExternalConfig.IsGatewayEnabled" (dict "a" (list $state.Values.external)))) "r") -}} {{- $ports := (coalesce nil) -}} {{- range $name, $listener := $state.Values.listeners.admin.external -}} {{- if (not (get (fromJson (include "redpanda.ExternalListener.IsEnabled" (dict "a" (list $listener)))) "r")) -}} {{- continue -}} {{- end -}} +{{- if (and $gwEnabled (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r")) -}} +{{- continue -}} +{{- end -}} {{- $nodePort := ($listener.port | int) -}} {{- if (gt ((get (fromJson (include "_shims.len" (dict "a" (list $listener.advertisedPorts)))) "r") | int) (0 | int)) -}} {{- $nodePort = (index $listener.advertisedPorts (0 | int)) -}} @@ -33,6 +37,9 @@ {{- if (not (get (fromJson (include "redpanda.ExternalListener.IsEnabled" (dict "a" (list $listener)))) "r")) -}} {{- continue -}} {{- end -}} +{{- if (and $gwEnabled (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r")) -}} +{{- continue -}} +{{- end -}} {{- $nodePort := ($listener.port | int) -}} {{- if (gt ((get (fromJson (include "_shims.len" (dict "a" (list $listener.advertisedPorts)))) "r") | int) (0 | int)) -}} {{- $nodePort = (index $listener.advertisedPorts (0 | int)) -}} @@ -46,6 +53,9 @@ {{- if (not (get (fromJson (include "redpanda.ExternalListener.IsEnabled" (dict "a" (list $listener)))) "r")) -}} {{- continue -}} {{- end -}} +{{- if (and $gwEnabled (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r")) -}} +{{- continue -}} +{{- end -}} {{- $nodePort := ($listener.port | int) -}} {{- if (gt ((get (fromJson (include "_shims.len" (dict "a" (list $listener.advertisedPorts)))) "r") | int) (0 | int)) -}} {{- $nodePort = (index $listener.advertisedPorts (0 | int)) -}} @@ -59,6 +69,9 @@ {{- if (not (get (fromJson (include "redpanda.ExternalListener.IsEnabled" (dict "a" (list $listener)))) "r")) -}} {{- continue -}} {{- end -}} +{{- if (and $gwEnabled (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r")) -}} +{{- continue -}} +{{- end -}} {{- $nodePort := ($listener.port | int) -}} {{- if (gt ((get (fromJson (include "_shims.len" (dict "a" (list $listener.advertisedPorts)))) "r") | int) (0 | int)) -}} {{- $nodePort = (index $listener.advertisedPorts (0 | int)) -}} @@ -68,6 +81,11 @@ {{- if $_is_returning -}} {{- break -}} {{- end -}} +{{- if (eq ((get (fromJson (include "_shims.len" (dict "a" (list $ports)))) "r") | int) (0 | int)) -}} +{{- $_is_returning = true -}} +{{- (dict "r" (coalesce nil)) | toJson -}} +{{- break -}} +{{- end -}} {{- $annotations := $state.Values.external.annotations -}} {{- if (eq (toJson $annotations) "null") -}} {{- $annotations = (dict) -}} diff --git a/charts/redpanda/chart/templates/_tlsroute.go.tpl b/charts/redpanda/chart/templates/_tlsroute.go.tpl new file mode 100644 index 000000000..161cd7c4a --- /dev/null +++ b/charts/redpanda/chart/templates/_tlsroute.go.tpl @@ -0,0 +1,144 @@ +{{- /* GENERATED FILE DO NOT EDIT */ -}} +{{- /* Transpiled by gotohelm from "github.com/redpanda-data/redpanda-operator/charts/redpanda/v25/tlsroute.go" */ -}} + +{{- define "redpanda.TLSRoutes" -}} +{{- $state := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- if (not (get (fromJson (include "redpanda.ExternalConfig.IsGatewayEnabled" (dict "a" (list $state.Values.external)))) "r")) -}} +{{- $_is_returning = true -}} +{{- (dict "r" (coalesce nil)) | toJson -}} +{{- break -}} +{{- end -}} +{{- $gw := $state.Values.external.gateway -}} +{{- $parentRefs := (get (fromJson (include "redpanda.toTLSRouteParentRefs" (dict "a" (list $gw.parentRefs)))) "r") -}} +{{- $labels := (get (fromJson (include "redpanda.FullLabels" (dict "a" (list $state)))) "r") -}} +{{- $fullname := (get (fromJson (include "redpanda.Fullname" (dict "a" (list $state)))) "r") -}} +{{- $pods := (get (fromJson (include "redpanda.PodNames" (dict "a" (list $state (mustMergeOverwrite (dict "Name" "" "Generation" "" "Statefulset" (dict "additionalSelectorLabels" (coalesce nil) "replicas" 0 "updateStrategy" (dict) "additionalRedpandaCmdFlags" (coalesce nil) "podTemplate" (dict) "budget" (dict "maxUnavailable" 0) "podAntiAffinity" (dict "topologyKey" "" "type" "" "weight" 0 "custom" (coalesce nil)) "sideCars" (dict "image" (dict "repository" "" "tag" "") "args" (coalesce nil) "pvcUnbinder" (dict "enabled" false "unbindAfter" "") "brokerDecommissioner" (dict "enabled" false "decommissionAfter" "" "decommissionRequeueTimeout" "") "configWatcher" (dict "enabled" false) "controllers" (dict "image" (coalesce nil) "enabled" false "createRBAC" false "healthProbeAddress" "" "metricsAddress" "" "pprofAddress" "" "run" (coalesce nil))) "initContainers" (dict "fsValidator" (dict "enabled" false "expectedFS" "") "setDataDirOwnership" (dict "enabled" false) "configurator" (dict)) "initContainerImage" (dict "repository" "" "tag" "")) "ServiceAnnotations" (coalesce nil)) (dict "Statefulset" $state.Values.statefulset)))))) "r") -}} +{{- range $_, $set := $state.Pools -}} +{{- $pods = (concat (default (list) $pods) (default (list) (get (fromJson (include "redpanda.PodNames" (dict "a" (list $state $set)))) "r"))) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- $routes := (coalesce nil) -}} +{{- range $name, $listener := $state.Values.listeners.kafka.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $rs := (get (fromJson (include "redpanda.tlsRoutesForListener" (dict "a" (list $fullname $state.Release.Namespace $labels $parentRefs $pods (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.host "")))) "r") (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.hostTemplate "")))) "r") $name "kafka" ($listener.port | int))))) "r") -}} +{{- $routes = (concat (default (list) $routes) (default (list) $rs)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $name, $listener := $state.Values.listeners.http.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $rs := (get (fromJson (include "redpanda.tlsRoutesForListener" (dict "a" (list $fullname $state.Release.Namespace $labels $parentRefs $pods (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.host "")))) "r") (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.hostTemplate "")))) "r") $name "http" ($listener.port | int))))) "r") -}} +{{- $routes = (concat (default (list) $routes) (default (list) $rs)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $name, $listener := $state.Values.listeners.admin.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $rs := (get (fromJson (include "redpanda.tlsRoutesForListener" (dict "a" (list $fullname $state.Release.Namespace $labels $parentRefs $pods (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.host "")))) "r") (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.hostTemplate "")))) "r") $name "admin" ($listener.port | int))))) "r") -}} +{{- $routes = (concat (default (list) $routes) (default (list) $rs)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- range $name, $listener := $state.Values.listeners.schemaRegistry.external -}} +{{- if (or (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $state.Values.external.enabled)))) "r")) (not (get (fromJson (include "redpanda.ExternalListener.IsGatewayListener" (dict "a" (list $listener)))) "r"))) -}} +{{- continue -}} +{{- end -}} +{{- $rs := (get (fromJson (include "redpanda.tlsRoutesForListener" (dict "a" (list $fullname $state.Release.Namespace $labels $parentRefs $pods (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.host "")))) "r") (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.hostTemplate "")))) "r") $name "schema" ($listener.port | int))))) "r") -}} +{{- $routes = (concat (default (list) $routes) (default (list) $rs)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- $_is_returning = true -}} +{{- (dict "r" $routes) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + +{{- define "redpanda.tlsRoutesForListener" -}} +{{- $fullname := (index .a 0) -}} +{{- $namespace := (index .a 1) -}} +{{- $labels := (index .a 2) -}} +{{- $parentRefs := (index .a 3) -}} +{{- $pods := (index .a 4) -}} +{{- $host := (index .a 5) -}} +{{- $hostTemplate := (index .a 6) -}} +{{- $name := (index .a 7) -}} +{{- $listenerTag := (index .a 8) -}} +{{- $port := (index .a 9) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $routes := (coalesce nil) -}} +{{- if (eq $host "") -}} +{{- $_ := (fail (printf "gateway listener %s/%s requires host" $listenerTag $name)) -}} +{{- end -}} +{{- if (and (and (eq $listenerTag "kafka") (gt ((get (fromJson (include "_shims.len" (dict "a" (list $pods)))) "r") | int) (1 | int))) (eq $hostTemplate "")) -}} +{{- $_ := (fail (printf "gateway listener %s/%s requires hostTemplate when replicas > 1" $listenerTag $name)) -}} +{{- end -}} +{{- $bootstrapSvcName := (printf "%s-gateway-bootstrap" $fullname) -}} +{{- $bootstrap := (mustMergeOverwrite (dict "metadata" (dict) "spec" (dict "parentRefs" (coalesce nil) "rules" (coalesce nil))) (mustMergeOverwrite (dict) (dict "apiVersion" "gateway.networking.k8s.io/v1alpha2" "kind" "TLSRoute")) (dict "metadata" (mustMergeOverwrite (dict) (dict "name" (printf "%s-%s-%s-bootstrap" $fullname $listenerTag $name) "namespace" $namespace "labels" $labels)) "spec" (mustMergeOverwrite (dict "parentRefs" (coalesce nil) "rules" (coalesce nil)) (dict "parentRefs" $parentRefs "hostnames" (list $host) "rules" (list (mustMergeOverwrite (dict) (dict "backendRefs" (list (mustMergeOverwrite (dict "name" "" "port" 0) (dict "name" $bootstrapSvcName "port" $port)))))))))) -}} +{{- $routes = (concat (default (list) $routes) (list $bootstrap)) -}} +{{- if (eq $hostTemplate "") -}} +{{- $_is_returning = true -}} +{{- (dict "r" $routes) | toJson -}} +{{- break -}} +{{- end -}} +{{- range $i, $podname := $pods -}} +{{- $brokerHost := (get (fromJson (include "redpanda.renderBrokerHost" (dict "a" (list $hostTemplate $i $podname)))) "r") -}} +{{- $brokerSvcName := (printf "gw-%s" $podname) -}} +{{- $route := (mustMergeOverwrite (dict "metadata" (dict) "spec" (dict "parentRefs" (coalesce nil) "rules" (coalesce nil))) (mustMergeOverwrite (dict) (dict "apiVersion" "gateway.networking.k8s.io/v1alpha2" "kind" "TLSRoute")) (dict "metadata" (mustMergeOverwrite (dict) (dict "name" (printf "%s-%s-%s-%d" $fullname $listenerTag $name $i) "namespace" $namespace "labels" $labels)) "spec" (mustMergeOverwrite (dict "parentRefs" (coalesce nil) "rules" (coalesce nil)) (dict "parentRefs" $parentRefs "hostnames" (list $brokerHost) "rules" (list (mustMergeOverwrite (dict) (dict "backendRefs" (list (mustMergeOverwrite (dict "name" "" "port" 0) (dict "name" $brokerSvcName "port" $port)))))))))) -}} +{{- $routes = (concat (default (list) $routes) (list $route)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- $_is_returning = true -}} +{{- (dict "r" $routes) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + +{{- define "redpanda.toTLSRouteParentRefs" -}} +{{- $refs := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $parentRefs := (coalesce nil) -}} +{{- range $_, $ref := $refs -}} +{{- $parentRefs = (concat (default (list) $parentRefs) (list $ref)) -}} +{{- end -}} +{{- if $_is_returning -}} +{{- break -}} +{{- end -}} +{{- $_is_returning = true -}} +{{- (dict "r" $parentRefs) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + +{{- define "redpanda.renderBrokerHost" -}} +{{- $tmpl := (index .a 0) -}} +{{- $ordinal := (index .a 1) -}} +{{- $podName := (index .a 2) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $result := (replace "$POD_ORDINAL" (printf "%d" $ordinal) $tmpl) -}} +{{- $result = (replace "$POD_NAME" $podName $result) -}} +{{- $_is_returning = true -}} +{{- (dict "r" $result) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + diff --git a/charts/redpanda/chart/templates/_values.go.tpl b/charts/redpanda/chart/templates/_values.go.tpl index 818f2a1a6..1d3de80ff 100644 --- a/charts/redpanda/chart/templates/_values.go.tpl +++ b/charts/redpanda/chart/templates/_values.go.tpl @@ -88,6 +88,31 @@ {{- end -}} {{- end -}} +{{- define "redpanda.ExternalConfig.IsGatewayEnabled" -}} +{{- $e := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $_is_returning = true -}} +{{- (dict "r" (and (and (and $e.enabled (ne (toJson $e.gateway) "null")) $e.gateway.enabled) (gt ((get (fromJson (include "_shims.len" (dict "a" (list $e.gateway.parentRefs)))) "r") | int) (0 | int)))) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + +{{- define "redpanda.GatewayConfig.GatewayAdvertisedPort" -}} +{{- $g := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- if (ne (toJson $g.advertisedPort) "null") -}} +{{- $_is_returning = true -}} +{{- (dict "r" $g.advertisedPort) | toJson -}} +{{- break -}} +{{- end -}} +{{- $_is_returning = true -}} +{{- (dict "r" (443 | int)) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + {{- define "redpanda.Logging.Translate" -}} {{- $l := (index .a 0) -}} {{- range $_ := (list 1) -}} @@ -152,13 +177,13 @@ {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} {{- if (and (ne (toJson $rr.limits) "null") (ne (toJson $rr.requests) "null")) -}} -{{- $_436_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.requests) "cpu" "0")))) "r") -}} -{{- $cpuReq := (index $_436_cpuReq_ok 0) -}} -{{- $ok := (index $_436_cpuReq_ok 1) -}} +{{- $_491_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.requests) "cpu" "0")))) "r") -}} +{{- $cpuReq := (index $_491_cpuReq_ok 0) -}} +{{- $ok := (index $_491_cpuReq_ok 1) -}} {{- if (not $ok) -}} -{{- $_438_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.limits) "cpu" "0")))) "r") -}} -{{- $cpuReq = (index $_438_cpuReq_ok 0) -}} -{{- $ok = (index $_438_cpuReq_ok 1) -}} +{{- $_493_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.limits) "cpu" "0")))) "r") -}} +{{- $cpuReq = (index $_493_cpuReq_ok 0) -}} +{{- $ok = (index $_493_cpuReq_ok 1) -}} {{- end -}} {{- if (and $ok (lt ((get (fromJson (include "_shims.resource_MilliValue" (dict "a" (list $cpuReq)))) "r") | int64) (1000 | int64))) -}} {{- $_is_returning = true -}} @@ -185,13 +210,13 @@ {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} {{- if (and (ne (toJson $rr.limits) "null") (ne (toJson $rr.requests) "null")) -}} -{{- $_462_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.requests) "cpu" "0")))) "r") -}} -{{- $cpuReq := (index $_462_cpuReq_ok 0) -}} -{{- $ok := (index $_462_cpuReq_ok 1) -}} +{{- $_517_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.requests) "cpu" "0")))) "r") -}} +{{- $cpuReq := (index $_517_cpuReq_ok 0) -}} +{{- $ok := (index $_517_cpuReq_ok 1) -}} {{- if (not $ok) -}} -{{- $_464_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.limits) "cpu" "0")))) "r") -}} -{{- $cpuReq = (index $_464_cpuReq_ok 0) -}} -{{- $ok = (index $_464_cpuReq_ok 1) -}} +{{- $_519_cpuReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.limits) "cpu" "0")))) "r") -}} +{{- $cpuReq = (index $_519_cpuReq_ok 0) -}} +{{- $ok = (index $_519_cpuReq_ok 1) -}} {{- end -}} {{- if (not $ok) -}} {{- $_is_returning = true -}} @@ -223,13 +248,13 @@ {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} {{- if (and (ne (toJson $rr.limits) "null") (ne (toJson $rr.requests) "null")) -}} -{{- $_521_memReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.requests) "memory" "0")))) "r") -}} -{{- $memReq := (index $_521_memReq_ok 0) -}} -{{- $ok := (index $_521_memReq_ok 1) -}} +{{- $_576_memReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.requests) "memory" "0")))) "r") -}} +{{- $memReq := (index $_576_memReq_ok 0) -}} +{{- $ok := (index $_576_memReq_ok 1) -}} {{- if (not $ok) -}} -{{- $_523_memReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.limits) "memory" "0")))) "r") -}} -{{- $memReq = (index $_523_memReq_ok 0) -}} -{{- $ok = (index $_523_memReq_ok 1) -}} +{{- $_578_memReq_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list ($rr.limits) "memory" "0")))) "r") -}} +{{- $memReq = (index $_578_memReq_ok 0) -}} +{{- $ok = (index $_578_memReq_ok 1) -}} {{- end -}} {{- if (not $ok) -}} {{- $_is_returning = true -}} @@ -305,9 +330,9 @@ {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} {{- $conf := (get (fromJson (include "redpanda.Storage.GetTieredStorageConfig" (dict "a" (list $s)))) "r") -}} -{{- $_641_b_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list $conf "cloud_storage_enabled" (coalesce nil))))) "r") -}} -{{- $b := (index $_641_b_ok 0) -}} -{{- $ok := (index $_641_b_ok 1) -}} +{{- $_696_b_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list $conf "cloud_storage_enabled" (coalesce nil))))) "r") -}} +{{- $b := (index $_696_b_ok 0) -}} +{{- $ok := (index $_696_b_ok 1) -}} {{- $_is_returning = true -}} {{- (dict "r" (and $ok (get (fromJson (include "_shims.typeassertion" (dict "a" (list "bool" $b)))) "r"))) | toJson -}} {{- break -}} @@ -351,18 +376,18 @@ {{- $state := (index .a 1) -}} {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} -{{- $_669_dir_7_ok_8 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $state.Values.config.node "cloud_storage_cache_directory") "")))) "r") -}} -{{- $dir_7 := (index $_669_dir_7_ok_8 0) -}} -{{- $ok_8 := (index $_669_dir_7_ok_8 1) -}} +{{- $_724_dir_7_ok_8 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $state.Values.config.node "cloud_storage_cache_directory") "")))) "r") -}} +{{- $dir_7 := (index $_724_dir_7_ok_8 0) -}} +{{- $ok_8 := (index $_724_dir_7_ok_8 1) -}} {{- if $ok_8 -}} {{- $_is_returning = true -}} {{- (dict "r" $dir_7) | toJson -}} {{- break -}} {{- end -}} {{- $tieredConfig := (get (fromJson (include "redpanda.Storage.GetTieredStorageConfig" (dict "a" (list $state.Values.storage)))) "r") -}} -{{- $_678_dir_9_ok_10 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $tieredConfig "cloud_storage_cache_directory") "")))) "r") -}} -{{- $dir_9 := (index $_678_dir_9_ok_10 0) -}} -{{- $ok_10 := (index $_678_dir_9_ok_10 1) -}} +{{- $_733_dir_9_ok_10 := (get (fromJson (include "_shims.typetest" (dict "a" (list "string" (index $tieredConfig "cloud_storage_cache_directory") "")))) "r") -}} +{{- $dir_9 := (index $_733_dir_9_ok_10 0) -}} +{{- $ok_10 := (index $_733_dir_9_ok_10 1) -}} {{- if $ok_10 -}} {{- $_is_returning = true -}} {{- (dict "r" $dir_9) | toJson -}} @@ -477,9 +502,9 @@ {{- $result := (dict) -}} {{- $s := (toJson $t) -}} {{- $tune := (fromJson $s) -}} -{{- $_838_m_ok := (get (fromJson (include "_shims.typetest" (dict "a" (list (printf "map[%s]%s" "string" "interface {}") $tune (coalesce nil))))) "r") -}} -{{- $m := (index $_838_m_ok 0) -}} -{{- $ok := (index $_838_m_ok 1) -}} +{{- $_893_m_ok := (get (fromJson (include "_shims.typetest" (dict "a" (list (printf "map[%s]%s" "string" "interface {}") $tune (coalesce nil))))) "r") -}} +{{- $m := (index $_893_m_ok 0) -}} +{{- $ok := (index $_893_m_ok 1) -}} {{- if (not $ok) -}} {{- $_is_returning = true -}} {{- (dict "r" (dict)) | toJson -}} @@ -626,9 +651,9 @@ {{- $seen := (dict) -}} {{- $deduped := (coalesce nil) -}} {{- range $_, $item := $items -}} -{{- $_1027___ok_11 := (get (fromJson (include "_shims.dicttest" (dict "a" (list $seen $item.key false)))) "r") -}} -{{- $_ := (index $_1027___ok_11 0) -}} -{{- $ok_11 := (index $_1027___ok_11 1) -}} +{{- $_1082___ok_11 := (get (fromJson (include "_shims.dicttest" (dict "a" (list $seen $item.key false)))) "r") -}} +{{- $_ := (index $_1082___ok_11 0) -}} +{{- $ok_11 := (index $_1082___ok_11 1) -}} {{- if $ok_11 -}} {{- continue -}} {{- end -}} @@ -851,9 +876,9 @@ {{- $name := (index .a 1) -}} {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} -{{- $_1315_cert_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list $m $name (dict "enabled" (coalesce nil) "caEnabled" false "applyInternalDNSNames" (coalesce nil) "duration" "" "issuerRef" (coalesce nil) "secretRef" (coalesce nil) "clientSecretRef" (coalesce nil)))))) "r") -}} -{{- $cert := (index $_1315_cert_ok 0) -}} -{{- $ok := (index $_1315_cert_ok 1) -}} +{{- $_1370_cert_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list $m $name (dict "enabled" (coalesce nil) "caEnabled" false "applyInternalDNSNames" (coalesce nil) "duration" "" "issuerRef" (coalesce nil) "secretRef" (coalesce nil) "clientSecretRef" (coalesce nil)))))) "r") -}} +{{- $cert := (index $_1370_cert_ok 0) -}} +{{- $ok := (index $_1370_cert_ok 1) -}} {{- if (not $ok) -}} {{- $_ := (fail (printf "Certificate %q referenced, but not found in the tls.certs map" $name)) -}} {{- end -}} @@ -1180,6 +1205,9 @@ {{- if (not (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.enabled $external.enabled)))) "r")) -}} {{- continue -}} {{- end -}} +{{- if (and (get (fromJson (include "redpanda.ExternalConfig.IsGatewayEnabled" (dict "a" (list $external)))) "r") (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.gateway false)))) "r")) -}} +{{- continue -}} +{{- end -}} {{- $fallbackPorts := (concat (default (list) $listener.advertisedPorts) (list ($l.port | int))) -}} {{- $ports = (concat (default (list) $ports) (list (mustMergeOverwrite (dict "port" 0 "targetPort" 0) (dict "name" (printf "%s-%s" $namePrefix $name) "protocol" "TCP" "appProtocol" $l.appProtocol "targetPort" ($listener.port | int) "port" ((get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $listener.nodePort (index $fallbackPorts (0 | int)))))) "r") | int))))) -}} {{- end -}} @@ -1286,7 +1314,7 @@ {{- $auth = $authAStr -}} {{- end -}} {{- $_is_returning = true -}} -{{- (dict "r" (mustMergeOverwrite (dict "enabled" (coalesce nil) "advertisedPorts" (coalesce nil) "port" 0 "nodePort" (coalesce nil) "tls" (coalesce nil)) (dict "enabled" $l.enabled "advertisedPorts" $l.advertisedPorts "port" ($l.port | int) "nodePort" $l.nodePort "tls" $l.tls "authenticationMethod" $auth "prefixTemplate" $l.prefixTemplate))) | toJson -}} +{{- (dict "r" (mustMergeOverwrite (dict "enabled" (coalesce nil) "advertisedPorts" (coalesce nil) "port" 0 "nodePort" (coalesce nil) "tls" (coalesce nil)) (dict "enabled" $l.enabled "advertisedPorts" $l.advertisedPorts "port" ($l.port | int) "nodePort" $l.nodePort "tls" $l.tls "authenticationMethod" $auth "prefixTemplate" $l.prefixTemplate "gateway" $l.gateway "host" $l.host "hostTemplate" $l.hostTemplate))) | toJson -}} {{- break -}} {{- end -}} {{- end -}} @@ -1301,6 +1329,16 @@ {{- end -}} {{- end -}} +{{- define "redpanda.ExternalListener.IsGatewayListener" -}} +{{- $l := (index .a 0) -}} +{{- range $_ := (list 1) -}} +{{- $_is_returning := false -}} +{{- $_is_returning = true -}} +{{- (dict "r" (get (fromJson (include "_shims.ptr_Deref" (dict "a" (list $l.gateway false)))) "r")) | toJson -}} +{{- break -}} +{{- end -}} +{{- end -}} + {{- define "redpanda.TunableConfig.Translate" -}} {{- $c := (index .a 0) -}} {{- range $_ := (list 1) -}} @@ -1332,9 +1370,9 @@ {{- $result := (dict) -}} {{- range $k, $v := $c -}} {{- if (not (empty $v)) -}} -{{- $_1845___ok_15 := (get (fromJson (include "_shims.asnumeric" (dict "a" (list $v)))) "r") -}} -{{- $_ := ((index $_1845___ok_15 0) | float64) -}} -{{- $ok_15 := (index $_1845___ok_15 1) -}} +{{- $_1928___ok_15 := (get (fromJson (include "_shims.asnumeric" (dict "a" (list $v)))) "r") -}} +{{- $_ := ((index $_1928___ok_15 0) | float64) -}} +{{- $ok_15 := (index $_1928___ok_15 1) -}} {{- if $ok_15 -}} {{- $_ := (set $result $k $v) -}} {{- else -}}{{- if (kindIs "bool" $v) -}} @@ -1360,9 +1398,9 @@ {{- $_is_returning := false -}} {{- $result := (dict) -}} {{- range $k, $v := $c -}} -{{- $_1865_b_16_ok_17 := (get (fromJson (include "_shims.typetest" (dict "a" (list "bool" $v false)))) "r") -}} -{{- $b_16 := (index $_1865_b_16_ok_17 0) -}} -{{- $ok_17 := (index $_1865_b_16_ok_17 1) -}} +{{- $_1948_b_16_ok_17 := (get (fromJson (include "_shims.typetest" (dict "a" (list "bool" $v false)))) "r") -}} +{{- $b_16 := (index $_1948_b_16_ok_17 0) -}} +{{- $ok_17 := (index $_1948_b_16_ok_17 1) -}} {{- if $ok_17 -}} {{- $_ := (set $result $k $b_16) -}} {{- continue -}} @@ -1405,15 +1443,15 @@ {{- $config := (index .a 1) -}} {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} -{{- $_1910___hasAccessKey := (get (fromJson (include "_shims.dicttest" (dict "a" (list $config "cloud_storage_access_key" (coalesce nil))))) "r") -}} -{{- $_ := (index $_1910___hasAccessKey 0) -}} -{{- $hasAccessKey := (index $_1910___hasAccessKey 1) -}} -{{- $_1911___hasSecretKey := (get (fromJson (include "_shims.dicttest" (dict "a" (list $config "cloud_storage_secret_key" (coalesce nil))))) "r") -}} -{{- $_ := (index $_1911___hasSecretKey 0) -}} -{{- $hasSecretKey := (index $_1911___hasSecretKey 1) -}} -{{- $_1912___hasSharedKey := (get (fromJson (include "_shims.dicttest" (dict "a" (list $config "cloud_storage_azure_shared_key" (coalesce nil))))) "r") -}} -{{- $_ := (index $_1912___hasSharedKey 0) -}} -{{- $hasSharedKey := (index $_1912___hasSharedKey 1) -}} +{{- $_1993___hasAccessKey := (get (fromJson (include "_shims.dicttest" (dict "a" (list $config "cloud_storage_access_key" (coalesce nil))))) "r") -}} +{{- $_ := (index $_1993___hasAccessKey 0) -}} +{{- $hasAccessKey := (index $_1993___hasAccessKey 1) -}} +{{- $_1994___hasSecretKey := (get (fromJson (include "_shims.dicttest" (dict "a" (list $config "cloud_storage_secret_key" (coalesce nil))))) "r") -}} +{{- $_ := (index $_1994___hasSecretKey 0) -}} +{{- $hasSecretKey := (index $_1994___hasSecretKey 1) -}} +{{- $_1995___hasSharedKey := (get (fromJson (include "_shims.dicttest" (dict "a" (list $config "cloud_storage_azure_shared_key" (coalesce nil))))) "r") -}} +{{- $_ := (index $_1995___hasSharedKey 0) -}} +{{- $hasSharedKey := (index $_1995___hasSharedKey 1) -}} {{- $envvars := (coalesce nil) -}} {{- if (and (not $hasAccessKey) (get (fromJson (include "redpanda.SecretRef.IsValid" (dict "a" (list $tsc.accessKey)))) "r")) -}} {{- $envvars = (concat (default (list) $envvars) (list (mustMergeOverwrite (dict "name" "") (dict "name" "REDPANDA_CLOUD_STORAGE_ACCESS_KEY" "valueFrom" (get (fromJson (include "redpanda.SecretRef.AsSource" (dict "a" (list $tsc.accessKey)))) "r"))))) -}} @@ -1436,12 +1474,12 @@ {{- $c := (index .a 0) -}} {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} -{{- $_1948___containerExists := (get (fromJson (include "_shims.dicttest" (dict "a" (list $c "cloud_storage_azure_container" (coalesce nil))))) "r") -}} -{{- $_ := (index $_1948___containerExists 0) -}} -{{- $containerExists := (index $_1948___containerExists 1) -}} -{{- $_1949___accountExists := (get (fromJson (include "_shims.dicttest" (dict "a" (list $c "cloud_storage_azure_storage_account" (coalesce nil))))) "r") -}} -{{- $_ := (index $_1949___accountExists 0) -}} -{{- $accountExists := (index $_1949___accountExists 1) -}} +{{- $_2031___containerExists := (get (fromJson (include "_shims.dicttest" (dict "a" (list $c "cloud_storage_azure_container" (coalesce nil))))) "r") -}} +{{- $_ := (index $_2031___containerExists 0) -}} +{{- $containerExists := (index $_2031___containerExists 1) -}} +{{- $_2032___accountExists := (get (fromJson (include "_shims.dicttest" (dict "a" (list $c "cloud_storage_azure_storage_account" (coalesce nil))))) "r") -}} +{{- $_ := (index $_2032___accountExists 0) -}} +{{- $accountExists := (index $_2032___accountExists 1) -}} {{- $_is_returning = true -}} {{- (dict "r" (and $containerExists $accountExists)) | toJson -}} {{- break -}} @@ -1452,9 +1490,9 @@ {{- $c := (index .a 0) -}} {{- range $_ := (list 1) -}} {{- $_is_returning := false -}} -{{- $_1954_value_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list $c `cloud_storage_cache_size` (coalesce nil))))) "r") -}} -{{- $value := (index $_1954_value_ok 0) -}} -{{- $ok := (index $_1954_value_ok 1) -}} +{{- $_2037_value_ok := (get (fromJson (include "_shims.dicttest" (dict "a" (list $c `cloud_storage_cache_size` (coalesce nil))))) "r") -}} +{{- $value := (index $_2037_value_ok 0) -}} +{{- $ok := (index $_2037_value_ok 1) -}} {{- if (not $ok) -}} {{- $_is_returning = true -}} {{- (dict "r" (coalesce nil)) | toJson -}} diff --git a/charts/redpanda/chart/values.schema.json b/charts/redpanda/chart/values.schema.json index 64e0b0ce1..f4437c868 100644 --- a/charts/redpanda/chart/values.schema.json +++ b/charts/redpanda/chart/values.schema.json @@ -4526,6 +4526,49 @@ ], "type": "object" }, + "gateway": { + "additionalProperties": false, + "properties": { + "advertisedPort": { + "type": "integer" + }, + "enabled": { + "type": "boolean" + }, + "parentRefs": { + "oneOf": [ + { + "items": { + "additionalProperties": false, + "properties": { + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "sectionName": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, "prefixTemplate": { "type": "string" }, @@ -4644,6 +4687,15 @@ "enabled": { "type": "boolean" }, + "gateway": { + "type": "boolean" + }, + "host": { + "type": "string" + }, + "hostTemplate": { + "type": "string" + }, "nodePort": { "type": "integer" }, @@ -4835,6 +4887,15 @@ "enabled": { "type": "boolean" }, + "gateway": { + "type": "boolean" + }, + "host": { + "type": "string" + }, + "hostTemplate": { + "type": "string" + }, "nodePort": { "type": "integer" }, @@ -5028,6 +5089,15 @@ "enabled": { "type": "boolean" }, + "gateway": { + "type": "boolean" + }, + "host": { + "type": "string" + }, + "hostTemplate": { + "type": "string" + }, "nodePort": { "type": "integer" }, @@ -5281,6 +5351,15 @@ "enabled": { "type": "boolean" }, + "gateway": { + "type": "boolean" + }, + "host": { + "type": "string" + }, + "hostTemplate": { + "type": "string" + }, "nodePort": { "type": "integer" }, diff --git a/charts/redpanda/gateway_advertise_test.go b/charts/redpanda/gateway_advertise_test.go new file mode 100644 index 000000000..52a3f4ef8 --- /dev/null +++ b/charts/redpanda/gateway_advertise_test.go @@ -0,0 +1,53 @@ +// Copyright 2026 Redpanda Data, Inc. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.md +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0 + +package redpanda + +import ( + "testing" + + "github.com/stretchr/testify/require" + "k8s.io/utils/ptr" + + "github.com/redpanda-data/redpanda-operator/gotohelm/helmette" +) + +func TestAdvertisedHostJSONGatewayUsesCurrentListenerConfig(t *testing.T) { + state := &RenderState{ + Release: &helmette.Release{ + Name: "redpanda", + Namespace: "default", + }, + Values: Values{ + External: ExternalConfig{ + Enabled: true, + Gateway: &GatewayConfig{ + Enabled: true, + AdvertisedPort: ptr.To[int32](8443), + ParentRefs: []GatewayParentRef{{Name: "shared-gateway"}}, + }, + }, + Statefulset: Statefulset{ + Replicas: 2, + }, + }, + } + + host := advertisedHostJSON( + state, + 8082, + 1, + "http.example.com", + "http-$POD_ORDINAL.example.com", + true, + ) + + require.Equal(t, "http-1.example.com", host["address"]) + require.Equal(t, int32(8443), host["port"]) +} diff --git a/charts/redpanda/secrets.go b/charts/redpanda/secrets.go index 5fababb8b..d203b54c0 100644 --- a/charts/redpanda/secrets.go +++ b/charts/redpanda/secrets.go @@ -398,7 +398,15 @@ func secretConfiguratorKafkaConfig(state *RenderState, sts Statefulset) []string } } - host := advertisedHostJSON(state, externalName, port, replicaIndex) + host := advertisedHostJSON( + state, + port, + replicaIndex, + ptr.Deref(externalVals.Host, ""), + ptr.Deref(externalVals.HostTemplate, ""), + externalVals.IsGatewayListener(), + ) + host["name"] = externalName // XXX: the original code used the stringified `host` value as a template // for re-expansion; however it was impossible to make this work usefully, /// even with the original yaml template. @@ -474,7 +482,15 @@ func secretConfiguratorHTTPConfig(state *RenderState, sts Statefulset) []string } } - host := advertisedHostJSON(state, externalName, port, replicaIndex) + host := advertisedHostJSON( + state, + port, + replicaIndex, + ptr.Deref(externalVals.Host, ""), + ptr.Deref(externalVals.HostTemplate, ""), + externalVals.IsGatewayListener(), + ) + host["name"] = externalName // XXX: the original code used the stringified `host` value as a template // for re-expansion; however it was impossible to make this work usefully, /// even with the original yaml template. @@ -537,9 +553,16 @@ func externalAdvertiseAddress(state *RenderState) string { } // was advertised-host -func advertisedHostJSON(state *RenderState, externalName string, port int32, replicaIndex int) map[string]any { - host := map[string]any{ - "name": externalName, +func advertisedHostJSON(state *RenderState, port int32, replicaIndex int, host string, hostTemplate string, isGateway bool) map[string]any { + // Gateway API mode: advertise the TLSRoute SNI hostname and the + // gateway's advertised port (default 443) rather than a NodePort/LB address. + // Only applies to listeners that opted into gateway mode. + if state.Values.External.IsGatewayEnabled() && isGateway { + return advertisedHostJSONGateway(state, replicaIndex, host, hostTemplate) + } + + hostMap := map[string]any{ + "name": "", "address": externalAdvertiseAddress(state), "port": port, } @@ -551,20 +574,51 @@ func advertisedHostJSON(state *RenderState, externalName string, port int32, rep address = state.Values.External.Addresses[0] } if domain := ptr.Deref(state.Values.External.Domain, ""); domain != "" { - host = map[string]any{ - "name": externalName, + hostMap = map[string]any{ + "name": "", "address": fmt.Sprintf("%s.%s", address, helmette.Tpl(state.Dot, domain, state.Dot)), "port": port, } } else { - host = map[string]any{ - "name": externalName, + hostMap = map[string]any{ + "name": "", "address": address, "port": port, } } } - return host + return hostMap +} + +// advertisedHostJSONGateway builds the advertised host entry for Gateway API +// mode. The address is the per-broker SNI hostname (from HostTemplate) and the +// port is the gateway's advertised port (default 443). +func advertisedHostJSONGateway(state *RenderState, replicaIndex int, host string, hostTemplate string) map[string]any { + gw := state.Values.External.Gateway + port := gw.GatewayAdvertisedPort() + + if hostTemplate == "" { + // Fallback: use the bootstrap host if no template is set. + hostTemplate = host + } + + pods := PodNames(state, Pool{Statefulset: state.Values.Statefulset}) + for _, set := range state.Pools { + pods = append(pods, PodNames(state, set)...) + } + + podName := "" + if replicaIndex < len(pods) { + podName = pods[replicaIndex] + } + + address := renderBrokerHost(hostTemplate, replicaIndex, podName) + + return map[string]any{ + "name": "", + "address": address, + "port": port, + } } // adminInternalHTTPProtocol was admin-http-protocol diff --git a/charts/redpanda/service.gateway.go b/charts/redpanda/service.gateway.go new file mode 100644 index 000000000..6ebf28ab6 --- /dev/null +++ b/charts/redpanda/service.gateway.go @@ -0,0 +1,151 @@ +// Copyright 2026 Redpanda Data, Inc. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.md +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0 + +// +gotohelm:filename=_service.gateway.go.tpl +package redpanda + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + + "github.com/redpanda-data/redpanda-operator/gotohelm/helmette" +) + +// GatewayServices returns ClusterIP Services for Gateway API TLSRoute-based +// external access: one bootstrap service (targeting all pods) and one +// per-broker service (targeting a specific pod via pod-name selector). +// TLSRoute resources reference these services as backends. +func GatewayServices(state *RenderState) []*corev1.Service { + if !state.Values.External.IsGatewayEnabled() { + return nil + } + + labels := FullLabels(state) + selector := ClusterPodLabelsSelector(state) + + // Collect external listener ports across all listener types. + ports := gatewayServicePorts(state) + if len(ports) == 0 { + return nil + } + + var services []*corev1.Service + + // Bootstrap service: targets all pods for initial client connection. + bootstrap := &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-gateway-bootstrap", Fullname(state)), + Namespace: state.Release.Namespace, + Labels: labels, + }, + Spec: corev1.ServiceSpec{ + Ports: ports, + PublishNotReadyAddresses: true, + Selector: selector, + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + } + services = append(services, bootstrap) + + // Per-broker services: one service per pod, selected by pod name. + pods := PodNames(state, Pool{Statefulset: state.Values.Statefulset}) + for _, set := range state.Pools { + pods = append(pods, PodNames(state, set)...) + } + + for _, podname := range pods { + podSelector := map[string]string{} + for k, v := range selector { + podSelector[k] = v + } + podSelector["statefulset.kubernetes.io/pod-name"] = podname + + svc := &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("gw-%s", podname), + Namespace: state.Release.Namespace, + Labels: labels, + }, + Spec: corev1.ServiceSpec{ + Ports: ports, + PublishNotReadyAddresses: true, + Selector: podSelector, + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + } + services = append(services, svc) + } + + return services +} + +// gatewayServicePorts collects external listener ports for Gateway ClusterIP +// services. These match the container ports that TLSRoutes will route to. +func gatewayServicePorts(state *RenderState) []corev1.ServicePort { + var ports []corev1.ServicePort + + for name, listener := range helmette.SortedMap(state.Values.Listeners.Admin.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + ports = append(ports, corev1.ServicePort{ + Name: fmt.Sprintf("admin-%s", name), + Protocol: corev1.ProtocolTCP, + Port: listener.Port, + }) + } + + for name, listener := range helmette.SortedMap(state.Values.Listeners.Kafka.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + ports = append(ports, corev1.ServicePort{ + Name: fmt.Sprintf("kafka-%s", name), + Protocol: corev1.ProtocolTCP, + Port: listener.Port, + }) + } + + for name, listener := range helmette.SortedMap(state.Values.Listeners.HTTP.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + ports = append(ports, corev1.ServicePort{ + Name: fmt.Sprintf("http-%s", name), + Protocol: corev1.ProtocolTCP, + Port: listener.Port, + }) + } + + for name, listener := range helmette.SortedMap(state.Values.Listeners.SchemaRegistry.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + ports = append(ports, corev1.ServicePort{ + Name: fmt.Sprintf("schema-%s", name), + Protocol: corev1.ProtocolTCP, + Port: listener.Port, + }) + } + + return ports +} diff --git a/charts/redpanda/service.nodeport.go b/charts/redpanda/service.nodeport.go index 612538ee4..550ec6d9c 100644 --- a/charts/redpanda/service.nodeport.go +++ b/charts/redpanda/service.nodeport.go @@ -28,11 +28,17 @@ func NodePortService(state *RenderState) *corev1.Service { return nil } + gwEnabled := state.Values.External.IsGatewayEnabled() + var ports []corev1.ServicePort for name, listener := range helmette.SortedMap(state.Values.Listeners.Admin.External) { if !listener.IsEnabled() { continue } + // Skip listeners that opted into Gateway API TLSRoute mode. + if gwEnabled && listener.IsGatewayListener() { + continue + } nodePort := listener.Port if len(listener.AdvertisedPorts) > 0 { @@ -51,6 +57,9 @@ func NodePortService(state *RenderState) *corev1.Service { if !listener.IsEnabled() { continue } + if gwEnabled && listener.IsGatewayListener() { + continue + } nodePort := listener.Port if len(listener.AdvertisedPorts) > 0 { @@ -69,6 +78,9 @@ func NodePortService(state *RenderState) *corev1.Service { if !listener.IsEnabled() { continue } + if gwEnabled && listener.IsGatewayListener() { + continue + } nodePort := listener.Port if len(listener.AdvertisedPorts) > 0 { @@ -87,6 +99,9 @@ func NodePortService(state *RenderState) *corev1.Service { if !listener.IsEnabled() { continue } + if gwEnabled && listener.IsGatewayListener() { + continue + } nodePort := listener.Port if len(listener.AdvertisedPorts) > 0 { @@ -101,6 +116,11 @@ func NodePortService(state *RenderState) *corev1.Service { }) } + // If all listeners opted into gateway mode, no NodePort service is needed. + if len(ports) == 0 { + return nil + } + annotations := state.Values.External.Annotations if annotations == nil { annotations = map[string]string{} diff --git a/charts/redpanda/testdata/template-cases.golden.txtar b/charts/redpanda/testdata/template-cases.golden.txtar index e97ce7546..bf618d9ac 100644 --- a/charts/redpanda/testdata/template-cases.golden.txtar +++ b/charts/redpanda/testdata/template-cases.golden.txtar @@ -106454,6 +106454,3295 @@ spec: # Source: redpanda/templates/entry-point.yaml apiVersion: batch/v1 kind: Job +metadata: + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-delete-policy: before-hook-creation + helm.sh/hook-weight: "-5" + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-configuration + namespace: default +spec: + template: + metadata: + annotations: {} + generateName: redpanda-post- + labels: + app.kubernetes.io/component: redpanda-post-install + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda-configuration + spec: + automountServiceAccountToken: false + containers: + - command: + - /redpanda-operator + - sync-cluster-config + - --users-directory + - /etc/secrets/users + - --redpanda-yaml + - /tmp/base-config/redpanda.yaml + - --bootstrap-yaml + - /tmp/config/.bootstrap.yaml + env: null + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: post-install + resources: {} + securityContext: {} + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /tmp/config + name: config + - mountPath: /tmp/base-config + name: base-config + imagePullSecrets: [] + initContainers: + - command: + - /redpanda-operator + - bootstrap + - --in-dir + - /tmp/base-config + - --out-dir + - /tmp/config + env: null + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: bootstrap-yaml-envsubst + resources: + limits: + cpu: 100m + memory: 125Mi + requests: + cpu: 100m + memory: 125Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /tmp/config/ + name: config + - mountPath: /tmp/base-config/ + name: base-config + nodeSelector: {} + restartPolicy: Never + securityContext: + fsGroup: 101 + fsGroupChangePolicy: OnRootMismatch + runAsUser: 101 + serviceAccountName: redpanda + tolerations: [] + volumes: + - name: redpanda-default-cert + secret: + defaultMode: 288 + secretName: redpanda-default-cert + - name: redpanda-external-cert + secret: + defaultMode: 288 + secretName: redpanda-external-cert + - configMap: + name: redpanda + name: base-config + - emptyDir: {} + name: config +-- testdata/TestTemplate/gateway-api-migration.yaml.golden -- +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +spec: + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + redpanda.com/poddisruptionbudget: redpanda +--- +# Source: redpanda/charts/console/templates/entry-point.yaml +apiVersion: v1 +automountServiceAccountToken: false +kind: ServiceAccount +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +automountServiceAccountToken: false +kind: ServiceAccount +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-sts-lifecycle + namespace: default +stringData: + common.sh: |- + #!/usr/bin/env bash + + # the SERVICE_NAME comes from the metadata.name of the pod, essentially the POD_NAME + CURL_URL="https://${SERVICE_NAME}.redpanda.default.svc.cluster.local:9644" + + # commands used throughout + CURL_NODE_ID_CMD="curl --silent --fail --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/node_config" + + CURL_MAINTENANCE_DELETE_CMD_PREFIX='curl -X DELETE --silent -o /dev/null -w "%{http_code}"' + CURL_MAINTENANCE_PUT_CMD_PREFIX='curl -X PUT --silent -o /dev/null -w "%{http_code}"' + CURL_MAINTENANCE_GET_CMD="curl -X GET --silent --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/maintenance" + postStart.sh: |- + #!/usr/bin/env bash + # This code should be similar if not exactly the same as that found in the panda-operator, see + # https://github.com/redpanda-data/redpanda/blob/e51d5b7f2ef76d5160ca01b8c7a8cf07593d29b6/src/go/k8s/pkg/resources/secret.go + + # path below should match the path defined on the statefulset + source /var/lifecycle/common.sh + + postStartHook () { + set -x + + touch /tmp/postStartHookStarted + + until NODE_ID=$(${CURL_NODE_ID_CMD} | grep -o '\"node_id\":[^,}]*' | grep -o '[^: ]*$'); do + sleep 0.5 + done + + echo "Clearing maintenance mode on node ${NODE_ID}" + CURL_MAINTENANCE_DELETE_CMD="${CURL_MAINTENANCE_DELETE_CMD_PREFIX} --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/brokers/${NODE_ID}/maintenance" + # a 400 here would mean not in maintenance mode + until [ "${status:-}" = '"200"' ] || [ "${status:-}" = '"400"' ]; do + status=$(${CURL_MAINTENANCE_DELETE_CMD}) + sleep 0.5 + done + + touch /tmp/postStartHookFinished + } + + postStartHook + true + preStop.sh: |- + #!/usr/bin/env bash + # This code should be similar if not exactly the same as that found in the panda-operator, see + # https://github.com/redpanda-data/redpanda/blob/e51d5b7f2ef76d5160ca01b8c7a8cf07593d29b6/src/go/k8s/pkg/resources/secret.go + + touch /tmp/preStopHookStarted + + # path below should match the path defined on the statefulset + source /var/lifecycle/common.sh + + set -x + + preStopHook () { + until NODE_ID=$(${CURL_NODE_ID_CMD} | grep -o '\"node_id\":[^,}]*' | grep -o '[^: ]*$'); do + sleep 0.5 + done + + echo "Setting maintenance mode on node ${NODE_ID}" + CURL_MAINTENANCE_PUT_CMD="${CURL_MAINTENANCE_PUT_CMD_PREFIX} --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/brokers/${NODE_ID}/maintenance" + until [ "${status:-}" = '"200"' ]; do + status=$(${CURL_MAINTENANCE_PUT_CMD}) + sleep 0.5 + done + + until [ "${finished:-}" = "true" ] || [ "${draining:-}" = "false" ]; do + res=$(${CURL_MAINTENANCE_GET_CMD}) + finished=$(echo $res | grep -o '\"finished\":[^,}]*' | grep -o '[^: ]*$') + draining=$(echo $res | grep -o '\"draining\":[^,}]*' | grep -o '[^: ]*$') + sleep 0.5 + done + + touch /tmp/preStopHookFinished + } + preStopHook + true +type: Opaque +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-configurator + namespace: default +stringData: + configurator.sh: |- + set -xe + SERVICE_NAME=$1 + KUBERNETES_NODE_NAME=$2 + POD_ORDINAL=${SERVICE_NAME##*-} + BROKER_INDEX=`expr $POD_ORDINAL + 1` + + CONFIG=/etc/redpanda/redpanda.yaml + + # Setup config files + cp /tmp/base-config/redpanda.yaml "${CONFIG}" + + LISTENER="{\"address\":\"${SERVICE_NAME}.redpanda.default.svc.cluster.local.\",\"name\":\"internal\",\"port\":9093}" + rpk redpanda config --config "$CONFIG" set redpanda.advertised_kafka_api[0] "$LISTENER" + + ADVERTISED_KAFKA_ADDRESSES=() + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30092}") + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30092}") + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30092}") + + rpk redpanda config --config "$CONFIG" set redpanda.advertised_kafka_api[1] "${ADVERTISED_KAFKA_ADDRESSES[$POD_ORDINAL]}" + + ADVERTISED_KAFKA_ADDRESSES=() + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"redpanda-0-broker.example.com\",\"name\":\"gw-listener\",\"port\":443}") + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"redpanda-1-broker.example.com\",\"name\":\"gw-listener\",\"port\":443}") + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"redpanda-2-broker.example.com\",\"name\":\"gw-listener\",\"port\":443}") + + rpk redpanda config --config "$CONFIG" set redpanda.advertised_kafka_api[2] "${ADVERTISED_KAFKA_ADDRESSES[$POD_ORDINAL]}" + + LISTENER="{\"address\":\"${SERVICE_NAME}.redpanda.default.svc.cluster.local.\",\"name\":\"internal\",\"port\":8082}" + rpk redpanda config --config "$CONFIG" set pandaproxy.advertised_pandaproxy_api[0] "$LISTENER" + + ADVERTISED_HTTP_ADDRESSES=() + + PREFIX_TEMPLATE="" + ADVERTISED_HTTP_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30082}") + + PREFIX_TEMPLATE="" + ADVERTISED_HTTP_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30082}") + + PREFIX_TEMPLATE="" + ADVERTISED_HTTP_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30082}") + + rpk redpanda config --config "$CONFIG" set pandaproxy.advertised_pandaproxy_api[1] "${ADVERTISED_HTTP_ADDRESSES[$POD_ORDINAL]}" +type: Opaque +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +data: + .bootstrap.json.in: '{"audit_enabled":"false","cloud_storage_cache_size":"5368709120","cloud_storage_enable_remote_read":"true","cloud_storage_enable_remote_write":"true","cloud_storage_enabled":"false","compacted_log_segment_size":"67108864","default_topic_replications":"3","enable_rack_awareness":"false","enable_sasl":"false","kafka_connection_rate_limit":"1000","kafka_enable_authorization":"false","log_segment_size_max":"268435456","log_segment_size_min":"16777216","max_compacted_log_segment_size":"536870912","storage_min_free_bytes":"1073741824"}' + bootstrap.yaml.fixups: '[]' + redpanda.yaml: |- + config_file: /etc/redpanda/redpanda.yaml + pandaproxy: + pandaproxy_api: + - address: 0.0.0.0 + name: internal + port: 8082 + - address: 0.0.0.0 + name: default + port: 8083 + pandaproxy_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/external/tls.crt + enabled: true + key_file: /etc/tls/certs/external/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/external/ca.crt + pandaproxy_client: + broker_tls: + enabled: true + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + brokers: + - address: redpanda-0.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-1.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-2.redpanda.default.svc.cluster.local. + port: 9093 + redpanda: + admin: + - address: 0.0.0.0 + name: internal + port: 9644 + - address: 0.0.0.0 + name: default + port: 9645 + admin_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/external/tls.crt + enabled: true + key_file: /etc/tls/certs/external/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/external/ca.crt + crash_loop_limit: 5 + empty_seed_starts_cluster: false + kafka_api: + - address: 0.0.0.0 + name: internal + port: 9093 + - address: 0.0.0.0 + name: default + port: 9094 + - address: 0.0.0.0 + name: gw-listener + port: 9095 + kafka_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/external/tls.crt + enabled: true + key_file: /etc/tls/certs/external/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/external/ca.crt + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: gw-listener + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + rpc_server: + address: 0.0.0.0 + port: 33145 + rpc_server_tls: + cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + seed_servers: + - host: + address: redpanda-0.redpanda.default.svc.cluster.local. + port: 33145 + - host: + address: redpanda-1.redpanda.default.svc.cluster.local. + port: 33145 + - host: + address: redpanda-2.redpanda.default.svc.cluster.local. + port: 33145 + rpk: + additional_start_flags: + - --default-log-level=info + - --memory=2048M + - --reserve-memory=205M + - --smp=1 + admin_api: + addresses: + - redpanda-0.redpanda.default.svc.cluster.local.:9644 + - redpanda-1.redpanda.default.svc.cluster.local.:9644 + - redpanda-2.redpanda.default.svc.cluster.local.:9644 + tls: + ca_file: /etc/tls/certs/default/ca.crt + enable_memory_locking: false + kafka_api: + brokers: + - redpanda-0.redpanda.default.svc.cluster.local.:9093 + - redpanda-1.redpanda.default.svc.cluster.local.:9093 + - redpanda-2.redpanda.default.svc.cluster.local.:9093 + tls: + ca_file: /etc/tls/certs/default/ca.crt + overprovisioned: false + schema_registry: + addresses: + - redpanda-0.redpanda.default.svc.cluster.local.:8081 + - redpanda-1.redpanda.default.svc.cluster.local.:8081 + - redpanda-2.redpanda.default.svc.cluster.local.:8081 + tls: + ca_file: /etc/tls/certs/default/ca.crt + tune_aio_events: true + schema_registry: + schema_registry_api: + - address: 0.0.0.0 + name: internal + port: 8081 + - address: 0.0.0.0 + name: default + port: 8084 + schema_registry_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/external/tls.crt + enabled: true + key_file: /etc/tls/certs/external/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/external/ca.crt + schema_registry_client: + broker_tls: + enabled: true + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + brokers: + - address: redpanda-0.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-1.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-2.redpanda.default.svc.cluster.local. + port: 9093 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +data: + profile: |- + admin_api: + addresses: + - redpanda-0:31644 + - redpanda-1:31644 + - redpanda-2:31644 + tls: + ca_file: ca.crt + kafka_api: + brokers: + - redpanda-0:30092 + - redpanda-1:30092 + - redpanda-2:30092 + tls: + ca_file: ca.crt + name: default + schema_registry: + addresses: + - redpanda-0:30081 + - redpanda-1:30081 + - redpanda-2:30081 + tls: + ca_file: ca.crt +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-rpk + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +data: + config.yaml: | + # from .Values.config + kafka: + brokers: + - redpanda-0.redpanda.default.svc.cluster.local.:9093 + - redpanda-1.redpanda.default.svc.cluster.local.:9093 + - redpanda-2.redpanda.default.svc.cluster.local.:9093 + tls: + caFilepath: /etc/tls/certs/secrets/redpanda-default-cert/ca.crt + enabled: true + redpanda: + adminApi: + enabled: true + tls: + caFilepath: /etc/tls/certs/secrets/redpanda-default-cert/ca.crt + enabled: true + urls: + - https://redpanda.default.svc.cluster.local.:9644 + schemaRegistry: + enabled: true + tls: + caFilepath: /etc/tls/certs/secrets/redpanda-default-cert/ca.crt + enabled: true + urls: + - https://redpanda-0.redpanda.default.svc.cluster.local.:8081 + - https://redpanda-1.redpanda.default.svc.cluster.local.:8081 + - https://redpanda-2.redpanda.default.svc.cluster.local.:8081 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-rpk-debug-bundle + namespace: default +rules: +- apiGroups: + - "" + resources: + - configmaps + - endpoints + - events + - limitranges + - persistentvolumeclaims + - pods + - pods/log + - replicationcontrollers + - resourcequotas + - serviceaccounts + - services + verbs: + - get + - list +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-sidecar + namespace: default +rules: +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-rpk-debug-bundle + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: redpanda-rpk-debug-bundle +subjects: +- kind: ServiceAccount + name: redpanda + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-sidecar + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: redpanda-sidecar +subjects: +- kind: ServiceAccount + name: redpanda + namespace: default +--- +# Source: redpanda/charts/console/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 0 + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: console + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external + namespace: default +spec: + externalTrafficPolicy: Local + ports: + - name: admin-default + nodePort: 31644 + port: 9645 + protocol: TCP + targetPort: 0 + - name: kafka-default + nodePort: 30092 + port: 9094 + protocol: TCP + targetPort: 0 + - name: http-default + nodePort: 30082 + port: 8083 + protocol: TCP + targetPort: 0 + - name: schema-default + nodePort: 30081 + port: 8084 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + sessionAffinity: None + type: NodePort +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + monitoring.redpanda.com/enabled: "false" + name: redpanda + namespace: default +spec: + clusterIP: None + ports: + - appProtocol: null + name: admin + port: 9644 + protocol: TCP + targetPort: 9644 + - name: http + port: 8082 + protocol: TCP + targetPort: 8082 + - name: kafka + port: 9093 + protocol: TCP + targetPort: 9093 + - name: rpc + port: 33145 + protocol: TCP + targetPort: 33145 + - name: schemaregistry + port: 8081 + protocol: TCP + targetPort: 8081 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-gateway-bootstrap + namespace: default +spec: + ports: + - name: kafka-gw-listener + port: 9095 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: gw-redpanda-0 + namespace: default +spec: + ports: + - name: kafka-gw-listener + port: 9095 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + statefulset.kubernetes.io/pod-name: redpanda-0 + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: gw-redpanda-1 + namespace: default +spec: + ports: + - name: kafka-gw-listener + port: 9095 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + statefulset.kubernetes.io/pod-name: redpanda-1 + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: gw-redpanda-2 + namespace: default +spec: + ports: + - name: kafka-gw-listener + port: 9095 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + statefulset.kubernetes.io/pod-name: redpanda-2 + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: console + strategy: {} + template: + metadata: + annotations: + checksum/config: 44e632405e10e419e4cb3a5f69d2911edabaa8fd561fc25ec1017dc35a99fc96 + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: console + spec: + affinity: {} + automountServiceAccountToken: false + containers: + - args: + - --config.filepath=/etc/console/configs/config.yaml + command: null + env: + - name: REDPANDA_METRICS_K8S_DEPLOYMENT_TYPE + value: helm + - name: REDPANDA_METRICS_K8S_CHART_VERSION + value: 3.7.0 + - name: REDPANDA_METRICS_K8S_CONSOLE_IMAGE_VERSION + value: redpandadata/console:v3.7.0 + - name: REDPANDA_METRICS_K8S_VERSION + value: v1.99.0-gke + - name: REDPANDA_METRICS_K8S_ENVIRONMENT + value: GCP + envFrom: [] + image: docker.redpanda.com/redpandadata/console:v3.7.0 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /admin/health + port: http + initialDelaySeconds: 0 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: console + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /admin/health + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: {} + securityContext: + runAsNonRoot: true + volumeMounts: + - mountPath: /etc/console/configs + name: configs + readOnly: true + - mountPath: /etc/tls/certs + name: redpanda-certificates + imagePullSecrets: [] + initContainers: null + nodeSelector: {} + priorityClassName: "" + securityContext: + fsGroup: 99 + fsGroupChangePolicy: Always + runAsUser: 99 + serviceAccountName: redpanda-console + tolerations: [] + topologySpreadConstraints: [] + volumes: + - configMap: + name: redpanda-console + name: configs + - name: redpanda-certificates + projected: + sources: + - secret: + items: + - key: ca.crt + path: secrets/redpanda-default-cert/ca.crt + name: redpanda-default-cert +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +spec: + podManagementPolicy: Parallel + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + serviceName: redpanda + template: + metadata: + annotations: + config.redpanda.com/checksum: f96f9c1fc729be3b095c57ec2682ba0491848d4f356d6b41343427a2e28d484c + labels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + cluster.redpanda.com/broker: "true" + helm.sh/chart: redpanda-26.1.1 + redpanda.com/poddisruptionbudget: redpanda + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + topologyKey: kubernetes.io/hostname + automountServiceAccountToken: false + containers: + - command: + - rpk + - redpanda + - start + - --advertise-rpc-addr=$(SERVICE_NAME).redpanda.default.svc.cluster.local.:33145 + env: + - name: SERVICE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: REDPANDA_METRICS_K8S_VERSION + value: v1.99.0-gke + - name: REDPANDA_METRICS_K8S_DEPLOYMENT_TYPE + value: helm + - name: REDPANDA_METRICS_K8S_CHART_VERSION + value: 26.1.1 + - name: REDPANDA_METRICS_K8S_OPERATOR_IMAGE_VERSION + value: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + - name: REDPANDA_METRICS_K8S_ENVIRONMENT + value: GCP + image: docker.redpanda.com/redpandadata/redpanda:v26.1.1 + lifecycle: + postStart: + exec: + command: + - bash + - -c + - 'timeout -v 45 bash -x /var/lifecycle/postStart.sh 2>&1 | sed "s/^/lifecycle-hook + post-start $(date): /" | tee /proc/1/fd/1; true' + preStop: + exec: + command: + - bash + - -c + - 'timeout -v 45 bash -x /var/lifecycle/preStop.sh 2>&1 | sed "s/^/lifecycle-hook + pre-stop $(date): /" | tee /proc/1/fd/1; true' + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + tcpSocket: + port: 9644 + name: redpanda + ports: + - containerPort: 9644 + name: admin + - containerPort: 9645 + name: admin-default + - containerPort: 8082 + name: http + - containerPort: 8083 + name: http-default + - containerPort: 9093 + name: kafka + - containerPort: 9094 + name: kafka-default + - containerPort: 9095 + name: kafka-gw-liste + - containerPort: 33145 + name: rpc + - containerPort: 8081 + name: schemaregistry + - containerPort: 8084 + name: schema-default + resources: + limits: + cpu: 1 + memory: 2.5Gi + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + startupProbe: + exec: + command: + - /bin/sh + - -c + - | + set -e + RESULT=$(curl --silent --fail -k -m 5 --cacert /etc/tls/certs/default/ca.crt "https://${SERVICE_NAME}.redpanda.default.svc.cluster.local.:9644/v1/status/ready") + echo $RESULT + echo $RESULT | grep ready + failureThreshold: 120 + initialDelaySeconds: 1 + periodSeconds: 10 + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: config + - mountPath: /tmp/base-config + name: base-config + - mountPath: /var/lifecycle + name: lifecycle-scripts + - mountPath: /var/lib/redpanda/data + name: datadir + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: kube-api-access + readOnly: true + - args: + - supervisor + - -- + - /redpanda-operator + - sidecar + - --redpanda-yaml + - /etc/redpanda/redpanda.yaml + - --redpanda-cluster-namespace + - default + - --redpanda-cluster-name + - redpanda + - --selector=helm.sh/chart=redpanda-26.1.1,app.kubernetes.io/name=redpanda,app.kubernetes.io/instance=redpanda + - --run-broker-probe + - --broker-probe-broker-url + - $(SERVICE_NAME).redpanda.default.svc.cluster.local.:9644 + command: + - /redpanda-operator + env: + - name: SERVICE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: sidecar + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 8093 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 0 + resources: {} + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: config + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: kube-api-access + readOnly: true + imagePullSecrets: [] + initContainers: + - command: + - /bin/bash + - -c + - rpk redpanda tune all + env: null + image: docker.redpanda.com/redpandadata/redpanda:v26.1.1 + name: tuning + resources: {} + securityContext: + capabilities: + add: + - SYS_RESOURCE + privileged: true + runAsGroup: 0 + runAsNonRoot: false + runAsUser: 0 + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: base-config + - mountPath: /var/lib/redpanda/data + name: datadir + - command: + - /bin/bash + - -c + - trap "exit 0" TERM; exec $CONFIGURATOR_SCRIPT "${SERVICE_NAME}" "${KUBERNETES_NODE_NAME}" + & wait $! + env: + - name: CONFIGURATOR_SCRIPT + value: /etc/secrets/configurator/scripts/configurator.sh + - name: SERVICE_NAME + valueFrom: + configMapKeyRef: null + fieldRef: + fieldPath: metadata.name + resourceFieldRef: null + secretKeyRef: null + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: HOST_IP_ADDRESS + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + image: docker.redpanda.com/redpandadata/redpanda:v26.1.1 + name: redpanda-configurator + resources: {} + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: config + - mountPath: /tmp/base-config + name: base-config + - mountPath: /etc/secrets/configurator/scripts/ + name: redpanda-configurator + - command: + - /redpanda-operator + - bootstrap + - --in-dir + - /tmp/base-config + - --out-dir + - /tmp/config + env: null + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: bootstrap-yaml-envsubst + resources: + limits: + cpu: 100m + memory: 125Mi + requests: + cpu: 100m + memory: 125Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /tmp/config/ + name: config + - mountPath: /tmp/base-config/ + name: base-config + nodeSelector: {} + priorityClassName: "" + securityContext: + fsGroup: 101 + fsGroupChangePolicy: OnRootMismatch + runAsUser: 101 + serviceAccountName: redpanda + terminationGracePeriodSeconds: 90 + tolerations: [] + topologySpreadConstraints: + - labelSelector: + matchLabels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + volumes: + - name: redpanda-default-cert + secret: + defaultMode: 288 + secretName: redpanda-default-cert + - name: redpanda-external-cert + secret: + defaultMode: 288 + secretName: redpanda-external-cert + - name: lifecycle-scripts + secret: + defaultMode: 509 + secretName: redpanda-sts-lifecycle + - configMap: + name: redpanda + name: base-config + - emptyDir: {} + name: config + - name: redpanda-configurator + secret: + defaultMode: 509 + secretName: redpanda-configurator + - name: datadir + persistentVolumeClaim: + claimName: datadir + - name: kube-api-access + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + expirationSeconds: 3607 + path: token + - configMap: + items: + - key: ca.crt + path: ca.crt + name: kube-root-ca.crt + - downwardAPI: + items: + - fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + path: namespace + updateStrategy: + type: RollingUpdate + volumeClaimTemplates: + - metadata: + annotations: null + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + name: datadir + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + status: {} +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-root-certificate + namespace: default +spec: + commonName: redpanda-default-root-certificate + duration: 43800h0m0s + isCA: true + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-default-selfsigned-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-default-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-root-certificate + namespace: default +spec: + commonName: redpanda-external-root-certificate + duration: 43800h0m0s + isCA: true + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-external-selfsigned-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-external-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-cert + namespace: default +spec: + dnsNames: + - redpanda-cluster.redpanda.default.svc.cluster.local + - redpanda-cluster.redpanda.default.svc + - redpanda-cluster.redpanda.default + - '*.redpanda-cluster.redpanda.default.svc.cluster.local' + - '*.redpanda-cluster.redpanda.default.svc' + - '*.redpanda-cluster.redpanda.default' + - redpanda.default.svc.cluster.local + - redpanda.default.svc + - redpanda.default + - '*.redpanda.default.svc.cluster.local' + - '*.redpanda.default.svc' + - '*.redpanda.default' + duration: 43800h0m0s + isCA: false + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-default-root-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-default-cert +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-cert + namespace: default +spec: + dnsNames: + - redpanda-cluster.redpanda.default.svc.cluster.local + - redpanda-cluster.redpanda.default.svc + - redpanda-cluster.redpanda.default + - '*.redpanda-cluster.redpanda.default.svc.cluster.local' + - '*.redpanda-cluster.redpanda.default.svc' + - '*.redpanda-cluster.redpanda.default' + - redpanda.default.svc.cluster.local + - redpanda.default.svc + - redpanda.default + - '*.redpanda.default.svc.cluster.local' + - '*.redpanda.default.svc' + - '*.redpanda.default' + duration: 43800h0m0s + isCA: false + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-external-root-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-external-cert +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-selfsigned-issuer + namespace: default +spec: + selfSigned: {} +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-root-issuer + namespace: default +spec: + ca: + secretName: redpanda-default-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-selfsigned-issuer + namespace: default +spec: + selfSigned: {} +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-root-issuer + namespace: default +spec: + ca: + secretName: redpanda-external-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-gw-listener-bootstrap + namespace: default +spec: + hostnames: + - redpanda.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: redpanda-gateway-bootstrap + port: 9095 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-gw-listener-0 + namespace: default +spec: + hostnames: + - redpanda-0-broker.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: gw-redpanda-0 + port: 9095 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-gw-listener-1 + namespace: default +spec: + hostnames: + - redpanda-1-broker.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: gw-redpanda-1 + port: 9095 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-gw-listener-2 + namespace: default +spec: + hostnames: + - redpanda-2-broker.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: gw-redpanda-2 + port: 9095 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-delete-policy: before-hook-creation + helm.sh/hook-weight: "-5" + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-configuration + namespace: default +spec: + template: + metadata: + annotations: {} + generateName: redpanda-post- + labels: + app.kubernetes.io/component: redpanda-post-install + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda-configuration + spec: + automountServiceAccountToken: false + containers: + - command: + - /redpanda-operator + - sync-cluster-config + - --users-directory + - /etc/secrets/users + - --redpanda-yaml + - /tmp/base-config/redpanda.yaml + - --bootstrap-yaml + - /tmp/config/.bootstrap.yaml + env: null + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: post-install + resources: {} + securityContext: {} + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /tmp/config + name: config + - mountPath: /tmp/base-config + name: base-config + imagePullSecrets: [] + initContainers: + - command: + - /redpanda-operator + - bootstrap + - --in-dir + - /tmp/base-config + - --out-dir + - /tmp/config + env: null + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: bootstrap-yaml-envsubst + resources: + limits: + cpu: 100m + memory: 125Mi + requests: + cpu: 100m + memory: 125Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /tmp/config/ + name: config + - mountPath: /tmp/base-config/ + name: base-config + nodeSelector: {} + restartPolicy: Never + securityContext: + fsGroup: 101 + fsGroupChangePolicy: OnRootMismatch + runAsUser: 101 + serviceAccountName: redpanda + tolerations: [] + volumes: + - name: redpanda-default-cert + secret: + defaultMode: 288 + secretName: redpanda-default-cert + - name: redpanda-external-cert + secret: + defaultMode: 288 + secretName: redpanda-external-cert + - configMap: + name: redpanda + name: base-config + - emptyDir: {} + name: config +-- testdata/TestTemplate/gateway-api-tlsroute.yaml.golden -- +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +spec: + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + redpanda.com/poddisruptionbudget: redpanda +--- +# Source: redpanda/charts/console/templates/entry-point.yaml +apiVersion: v1 +automountServiceAccountToken: false +kind: ServiceAccount +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +automountServiceAccountToken: false +kind: ServiceAccount +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-sts-lifecycle + namespace: default +stringData: + common.sh: |- + #!/usr/bin/env bash + + # the SERVICE_NAME comes from the metadata.name of the pod, essentially the POD_NAME + CURL_URL="https://${SERVICE_NAME}.redpanda.default.svc.cluster.local:9644" + + # commands used throughout + CURL_NODE_ID_CMD="curl --silent --fail --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/node_config" + + CURL_MAINTENANCE_DELETE_CMD_PREFIX='curl -X DELETE --silent -o /dev/null -w "%{http_code}"' + CURL_MAINTENANCE_PUT_CMD_PREFIX='curl -X PUT --silent -o /dev/null -w "%{http_code}"' + CURL_MAINTENANCE_GET_CMD="curl -X GET --silent --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/maintenance" + postStart.sh: |- + #!/usr/bin/env bash + # This code should be similar if not exactly the same as that found in the panda-operator, see + # https://github.com/redpanda-data/redpanda/blob/e51d5b7f2ef76d5160ca01b8c7a8cf07593d29b6/src/go/k8s/pkg/resources/secret.go + + # path below should match the path defined on the statefulset + source /var/lifecycle/common.sh + + postStartHook () { + set -x + + touch /tmp/postStartHookStarted + + until NODE_ID=$(${CURL_NODE_ID_CMD} | grep -o '\"node_id\":[^,}]*' | grep -o '[^: ]*$'); do + sleep 0.5 + done + + echo "Clearing maintenance mode on node ${NODE_ID}" + CURL_MAINTENANCE_DELETE_CMD="${CURL_MAINTENANCE_DELETE_CMD_PREFIX} --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/brokers/${NODE_ID}/maintenance" + # a 400 here would mean not in maintenance mode + until [ "${status:-}" = '"200"' ] || [ "${status:-}" = '"400"' ]; do + status=$(${CURL_MAINTENANCE_DELETE_CMD}) + sleep 0.5 + done + + touch /tmp/postStartHookFinished + } + + postStartHook + true + preStop.sh: |- + #!/usr/bin/env bash + # This code should be similar if not exactly the same as that found in the panda-operator, see + # https://github.com/redpanda-data/redpanda/blob/e51d5b7f2ef76d5160ca01b8c7a8cf07593d29b6/src/go/k8s/pkg/resources/secret.go + + touch /tmp/preStopHookStarted + + # path below should match the path defined on the statefulset + source /var/lifecycle/common.sh + + set -x + + preStopHook () { + until NODE_ID=$(${CURL_NODE_ID_CMD} | grep -o '\"node_id\":[^,}]*' | grep -o '[^: ]*$'); do + sleep 0.5 + done + + echo "Setting maintenance mode on node ${NODE_ID}" + CURL_MAINTENANCE_PUT_CMD="${CURL_MAINTENANCE_PUT_CMD_PREFIX} --cacert /etc/tls/certs/default/ca.crt ${CURL_URL}/v1/brokers/${NODE_ID}/maintenance" + until [ "${status:-}" = '"200"' ]; do + status=$(${CURL_MAINTENANCE_PUT_CMD}) + sleep 0.5 + done + + until [ "${finished:-}" = "true" ] || [ "${draining:-}" = "false" ]; do + res=$(${CURL_MAINTENANCE_GET_CMD}) + finished=$(echo $res | grep -o '\"finished\":[^,}]*' | grep -o '[^: ]*$') + draining=$(echo $res | grep -o '\"draining\":[^,}]*' | grep -o '[^: ]*$') + sleep 0.5 + done + + touch /tmp/preStopHookFinished + } + preStopHook + true +type: Opaque +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-configurator + namespace: default +stringData: + configurator.sh: |- + set -xe + SERVICE_NAME=$1 + KUBERNETES_NODE_NAME=$2 + POD_ORDINAL=${SERVICE_NAME##*-} + BROKER_INDEX=`expr $POD_ORDINAL + 1` + + CONFIG=/etc/redpanda/redpanda.yaml + + # Setup config files + cp /tmp/base-config/redpanda.yaml "${CONFIG}" + + LISTENER="{\"address\":\"${SERVICE_NAME}.redpanda.default.svc.cluster.local.\",\"name\":\"internal\",\"port\":9093}" + rpk redpanda config --config "$CONFIG" set redpanda.advertised_kafka_api[0] "$LISTENER" + + ADVERTISED_KAFKA_ADDRESSES=() + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"redpanda-0-broker.example.com\",\"name\":\"default\",\"port\":9094}") + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"redpanda-1-broker.example.com\",\"name\":\"default\",\"port\":9094}") + + PREFIX_TEMPLATE="" + ADVERTISED_KAFKA_ADDRESSES+=("{\"address\":\"redpanda-2-broker.example.com\",\"name\":\"default\",\"port\":9094}") + + rpk redpanda config --config "$CONFIG" set redpanda.advertised_kafka_api[1] "${ADVERTISED_KAFKA_ADDRESSES[$POD_ORDINAL]}" + + LISTENER="{\"address\":\"${SERVICE_NAME}.redpanda.default.svc.cluster.local.\",\"name\":\"internal\",\"port\":8082}" + rpk redpanda config --config "$CONFIG" set pandaproxy.advertised_pandaproxy_api[0] "$LISTENER" + + ADVERTISED_HTTP_ADDRESSES=() + + PREFIX_TEMPLATE="" + ADVERTISED_HTTP_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30082}") + + PREFIX_TEMPLATE="" + ADVERTISED_HTTP_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30082}") + + PREFIX_TEMPLATE="" + ADVERTISED_HTTP_ADDRESSES+=("{\"address\":\"${SERVICE_NAME}\",\"name\":\"default\",\"port\":30082}") + + rpk redpanda config --config "$CONFIG" set pandaproxy.advertised_pandaproxy_api[1] "${ADVERTISED_HTTP_ADDRESSES[$POD_ORDINAL]}" +type: Opaque +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +data: + .bootstrap.json.in: '{"audit_enabled":"false","cloud_storage_cache_size":"5368709120","cloud_storage_enable_remote_read":"true","cloud_storage_enable_remote_write":"true","cloud_storage_enabled":"false","compacted_log_segment_size":"67108864","default_topic_replications":"3","enable_rack_awareness":"false","enable_sasl":"false","kafka_connection_rate_limit":"1000","kafka_enable_authorization":"false","log_segment_size_max":"268435456","log_segment_size_min":"16777216","max_compacted_log_segment_size":"536870912","storage_min_free_bytes":"1073741824"}' + bootstrap.yaml.fixups: '[]' + redpanda.yaml: |- + config_file: /etc/redpanda/redpanda.yaml + pandaproxy: + pandaproxy_api: + - address: 0.0.0.0 + name: internal + port: 8082 + - address: 0.0.0.0 + name: default + port: 8083 + pandaproxy_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/external/tls.crt + enabled: true + key_file: /etc/tls/certs/external/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/external/ca.crt + pandaproxy_client: + broker_tls: + enabled: true + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + brokers: + - address: redpanda-0.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-1.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-2.redpanda.default.svc.cluster.local. + port: 9093 + redpanda: + admin: + - address: 0.0.0.0 + name: internal + port: 9644 + - address: 0.0.0.0 + name: default + port: 9645 + admin_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/external/tls.crt + enabled: true + key_file: /etc/tls/certs/external/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/external/ca.crt + crash_loop_limit: 5 + empty_seed_starts_cluster: false + kafka_api: + - address: 0.0.0.0 + name: internal + port: 9093 + - address: 0.0.0.0 + name: default + port: 9094 + kafka_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + rpc_server: + address: 0.0.0.0 + port: 33145 + rpc_server_tls: + cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + seed_servers: + - host: + address: redpanda-0.redpanda.default.svc.cluster.local. + port: 33145 + - host: + address: redpanda-1.redpanda.default.svc.cluster.local. + port: 33145 + - host: + address: redpanda-2.redpanda.default.svc.cluster.local. + port: 33145 + rpk: + additional_start_flags: + - --default-log-level=info + - --memory=2048M + - --reserve-memory=205M + - --smp=1 + admin_api: + addresses: + - redpanda-0.redpanda.default.svc.cluster.local.:9644 + - redpanda-1.redpanda.default.svc.cluster.local.:9644 + - redpanda-2.redpanda.default.svc.cluster.local.:9644 + tls: + ca_file: /etc/tls/certs/default/ca.crt + enable_memory_locking: false + kafka_api: + brokers: + - redpanda-0.redpanda.default.svc.cluster.local.:9093 + - redpanda-1.redpanda.default.svc.cluster.local.:9093 + - redpanda-2.redpanda.default.svc.cluster.local.:9093 + tls: + ca_file: /etc/tls/certs/default/ca.crt + overprovisioned: false + schema_registry: + addresses: + - redpanda-0.redpanda.default.svc.cluster.local.:8081 + - redpanda-1.redpanda.default.svc.cluster.local.:8081 + - redpanda-2.redpanda.default.svc.cluster.local.:8081 + tls: + ca_file: /etc/tls/certs/default/ca.crt + tune_aio_events: true + schema_registry: + schema_registry_api: + - address: 0.0.0.0 + name: internal + port: 8081 + - address: 0.0.0.0 + name: default + port: 8084 + schema_registry_api_tls: + - cert_file: /etc/tls/certs/default/tls.crt + enabled: true + key_file: /etc/tls/certs/default/tls.key + name: internal + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + - cert_file: /etc/tls/certs/external/tls.crt + enabled: true + key_file: /etc/tls/certs/external/tls.key + name: default + require_client_auth: false + truststore_file: /etc/tls/certs/external/ca.crt + schema_registry_client: + broker_tls: + enabled: true + require_client_auth: false + truststore_file: /etc/tls/certs/default/ca.crt + brokers: + - address: redpanda-0.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-1.redpanda.default.svc.cluster.local. + port: 9093 + - address: redpanda-2.redpanda.default.svc.cluster.local. + port: 9093 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +data: + profile: |- + admin_api: + addresses: + - redpanda-0:31644 + - redpanda-1:31644 + - redpanda-2:31644 + tls: + ca_file: ca.crt + kafka_api: + brokers: + - redpanda-0:31092 + - redpanda-1:31092 + - redpanda-2:31092 + tls: + ca_file: ca.crt + name: default + schema_registry: + addresses: + - redpanda-0:30081 + - redpanda-1:30081 + - redpanda-2:30081 + tls: + ca_file: ca.crt +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-rpk + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +data: + config.yaml: | + # from .Values.config + kafka: + brokers: + - redpanda-0.redpanda.default.svc.cluster.local.:9093 + - redpanda-1.redpanda.default.svc.cluster.local.:9093 + - redpanda-2.redpanda.default.svc.cluster.local.:9093 + tls: + caFilepath: /etc/tls/certs/secrets/redpanda-default-cert/ca.crt + enabled: true + redpanda: + adminApi: + enabled: true + tls: + caFilepath: /etc/tls/certs/secrets/redpanda-default-cert/ca.crt + enabled: true + urls: + - https://redpanda.default.svc.cluster.local.:9644 + schemaRegistry: + enabled: true + tls: + caFilepath: /etc/tls/certs/secrets/redpanda-default-cert/ca.crt + enabled: true + urls: + - https://redpanda-0.redpanda.default.svc.cluster.local.:8081 + - https://redpanda-1.redpanda.default.svc.cluster.local.:8081 + - https://redpanda-2.redpanda.default.svc.cluster.local.:8081 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-rpk-debug-bundle + namespace: default +rules: +- apiGroups: + - "" + resources: + - configmaps + - endpoints + - events + - limitranges + - persistentvolumeclaims + - pods + - pods/log + - replicationcontrollers + - resourcequotas + - serviceaccounts + - services + verbs: + - get + - list +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-sidecar + namespace: default +rules: +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-rpk-debug-bundle + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: redpanda-rpk-debug-bundle +subjects: +- kind: ServiceAccount + name: redpanda + namespace: default +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-sidecar + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: redpanda-sidecar +subjects: +- kind: ServiceAccount + name: redpanda + namespace: default +--- +# Source: redpanda/charts/console/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +spec: + ports: + - name: http + port: 8080 + protocol: TCP + targetPort: 0 + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: console + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external + namespace: default +spec: + externalTrafficPolicy: Local + ports: + - name: admin-default + nodePort: 31644 + port: 9645 + protocol: TCP + targetPort: 0 + - name: http-default + nodePort: 30082 + port: 8083 + protocol: TCP + targetPort: 0 + - name: schema-default + nodePort: 30081 + port: 8084 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + sessionAffinity: None + type: NodePort +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + annotations: {} + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + monitoring.redpanda.com/enabled: "false" + name: redpanda + namespace: default +spec: + clusterIP: None + ports: + - appProtocol: null + name: admin + port: 9644 + protocol: TCP + targetPort: 9644 + - name: http + port: 8082 + protocol: TCP + targetPort: 8082 + - name: kafka + port: 9093 + protocol: TCP + targetPort: 9093 + - name: rpc + port: 33145 + protocol: TCP + targetPort: 33145 + - name: schemaregistry + port: 8081 + protocol: TCP + targetPort: 8081 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-gateway-bootstrap + namespace: default +spec: + ports: + - name: kafka-default + port: 9094 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: gw-redpanda-0 + namespace: default +spec: + ports: + - name: kafka-default + port: 9094 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + statefulset.kubernetes.io/pod-name: redpanda-0 + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: gw-redpanda-1 + namespace: default +spec: + ports: + - name: kafka-default + port: 9094 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + statefulset.kubernetes.io/pod-name: redpanda-1 + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: gw-redpanda-2 + namespace: default +spec: + ports: + - name: kafka-default + port: 9094 + protocol: TCP + targetPort: 0 + publishNotReadyAddresses: true + selector: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + statefulset.kubernetes.io/pod-name: redpanda-2 + sessionAffinity: None + type: ClusterIP +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: console + app.kubernetes.io/version: v3.7.0 + helm.sh/chart: console-3.7.0 + name: redpanda-console + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: console + strategy: {} + template: + metadata: + annotations: + checksum/config: 44e632405e10e419e4cb3a5f69d2911edabaa8fd561fc25ec1017dc35a99fc96 + labels: + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: console + spec: + affinity: {} + automountServiceAccountToken: false + containers: + - args: + - --config.filepath=/etc/console/configs/config.yaml + command: null + env: + - name: REDPANDA_METRICS_K8S_DEPLOYMENT_TYPE + value: helm + - name: REDPANDA_METRICS_K8S_CHART_VERSION + value: 3.7.0 + - name: REDPANDA_METRICS_K8S_CONSOLE_IMAGE_VERSION + value: redpandadata/console:v3.7.0 + - name: REDPANDA_METRICS_K8S_VERSION + value: v1.99.0-gke + - name: REDPANDA_METRICS_K8S_ENVIRONMENT + value: GCP + envFrom: [] + image: docker.redpanda.com/redpandadata/console:v3.7.0 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /admin/health + port: http + initialDelaySeconds: 0 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: console + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /admin/health + port: http + initialDelaySeconds: 10 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: {} + securityContext: + runAsNonRoot: true + volumeMounts: + - mountPath: /etc/console/configs + name: configs + readOnly: true + - mountPath: /etc/tls/certs + name: redpanda-certificates + imagePullSecrets: [] + initContainers: null + nodeSelector: {} + priorityClassName: "" + securityContext: + fsGroup: 99 + fsGroupChangePolicy: Always + runAsUser: 99 + serviceAccountName: redpanda-console + tolerations: [] + topologySpreadConstraints: [] + volumes: + - configMap: + name: redpanda-console + name: configs + - name: redpanda-certificates + projected: + sources: + - secret: + items: + - key: ca.crt + path: secrets/redpanda-default-cert/ca.crt + name: redpanda-default-cert +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda + namespace: default +spec: + podManagementPolicy: Parallel + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + serviceName: redpanda + template: + metadata: + annotations: + config.redpanda.com/checksum: e5b4f6eb32c0dcd720400c66c2ed67133071f6fa09f483e8049af4b845a6d9a1 + labels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + cluster.redpanda.com/broker: "true" + helm.sh/chart: redpanda-26.1.1 + redpanda.com/poddisruptionbudget: redpanda + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + topologyKey: kubernetes.io/hostname + automountServiceAccountToken: false + containers: + - command: + - rpk + - redpanda + - start + - --advertise-rpc-addr=$(SERVICE_NAME).redpanda.default.svc.cluster.local.:33145 + env: + - name: SERVICE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: REDPANDA_METRICS_K8S_VERSION + value: v1.99.0-gke + - name: REDPANDA_METRICS_K8S_DEPLOYMENT_TYPE + value: helm + - name: REDPANDA_METRICS_K8S_CHART_VERSION + value: 26.1.1 + - name: REDPANDA_METRICS_K8S_OPERATOR_IMAGE_VERSION + value: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + - name: REDPANDA_METRICS_K8S_ENVIRONMENT + value: GCP + image: docker.redpanda.com/redpandadata/redpanda:v26.1.1 + lifecycle: + postStart: + exec: + command: + - bash + - -c + - 'timeout -v 45 bash -x /var/lifecycle/postStart.sh 2>&1 | sed "s/^/lifecycle-hook + post-start $(date): /" | tee /proc/1/fd/1; true' + preStop: + exec: + command: + - bash + - -c + - 'timeout -v 45 bash -x /var/lifecycle/preStop.sh 2>&1 | sed "s/^/lifecycle-hook + pre-stop $(date): /" | tee /proc/1/fd/1; true' + livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + tcpSocket: + port: 9644 + name: redpanda + ports: + - containerPort: 9644 + name: admin + - containerPort: 9645 + name: admin-default + - containerPort: 8082 + name: http + - containerPort: 8083 + name: http-default + - containerPort: 9093 + name: kafka + - containerPort: 9094 + name: kafka-default + - containerPort: 33145 + name: rpc + - containerPort: 8081 + name: schemaregistry + - containerPort: 8084 + name: schema-default + resources: + limits: + cpu: 1 + memory: 2.5Gi + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + startupProbe: + exec: + command: + - /bin/sh + - -c + - | + set -e + RESULT=$(curl --silent --fail -k -m 5 --cacert /etc/tls/certs/default/ca.crt "https://${SERVICE_NAME}.redpanda.default.svc.cluster.local.:9644/v1/status/ready") + echo $RESULT + echo $RESULT | grep ready + failureThreshold: 120 + initialDelaySeconds: 1 + periodSeconds: 10 + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: config + - mountPath: /tmp/base-config + name: base-config + - mountPath: /var/lifecycle + name: lifecycle-scripts + - mountPath: /var/lib/redpanda/data + name: datadir + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: kube-api-access + readOnly: true + - args: + - supervisor + - -- + - /redpanda-operator + - sidecar + - --redpanda-yaml + - /etc/redpanda/redpanda.yaml + - --redpanda-cluster-namespace + - default + - --redpanda-cluster-name + - redpanda + - --selector=helm.sh/chart=redpanda-26.1.1,app.kubernetes.io/name=redpanda,app.kubernetes.io/instance=redpanda + - --run-broker-probe + - --broker-probe-broker-url + - $(SERVICE_NAME).redpanda.default.svc.cluster.local.:9644 + command: + - /redpanda-operator + env: + - name: SERVICE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: sidecar + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: 8093 + initialDelaySeconds: 1 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 0 + resources: {} + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: config + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: kube-api-access + readOnly: true + imagePullSecrets: [] + initContainers: + - command: + - /bin/bash + - -c + - rpk redpanda tune all + env: null + image: docker.redpanda.com/redpandadata/redpanda:v26.1.1 + name: tuning + resources: {} + securityContext: + capabilities: + add: + - SYS_RESOURCE + privileged: true + runAsGroup: 0 + runAsNonRoot: false + runAsUser: 0 + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: base-config + - mountPath: /var/lib/redpanda/data + name: datadir + - command: + - /bin/bash + - -c + - trap "exit 0" TERM; exec $CONFIGURATOR_SCRIPT "${SERVICE_NAME}" "${KUBERNETES_NODE_NAME}" + & wait $! + env: + - name: CONFIGURATOR_SCRIPT + value: /etc/secrets/configurator/scripts/configurator.sh + - name: SERVICE_NAME + valueFrom: + configMapKeyRef: null + fieldRef: + fieldPath: metadata.name + resourceFieldRef: null + secretKeyRef: null + - name: KUBERNETES_NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: HOST_IP_ADDRESS + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + image: docker.redpanda.com/redpandadata/redpanda:v26.1.1 + name: redpanda-configurator + resources: {} + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + volumeMounts: + - mountPath: /etc/tls/certs/default + name: redpanda-default-cert + - mountPath: /etc/tls/certs/external + name: redpanda-external-cert + - mountPath: /etc/redpanda + name: config + - mountPath: /tmp/base-config + name: base-config + - mountPath: /etc/secrets/configurator/scripts/ + name: redpanda-configurator + - command: + - /redpanda-operator + - bootstrap + - --in-dir + - /tmp/base-config + - --out-dir + - /tmp/config + env: null + image: docker.redpanda.com/redpandadata/redpanda-operator:v26.1.1 + name: bootstrap-yaml-envsubst + resources: + limits: + cpu: 100m + memory: 125Mi + requests: + cpu: 100m + memory: 125Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /tmp/config/ + name: config + - mountPath: /tmp/base-config/ + name: base-config + nodeSelector: {} + priorityClassName: "" + securityContext: + fsGroup: 101 + fsGroupChangePolicy: OnRootMismatch + runAsUser: 101 + serviceAccountName: redpanda + terminationGracePeriodSeconds: 90 + tolerations: [] + topologySpreadConstraints: + - labelSelector: + matchLabels: + app.kubernetes.io/component: redpanda-statefulset + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + volumes: + - name: redpanda-default-cert + secret: + defaultMode: 288 + secretName: redpanda-default-cert + - name: redpanda-external-cert + secret: + defaultMode: 288 + secretName: redpanda-external-cert + - name: lifecycle-scripts + secret: + defaultMode: 509 + secretName: redpanda-sts-lifecycle + - configMap: + name: redpanda + name: base-config + - emptyDir: {} + name: config + - name: redpanda-configurator + secret: + defaultMode: 509 + secretName: redpanda-configurator + - name: datadir + persistentVolumeClaim: + claimName: datadir + - name: kube-api-access + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + expirationSeconds: 3607 + path: token + - configMap: + items: + - key: ca.crt + path: ca.crt + name: kube-root-ca.crt + - downwardAPI: + items: + - fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + path: namespace + updateStrategy: + type: RollingUpdate + volumeClaimTemplates: + - metadata: + annotations: null + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/name: redpanda + name: datadir + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi + status: {} +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-root-certificate + namespace: default +spec: + commonName: redpanda-default-root-certificate + duration: 43800h0m0s + isCA: true + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-default-selfsigned-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-default-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-root-certificate + namespace: default +spec: + commonName: redpanda-external-root-certificate + duration: 43800h0m0s + isCA: true + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-external-selfsigned-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-external-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-cert + namespace: default +spec: + dnsNames: + - redpanda-cluster.redpanda.default.svc.cluster.local + - redpanda-cluster.redpanda.default.svc + - redpanda-cluster.redpanda.default + - '*.redpanda-cluster.redpanda.default.svc.cluster.local' + - '*.redpanda-cluster.redpanda.default.svc' + - '*.redpanda-cluster.redpanda.default' + - redpanda.default.svc.cluster.local + - redpanda.default.svc + - redpanda.default + - '*.redpanda.default.svc.cluster.local' + - '*.redpanda.default.svc' + - '*.redpanda.default' + duration: 43800h0m0s + isCA: false + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-default-root-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-default-cert +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-cert + namespace: default +spec: + dnsNames: + - redpanda-cluster.redpanda.default.svc.cluster.local + - redpanda-cluster.redpanda.default.svc + - redpanda-cluster.redpanda.default + - '*.redpanda-cluster.redpanda.default.svc.cluster.local' + - '*.redpanda-cluster.redpanda.default.svc' + - '*.redpanda-cluster.redpanda.default' + - redpanda.default.svc.cluster.local + - redpanda.default.svc + - redpanda.default + - '*.redpanda.default.svc.cluster.local' + - '*.redpanda.default.svc' + - '*.redpanda.default' + duration: 43800h0m0s + isCA: false + issuerRef: + group: cert-manager.io + kind: Issuer + name: redpanda-external-root-issuer + privateKey: + algorithm: ECDSA + size: 256 + secretName: redpanda-external-cert +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-selfsigned-issuer + namespace: default +spec: + selfSigned: {} +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-default-root-issuer + namespace: default +spec: + ca: + secretName: redpanda-default-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-selfsigned-issuer + namespace: default +spec: + selfSigned: {} +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-external-root-issuer + namespace: default +spec: + ca: + secretName: redpanda-external-root-certificate +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-default-bootstrap + namespace: default +spec: + hostnames: + - redpanda.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: redpanda-gateway-bootstrap + port: 9094 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-default-0 + namespace: default +spec: + hostnames: + - redpanda-0-broker.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: gw-redpanda-0 + port: 9094 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-default-1 + namespace: default +spec: + hostnames: + - redpanda-1-broker.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: gw-redpanda-1 + port: 9094 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TLSRoute +metadata: + labels: + app.kubernetes.io/component: redpanda + app.kubernetes.io/instance: redpanda + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: redpanda + helm.sh/chart: redpanda-26.1.1 + name: redpanda-kafka-default-2 + namespace: default +spec: + hostnames: + - redpanda-2-broker.example.com + parentRefs: + - name: kafka-gateway + sectionName: kafka + rules: + - backendRefs: + - name: gw-redpanda-2 + port: 9094 +--- +# Source: redpanda/templates/entry-point.yaml +apiVersion: batch/v1 +kind: Job metadata: annotations: helm.sh/hook: post-install,post-upgrade diff --git a/charts/redpanda/testdata/template-cases.txtar b/charts/redpanda/testdata/template-cases.txtar index 2a9e1ab80..846b993f0 100644 --- a/charts/redpanda/testdata/template-cases.txtar +++ b/charts/redpanda/testdata/template-cases.txtar @@ -1240,3 +1240,70 @@ statefulset: - name: "3rd-party-certs" secret: secretName: "redpanda-external-cert" + +-- gateway-api-tlsroute -- +# Gateway API TLSRoute-based external access with per-listener SNI hostnames. +# Verifies that ClusterIP services and TLSRoute resources are generated, +# and that NodePort/LoadBalancer services are NOT created. +# ASSERT-NO-ERROR +# ASSERT-GOLDEN +external: + enabled: true + gateway: + enabled: true + parentRefs: + - name: kafka-gateway + sectionName: kafka + advertisedPort: 9094 +tls: + enabled: true + certs: + default: + caEnabled: true +listeners: + kafka: + external: + default: + port: 9094 + gateway: true + host: redpanda.example.com + hostTemplate: redpanda-$POD_ORDINAL-broker.example.com + tls: + cert: default + +-- gateway-api-migration -- +# Gradual migration: existing NodePort listener coexists with a new TLSRoute +# listener on a different port. Verifies that: +# - The NodePort service includes only the traditional listener port (9094) +# - Gateway ClusterIP services include only the TLSRoute listener port (9095) +# - TLSRoutes are created only for the gateway listener +# ASSERT-NO-ERROR +# ASSERT-GOLDEN +external: + enabled: true + type: NodePort + gateway: + enabled: true + parentRefs: + - name: kafka-gateway + sectionName: kafka + advertisedPort: 443 +tls: + enabled: true + certs: + default: + caEnabled: true +listeners: + kafka: + external: + default: + port: 9094 + advertisedPorts: + - 30092 + gw-listener: + port: 9095 + gateway: true + host: redpanda.example.com + hostTemplate: redpanda-$POD_ORDINAL-broker.example.com + tls: + cert: default diff --git a/charts/redpanda/tlsroute.go b/charts/redpanda/tlsroute.go new file mode 100644 index 000000000..43a09b7fe --- /dev/null +++ b/charts/redpanda/tlsroute.go @@ -0,0 +1,214 @@ +// Copyright 2026 Redpanda Data, Inc. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.md +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0 + +// +gotohelm:filename=_tlsroute.go.tpl +package redpanda + +import ( + "fmt" + "strings" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/ptr" + + "github.com/redpanda-data/redpanda-operator/gotohelm/helmette" +) + +// Lightweight TLSRoute types that produce the correct YAML for +// gateway.networking.k8s.io/v1alpha2 TLSRoute resources. +// We define these locally because the upstream Gateway API Go types use type +// aliases (v1alpha2.X = v1.X) that the gotohelm transpiler cannot handle. + +// TLSRoute mirrors the Gateway API TLSRoute resource. +type TLSRoute struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec TLSRouteSpec `json:"spec"` +} + +// TLSRouteSpec defines the desired state of a TLSRoute. +type TLSRouteSpec struct { + ParentRefs []TLSRouteParentRef `json:"parentRefs"` + Hostnames []string `json:"hostnames,omitempty"` + Rules []TLSRouteRule `json:"rules"` +} + +// TLSRouteParentRef identifies a parent resource (typically a Gateway). +type TLSRouteParentRef struct { + Group *string `json:"group,omitempty"` + Kind *string `json:"kind,omitempty"` + Name string `json:"name"` + Namespace *string `json:"namespace,omitempty"` + SectionName *string `json:"sectionName,omitempty"` +} + +// TLSRouteRule configures a routing rule. +type TLSRouteRule struct { + BackendRefs []TLSRouteBackendRef `json:"backendRefs,omitempty"` +} + +// TLSRouteBackendRef identifies a backend to route traffic to. +type TLSRouteBackendRef struct { + Name string `json:"name"` + Port int32 `json:"port"` +} + +// DeepCopyObject implements runtime.Object for TLSRoute to satisfy kube.Object. +// +gotohelm:ignore=true +func (t *TLSRoute) DeepCopyObject() runtime.Object { + cp := *t + return &cp +} + +// TLSRoutes returns Gateway API TLSRoute resources for external access. +func TLSRoutes(state *RenderState) []*TLSRoute { + if !state.Values.External.IsGatewayEnabled() { + return nil + } + + gw := state.Values.External.Gateway + parentRefs := toTLSRouteParentRefs(gw.ParentRefs) + labels := FullLabels(state) + fullname := Fullname(state) + + pods := PodNames(state, Pool{Statefulset: state.Values.Statefulset}) + for _, set := range state.Pools { + pods = append(pods, PodNames(state, set)...) + } + + var routes []*TLSRoute + + for name, listener := range helmette.SortedMap(state.Values.Listeners.Kafka.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + rs := tlsRoutesForListener(fullname, state.Release.Namespace, labels, parentRefs, pods, ptr.Deref(listener.Host, ""), ptr.Deref(listener.HostTemplate, ""), name, "kafka", listener.Port) + routes = append(routes, rs...) + } + + for name, listener := range helmette.SortedMap(state.Values.Listeners.HTTP.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + rs := tlsRoutesForListener(fullname, state.Release.Namespace, labels, parentRefs, pods, ptr.Deref(listener.Host, ""), ptr.Deref(listener.HostTemplate, ""), name, "http", listener.Port) + routes = append(routes, rs...) + } + + for name, listener := range helmette.SortedMap(state.Values.Listeners.Admin.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + rs := tlsRoutesForListener(fullname, state.Release.Namespace, labels, parentRefs, pods, ptr.Deref(listener.Host, ""), ptr.Deref(listener.HostTemplate, ""), name, "admin", listener.Port) + routes = append(routes, rs...) + } + + for name, listener := range helmette.SortedMap(state.Values.Listeners.SchemaRegistry.External) { + if !ptr.Deref(listener.Enabled, state.Values.External.Enabled) || !listener.IsGatewayListener() { + continue + } + rs := tlsRoutesForListener(fullname, state.Release.Namespace, labels, parentRefs, pods, ptr.Deref(listener.Host, ""), ptr.Deref(listener.HostTemplate, ""), name, "schema", listener.Port) + routes = append(routes, rs...) + } + + return routes +} + +func tlsRoutesForListener(fullname string, namespace string, labels map[string]string, parentRefs []TLSRouteParentRef, pods []string, host string, hostTemplate string, name string, listenerTag string, port int32) []*TLSRoute { + var routes []*TLSRoute + + if host == "" { + panic(fmt.Sprintf("gateway listener %s/%s requires host", listenerTag, name)) + } + + if listenerTag == "kafka" && len(pods) > 1 && hostTemplate == "" { + panic(fmt.Sprintf("gateway listener %s/%s requires hostTemplate when replicas > 1", listenerTag, name)) + } + + bootstrapSvcName := fmt.Sprintf("%s-gateway-bootstrap", fullname) + + bootstrap := &TLSRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "gateway.networking.k8s.io/v1alpha2", + Kind: "TLSRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%s-%s-bootstrap", fullname, listenerTag, name), + Namespace: namespace, + Labels: labels, + }, + Spec: TLSRouteSpec{ + ParentRefs: parentRefs, + Hostnames: []string{host}, + Rules: []TLSRouteRule{ + { + BackendRefs: []TLSRouteBackendRef{ + { + Name: bootstrapSvcName, + Port: port, + }, + }, + }, + }, + }, + } + routes = append(routes, bootstrap) + + if hostTemplate == "" { + return routes + } + + for i, podname := range pods { + brokerHost := renderBrokerHost(hostTemplate, i, podname) + brokerSvcName := fmt.Sprintf("gw-%s", podname) + + route := &TLSRoute{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "gateway.networking.k8s.io/v1alpha2", + Kind: "TLSRoute", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%s-%s-%d", fullname, listenerTag, name, i), + Namespace: namespace, + Labels: labels, + }, + Spec: TLSRouteSpec{ + ParentRefs: parentRefs, + Hostnames: []string{brokerHost}, + Rules: []TLSRouteRule{ + { + BackendRefs: []TLSRouteBackendRef{ + { + Name: brokerSvcName, + Port: port, + }, + }, + }, + }, + }, + } + routes = append(routes, route) + } + + return routes +} + +func toTLSRouteParentRefs(refs []GatewayParentRef) []TLSRouteParentRef { + var parentRefs []TLSRouteParentRef + for _, ref := range refs { + parentRefs = append(parentRefs, TLSRouteParentRef(ref)) + } + return parentRefs +} + +func renderBrokerHost(tmpl string, ordinal int, podName string) string { + result := strings.ReplaceAll(tmpl, "$POD_ORDINAL", fmt.Sprintf("%d", ordinal)) + result = strings.ReplaceAll(result, "$POD_NAME", podName) + return result +} diff --git a/charts/redpanda/tlsroute_test.go b/charts/redpanda/tlsroute_test.go new file mode 100644 index 000000000..5779148b3 --- /dev/null +++ b/charts/redpanda/tlsroute_test.go @@ -0,0 +1,79 @@ +// Copyright 2026 Redpanda Data, Inc. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.md +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0 + +package redpanda + +import ( + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestTLSRoutesForListenerRequiresHost(t *testing.T) { + require.PanicsWithValue(t, + "gateway listener kafka/default requires host", + func() { + tlsRoutesForListener( + "redpanda", + "default", + map[string]string{"app": "redpanda"}, + []TLSRouteParentRef{{Name: "shared-gateway"}}, + []string{"redpanda-0"}, + "", + "", + "default", + "kafka", + 9094, + ) + }, + ) +} + +func TestTLSRoutesForKafkaListenerRequiresHostTemplateForMultiBroker(t *testing.T) { + require.PanicsWithValue(t, + "gateway listener kafka/default requires hostTemplate when replicas > 1", + func() { + tlsRoutesForListener( + "redpanda", + "default", + map[string]string{"app": "redpanda"}, + []TLSRouteParentRef{{Name: "shared-gateway"}}, + []string{"redpanda-0", "redpanda-1"}, + "redpanda.example.com", + "", + "default", + "kafka", + 9094, + ) + }, + ) +} + +func TestTLSRoutesForHTTPListenerAllowsBootstrapOnlyHost(t *testing.T) { + routes := tlsRoutesForListener( + "redpanda", + "default", + map[string]string{"app": "redpanda"}, + []TLSRouteParentRef{{Name: "shared-gateway"}}, + []string{"redpanda-0", "redpanda-1"}, + "proxy.example.com", + "", + "default", + "http", + 8082, + ) + + require.Len(t, routes, 1) + require.Equal(t, metav1.TypeMeta{ + APIVersion: "gateway.networking.k8s.io/v1alpha2", + Kind: "TLSRoute", + }, routes[0].TypeMeta) + require.Equal(t, []string{"proxy.example.com"}, routes[0].Spec.Hostnames) +} diff --git a/charts/redpanda/values.go b/charts/redpanda/values.go index 56346efc7..b5694a9b3 100644 --- a/charts/redpanda/values.go +++ b/charts/redpanda/values.go @@ -260,6 +260,61 @@ type ExternalConfig struct { SourceRanges []string `json:"sourceRanges"` Service Enableable `json:"service"` ExternalDNS *Enableable `json:"externalDns"` + // Gateway configures Gateway API TLSRoute-based external access. + // When enabled, ClusterIP services and TLSRoute resources are created + // instead of NodePort/LoadBalancer services. The Gateway itself must be + // managed separately; the chart only creates TLSRoute resources that + // reference it. + Gateway *GatewayConfig `json:"gateway,omitempty"` +} + +// GatewayConfig holds configuration for Gateway API-based external access +// using TLSRoute resources with SNI-based routing. +type GatewayConfig struct { + // Enabled activates Gateway API TLSRoute-based external access. When true, + // this takes precedence over the NodePort/LoadBalancer external.type setting. + Enabled bool `json:"enabled"` + // ParentRefs defines which Gateway(s) handle the TLSRoutes. At least one + // parent reference must be provided. These are passed directly into each + // TLSRoute's spec.parentRefs. + ParentRefs []GatewayParentRef `json:"parentRefs"` + // AdvertisedPort is the port advertised to clients. Defaults to 443 + // because the actual listening port is configured on the Gateway, not + // on the TLSRoute. + AdvertisedPort *int32 `json:"advertisedPort,omitempty"` +} + +// GatewayParentRef identifies a Gateway (or ListenerSet) that should handle +// the TLSRoute traffic. The schema mirrors the upstream Gateway API +// ParentReference so users see familiar field names. +type GatewayParentRef struct { + // Group is the API group of the referent. Defaults to + // "gateway.networking.k8s.io". + Group *string `json:"group,omitempty"` + // Kind is the kind of the referent. Defaults to "Gateway". + Kind *string `json:"kind,omitempty"` + // Name is the name of the referent. + Name string `json:"name"` + // Namespace is the namespace of the referent. When unspecified, refers + // to the local namespace of the TLSRoute. + Namespace *string `json:"namespace,omitempty"` + // SectionName is the name of a section within the target resource. + SectionName *string `json:"sectionName,omitempty"` +} + +// IsGatewayEnabled returns true when Gateway API TLSRoute-based external +// access is configured and enabled. +func (e *ExternalConfig) IsGatewayEnabled() bool { + return e.Enabled && e.Gateway != nil && e.Gateway.Enabled && len(e.Gateway.ParentRefs) > 0 +} + +// GatewayAdvertisedPort returns the port to advertise to clients when using +// Gateway API. Defaults to 443. +func (g *GatewayConfig) GatewayAdvertisedPort() int32 { + if g.AdvertisedPort != nil { + return *g.AdvertisedPort + } + return 443 } type Enableable struct { @@ -1660,6 +1715,11 @@ func (l *ListenerConfig[T]) ServicePorts(namePrefix string, external *ExternalCo if !ptr.Deref(listener.Enabled, external.Enabled) { continue } + // Skip listeners that opted into Gateway API TLSRoute mode; + // they get their own ClusterIP services instead. + if external.IsGatewayEnabled() && ptr.Deref(listener.Gateway, false) { + continue + } fallbackPorts := append(listener.AdvertisedPorts, l.Port) @@ -1773,6 +1833,20 @@ type ExternalListener[T ~string] struct { AuthenticationMethod *T `json:"authenticationMethod,omitempty"` PrefixTemplate *string `json:"prefixTemplate,omitempty"` + + // Gateway opts this individual listener into Gateway API TLSRoute mode. + // Requires external.gateway to be configured with parentRefs. + // When true, a TLSRoute is created for this listener instead of + // including it in NodePort/LoadBalancer services. This allows gradual + // migration: some listeners can use TLSRoute while others remain on + // NodePort/LoadBalancer. + Gateway *bool `json:"gateway,omitempty"` + // Host is the SNI hostname for the bootstrap TLSRoute (requires gateway: true). + Host *string `json:"host,omitempty"` + // HostTemplate is a template for per-broker TLSRoute SNI hostnames. + // Available variables: $POD_ORDINAL, $POD_NAME. + // Example: "kafka-$POD_ORDINAL-broker.example.com" + HostTemplate *string `json:"hostTemplate,omitempty"` } func (l *ExternalListener[T]) AsString() ExternalListener[string] { @@ -1790,6 +1864,9 @@ func (l *ExternalListener[T]) AsString() ExternalListener[string] { TLS: l.TLS, AuthenticationMethod: auth, PrefixTemplate: l.PrefixTemplate, + Gateway: l.Gateway, + Host: l.Host, + HostTemplate: l.HostTemplate, } } @@ -1802,6 +1879,12 @@ func (l *ExternalListener[T]) IsEnabled() bool { return ptr.Deref(l.Enabled, true) && l.Port > 0 } +// IsGatewayListener returns true when this listener has opted into Gateway API +// TLSRoute mode via the gateway: true field. +func (l *ExternalListener[T]) IsGatewayListener() bool { + return ptr.Deref(l.Gateway, false) +} + type TunableConfig map[string]any // +gotohelm:ignore=true diff --git a/charts/redpanda/values_partial.gen.go b/charts/redpanda/values_partial.gen.go index 626ad73c2..bf35ed55c 100644 --- a/charts/redpanda/values_partial.gen.go +++ b/charts/redpanda/values_partial.gen.go @@ -95,15 +95,16 @@ type PartialTLS struct { } type PartialExternalConfig struct { - Addresses []string "json:\"addresses,omitempty\"" - Annotations map[string]string "json:\"annotations,omitempty\"" - Domain *string "json:\"domain,omitempty\"" - Enabled *bool "json:\"enabled,omitempty\" jsonschema:\"required\"" - Type *corev1.ServiceType "json:\"type,omitempty\" jsonschema:\"pattern=^(LoadBalancer|NodePort)$\"" - PrefixTemplate *string "json:\"prefixTemplate,omitempty\"" - SourceRanges []string "json:\"sourceRanges,omitempty\"" - Service *PartialEnableable "json:\"service,omitempty\"" - ExternalDNS *PartialEnableable "json:\"externalDns,omitempty\"" + Addresses []string "json:\"addresses,omitempty\"" + Annotations map[string]string "json:\"annotations,omitempty\"" + Domain *string "json:\"domain,omitempty\"" + Enabled *bool "json:\"enabled,omitempty\" jsonschema:\"required\"" + Type *corev1.ServiceType "json:\"type,omitempty\" jsonschema:\"pattern=^(LoadBalancer|NodePort)$\"" + PrefixTemplate *string "json:\"prefixTemplate,omitempty\"" + SourceRanges []string "json:\"sourceRanges,omitempty\"" + Service *PartialEnableable "json:\"service,omitempty\"" + ExternalDNS *PartialEnableable "json:\"externalDns,omitempty\"" + Gateway *PartialGatewayConfig "json:\"gateway,omitempty\"" } type PartialLogging struct { @@ -325,6 +326,12 @@ type PartialSASLAuth struct { BootstrapUser *PartialBootstrapUser "json:\"bootstrapUser,omitempty\"" } +type PartialGatewayConfig struct { + Enabled *bool "json:\"enabled,omitempty\"" + ParentRefs []PartialGatewayParentRef "json:\"parentRefs,omitempty\"" + AdvertisedPort *int32 "json:\"advertisedPort,omitempty\"" +} + type PartialListenerConfig[T ~string] struct { Enabled *bool "json:\"enabled,omitempty\"" External map[string]PartialExternalListener[T] "json:\"external,omitempty\"" @@ -403,6 +410,14 @@ type PartialSASLUser struct { Mechanism *SASLMechanism "json:\"mechanism,omitempty\"" } +type PartialGatewayParentRef struct { + Group *string "json:\"group,omitempty\"" + Kind *string "json:\"kind,omitempty\"" + Name *string "json:\"name,omitempty\"" + Namespace *string "json:\"namespace,omitempty\"" + SectionName *string "json:\"sectionName,omitempty\"" +} + type PartialExternalListener[T ~string] struct { Enabled *bool "json:\"enabled,omitempty\"" AdvertisedPorts []int32 "json:\"advertisedPorts,omitempty\" jsonschema:\"minItems=1\"" @@ -411,6 +426,9 @@ type PartialExternalListener[T ~string] struct { TLS *PartialExternalTLS "json:\"tls,omitempty\"" AuthenticationMethod *T "json:\"authenticationMethod,omitempty\"" PrefixTemplate *string "json:\"prefixTemplate,omitempty\"" + Gateway *bool "json:\"gateway,omitempty\"" + Host *string "json:\"host,omitempty\"" + HostTemplate *string "json:\"hostTemplate,omitempty\"" } type PartialTrustStore struct { diff --git a/operator/api/applyconfiguration/redpanda/v1alpha2/external.go b/operator/api/applyconfiguration/redpanda/v1alpha2/external.go index b2eb0df38..a4bca90ba 100644 --- a/operator/api/applyconfiguration/redpanda/v1alpha2/external.go +++ b/operator/api/applyconfiguration/redpanda/v1alpha2/external.go @@ -14,15 +14,16 @@ package v1alpha2 // ExternalApplyConfiguration represents a declarative configuration of the External type for use // with apply. type ExternalApplyConfiguration struct { - Addresses []string `json:"addresses,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` - Domain *string `json:"domain,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - Service *ExternalServiceApplyConfiguration `json:"service,omitempty"` - SourceRanges []string `json:"sourceRanges,omitempty"` - Type *string `json:"type,omitempty"` - ExternalDNS *ExternalDNSApplyConfiguration `json:"externalDns,omitempty"` - PrefixTemplate *string `json:"prefixTemplate,omitempty"` + Addresses []string `json:"addresses,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + Domain *string `json:"domain,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Service *ExternalServiceApplyConfiguration `json:"service,omitempty"` + SourceRanges []string `json:"sourceRanges,omitempty"` + Type *string `json:"type,omitempty"` + ExternalDNS *ExternalDNSApplyConfiguration `json:"externalDns,omitempty"` + PrefixTemplate *string `json:"prefixTemplate,omitempty"` + Gateway *GatewayExternalConfigApplyConfiguration `json:"gateway,omitempty"` } // ExternalApplyConfiguration constructs a declarative configuration of the External type for use with @@ -112,3 +113,11 @@ func (b *ExternalApplyConfiguration) WithPrefixTemplate(value string) *ExternalA b.PrefixTemplate = &value return b } + +// WithGateway sets the Gateway field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Gateway field is set to the value of the last call. +func (b *ExternalApplyConfiguration) WithGateway(value *GatewayExternalConfigApplyConfiguration) *ExternalApplyConfiguration { + b.Gateway = value + return b +} diff --git a/operator/api/applyconfiguration/redpanda/v1alpha2/gatewayexternalconfig.go b/operator/api/applyconfiguration/redpanda/v1alpha2/gatewayexternalconfig.go new file mode 100644 index 000000000..ec59050a1 --- /dev/null +++ b/operator/api/applyconfiguration/redpanda/v1alpha2/gatewayexternalconfig.go @@ -0,0 +1,55 @@ +// Copyright 2026 Redpanda Data, Inc. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.md +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0 + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha2 + +// GatewayExternalConfigApplyConfiguration represents a declarative configuration of the GatewayExternalConfig type for use +// with apply. +type GatewayExternalConfigApplyConfiguration struct { + Enabled *bool `json:"enabled,omitempty"` + ParentRefs []GatewayParentRefConfigApplyConfiguration `json:"parentRefs,omitempty"` + AdvertisedPort *int32 `json:"advertisedPort,omitempty"` +} + +// GatewayExternalConfigApplyConfiguration constructs a declarative configuration of the GatewayExternalConfig type for use with +// apply. +func GatewayExternalConfig() *GatewayExternalConfigApplyConfiguration { + return &GatewayExternalConfigApplyConfiguration{} +} + +// WithEnabled sets the Enabled field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Enabled field is set to the value of the last call. +func (b *GatewayExternalConfigApplyConfiguration) WithEnabled(value bool) *GatewayExternalConfigApplyConfiguration { + b.Enabled = &value + return b +} + +// WithParentRefs adds the given value to the ParentRefs field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the ParentRefs field. +func (b *GatewayExternalConfigApplyConfiguration) WithParentRefs(values ...*GatewayParentRefConfigApplyConfiguration) *GatewayExternalConfigApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithParentRefs") + } + b.ParentRefs = append(b.ParentRefs, *values[i]) + } + return b +} + +// WithAdvertisedPort sets the AdvertisedPort field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the AdvertisedPort field is set to the value of the last call. +func (b *GatewayExternalConfigApplyConfiguration) WithAdvertisedPort(value int32) *GatewayExternalConfigApplyConfiguration { + b.AdvertisedPort = &value + return b +} diff --git a/operator/api/applyconfiguration/redpanda/v1alpha2/gatewayparentrefconfig.go b/operator/api/applyconfiguration/redpanda/v1alpha2/gatewayparentrefconfig.go new file mode 100644 index 000000000..a52231a60 --- /dev/null +++ b/operator/api/applyconfiguration/redpanda/v1alpha2/gatewayparentrefconfig.go @@ -0,0 +1,68 @@ +// Copyright 2026 Redpanda Data, Inc. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.md +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0 + +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1alpha2 + +// GatewayParentRefConfigApplyConfiguration represents a declarative configuration of the GatewayParentRefConfig type for use +// with apply. +type GatewayParentRefConfigApplyConfiguration struct { + Group *string `json:"group,omitempty"` + Kind *string `json:"kind,omitempty"` + Name *string `json:"name,omitempty"` + Namespace *string `json:"namespace,omitempty"` + SectionName *string `json:"sectionName,omitempty"` +} + +// GatewayParentRefConfigApplyConfiguration constructs a declarative configuration of the GatewayParentRefConfig type for use with +// apply. +func GatewayParentRefConfig() *GatewayParentRefConfigApplyConfiguration { + return &GatewayParentRefConfigApplyConfiguration{} +} + +// WithGroup sets the Group field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Group field is set to the value of the last call. +func (b *GatewayParentRefConfigApplyConfiguration) WithGroup(value string) *GatewayParentRefConfigApplyConfiguration { + b.Group = &value + return b +} + +// WithKind sets the Kind field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Kind field is set to the value of the last call. +func (b *GatewayParentRefConfigApplyConfiguration) WithKind(value string) *GatewayParentRefConfigApplyConfiguration { + b.Kind = &value + return b +} + +// WithName sets the Name field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Name field is set to the value of the last call. +func (b *GatewayParentRefConfigApplyConfiguration) WithName(value string) *GatewayParentRefConfigApplyConfiguration { + b.Name = &value + return b +} + +// WithNamespace sets the Namespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the Namespace field is set to the value of the last call. +func (b *GatewayParentRefConfigApplyConfiguration) WithNamespace(value string) *GatewayParentRefConfigApplyConfiguration { + b.Namespace = &value + return b +} + +// WithSectionName sets the SectionName field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SectionName field is set to the value of the last call. +func (b *GatewayParentRefConfigApplyConfiguration) WithSectionName(value string) *GatewayParentRefConfigApplyConfiguration { + b.SectionName = &value + return b +} diff --git a/operator/api/redpanda/v1alpha2/redpanda_clusterspec_types.go b/operator/api/redpanda/v1alpha2/redpanda_clusterspec_types.go index 150338b8a..4309c6427 100644 --- a/operator/api/redpanda/v1alpha2/redpanda_clusterspec_types.go +++ b/operator/api/redpanda/v1alpha2/redpanda_clusterspec_types.go @@ -520,6 +520,32 @@ type External struct { ExternalDNS *ExternalDNS `json:"externalDns,omitempty"` // Specifies a naming prefix template for external Services. PrefixTemplate *string `json:"prefixTemplate,omitempty"` + // Configures Gateway API TLSRoute-based external access. When enabled, ClusterIP services and TLSRoute resources are created instead of NodePort/LoadBalancer services. The Gateway itself must be managed externally. + Gateway *GatewayExternalConfig `json:"gateway,omitempty"` +} + +// GatewayExternalConfig holds configuration for Gateway API-based external access using TLSRoute resources with SNI-based routing. +type GatewayExternalConfig struct { + // Enables Gateway API TLSRoute-based external access. + Enabled *bool `json:"enabled,omitempty"` + // Defines which Gateway(s) handle the TLSRoutes. At least one parent reference must be provided. + ParentRefs []GatewayParentRefConfig `json:"parentRefs,omitempty"` + // The port advertised to clients. Defaults to 443. + AdvertisedPort *int32 `json:"advertisedPort,omitempty"` +} + +// GatewayParentRefConfig identifies a Gateway (or ListenerSet) that should handle the TLSRoute traffic. Schema mirrors the upstream Gateway API ParentReference. +type GatewayParentRefConfig struct { + // API group of the referent. Defaults to "gateway.networking.k8s.io". + Group *string `json:"group,omitempty"` + // Kind of the referent. Defaults to "Gateway". + Kind *string `json:"kind,omitempty"` + // Name of the referent. + Name string `json:"name"` + // Namespace of the referent. + Namespace *string `json:"namespace,omitempty"` + // Name of a section within the target resource. + SectionName *string `json:"sectionName,omitempty"` } // Logging configures logging settings in the Helm values. See https://docs.redpanda.com/current/manage/kubernetes/troubleshooting/troubleshoot/. @@ -973,6 +999,12 @@ type ExternalListener struct { // Specifies the network port that the external Service listens on. AdvertisedPorts []int32 `json:"advertisedPorts,omitempty"` NodePort *int32 `json:"nodePort,omitempty"` + // Opts this listener into Gateway API TLSRoute mode. Requires external.gateway to be configured. When true, a TLSRoute is created for this listener instead of including it in NodePort/LoadBalancer services. + Gateway *bool `json:"gateway,omitempty"` + // Host is the SNI hostname for the bootstrap TLSRoute when using Gateway API external access. + Host *string `json:"host,omitempty"` + // HostTemplate is a Go template for per-broker TLSRoute SNI hostnames. Supports $POD_ORDINAL and $POD_NAME variables. + HostTemplate *string `json:"hostTemplate,omitempty"` } // Admin configures settings for the Admin API listeners. diff --git a/operator/api/redpanda/v1alpha2/redpanda_types_test.go b/operator/api/redpanda/v1alpha2/redpanda_types_test.go index 3cca517a7..c4ba3263f 100644 --- a/operator/api/redpanda/v1alpha2/redpanda_types_test.go +++ b/operator/api/redpanda/v1alpha2/redpanda_types_test.go @@ -149,6 +149,17 @@ func TestHelmValuesCompat(t *testing.T) { // Incorrect type (should be a *resource.Quantity) on an anonymous struct in Partial Values. from.Storage.Tiered.PersistentVolume.Size = nil } + // GatewayParentRef.Name is `string` (not *string) in the Helm chart + // but the partial generator makes it `*string`. Ensure Name is always + // non-nil so the partial's JSON includes "name":"" matching the CRD's + // required field which always serializes. + if from.External != nil && from.External.Gateway != nil { + for i := range from.External.Gateway.ParentRefs { + if from.External.Gateway.ParentRefs[i].Name == nil { + from.External.Gateway.ParentRefs[i].Name = ptr.To("") + } + } + } }) })) } diff --git a/operator/api/redpanda/v1alpha2/testdata/crd-docs.adoc b/operator/api/redpanda/v1alpha2/testdata/crd-docs.adoc index ba6a379ae..3d2e42e50 100644 --- a/operator/api/redpanda/v1alpha2/testdata/crd-docs.adoc +++ b/operator/api/redpanda/v1alpha2/testdata/crd-docs.adoc @@ -1190,6 +1190,7 @@ External defines external connectivity settings in the Helm values. | *`type`* __string__ | Specifies the external Service type. Only NodePort and LoadBalancer are supported. If undefined, then advertised listeners will be configured in Redpanda, but the Helm chart will not create a Service. NodePort is recommended in cases where latency is a priority. + | | | *`externalDns`* __xref:{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-externaldns[$$ExternalDNS$$]__ | Defines externalDNS configurations. + | | | *`prefixTemplate`* __string__ | Specifies a naming prefix template for external Services. + | | +| *`gateway`* __xref:{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-gatewayexternalconfig[$$GatewayExternalConfig$$]__ | Configures Gateway API TLSRoute-based external access. When enabled, ClusterIP services and TLSRoute resources are created instead of NodePort/LoadBalancer services. The Gateway itself must be managed externally. + | | |=== @@ -1248,6 +1249,9 @@ internal and external listeners. However, it is ignored when specified + on internal listeners. + | | | *`advertisedPorts`* __integer array__ | Specifies the network port that the external Service listens on. + | | | *`nodePort`* __integer__ | | | +| *`gateway`* __boolean__ | Opts this listener into Gateway API TLSRoute mode. Requires external.gateway to be configured. When true, a TLSRoute is created for this listener instead of including it in NodePort/LoadBalancer services. + | | +| *`host`* __string__ | Host is the SNI hostname for the bootstrap TLSRoute when using Gateway API external access. + | | +| *`hostTemplate`* __string__ | HostTemplate is a Go template for per-broker TLSRoute SNI hostnames. Supports $POD_ORDINAL and $POD_NAME variables. + | | |=== @@ -1334,6 +1338,54 @@ FilterType specifies the type, either include or exclude of a consumer group fil |=== +[id="{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-gatewayexternalconfig"] +==== GatewayExternalConfig + + + +GatewayExternalConfig holds configuration for Gateway API-based external access using TLSRoute resources with SNI-based routing. + + + +.Appears In: +**** +- xref:{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-external[$$External$$] +**** + +[cols="20a,50a,15a,15a", options="header"] +|=== +| Field | Description | Default | Validation +| *`enabled`* __boolean__ | Enables Gateway API TLSRoute-based external access. + | | +| *`parentRefs`* __xref:{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-gatewayparentrefconfig[$$GatewayParentRefConfig$$] array__ | Defines which Gateway(s) handle the TLSRoutes. At least one parent reference must be provided. + | | +| *`advertisedPort`* __integer__ | The port advertised to clients. Defaults to 443. + | | +|=== + + +[id="{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-gatewayparentrefconfig"] +==== GatewayParentRefConfig + + + +GatewayParentRefConfig identifies a Gateway (or ListenerSet) that should handle the TLSRoute traffic. Schema mirrors the upstream Gateway API ParentReference. + + + +.Appears In: +**** +- xref:{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-gatewayexternalconfig[$$GatewayExternalConfig$$] +**** + +[cols="20a,50a,15a,15a", options="header"] +|=== +| Field | Description | Default | Validation +| *`group`* __string__ | API group of the referent. Defaults to "gateway.networking.k8s.io". + | | +| *`kind`* __string__ | Kind of the referent. Defaults to "Gateway". + | | +| *`name`* __string__ | Name of the referent. + | | +| *`namespace`* __string__ | Namespace of the referent. + | | +| *`sectionName`* __string__ | Name of a section within the target resource. + | | +|=== + + [id="{anchor_prefix}-github-com-redpanda-data-redpanda-operator-operator-api-redpanda-v1alpha2-group"] ==== Group diff --git a/operator/api/redpanda/v1alpha2/zz_generated.deepcopy.go b/operator/api/redpanda/v1alpha2/zz_generated.deepcopy.go index b025e449d..ea6398c5d 100644 --- a/operator/api/redpanda/v1alpha2/zz_generated.deepcopy.go +++ b/operator/api/redpanda/v1alpha2/zz_generated.deepcopy.go @@ -1524,6 +1524,11 @@ func (in *External) DeepCopyInto(out *External) { *out = new(string) **out = **in } + if in.Gateway != nil { + in, out := &in.Gateway, &out.Gateway + *out = new(GatewayExternalConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new External. @@ -1570,6 +1575,21 @@ func (in *ExternalListener) DeepCopyInto(out *ExternalListener) { *out = new(int32) **out = **in } + if in.Gateway != nil { + in, out := &in.Gateway, &out.Gateway + *out = new(bool) + **out = **in + } + if in.Host != nil { + in, out := &in.Host, &out.Host + *out = new(string) + **out = **in + } + if in.HostTemplate != nil { + in, out := &in.HostTemplate, &out.HostTemplate + *out = new(string) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalListener. @@ -1652,6 +1672,73 @@ func (in *FsValidator) DeepCopy() *FsValidator { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayExternalConfig) DeepCopyInto(out *GatewayExternalConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.ParentRefs != nil { + in, out := &in.ParentRefs, &out.ParentRefs + *out = make([]GatewayParentRefConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.AdvertisedPort != nil { + in, out := &in.AdvertisedPort, &out.AdvertisedPort + *out = new(int32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayExternalConfig. +func (in *GatewayExternalConfig) DeepCopy() *GatewayExternalConfig { + if in == nil { + return nil + } + out := new(GatewayExternalConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayParentRefConfig) DeepCopyInto(out *GatewayParentRefConfig) { + *out = *in + if in.Group != nil { + in, out := &in.Group, &out.Group + *out = new(string) + **out = **in + } + if in.Kind != nil { + in, out := &in.Kind, &out.Kind + *out = new(string) + **out = **in + } + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } + if in.SectionName != nil { + in, out := &in.SectionName, &out.SectionName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayParentRefConfig. +func (in *GatewayParentRefConfig) DeepCopy() *GatewayParentRefConfig { + if in == nil { + return nil + } + out := new(GatewayParentRefConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Group) DeepCopyInto(out *Group) { *out = *in diff --git a/operator/chart/files/rbac/v2-manager.ClusterRole.yaml b/operator/chart/files/rbac/v2-manager.ClusterRole.yaml index 6c331a9d2..e1e6d0a97 100644 --- a/operator/chart/files/rbac/v2-manager.ClusterRole.yaml +++ b/operator/chart/files/rbac/v2-manager.ClusterRole.yaml @@ -178,6 +178,18 @@ rules: - patch - update - watch + - apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: diff --git a/operator/chart/testdata/template-cases.golden.txtar b/operator/chart/testdata/template-cases.golden.txtar index 2e6d6f1d9..b9a9bd932 100644 --- a/operator/chart/testdata/template-cases.golden.txtar +++ b/operator/chart/testdata/template-cases.golden.txtar @@ -435,6 +435,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -1219,6 +1231,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -1811,6 +1835,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -2622,6 +2658,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -3234,6 +3282,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -4031,6 +4091,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -4787,6 +4859,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -5787,6 +5871,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -6484,6 +6580,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -7282,6 +7390,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -7878,6 +7998,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -8714,6 +8846,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -9398,6 +9542,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -10280,6 +10436,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -10997,6 +11165,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -11810,6 +11990,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -12409,6 +12601,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -13212,6 +13416,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -13813,6 +14029,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -14649,6 +14877,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -15248,6 +15488,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -15888,6 +16140,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -16501,6 +16765,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -17310,6 +17586,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -18085,6 +18373,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -19099,6 +19399,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -19707,6 +20019,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -20395,6 +20719,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -20982,6 +21318,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -21793,6 +22141,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -22400,6 +22760,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -23204,6 +23576,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -24170,6 +24554,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -25189,6 +25585,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -25797,6 +26205,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -26640,6 +27060,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -27397,6 +27829,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -28357,6 +28801,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -29326,6 +29782,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -30279,6 +30747,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -31038,6 +31518,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -32237,6 +32729,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -32844,6 +33348,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -33660,6 +34176,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -34434,6 +34962,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -35557,6 +36097,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -36508,6 +37060,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -37512,6 +38076,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -38530,6 +39106,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -39561,6 +40149,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -40179,6 +40779,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -41195,6 +41807,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -41962,6 +42586,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -43007,6 +43643,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -44296,6 +44944,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -45496,6 +46156,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -46214,6 +46886,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -47049,6 +47733,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -47810,6 +48506,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -49078,6 +49786,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -51399,6 +52119,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -52769,6 +53501,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -54332,6 +55076,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -55442,6 +56198,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -57731,6 +58499,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -59080,6 +59860,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -59797,6 +60589,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -61183,6 +61987,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -62564,6 +63380,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -63664,6 +64492,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -65129,6 +65969,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -66467,6 +67319,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -67205,6 +68069,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -68355,6 +69231,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -69261,6 +70149,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -70653,6 +71553,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -71370,6 +72282,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -72663,6 +73587,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -73383,6 +74319,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -74210,6 +75158,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -74893,6 +75853,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -75720,6 +76692,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -76402,6 +77386,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -77185,6 +78181,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -77777,6 +78785,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -78577,6 +79597,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -79169,6 +80201,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -79952,6 +80996,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -80544,6 +81600,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -81327,6 +82395,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -81919,6 +82999,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -82710,6 +83802,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -83302,6 +84406,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -84093,6 +85209,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -84695,6 +85823,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -85560,6 +86700,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -86253,6 +87405,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -87110,6 +88274,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -87793,6 +88969,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -88707,6 +89895,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -89299,6 +90499,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: @@ -90089,6 +91301,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: diff --git a/operator/config/crd/bases/cluster.redpanda.com_redpandas.yaml b/operator/config/crd/bases/cluster.redpanda.com_redpandas.yaml index 21609c088..bcbd37fa4 100644 --- a/operator/config/crd/bases/cluster.redpanda.com_redpandas.yaml +++ b/operator/config/crd/bases/cluster.redpanda.com_redpandas.yaml @@ -1867,6 +1867,51 @@ spec: matches `external.addresses[i]`.`external.domain`. type: boolean type: object + gateway: + description: Configures Gateway API TLSRoute-based external + access. When enabled, ClusterIP services and TLSRoute resources + are created instead of NodePort/LoadBalancer services. The + Gateway itself must be managed externally. + properties: + advertisedPort: + description: The port advertised to clients. Defaults + to 443. + format: int32 + type: integer + enabled: + description: Enables Gateway API TLSRoute-based external + access. + type: boolean + parentRefs: + description: Defines which Gateway(s) handle the TLSRoutes. + At least one parent reference must be provided. + items: + description: GatewayParentRefConfig identifies a Gateway + (or ListenerSet) that should handle the TLSRoute traffic. + Schema mirrors the upstream Gateway API ParentReference. + properties: + group: + description: API group of the referent. Defaults + to "gateway.networking.k8s.io". + type: string + kind: + description: Kind of the referent. Defaults to "Gateway". + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent. + type: string + sectionName: + description: Name of a section within the target + resource. + type: string + required: + - name + type: object + type: array + type: object prefixTemplate: description: Specifies a naming prefix template for external Services. @@ -1996,6 +2041,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer @@ -2229,6 +2290,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer @@ -2467,6 +2544,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer @@ -2788,6 +2881,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer @@ -35661,6 +35770,51 @@ spec: matches `external.addresses[i]`.`external.domain`. type: boolean type: object + gateway: + description: Configures Gateway API TLSRoute-based external + access. When enabled, ClusterIP services and TLSRoute resources + are created instead of NodePort/LoadBalancer services. The + Gateway itself must be managed externally. + properties: + advertisedPort: + description: The port advertised to clients. Defaults + to 443. + format: int32 + type: integer + enabled: + description: Enables Gateway API TLSRoute-based external + access. + type: boolean + parentRefs: + description: Defines which Gateway(s) handle the TLSRoutes. + At least one parent reference must be provided. + items: + description: GatewayParentRefConfig identifies a Gateway + (or ListenerSet) that should handle the TLSRoute traffic. + Schema mirrors the upstream Gateway API ParentReference. + properties: + group: + description: API group of the referent. Defaults + to "gateway.networking.k8s.io". + type: string + kind: + description: Kind of the referent. Defaults to "Gateway". + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent. + type: string + sectionName: + description: Name of a section within the target + resource. + type: string + required: + - name + type: object + type: array + type: object prefixTemplate: description: Specifies a naming prefix template for external Services. @@ -35790,6 +35944,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer @@ -36023,6 +36193,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer @@ -36261,6 +36447,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer @@ -36582,6 +36784,22 @@ spec: description: Specifies whether this Listener is enabled. type: boolean + gateway: + description: Opts this listener into Gateway API + TLSRoute mode. Requires external.gateway to be + configured. When true, a TLSRoute is created for + this listener instead of including it in NodePort/LoadBalancer + services. + type: boolean + host: + description: Host is the SNI hostname for the bootstrap + TLSRoute when using Gateway API external access. + type: string + hostTemplate: + description: HostTemplate is a Go template for per-broker + TLSRoute SNI hostnames. Supports $POD_ORDINAL + and $POD_NAME variables. + type: string nodePort: format: int32 type: integer diff --git a/operator/config/crd/bases/cluster.redpanda.com_stretchclusters.yaml b/operator/config/crd/bases/cluster.redpanda.com_stretchclusters.yaml index 4e1fc0a44..1440dd017 100644 --- a/operator/config/crd/bases/cluster.redpanda.com_stretchclusters.yaml +++ b/operator/config/crd/bases/cluster.redpanda.com_stretchclusters.yaml @@ -383,6 +383,48 @@ spec: `external.addresses[i]`.`external.domain`. type: boolean type: object + gateway: + description: Configures Gateway API TLSRoute-based external access. + When enabled, ClusterIP services and TLSRoute resources are + created instead of NodePort/LoadBalancer services. The Gateway + itself must be managed externally. + properties: + advertisedPort: + description: The port advertised to clients. Defaults to 443. + format: int32 + type: integer + enabled: + description: Enables Gateway API TLSRoute-based external access. + type: boolean + parentRefs: + description: Defines which Gateway(s) handle the TLSRoutes. + At least one parent reference must be provided. + items: + description: GatewayParentRefConfig identifies a Gateway + (or ListenerSet) that should handle the TLSRoute traffic. + Schema mirrors the upstream Gateway API ParentReference. + properties: + group: + description: API group of the referent. Defaults to + "gateway.networking.k8s.io". + type: string + kind: + description: Kind of the referent. Defaults to "Gateway". + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent. + type: string + sectionName: + description: Name of a section within the target resource. + type: string + required: + - name + type: object + type: array + type: object prefixTemplate: description: Specifies a naming prefix template for external Services. type: string diff --git a/operator/config/rbac/bases/operator/role.yaml b/operator/config/rbac/bases/operator/role.yaml index da5c8445b..c0105f2d2 100644 --- a/operator/config/rbac/bases/operator/role.yaml +++ b/operator/config/rbac/bases/operator/role.yaml @@ -229,6 +229,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: diff --git a/operator/config/rbac/itemized/v2-manager.yaml b/operator/config/rbac/itemized/v2-manager.yaml index 0b832109b..e4de3cdce 100644 --- a/operator/config/rbac/itemized/v2-manager.yaml +++ b/operator/config/rbac/itemized/v2-manager.yaml @@ -178,6 +178,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: diff --git a/operator/internal/controller/redpanda/redpanda_controller.go b/operator/internal/controller/redpanda/redpanda_controller.go index 5cffd2fac..8e5d66d4c 100644 --- a/operator/internal/controller/redpanda/redpanda_controller.go +++ b/operator/internal/controller/redpanda/redpanda_controller.go @@ -107,6 +107,9 @@ type RedpandaReconciler struct { // +kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=cluster.redpanda.com,resources=consoles,verbs=get;list;watch;create;update;patch;delete +// Gateway API TLSRoute resources for external access +// +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=tlsroutes,verbs=get;list;watch;create;update;patch;delete + // redpanda resources // +kubebuilder:rbac:groups=cluster.redpanda.com,resources=redpandas,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=cluster.redpanda.com,resources=redpandas/status,verbs=get;update;patch diff --git a/operator/internal/controller/redpanda/testdata/role.yaml b/operator/internal/controller/redpanda/testdata/role.yaml index d2087cd0b..a4b8c71b6 100644 --- a/operator/internal/controller/redpanda/testdata/role.yaml +++ b/operator/internal/controller/redpanda/testdata/role.yaml @@ -210,6 +210,18 @@ rules: - patch - update - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - tlsroutes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - monitoring.coreos.com resources: diff --git a/operator/internal/controller/scheme.go b/operator/internal/controller/scheme.go index 40a1c2111..040c9cdb6 100644 --- a/operator/internal/controller/scheme.go +++ b/operator/internal/controller/scheme.go @@ -14,10 +14,12 @@ import ( monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" mcsv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" + redpanda "github.com/redpanda-data/redpanda-operator/charts/redpanda/v25" redpandav1alpha1 "github.com/redpanda-data/redpanda-operator/operator/api/redpanda/v1alpha1" redpandav1alpha2 "github.com/redpanda-data/redpanda-operator/operator/api/redpanda/v1alpha2" vectorizedv1alpha1 "github.com/redpanda-data/redpanda-operator/operator/api/vectorized/v1alpha1" @@ -72,4 +74,11 @@ func init() { for _, fn := range multiclusterSchemeFns { utilruntime.Must(fn(MulticlusterScheme)) } + + // Register the chart's lightweight TLSRoute type so the operator's + // scheme can decode TLSRoute objects rendered by the Helm chart. + tlsRouteGV := schema.GroupVersion{Group: "gateway.networking.k8s.io", Version: "v1alpha2"} + for _, s := range []*runtime.Scheme{V2Scheme, UnifiedScheme} { + s.AddKnownTypeWithName(tlsRouteGV.WithKind("TLSRoute"), &redpanda.TLSRoute{}) + } }