From c346fcd7306a9cb6d6de15e4eec3d5fa453b59d3 Mon Sep 17 00:00:00 2001 From: Clemens Beck Date: Fri, 14 Nov 2025 13:04:59 +0100 Subject: [PATCH 1/7] Add Beta GatewayAPI support with Envoy Gateway * Support exposing core components via Routes. Satelite components like OpenBao and Zoekt do not support Routes yet. * Bundle Envoy Gateway as optional component. * Render additional Envoy Gateway resources for a proper out of the box experience. * Add a vcluster-based envionment for running tests and QA in CI. Changelog: added Closes https://gitlab.com/gitlab-org/charts/gitlab/-/issues/5563 --- .gitlab-ci.yml | 20 +++- ...cluster.134.amd64.gatewayapi.gitlab-ci.yml | 91 ++++++++++++++++++ Chart.lock | 7 +- Chart.yaml | 5 + charts/certmanager-issuer/Chart.yaml | 4 +- .../certmanager-issuer/files/create_issuer.sh | 19 ++++ .../templates/_create_issuer.sh | 12 --- .../templates/_gateway_issuer.yaml | 25 +++++ .../templates/cert-manager.yml | 15 --- .../templates/configmap.yaml | 23 +++++ .../templates/issuer-job.yaml | 11 ++- .../gitlab-pages/templates/httproute.yaml | 36 +++++++ charts/gitlab/charts/gitlab-pages/values.yaml | 6 ++ .../gitlab-shell/templates/tcproute.yaml | 20 ++++ charts/gitlab/charts/gitlab-shell/values.yaml | 6 ++ .../kas/templates/httproute-workspaces.yaml | 30 ++++++ .../charts/kas/templates/httproute.yaml | 57 ++++++++++++ charts/gitlab/charts/kas/values.yaml | 8 ++ .../webservice/templates/httproute.yaml | 28 ++++++ charts/gitlab/charts/webservice/values.yaml | 6 ++ charts/gitlab/templates/_kas.tpl | 25 ----- charts/gitlab/templates/_pages.tpl | 9 -- charts/minio/templates/httproute.yaml | 29 ++++++ charts/minio/values.yaml | 6 ++ charts/registry/templates/httproute.yaml | 31 +++++++ charts/registry/values.yaml | 9 ++ doc/charts/globals.md | 93 +++++++++++++++++++ doc/development/_index.md | 1 + examples/values-gatewayapi.yaml | 26 ++++++ scripts/ci/autodevops.sh | 37 ++++---- scripts/ci/values/gatewayapi.values.yaml | 44 +++++++++ scripts/ci/values/ingress.values.yaml | 13 +++ .../values/vcluster.externaldns.values.yaml | 20 ++++ .../ci/values/vcluster.ingress.values.yaml | 9 ++ spec/configuration/certmanager_issuer_spec.rb | 11 ++- spec/configuration/gatewayapi_spec.rb | 47 ++++++++++ templates/_gateway.tpl | 58 ++++++++++++ templates/_helpers.tpl | 34 +++++++ templates/envoypatchpolicy.yaml | 31 +++++++ templates/envoyproxy.yaml | 13 +++ templates/gateway.yaml | 69 ++++++++++++++ templates/gatewayclass.yaml | 18 ++++ values.yaml | 70 ++++++++++++++ 43 files changed, 1035 insertions(+), 97 deletions(-) create mode 100644 .gitlab/ci/environments/vcluster.134.amd64.gatewayapi.gitlab-ci.yml create mode 100755 charts/certmanager-issuer/files/create_issuer.sh delete mode 100755 charts/certmanager-issuer/templates/_create_issuer.sh create mode 100644 charts/certmanager-issuer/templates/_gateway_issuer.yaml delete mode 100644 charts/certmanager-issuer/templates/cert-manager.yml create mode 100644 charts/certmanager-issuer/templates/configmap.yaml create mode 100644 charts/gitlab/charts/gitlab-pages/templates/httproute.yaml create mode 100644 charts/gitlab/charts/gitlab-shell/templates/tcproute.yaml create mode 100644 charts/gitlab/charts/kas/templates/httproute-workspaces.yaml create mode 100644 charts/gitlab/charts/kas/templates/httproute.yaml create mode 100644 charts/gitlab/charts/webservice/templates/httproute.yaml create mode 100644 charts/minio/templates/httproute.yaml create mode 100644 charts/registry/templates/httproute.yaml create mode 100644 examples/values-gatewayapi.yaml create mode 100644 scripts/ci/values/gatewayapi.values.yaml create mode 100644 scripts/ci/values/ingress.values.yaml create mode 100644 scripts/ci/values/vcluster.externaldns.values.yaml create mode 100644 scripts/ci/values/vcluster.ingress.values.yaml create mode 100644 spec/configuration/gatewayapi_spec.rb create mode 100644 templates/_gateway.tpl create mode 100644 templates/envoypatchpolicy.yaml create mode 100644 templates/envoyproxy.yaml create mode 100644 templates/gateway.yaml create mode 100644 templates/gatewayclass.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 74f3f45036..e2842378fa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -103,9 +103,6 @@ stages: include: - local: '/.gitlab/ci/rules.gitlab-ci.yml' - local: '/.gitlab/ci/vcluster-review-apps.gitlab-ci.yml' - - local: '/.gitlab/ci/environments/gkevc134.gitlab-ci.yml' - rules: - - if: '$LIMIT_TO == "gkevc134"' - local: '/.gitlab/ci/operator.gitlab-ci.yml' rules: - if: '$LIMIT_TO == "" || $LIMIT_TO == null' @@ -121,6 +118,9 @@ include: - local: '/.gitlab/ci/environments/vcluster.134.arm64.gitlab-ci.yml' rules: - if: '$LIMIT_TO == "" || $LIMIT_TO == "v134a"' + - local: '/.gitlab/ci/environments/vcluster.134.amd64.gatewayapi.gitlab-ci.yml' + rules: + - if: '$LIMIT_TO == "" || $LIMIT_TO == "v134gw"' - local: '/.gitlab/ci/environments/gke.134.amd64.gitlab-ci.yml' rules: - if: '$LIMIT_TO == "" || $LIMIT_TO == "gke134"' @@ -386,6 +386,15 @@ trigger-v134a: rules: - !reference [.trigger_review_secondary, rules] +trigger-v134-envoy-gw: + extends: .trigger_review_job + needs: + - trigger_review_current + variables: + LIMIT_TO: v134gw + rules: + - !reference [.trigger_review_current, rules] + trigger-gke134: extends: .trigger_review_job needs: @@ -398,11 +407,12 @@ trigger-gke134: trigger-eks133: extends: .trigger_review_job needs: - - trigger_review_current + # TODO revert to current + - trigger_review_secondary variables: LIMIT_TO: eks133 rules: - - !reference [.trigger_review_current, rules] + - !reference [.trigger_review_secondary, rules] # Jobs using auto_stop_in that exit with a failure will not execute the on_stop # action. We get frequent failures during review_* jobs. Their accompanying # partially deployed environments then hang around forever which may eventually diff --git a/.gitlab/ci/environments/vcluster.134.amd64.gatewayapi.gitlab-ci.yml b/.gitlab/ci/environments/vcluster.134.amd64.gatewayapi.gitlab-ci.yml new file mode 100644 index 0000000000..73a6824922 --- /dev/null +++ b/.gitlab/ci/environments/vcluster.134.amd64.gatewayapi.gitlab-ci.yml @@ -0,0 +1,91 @@ +include: + - component: "gitlab.com/gitlab-org/quality/pipeline-common/allure-report@9.6.3" + inputs: + job_name: "e2e-test-v134gw" + job_stage: "qa-report" + gitlab_auth_token_variable_name: "DANGER_GITLAB_API_TOKEN" + aws_access_key_id_variable_name: "QA_ALLURE_AWS_ACCESS_KEY_ID" + aws_secret_access_key_variable_name: "QA_ALLURE_AWS_SECRET_ACCESS_KEY" + allure_results_glob: "gitlab-qa-run-*/**/allure-results" + rules: + - if: '$CI_SERVER_HOST != "gitlab.com"' + when: never + - if: '$CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "parent_pipeline"' + +.v134gw_base: + extends: + - .vcluster_base + variables: + VCLUSTER_K8S_VERSION: "v1.34.0" + VCLUSTER_NAME: "v134gw-${REVIEW_REF_PREFIX}${CI_COMMIT_SHORT_SHA}" + HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}-vc134gw" + # the VARIABLES_FILE value is from the CI_JOB_NAME of the review job + VARIABLES_FILE: "variables/review_v134gw" + DOMAIN: "-${HOST_SUFFIX}.${KUBE_INGRESS_BASE_DOMAIN}" + USE_GATEWAY_API: "true" + environment: + name: gkevc_134/$REVIEW_REF_PREFIX$CI_COMMIT_SHORT_SHA + url: "https://gitlab${DOMAIN}" + +create_review_v134gw: + stage: review + image: ${BUSYBOX_IMAGE} + extends: .v134gw_base + variables: + GIT_STRATEGY: none + script: + - echo "Configuring gkevc_134/$REVIEW_REF_PREFIX$CI_COMMIT_SHORT_SHA to automatically stop in $REVIEW_APPS_AUTO_STOP_IN." + environment: + on_stop: stop_review_v134gw + auto_stop_in: $REVIEW_APPS_AUTO_STOP_IN + action: start + +review_v134gw: + extends: + - .vcluster_review_template + - .v134gw_base + environment: + action: access + +stop_review_v134gw: + extends: + - .stop_vcluster_review_template + - .v134gw_base + environment: + action: stop + +review_specs_v134gw: + extends: + - .vcluster_specs_template + - .v134gw_base + environment: + action: access + needs: ['review_v134gw'] + +qa_v134gw: + extends: + - .qa_branch + - .v134gw_base + variables: + TEST_SUITE: $QA_SANITY_SUITE_OPTIONS + environment: + action: access + needs: + - review_v134gw + - job: review_specs_v134gw + artifacts: false + +qa_v134gw_full_suite_manual_trigger: + extends: .qa_full_suite_manual_trigger + script: echo 'The job will trigger Full E2E suite against GKE134 vcluster' + +qa_v134gw_manual_full_suite: + extends: + - .qa_branch + - .v134gw_base + parallel: 7 + variables: + TEST_SUITE: $QA_FULL_SUITE_OPTIONS + environment: + action: access + needs: ["qa_v134gw_full_suite_manual_trigger"] diff --git a/Chart.lock b/Chart.lock index 2481d5c6c0..a4f67884a1 100644 --- a/Chart.lock +++ b/Chart.lock @@ -44,5 +44,8 @@ dependencies: - name: kubernetes-ingress repository: https://haproxytech.github.io/helm-charts version: 1.39.4 -digest: sha256:22d52ca59dc7450668a0c66ed4d8c3f07e4ff765ecc22e2218cdd4f216eb2009 -generated: "2025-12-08T13:23:46.514649333Z" +- name: gateway-helm + repository: oci://registry-1.docker.io/envoyproxy + version: 1.6.0 +digest: sha256:f436c2d2a2dabe716f450d70bc67d08301c5ed68c8eb3a4e41cad57e9af4a3de +generated: "2025-12-10T20:59:45.642314003+01:00" diff --git a/Chart.yaml b/Chart.yaml index 8563c89b18..fe2287d497 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -67,3 +67,8 @@ dependencies: version: 1.39.4 condition: haproxy.install repository: https://haproxytech.github.io/helm-charts +- name: gateway-helm + alias: envoy-gateway + repository: oci://registry-1.docker.io/envoyproxy + version: 1.6.0 + condition: global.gatewayApi.installEnvoy \ No newline at end of file diff --git a/charts/certmanager-issuer/Chart.yaml b/charts/certmanager-issuer/Chart.yaml index 25e61afc7d..43ab83e70d 100644 --- a/charts/certmanager-issuer/Chart.yaml +++ b/charts/certmanager-issuer/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: certmanager-issuer -version: 0.2.1 -appVersion: 0.2.2 +version: 0.3.0 +appVersion: 0.3.0 description: Configuration Job to add LetsEncrypt Issuer to cert-manager keywords: - gitlab diff --git a/charts/certmanager-issuer/files/create_issuer.sh b/charts/certmanager-issuer/files/create_issuer.sh new file mode 100755 index 0000000000..d2a7881609 --- /dev/null +++ b/charts/certmanager-issuer/files/create_issuer.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set +e ; + +echo "Creating the certmanager issuer..." +if [ -f scripts/issuer.yml ]; then + # The CRD may not exist yet. We need to retry until this passes + while ! kubectl --namespace="$POD_NAMESPACE" apply -f scripts/issuer.yml; do + sleep 1; + done ; +fi ; + +if [ -f scripts/gateway_issuer.yaml ]; then + # The CRD may not exist yet. We need to retry until this passes + while ! kubectl --namespace="$POD_NAMESPACE" apply -f scripts/gateway_issuer.yaml; do + sleep 1; + done ; +fi ; + +set -e ; # reset `e` as active diff --git a/charts/certmanager-issuer/templates/_create_issuer.sh b/charts/certmanager-issuer/templates/_create_issuer.sh deleted file mode 100755 index 57b318b5c5..0000000000 --- a/charts/certmanager-issuer/templates/_create_issuer.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e ; - -issuer_file=$1 -namespace={{ .Release.Namespace }} - -echo "Creating the certmanager issuer..." -set +e ; # The CRD may not exist yet. We need to retry until this passes -while ! kubectl --namespace=$namespace apply -f ${issuer_file:=issuer.yml}; do - sleep 1; -done ; -set -e ; # reset `e` as active diff --git a/charts/certmanager-issuer/templates/_gateway_issuer.yaml b/charts/certmanager-issuer/templates/_gateway_issuer.yaml new file mode 100644 index 0000000000..bdfcd125ff --- /dev/null +++ b/charts/certmanager-issuer/templates/_gateway_issuer.yaml @@ -0,0 +1,25 @@ +{{- if .Values.global.gatewayApi.configureCertmanager }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ include "gitlab.gatewayApi.certmanager.issuer" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" . | nindent 4 }} + {{- include "gitlab.commonLabels" . | nindent 4 }} +spec: + acme: + server: {{ .Values.server | quote }} + {{- with .Values.email }} + email: {{ . }} + {{- end }} + privateKeySecretRef: + name: {{ .Release.Name }}-gateway-acme-key + solvers: + - http01: + gatewayHTTPRoute: + parentRefs: + - name: {{ include "gitlab.gatewayApi.gateway" . }} + namespace: {{ $.Release.Namespace }} + kind: Gateway +{{- end }} \ No newline at end of file diff --git a/charts/certmanager-issuer/templates/cert-manager.yml b/charts/certmanager-issuer/templates/cert-manager.yml deleted file mode 100644 index 2a59eb0f14..0000000000 --- a/charts/certmanager-issuer/templates/cert-manager.yml +++ /dev/null @@ -1,15 +0,0 @@ -{{ if (pluck "configureCertmanager" .Values.global.ingress (dict "configureCertmanager" false) | first) }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "fullname" . }}-certmanager - namespace: {{ $.Release.Namespace }} - labels: - {{- include "gitlab.standardLabels" . | nindent 4 }} - {{- include "gitlab.commonLabels" . | nindent 4 }} -data: - create-issuer: | -{{ include (print $.Template.BasePath "/_create_issuer.sh") . | indent 4 }} - issuer.yml: | -{{ include (print $.Template.BasePath "/_issuer.yaml") . | indent 4 }} -{{ end }} diff --git a/charts/certmanager-issuer/templates/configmap.yaml b/charts/certmanager-issuer/templates/configmap.yaml new file mode 100644 index 0000000000..0ce3edf04c --- /dev/null +++ b/charts/certmanager-issuer/templates/configmap.yaml @@ -0,0 +1,23 @@ +{{- $configureIngressCertmanager := (pluck "configureCertmanager" .Values.global.ingress (dict "configureCertmanager" false) | first) }} +{{- $configureGatewayCertmanager := .Values.global.gatewayApi.configureCertmanager }} +{{- if or $configureGatewayCertmanager $configureIngressCertmanager }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "fullname" . }}-certmanager + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" . | nindent 4 }} + {{- include "gitlab.commonLabels" . | nindent 4 }} +data: + create-issuer: | + {{- .Files.Get "files/create_issuer.sh" | indent 4 }} + {{- if $configureIngressCertmanager }} + issuer.yml: | + {{- include (print $.Template.BasePath "/_issuer.yaml") . | indent 4 }} + {{- end }} + {{- if $configureGatewayCertmanager }} + gateway_issuer.yaml: | + {{- include (print $.Template.BasePath "/_gateway_issuer.yaml") . | indent 4 }} + {{- end }} +{{ end }} \ No newline at end of file diff --git a/charts/certmanager-issuer/templates/issuer-job.yaml b/charts/certmanager-issuer/templates/issuer-job.yaml index b20d71872d..27403ff9d0 100644 --- a/charts/certmanager-issuer/templates/issuer-job.yaml +++ b/charts/certmanager-issuer/templates/issuer-job.yaml @@ -1,4 +1,6 @@ -{{ if (pluck "configureCertmanager" .Values.global.ingress (dict "configureCertmanager" false) | first) }} +{{- $configureIngressCertmanager := (pluck "configureCertmanager" .Values.global.ingress (dict "configureCertmanager" false) | first) }} +{{- $configureGatewayCertmanager := .Values.global.gatewayApi.configureCertmanager }} +{{- if or $configureGatewayCertmanager $configureIngressCertmanager }} {{- $imageCfg := dict "global" .Values.global.image "local" .Values.global.kubectl.image -}} apiVersion: batch/v1 kind: Job @@ -29,12 +31,17 @@ spec: containers: - name: create-issuer image: {{ include "gitlab.kubectl.image" . }} - command: ['/bin/bash', '/scripts/create-issuer', '/scripts/issuer.yml'] + command: ['/bin/bash', '/scripts/create-issuer'] {{- include "gitlab.image.pullPolicy" $imageCfg | indent 10 }} {{- include "gitlab.containerSecurityContext" $ | indent 10 }} volumeMounts: - name: scripts mountPath: /scripts + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace resources: {{ toYaml .Values.resources | indent 12 }} volumes: diff --git a/charts/gitlab/charts/gitlab-pages/templates/httproute.yaml b/charts/gitlab/charts/gitlab-pages/templates/httproute.yaml new file mode 100644 index 0000000000..41630b0fb9 --- /dev/null +++ b/charts/gitlab/charts/gitlab-pages/templates/httproute.yaml @@ -0,0 +1,36 @@ +{{- $externalAddresses := concat $.Values.global.pages.externalHttp $.Values.global.pages.externalHttps | uniq }} +{{- if empty $externalAddresses }} +{{- if eq "true" (include "gitlab.gatewayApi.route.enabled" .) }} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ template "fullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" $ | nindent 4 }} + {{- include "gitlab.commonLabels" $ | nindent 4 }} + annotations: + {{ .Values.gatewayRoute.annotations | toYaml | nindent 4 }} +spec: + parentRefs: + - name: {{ template "gitlab.gatewayApi.route.gateway" . }} + sectionName: {{ .Values.gatewayRoute.sectionName }} + hostnames: + {{- $hostname := (include "gitlab.pages.hostname" .) }} + {{- if $.Values.global.pages.namespaceInPath }} + - {{ $hostname | quote }} + {{- else }} + - {{ printf "*.%s" $hostname | quote }} + {{- end }} + rules: + - backendRefs: + - kind: Service + name: {{ template "fullname" . }} + port: {{ .Values.service.externalPort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: / +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/gitlab/charts/gitlab-pages/values.yaml b/charts/gitlab/charts/gitlab-pages/values.yaml index b2ec00d97b..8afedecc10 100644 --- a/charts/gitlab/charts/gitlab-pages/values.yaml +++ b/charts/gitlab/charts/gitlab-pages/values.yaml @@ -114,6 +114,12 @@ ingress: tls: {} path: # / +gatewayRoute: + enabled: null + sectionName: "pages-web" + gatewayName: "" + annotations: {} + # Tolerations for pod scheduling tolerations: [] diff --git a/charts/gitlab/charts/gitlab-shell/templates/tcproute.yaml b/charts/gitlab/charts/gitlab-shell/templates/tcproute.yaml new file mode 100644 index 0000000000..ffe60d53cd --- /dev/null +++ b/charts/gitlab/charts/gitlab-shell/templates/tcproute.yaml @@ -0,0 +1,20 @@ +{{- if eq "true" (include "gitlab.gatewayApi.route.enabled" .) -}} +apiVersion: gateway.networking.k8s.io/v1alpha2 +kind: TCPRoute +metadata: + name: {{ template "fullname" . }} + namespace: {{ $.Release.Namespace | quote }} + labels: + {{- include "gitlab.standardLabels" . | nindent 4 }} + {{- include "gitlab.commonLabels" . | nindent 4 }} + annotations: + {{ .Values.gatewayRoute.annotations | toYaml | nindent 4 }} +spec: + parentRefs: + - name: {{ template "gitlab.gatewayApi.route.gateway" . }} + sectionName: {{ .Values.gatewayRoute.sectionName }} + rules: + - backendRefs: + - name: {{ template "fullname" . }} + port: {{ include "gitlab.shell.port" . | int }} +{{- end }} \ No newline at end of file diff --git a/charts/gitlab/charts/gitlab-shell/values.yaml b/charts/gitlab/charts/gitlab-shell/values.yaml index b485bbcc7d..9a85a6d433 100644 --- a/charts/gitlab/charts/gitlab-shell/values.yaml +++ b/charts/gitlab/charts/gitlab-shell/values.yaml @@ -68,6 +68,12 @@ maxUnavailable: 1 minReplicas: 2 maxReplicas: 10 +gatewayRoute: + enabled: null + sectionName: "gitlab-ssh" + gatewayName: "" + annotations: {} + # When using traefik ingress traefik: entrypoint: gitlab-shell diff --git a/charts/gitlab/charts/kas/templates/httproute-workspaces.yaml b/charts/gitlab/charts/kas/templates/httproute-workspaces.yaml new file mode 100644 index 0000000000..0f3bfd291c --- /dev/null +++ b/charts/gitlab/charts/kas/templates/httproute-workspaces.yaml @@ -0,0 +1,30 @@ +{{- if eq "true" (include "gitlab.gatewayApi.route.enabled" .) -}} +{{- if .Values.global.workspaces.enabled }} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ template "fullname" . }}-workspaces + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" $ | nindent 4 }} + {{- include "gitlab.commonLabels" $ | nindent 4 }} + annotations: + {{ .Values.gatewayRoute.annotations | toYaml | nindent 4 }} +spec: + parentRefs: + - name: {{ template "gitlab.gatewayApi.route.gateway" . }} + sectionName: {{ .gatewayApi.workspacesSectionName }} + hostnames: + - {{ include "gitlab.workspaces.wildcardHostname" . | quote }} + rules: + - backendRefs: + - kind: Service + name: {{ template "gitlab.kas.serviceName" . }} + port: {{ .Values.service.workspacesServerPort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: {{ .Values.ingress.workspacesServerApiPath | quote }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/gitlab/charts/kas/templates/httproute.yaml b/charts/gitlab/charts/kas/templates/httproute.yaml new file mode 100644 index 0000000000..a7a8aeb3fe --- /dev/null +++ b/charts/gitlab/charts/kas/templates/httproute.yaml @@ -0,0 +1,57 @@ +{{- if eq "true" (include "gitlab.gatewayApi.route.enabled" .) -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ template "fullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" $ | nindent 4 }} + {{- include "gitlab.commonLabels" $ | nindent 4 }} + annotations: + {{ .Values.gatewayRoute.annotations | toYaml | nindent 4 }} +spec: + parentRefs: + - name: {{ template "gitlab.gatewayApi.route.gateway" . }} + sectionName: {{ .Values.gatewayRoute.sectionName }} + hostnames: + - {{ include "gitlab.kas.hostname" . | quote }} + rules: + - backendRefs: + - kind: Service + name: {{ template "gitlab.kas.serviceName" . }} + port: {{ .Values.service.kubernetesApiPort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: {{ .Values.ingress.k8sApiPath | quote }} + - backendRefs: + - kind: Service + name: {{ template "gitlab.kas.serviceName" . }} + port: {{ .Values.service.externalPort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: {{ .Values.ingress.agentPath | quote }} + - backendRefs: + - kind: Service + name: {{ template "gitlab.kas.serviceName" . }} + port: {{ .Values.service.autoflowCodecServerApiPort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: {{ .Values.ingress.autoflowCodecServerApiPath | quote }} + {{- if .Values.global.workspaces.enabled }} + - backendRefs: + - kind: Service + name: {{ template "gitlab.kas.serviceName" . }} + port: {{ .Values.service.workspacesServerPort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: {{ .Values.ingress.workspacesServerApiPath | quote }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/gitlab/charts/kas/values.yaml b/charts/gitlab/charts/kas/values.yaml index e4c8593c00..c8ea9022e9 100644 --- a/charts/gitlab/charts/kas/values.yaml +++ b/charts/gitlab/charts/kas/values.yaml @@ -73,6 +73,14 @@ image: # tag: latest # pullPolicy: IfNotPresent # pullSecrets: [] + +gatewayRoute: + enabled: null + sectionName: "kas-web" + workspacesSectionName: "kas-workspaces-web" + gatewayName: "" + annotations: {} + ingress: apiVersion: annotations: {} diff --git a/charts/gitlab/charts/webservice/templates/httproute.yaml b/charts/gitlab/charts/webservice/templates/httproute.yaml new file mode 100644 index 0000000000..ec31d27dc0 --- /dev/null +++ b/charts/gitlab/charts/webservice/templates/httproute.yaml @@ -0,0 +1,28 @@ +{{- if eq "true" (include "gitlab.gatewayApi.route.enabled" .) -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ .Release.Name }}-gitlab + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" $ | nindent 4 }} + {{- include "gitlab.commonLabels" $ | nindent 4 }} + annotations: + {{ .Values.gatewayRoute.annotations | toYaml | nindent 4 }} +spec: + parentRefs: + - name: {{ template "gitlab.gatewayApi.route.gateway" . }} + sectionName: {{ .Values.gatewayRoute.sectionName }} + hostnames: + - {{ include "gitlab.gitlab.hostname" . | quote }} + rules: + - backendRefs: + - kind: Service + name: {{ .Release.Name }}-webservice-default + port: {{ .Values.service.workhorseExternalPort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: / +{{- end }} \ No newline at end of file diff --git a/charts/gitlab/charts/webservice/values.yaml b/charts/gitlab/charts/webservice/values.yaml index f72bebe851..5e9a586a4c 100644 --- a/charts/gitlab/charts/webservice/values.yaml +++ b/charts/gitlab/charts/webservice/values.yaml @@ -108,6 +108,12 @@ service: # loadBalancerSourceRanges: enabled: true +gatewayRoute: + enabled: null + sectionName: "gitlab-web" + gatewayName: "" + annotations: {} + ingress: apiVersion: enabled: diff --git a/charts/gitlab/templates/_kas.tpl b/charts/gitlab/templates/_kas.tpl index af0b31e7ed..b16c9416ef 100644 --- a/charts/gitlab/templates/_kas.tpl +++ b/charts/gitlab/templates/_kas.tpl @@ -11,15 +11,6 @@ {{- end -}} {{- end -}}{{/* "gitlab.kas.mountSecrets" */}} -{{/* -Returns the KAS external hostname (for agentk connections) -If the hostname is set in `global.hosts.kas.name`, that will be returned, -otherwise the hostname will be assembed using `kas` as the prefix, and the `gitlab.assembleHost` function. -*/}} -{{- define "gitlab.kas.hostname" -}} -{{- coalesce $.Values.global.hosts.kas.name (include "gitlab.assembleHost" (dict "name" "kas" "context" . )) -}} -{{- end -}} - {{/* Returns the KAS external URL (for external agentk connections) */}} @@ -36,22 +27,6 @@ Returns the KAS external URL (for external agentk connections) {{- end -}} {{- end -}} -{{/* -Returns the workspaces external hostname -*/}} -{{- define "gitlab.workspaces.hostname" -}} -{{- $hostname := $.Values.global.hosts.workspaces.name | required "Missing required workspaces host. Make sure to set `.Values.global.hosts.workspaces.name`" -}} -{{- $hostname -}} -{{- end -}} - -{{/* -Returns the workspaces wildcard hostname -*/}} -{{- define "gitlab.workspaces.wildcardHostname" -}} -{{- $hostname := include "gitlab.workspaces.hostname" . -}} -{{- print "*." $hostname -}} -{{- end -}} - {{- define "gitlab.kas.internal.scheme" -}} {{- printf "%s" (ternary "grpcs" "grpc" (eq $.Values.global.kas.tls.enabled true)) -}} {{- end -}} diff --git a/charts/gitlab/templates/_pages.tpl b/charts/gitlab/templates/_pages.tpl index 41df1c1d5c..f76b52075f 100644 --- a/charts/gitlab/templates/_pages.tpl +++ b/charts/gitlab/templates/_pages.tpl @@ -46,15 +46,6 @@ pages: {{- end -}} {{- end -}} -{{/* -Returns the Pages hostname. -If the hostname is set in `global.hosts.pages.name`, that will be returned, -otherwise the hostname will be assembed using `pages` as the prefix, and the `gitlab.assembleHost` function. -*/}} -{{- define "gitlab.pages.hostname" -}} -{{- coalesce $.Values.global.pages.host $.Values.global.hosts.pages.name (include "gitlab.assembleHost" (dict "name" "pages" "context" . )) -}} -{{- end -}} - {{/* Returns consolidated `pages.https` as "true" or "" diff --git a/charts/minio/templates/httproute.yaml b/charts/minio/templates/httproute.yaml new file mode 100644 index 0000000000..56a822727d --- /dev/null +++ b/charts/minio/templates/httproute.yaml @@ -0,0 +1,29 @@ + +{{- if eq "true" (include "gitlab.gatewayApi.route.enabled" .) -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ template "minio.fullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" $ | nindent 4 }} + {{- include "gitlab.commonLabels" $ | nindent 4 }} + annotations: + {{ .Values.gatewayRoute.annotations | toYaml | nindent 4 }} +spec: + parentRefs: + - name: {{ template "gitlab.gatewayApi.route.gateway" . }} + sectionName: {{ .Values.gatewayRoute.sectionName }} + hostnames: + - {{ include "gitlab.minio.hostname" . | quote }} + rules: + - backendRefs: + - kind: Service + name: {{ template "minio.fullname" . }}-svc + port: {{ .Values.servicePort }} + weight: 1 + matches: + - path: + type: PathPrefix + value: / +{{- end }} \ No newline at end of file diff --git a/charts/minio/values.yaml b/charts/minio/values.yaml index 2213836222..45bf708b4c 100755 --- a/charts/minio/values.yaml +++ b/charts/minio/values.yaml @@ -10,6 +10,12 @@ minioMc: image: "minio/mc" tag: "RELEASE.2018-07-13T00-53-22Z" +gatewayRoute: + enabled: null + sectionName: "minio-web" + gatewayName: "" + annotations: {} + ingress: apiVersion: enabled: diff --git a/charts/registry/templates/httproute.yaml b/charts/registry/templates/httproute.yaml new file mode 100644 index 0000000000..c18de4627e --- /dev/null +++ b/charts/registry/templates/httproute.yaml @@ -0,0 +1,31 @@ +{{- if eq "true" (include "gitlab.gatewayApi.route.enabled" .) -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ template "registry.fullname" . }} + namespace: {{ $.Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" $ | nindent 4 }} + {{- include "gitlab.commonLabels" $ | nindent 4 }} + annotations: + {{ .Values.gatewayRoute.annotations | toYaml | nindent 4 }} +spec: + parentRefs: + - name: {{ template "gitlab.gatewayApi.route.gateway" . }} + sectionName: {{ .Values.gatewayRoute.sectionName }} + hostnames: + - {{ include "registry.hostname" . }} + rules: + - backendRefs: + - kind: Service + name: {{ template "registry.fullname" . }} + port: {{ .Values.service.externalPort }} + weight: 1 + {{- with .Values.gatewayRoute.timeouts }} + timeouts: {{ . | toJson }} + {{- end }} + matches: + - path: + type: PathPrefix + value: / +{{- end }} \ No newline at end of file diff --git a/charts/registry/values.yaml b/charts/registry/values.yaml index d8e1e1d5d8..27e254b50b 100644 --- a/charts/registry/values.yaml +++ b/charts/registry/values.yaml @@ -79,6 +79,15 @@ networkpolicy: rules: [] annotations: {} +gatewayRoute: + enabled: null + sectionName: "registry-web" + gatewayName: "" + annotations: {} + timeouts: + request: 900s + backendRequest: 900s + ingress: apiVersion: enabled: diff --git a/doc/charts/globals.md b/doc/charts/globals.md index 462a64c9a1..47f4792c2f 100644 --- a/doc/charts/globals.md +++ b/doc/charts/globals.md @@ -196,6 +196,99 @@ Ingress object is created for each validation. `global.ingress.useNewIngressForCerts` cannot be set to `true` when used with GKE Ingress Controllers. +## Gateway API + +{{< details >}} + +- Status: Beta + +{{< /details >}} + +{{< alert type="warning" >}} + +Gateway API support is currently under active development. Please be aware that: + +1. Complete validation across all deployment scenarios has not yet been fully verified. +1. Configuration values and default settings for Gateway API features are subject to change without notice. +1. The Gateway API resources are currently only tested with [Envoy Gateway](https://gateway.envoyproxy.io/). + Other Gateway API controllers might need additional configuration. + +Full support is planned to release before March 2026. + +{{< /alert >}} + +| Name | Type | Default | Description | +|:-------------------------------|:-------:|:---------------|:------------| +| `enabled` | Boolean | false | Enable deployment of GatewayAPI resources. | +| `class.name` | String | `gitlab-gw` | Name of the Gateway class bound to the Gateway. | +| `class.controllerName` | String | `gateway.envoyproxy.io/gitlab-gatewayclass-controller` | Controller name of the GatewayClass. | +| `protocol` | String | `HTTPS` | Default protocol for all listeners. | +| `installEnvoy` | Boolean | false | Install Envoy Gateway and configure with Envoy-specific custom resources. | +| `envoyProxySpec` | Object | see values | Configuration of the default `EnvoyProxy` resource. | + +The Gateway listener configuration uses the following values. Each listener is only +enabled if the underlying component is. + +```yaml +listeners: + certmanager-http: + protocol: HTTP + gitlab-web: + tls: + mode: Terminate + certificateRefs: + - name: gitlab-tls + gitlab-ssh: + protocol: "TCP" + registry-web: + tls: + mode: Terminate + certificateRefs: + - name: registry-tls + pages-web: + tls: + mode: Terminate + certificateRefs: + - name: pages-tls + kas-web: + tls: + mode: Terminate + certificateRefs: + - name: kas-tls + kas-workspaces-web: + tls: + mode: Terminate + certificateRefs: + - name: kas-workspaces-tls + kas-registry-web: + tls: + mode: Terminate + certificateRefs: + - name: kas-workspaces-tls + minio-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: minio-tls +``` + +### Certmanager + +To enable certmanager with Gateway API, set `global.gatewayApi.configureCertmanager=true` and enable +the gateway API in your certmanager release: + +```yaml +certmanager: + config: + apiVersion: controller.config.cert-manager.io/v1alpha1 + kind: ControllerConfiguration + enableGatewayAPI: true +``` + +Setting `configureCertmanager` configures the chart to render the relevant annotations to the +Gateway manifest, and enables the creation of a HTTP01 Issuer configured for Gateway API. + ## GitLab Version {{< alert type="note" >}} diff --git a/doc/development/_index.md b/doc/development/_index.md index 400d230d82..50868f6920 100644 --- a/doc/development/_index.md +++ b/doc/development/_index.md @@ -108,6 +108,7 @@ GKE platform only. | Minor version | GKE | EKS | vCluster | | --- | --- | --- | --- | | 1.34 | current | NA | secondary | +| 1.34 (Envoy) | NA | NA | current | | 1.34 ARM | NA | NA | secondary | | 1.33 | NA | current | secondary | | 1.32 | NA | NA | current | diff --git a/examples/values-gatewayapi.yaml b/examples/values-gatewayapi.yaml new file mode 100644 index 0000000000..742899fe33 --- /dev/null +++ b/examples/values-gatewayapi.yaml @@ -0,0 +1,26 @@ +# Disable bundled NGINX Ingress controller. +nginx-ingress: + enabled: false + +# Configure bundled certmanager for Gateway API support. +certmanager: + config: + apiVersion: controller.config.cert-manager.io/v1alpha1 + kind: ControllerConfiguration + enableGatewayAPI: true + +global: + # Disable rendering of Ingress resources. + ingress: + enabled: false + gatewayApi: + # Install a Gateway and Routes for each component. + enabled: true + # Install the bundled Envoy Gateway chart, a GatewayClass, a EnvoyPatchPolicy, and the EnvoyProxy resources. + installEnvoy: true + # Create a Gateway API compatible certmanager Issuer and configure the Gateway to use it. + configureCertmanager: true + # Default web protocol. + protocol: "HTTP" # or 'HTTP' + class: + create: true \ No newline at end of file diff --git a/scripts/ci/autodevops.sh b/scripts/ci/autodevops.sh index 24f1f485e1..fec86fef8c 100755 --- a/scripts/ci/autodevops.sh +++ b/scripts/ci/autodevops.sh @@ -149,20 +149,21 @@ CIYAML requests: cpu: 100m CIYAML - - if [ -n "${ADD_NGINX_DNS_ANNOTATIONS}" ]; then - echo "ADD_NGINX_DNS_ANNOTATIONS detected" - DOMAIN="-$HOST_SUFFIX.$KUBE_INGRESS_BASE_DOMAIN" - # configure nginx and external-dns - cat << CIYAML > ci.nginx.yaml - nginx-ingress: - controller: - service: - annotations: - external-dns.alpha.kubernetes.io/ttl: "10" - external-dns.alpha.kubernetes.io/hostname: "kas${DOMAIN},minio${DOMAIN},registry${DOMAIN},gitlab${DOMAIN}" -CIYAML - NGINX_CONFIGURATION="-f ci.nginx.yaml" + + DOMAIN="-$HOST_SUFFIX.$KUBE_INGRESS_BASE_DOMAIN" + envsubst < ./scripts/ci/values/vcluster.externaldns.values.yaml > ./vcluster.externaldns.values.yaml + envsubst < ./scripts/ci/values/ingress.values.yaml > ./ingress.values.yaml + envsubst < ./scripts/ci/values/gatewayapi.values.yaml > ./gatewayapi.values.yaml + + NETWORKING_CONF="-f ingress.values.yaml" + if [ -n "${USE_GATEWAY_API}" ]; then + echo "USE_GATEWAY_API detected" + NETWORKING_CONF="-f gatewayapi.values.yaml" + fi + + if [ -n "${VCLUSTER_NAME}" ]; then + echo "VCLUSTER deployment detected" + NETWORKING_CONF="${NETWORKING_CONF} -f vcluster.externaldns.values.yaml" fi # PostgreSQL max_connection defaults to 100, which is apparently not enough to pass QA. @@ -200,7 +201,7 @@ CIYAML $WAIT \ ${SENTRY_CONFIGURATION} \ ${ARCH_CONFIGURATION} \ - ${NGINX_CONFIGURATION} \ + ${NETWORKING_CONF} \ -f ci.details.yaml \ -f ci.scale.yaml \ -f ci.psql.yaml \ @@ -209,13 +210,7 @@ CIYAML --set releaseOverride="$RELEASE_NAME" \ --set global.hosts.hostSuffix="$HOST_SUFFIX" \ --set global.hosts.domain="$KUBE_INGRESS_BASE_DOMAIN" \ - --set global.ingress.annotations."external-dns\.alpha\.kubernetes\.io/ttl"="10" \ - --set global.ingress.tls.secretName=helm-charts-win-tls \ - --set global.ingress.configureCertmanager=false \ --set global.appConfig.initialDefaults.signupEnabled=false \ - --set nginx-ingress.controller.electionID="$RELEASE_NAME-nginx-election" \ - --set nginx-ingress.controller.ingressClassByName=true \ - --set nginx-ingress.controller.ingressClassResource.controllerValue="ci.gitlab.com/$RELEASE_NAME" \ --set installCertmanager=false \ --set global.extraEnv.GITLAB_LICENSE_MODE="test" \ --set global.extraEnv.CUSTOMER_PORTAL_URL="https://customers.staging.gitlab.com" \ diff --git a/scripts/ci/values/gatewayapi.values.yaml b/scripts/ci/values/gatewayapi.values.yaml new file mode 100644 index 0000000000..f2278bbff4 --- /dev/null +++ b/scripts/ci/values/gatewayapi.values.yaml @@ -0,0 +1,44 @@ +nginx-ingress: + enabled: false + +global: + ingress: + enabled: false + configureCertmanager: false + gatewayApi: + enabled: true + installEnvoy: true + class: + create: true + configureCertmanager: false + listeners: + gitlab-web: + tls: + certificateRefs: + - name: helm-charts-win-tls + registry-web: + tls: + certificateRefs: + - name: helm-charts-win-tls + kas-web: + tls: + certificateRefs: + - name: helm-charts-win-tls + minio-web: + tls: + certificateRefs: + - name: helm-charts-win-tls + +gitlab: + webservice: + gatewayRoute: + annotations: + external-dns.alpha.kubernetes.io/hostname: "gitlab${DOMAIN}" + kas: + gatewayRoute: + annotations: + external-dns.alpha.kubernetes.io/hostname: "kas${DOMAIN}" +registry: + gatewayRoute: + annotations: + external-dns.alpha.kubernetes.io/hostname: "registry${DOMAIN}" \ No newline at end of file diff --git a/scripts/ci/values/ingress.values.yaml b/scripts/ci/values/ingress.values.yaml new file mode 100644 index 0000000000..376974c539 --- /dev/null +++ b/scripts/ci/values/ingress.values.yaml @@ -0,0 +1,13 @@ +nginx-ingress: + controller: + electionID: "$RELEASE_NAME-nginx-election" + ingressClassByName: true + controllerValue: "ci.gitlab.com/$RELEASE_NAME" + +global: + ingress: + annotations: + external-dns.alpha.kubernetes.io/ttl: "10" + tls: + secretName: helm-charts-win-tls + configureCertmanager: false \ No newline at end of file diff --git a/scripts/ci/values/vcluster.externaldns.values.yaml b/scripts/ci/values/vcluster.externaldns.values.yaml new file mode 100644 index 0000000000..9d7b94a158 --- /dev/null +++ b/scripts/ci/values/vcluster.externaldns.values.yaml @@ -0,0 +1,20 @@ +# Configure envoy or NGINX managed LoadBalancer Service to have the annotations +# for external DNS. Allows the host cluster to create the DNS entries without +# access to the Ingress or Gateway Routes. + +global: + gatewayApi: + envoyProxySpec: + provider: + kubernetes: + envoyService: + annotations: + external-dns.alpha.kubernetes.io/ttl: "10" + external-dns.alpha.kubernetes.io/hostname: "kas${DOMAIN},minio${DOMAIN},registry${DOMAIN},gitlab${DOMAIN}" + +nginx-ingress: + controller: + service: + annotations: + external-dns.alpha.kubernetes.io/ttl: "10" + external-dns.alpha.kubernetes.io/hostname: "kas${DOMAIN},minio${DOMAIN},registry${DOMAIN},gitlab${DOMAIN}" \ No newline at end of file diff --git a/scripts/ci/values/vcluster.ingress.values.yaml b/scripts/ci/values/vcluster.ingress.values.yaml new file mode 100644 index 0000000000..598da7b6ce --- /dev/null +++ b/scripts/ci/values/vcluster.ingress.values.yaml @@ -0,0 +1,9 @@ +# Configure NGINX managed LoadBalancer Service to have the annotations for external DNS. +# Allows the host cluster to create the DNS entries without access to the Ingress or Gateway Routes. + +nginx-ingress: + controller: + service: + annotations: + external-dns.alpha.kubernetes.io/ttl: "10" + external-dns.alpha.kubernetes.io/hostname: "kas${DOMAIN},minio${DOMAIN},registry${DOMAIN},gitlab${DOMAIN}" \ No newline at end of file diff --git a/spec/configuration/certmanager_issuer_spec.rb b/spec/configuration/certmanager_issuer_spec.rb index 3e703d5a5e..d55c411cf2 100644 --- a/spec/configuration/certmanager_issuer_spec.rb +++ b/spec/configuration/certmanager_issuer_spec.rb @@ -38,7 +38,7 @@ describe 'certmanager_issuer configuration' do "namespace" => "default", "labels" => { "app" => "certmanager-issuer", - "chart" => "certmanager-issuer-0.2.1", + "chart" => "certmanager-issuer-0.3.0", "release" => "test", "heritage" => "Helm" } @@ -50,7 +50,7 @@ describe 'certmanager_issuer configuration' do "metadata" => include( "labels" => include( "app" => "certmanager-issuer", - "chart" => "certmanager-issuer-0.2.1", + "chart" => "certmanager-issuer-0.3.0", "release" => "test", "heritage" => "Helm" ) @@ -62,7 +62,7 @@ describe 'certmanager_issuer configuration' do "containers" => include( include( "name" => "create-issuer", - "command" => ["/bin/bash", "/scripts/create-issuer", "/scripts/issuer.yml"], + "command" => ["/bin/bash", "/scripts/create-issuer"], "image" => "registry.gitlab.com/gitlab-org/build/cng/kubectl:v42.0.0", "securityContext" => { "allowPrivilegeEscalation" => false, @@ -86,7 +86,10 @@ describe 'certmanager_issuer configuration' do context 'when configureCertmanager is disabled' do it 'does not create any certmanager_issuer related resource' do template = HelmTemplate.new(default_values.deep_merge!( - { 'global' => { 'ingress' => { 'configureCertmanager' => false } } }) + { 'global' => { + 'ingress' => { 'configureCertmanager' => false }, + 'gatewayApi' => { 'configureCertmanager' => false } + } }) ) required_resources.each do |resource| diff --git a/spec/configuration/gatewayapi_spec.rb b/spec/configuration/gatewayapi_spec.rb new file mode 100644 index 0000000000..f799c39d06 --- /dev/null +++ b/spec/configuration/gatewayapi_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'helm_template_helper' +require 'yaml' + +describe 'Gateway API configuration' do + let(:template) { HelmTemplate.new(values) } + let(:gatewayclass) { template["GatewayClass/gitlab-gw"] } + let(:gateway) { template["Gateway/test-gw"] } + + let(:shell_route) { template["TCPRoute/test-gitlab-shell"] } + let(:webservice_route) { template["HTTPRoute/test-gitlab"] } + let(:registry_route) { template["HTTPRoute/test-registry"] } + let(:kas_route) { template["HTTPRoute/test-kas"] } + let(:pages_route) { template["HTTPRoute/test-gitlab-pages"] } + + describe "Gateway API is enabled" do + let(:values) do + HelmTemplate.with_defaults(%( + global: + pages: + enabled: true + gatewayApi: + enabled: true + installEnvoy: true + )) + end + + it 'renders the template' do + expect(template.exit_code).to eq(0), "Unexpected error code #{template.exit_code} -- #{template.stderr}" + end + + it 'creates Gateway and GatewayClass' do + expect(gatewayclass).not_to be_nil + expect(gateway).not_to be_nil + end + + it 'creates the routes' do + expect(pages_route).not_to be_nil + expect(registry_route).not_to be_nil + expect(shell_route).not_to be_nil + expect(kas_route).not_to be_nil + expect(webservice_route).not_to be_nil + end + end +end diff --git a/templates/_gateway.tpl b/templates/_gateway.tpl new file mode 100644 index 0000000000..c41bd64f77 --- /dev/null +++ b/templates/_gateway.tpl @@ -0,0 +1,58 @@ +{{- define "gitlab.gatewayApi.class.name" -}} +{{- .Values.global.gatewayApi.class.name -}} +{{- end -}} + +{{- define "gitlab.gatewayApi.envoyProxy.config.name" -}} +{{- printf "%s-envoy-proxy" .Release.Name -}} +{{- end -}} + +{{- define "gitlab.gatewayApi.gateway" -}} +{{ printf "%s-gw" .Release.Name }} +{{- end -}} + +{{- define "gitlab.gatewayApi.gateway.listener" -}} +{{- $name := .local.name }} +{{- $protocol := .local.protocol | default .root.protocol }} +{{- $port := 443 }} +{{- if eq "HTTP" $protocol }} +{{- $port = 80 }} +{{- end }} +{{- if eq "TCP" $protocol }} +{{- $port = 22 }} +{{- end }} +- name: {{ $name }} + protocol: {{ $protocol | upper }} + port: {{ $port }} + allowedRoutes: + namespaces: + from: Same +{{- with .local.hostname }} + hostname: {{ . }} +{{- end }} +{{- with .local.tls }} + tls: +{{- toYaml . | nindent 4 }} +{{- end }} +{{- end -}} + +{{- define "gitlab.gatewayApi.route.gateway" -}} +{{ .Values.gatewayRoute.gatewayName | default (include "gitlab.gatewayApi.gateway" .) }} +{{- end -}} + +{{- define "gitlab.gatewayApi.route.enabled" -}} +{{- if not (eq nil .Values.gatewayRoute.enabled) -}} +{{- .Values.gatewayRoute.enabled -}} +{{- else }} +{{- .Values.global.gatewayApi.enabled -}} +{{- end -}} +{{- end -}} + +{{- define "gitlab.gatewayApi.certmanager.issuer" -}} +{{- printf "%s-gw-issuer" .Release.Name -}} +{{- end -}} + +{{- define "gitlab.gatewayApi.certmanager.annotations" -}} +{{- if .Values.global.gatewayApi.configureCertmanager -}} +cert-manager.io/issuer: {{ include "gitlab.gatewayApi.certmanager.issuer" . }} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 219a8c19d1..6a6a5d2036 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -757,3 +757,37 @@ Usage: {{ include "gitlab.topologyService.configureScript" $ | nindent 4 }} fi {{- end }} {{- end -}} + +{{/* +Returns the workspaces external hostname +*/}} +{{- define "gitlab.workspaces.hostname" -}} +{{- $hostname := $.Values.global.hosts.workspaces.name | required "Missing required workspaces host. Make sure to set `.Values.global.hosts.workspaces.name`" -}} +{{- $hostname -}} +{{- end -}} + +{{/* +Returns the workspaces wildcard hostname +*/}} +{{- define "gitlab.workspaces.wildcardHostname" -}} +{{- $hostname := include "gitlab.workspaces.hostname" . -}} +{{- print "*." $hostname -}} +{{- end -}} + +{{/* +Returns the KAS external hostname (for agentk connections) +If the hostname is set in `global.hosts.kas.name`, that will be returned, +otherwise the hostname will be assembed using `kas` as the prefix, and the `gitlab.assembleHost` function. +*/}} +{{- define "gitlab.kas.hostname" -}} +{{- coalesce $.Values.global.hosts.kas.name (include "gitlab.assembleHost" (dict "name" "kas" "context" . )) -}} +{{- end -}} + +{{/* +Returns the Pages hostname. +If the hostname is set in `global.hosts.pages.name`, that will be returned, +otherwise the hostname will be assembed using `pages` as the prefix, and the `gitlab.assembleHost` function. +*/}} +{{- define "gitlab.pages.hostname" -}} +{{- coalesce $.Values.global.pages.host $.Values.global.hosts.pages.name (include "gitlab.assembleHost" (dict "name" "pages" "context" . )) -}} +{{- end -}} diff --git a/templates/envoypatchpolicy.yaml b/templates/envoypatchpolicy.yaml new file mode 100644 index 0000000000..d148e30a2f --- /dev/null +++ b/templates/envoypatchpolicy.yaml @@ -0,0 +1,31 @@ +{{- if and .Values.global.gatewayApi.enabled .Values.global.gatewayApi.installEnvoy }} +{{- $gw := (include "gitlab.gatewayApi.gateway" .) }} +{{- $gitlabWebProtocol := (index .Values.global.gatewayApi.listeners "gitlab-web").protocol | default .Values.global.gatewayApi.protocol }} +{{- $patchPathPrefix := "/default_filter_chain" }} +{{- if eq (upper $gitlabWebProtocol) "HTTPS" }} +{{- $patchPathPrefix = "/filter_chains/0" }} +{{- end }} +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyPatchPolicy +metadata: + name: {{ .Release.Name }}-policy + namespace: {{ .Release.Namespace }} + labels: + {{- include "gitlab.standardLabels" . | nindent 4 }} + {{- include "gitlab.commonLabels" . | nindent 4 }} + debug: {{ $gitlabWebProtocol }} +spec: + targetRef: + group: gateway.networking.k8s.io + kind: Gateway + name: {{ $gw }} + type: JSONPatch + jsonPatches: + # Keep paths with escaped slashed unchanged. Escaped slashes are commonly used in GitLab API calls to identify projects. + - type: "type.googleapis.com/envoy.config.listener.v3.Listener" + name: {{ .Release.Namespace }}/{{ $gw }}/gitlab-web + operation: + op: add + path: {{ printf "%s/filters/0/typed_config/path_with_escaped_slashes_action" $patchPathPrefix | quote }} + value: "KEEP_UNCHANGED" +{{- end }} \ No newline at end of file diff --git a/templates/envoyproxy.yaml b/templates/envoyproxy.yaml new file mode 100644 index 0000000000..6140be3603 --- /dev/null +++ b/templates/envoyproxy.yaml @@ -0,0 +1,13 @@ + +{{- if and .Values.global.gatewayApi.enabled .Values.global.gatewayApi.class.create .Values.global.gatewayApi.installEnvoy }} +apiVersion: gateway.envoyproxy.io/v1alpha1 +kind: EnvoyProxy +metadata: + name: {{ include "gitlab.gatewayApi.envoyProxy.config.name" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitlab.standardLabels" . | nindent 4 }} + {{- include "gitlab.commonLabels" . | nindent 4 }} +spec: + {{ .Values.global.gatewayApi.envoyProxySpec | toYaml | nindent 2 }} +{{- end }} \ No newline at end of file diff --git a/templates/gateway.yaml b/templates/gateway.yaml new file mode 100644 index 0000000000..5ae0db7a99 --- /dev/null +++ b/templates/gateway.yaml @@ -0,0 +1,69 @@ + +{{- if .Values.global.gatewayApi.enabled }} +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: {{ include "gitlab.gatewayApi.gateway" . }} + namespace: "{{ .Release.Namespace }}" + labels: + {{- include "gitlab.standardLabels" . | nindent 4 }} + {{- include "gitlab.commonLabels" . | nindent 4 }} + annotations: + {{- include "gitlab.gatewayApi.certmanager.annotations" . | nindent 4 }} +spec: + gatewayClassName: {{ include "gitlab.gatewayApi.class.name" . | quote }} + listeners: + {{- $root := .Values.global.gatewayApi }} + {{- $listeners := $root.listeners }} + {{- $listener := dict }} + {{- if .Values.global.gatewayApi.configureCertmanager }} + {{- $listener = index $listeners "certmanager-http" }} + {{- $_ := set $listener "name" "certmanager-http" }} + {{- include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- end }} + {{- if .Values.gitlab.webservice.enabled }} + {{- $listener = index $listeners "gitlab-web" }} + {{- $_ := set $listener "name" "gitlab-web" }} + {{- $_ := set $listener "hostname" (include "gitlab.gitlab.hostname" .) }} + {{- include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- end }} + {{- if .Values.global.pages.enabled }} + {{- $listener = index $listeners "pages-web" }} + {{- $_ := set $listener "name" "pages-web" }} + {{- $hostname := (include "gitlab.pages.hostname" .) }} + {{- if $.Values.global.pages.namespaceInPath }} + {{- $hostname = (printf "*.%s" $hostname) }} + {{- end }} + {{- $_ := set $listener "hostname" $hostname }} + {{ include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- end }} + {{- if .Values.registry.enabled }} + {{- $listener = index $listeners "registry-web" }} + {{- $_ := set $listener "name" "registry-web" }} + {{- $_ := set $listener "hostname" (include "gitlab.registry.hostname" .) }} + {{- include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- end }} + {{- if .Values.global.kas.enabled }} + {{- $listener = index $listeners "kas-web" }} + {{- $_ := set $listener "name" "kas-web" }} + {{- $_ := set $listener "hostname" (include "gitlab.kas.hostname" .) }} + {{- include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- if .Values.global.workspaces.enabled }} + {{- $listener = index $listeners "kas-workspaces-web" }} + {{- $_ := set $listener "name" "kas-workspaces-web" }} + {{- $_ := set $listener "hostname" (include "gitlab.workspaces.wildcardHostname" .) }} + {{- include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- end }} + {{- end }} + {{- if index .Values.gitlab "gitlab-shell" "enabled" }} + {{- $listener = index $listeners "gitlab-ssh" }} + {{- $_ := set $listener "name" "gitlab-ssh" }} + {{- include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- end }} + {{- if .Values.global.minio.enabled }} + {{- $listener = index $listeners "minio-web" }} + {{- $_ := set $listener "name" "minio-web" }} + {{- $_ := set $listener "hostname" (include "gitlab.minio.hostname" .) }} + {{- include "gitlab.gatewayApi.gateway.listener" (dict "local" $listener "root" $root) | nindent 2 }} + {{- end }} +{{ end }} \ No newline at end of file diff --git a/templates/gatewayclass.yaml b/templates/gatewayclass.yaml new file mode 100644 index 0000000000..5fd8ca6291 --- /dev/null +++ b/templates/gatewayclass.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.global.gatewayApi.enabled .Values.global.gatewayApi.installEnvoy }} +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: {{ include "gitlab.gatewayApi.class.name" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "gitlab.standardLabels" . | nindent 4 }} + {{- include "gitlab.commonLabels" . | nindent 4 }} + {{- include "gitlab.serviceLabels" . | nindent 4 }} +spec: + controllerName: {{ .Values.global.gatewayApi.class.controllerName }} + parametersRef: + group: gateway.envoyproxy.io + kind: EnvoyProxy + name: {{ include "gitlab.gatewayApi.envoyProxy.config.name" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} \ No newline at end of file diff --git a/values.yaml b/values.yaml index e7f6d5f1d0..7117f8b399 100644 --- a/values.yaml +++ b/values.yaml @@ -75,6 +75,68 @@ global: openbao: {} workspaces: {} + gatewayApi: + enabled: false + envoyProxySpec: + provider: + type: Kubernetes + kubernetes: + envoyService: + type: LoadBalancer + class: + name: "gitlab-gw" + controllerName: "gateway.envoyproxy.io/gitlab-gatewayclass-controller" + installEnvoy: false + configureCertmanager: false + protocol: "HTTPS" + listeners: + certmanager-http: + protocol: HTTP + gitlab-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: gitlab-tls + gitlab-ssh: + protocol: "TCP" + registry-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: registry-tls + pages-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: pages-tls + kas-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: kas-tls + kas-workspaces-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: kas-workspaces-tls + kas-registry-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: kas-workspaces-tls + minio-web: + protocol: "" + tls: + mode: Terminate + certificateRefs: + - name: minio-tls + ## https://docs.gitlab.com/charts/charts/globals#configure-ingress-settings ingress: apiVersion: "" @@ -1567,3 +1629,11 @@ openbao: database: '' username: '' sslMode: '' + +envoy-gateway: + config: + envoyGateway: + gateway: + controllerName: gateway.envoyproxy.io/gitlab-gatewayclass-controller + extensionApis: + enableEnvoyPatchPolicy: true \ No newline at end of file -- GitLab From a7793b7f5685e26f133c46cb5e63912f1a21c2c0 Mon Sep 17 00:00:00 2001 From: Clemens Beck Date: Tue, 25 Nov 2025 12:14:32 +0100 Subject: [PATCH 2/7] Document simple migration and support static addresses * Document a migration from NGINX Ingress to Envoy Gateway. The migration involves downtimes. * Support binding static IP addresses to the Gateway. --- doc/charts/envoygateway/_index.md | 110 ++++++++++++++++++++++++++++++ examples/values-gatewayapi.yaml | 2 +- templates/gateway.yaml | 2 + values.yaml | 3 +- 4 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 doc/charts/envoygateway/_index.md diff --git a/doc/charts/envoygateway/_index.md b/doc/charts/envoygateway/_index.md new file mode 100644 index 0000000000..61dc84c539 --- /dev/null +++ b/doc/charts/envoygateway/_index.md @@ -0,0 +1,110 @@ +--- +stage: GitLab Delivery +group: Operate +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments +title: Using Envoy Gateway +--- + +{{< details >}} + +- Tier: Free, Premium, Ultimate +- Offering: GitLab Self-Managed +- Status: Beta + +{{< /details >}} + +GitLab chart bundled Envoy Gateway to support migrating from the bundled NGINX Ingress towards Gateway API. + +## Configuring Envoy Gateway + +To configure [Envoy Gateway](https://gateway.envoyproxy.io/docs/) and [Envoy Gateway Helm chart](https://github.com/envoyproxy/gateway/tree/main/charts/gateway-helm) +for configuration details. + +## Configuring Gateway API resources + +GitLab chart supports deploying a pre-configured `Gateway`, `EnvoyProxy`, `EnvoyPatchPolicy`, and +routes for each component. + +For more information check the [global Gateway API documentation](../globals.md#gateway-api). + +## Migrating from the bundled NGINX Ingress + +{{< alert type="warning" >}} + +This migration results in downtime. + +{{< /alert >}} + +To migrate from (NGINX) Ingress to Gateway API and Envoy Gateway: + +1. Install Envoy and Gateway API CRDs: + + ```script + helm template eg-crds oci://docker.io/envoyproxy/gateway-crds-helm \ + --version v1.6.0 \ + --set crds.gatewayAPI.enabled=true \ + --set crds.envoyGateway.enabled=true \ + | kubectl apply --server-side -f - + ``` + +1. If not, install the Gateway API CRDs through your cloud provider or [manually apply](https://gateway-api.sigs.k8s.io/guides/#installing-gateway-api) + to your cluster. + +1. Disable NGINX Ingress and Ingress resources: + + ```yaml + # Disable bundled NGINX Ingress controller. + nginx-ingress: + enabled: false + + global: + # Disable rendering of Ingress resources. + ingress: + enabled: false + ``` + +1. Configure Certmanager for Gateway API: + + ```yaml + # Configure bundled certmanager for Gateway API support. + certmanager: + config: + apiVersion: controller.config.cert-manager.io/v1alpha1 + kind: ControllerConfiguration + enableGatewayAPI: true + + global: + gatewayApi: + configureCertmanager: true + ``` + +1. Enable Envoy and Gateway API resources: + + ```yaml + global: + # Disable rendering of Ingress resources. + gatewayApi: + # Install a Gateway and Routes for each component. + enabled: true + # Install the bundled Envoy Gateway chart, a GatewayClass, a EnvoyPatchPolicy, and the EnvoyProxy resources. + installEnvoy: true + # Create a Gateway API compatible certmanager Issuer and configure the Gateway to use it. + class: + create: true + ``` + +1. Configure the Gateway to bind the existing IP address: + + ```yaml + # Depending on your cloud provider you might to migrate additional annotations. + global: + hosts: + # Unset, only used by the bundled NGINX Ingress. + externalIP: "" + gatewayApi: + addresses: + - type: IPAddress + value: "127.1.1.1" + ``` + +1. Upgrade your GitLab chart release with the updated values. diff --git a/examples/values-gatewayapi.yaml b/examples/values-gatewayapi.yaml index 742899fe33..7c24bd085d 100644 --- a/examples/values-gatewayapi.yaml +++ b/examples/values-gatewayapi.yaml @@ -21,6 +21,6 @@ global: # Create a Gateway API compatible certmanager Issuer and configure the Gateway to use it. configureCertmanager: true # Default web protocol. - protocol: "HTTP" # or 'HTTP' + protocol: "HTTPS" # or 'HTTP' class: create: true \ No newline at end of file diff --git a/templates/gateway.yaml b/templates/gateway.yaml index 5ae0db7a99..2c98351c7b 100644 --- a/templates/gateway.yaml +++ b/templates/gateway.yaml @@ -12,6 +12,8 @@ metadata: {{- include "gitlab.gatewayApi.certmanager.annotations" . | nindent 4 }} spec: gatewayClassName: {{ include "gitlab.gatewayApi.class.name" . | quote }} + addresses: + {{ .Values.global.gatewayApi.addresses | toYaml | nindent 4 }} listeners: {{- $root := .Values.global.gatewayApi }} {{- $listeners := $root.listeners }} diff --git a/values.yaml b/values.yaml index 7117f8b399..1de78ffb3c 100644 --- a/values.yaml +++ b/values.yaml @@ -89,6 +89,7 @@ global: installEnvoy: false configureCertmanager: false protocol: "HTTPS" + addresses: [] listeners: certmanager-http: protocol: HTTP @@ -1636,4 +1637,4 @@ envoy-gateway: gateway: controllerName: gateway.envoyproxy.io/gitlab-gatewayclass-controller extensionApis: - enableEnvoyPatchPolicy: true \ No newline at end of file + enableEnvoyPatchPolicy: true -- GitLab From 9cc4ef7f2a2429797c7be1141127c0fdeba83202 Mon Sep 17 00:00:00 2001 From: Clemens Beck Date: Wed, 26 Nov 2025 14:56:56 +0100 Subject: [PATCH 3/7] Reuse external IP bound by NGINX Fall back to reuse the external IP bound by NGINX if no addresses/IPs for the Gateway have been defined. --- doc/charts/envoygateway/_index.md | 8 +++++--- spec/configuration/gatewayapi_spec.rb | 9 +++++++++ templates/gateway.yaml | 7 +++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/doc/charts/envoygateway/_index.md b/doc/charts/envoygateway/_index.md index 61dc84c539..bd65fc676c 100644 --- a/doc/charts/envoygateway/_index.md +++ b/doc/charts/envoygateway/_index.md @@ -93,14 +93,16 @@ To migrate from (NGINX) Ingress to Gateway API and Envoy Gateway: create: true ``` -1. Configure the Gateway to bind the existing IP address: +1. Optional: Configure the Gateway to bind a static IP address. By default the IP configured via `global.hosts.externalIP` + is reused. ```yaml # Depending on your cloud provider you might to migrate additional annotations. global: hosts: - # Unset, only used by the bundled NGINX Ingress. - externalIP: "" + # Only used by Envoy if bundled NGINX Ingress is disabled and no custom + # gateway addresses are defined. + externalIP: "127.0.0.1" gatewayApi: addresses: - type: IPAddress diff --git a/spec/configuration/gatewayapi_spec.rb b/spec/configuration/gatewayapi_spec.rb index f799c39d06..2b09e3b347 100644 --- a/spec/configuration/gatewayapi_spec.rb +++ b/spec/configuration/gatewayapi_spec.rb @@ -18,7 +18,12 @@ describe 'Gateway API configuration' do describe "Gateway API is enabled" do let(:values) do HelmTemplate.with_defaults(%( + nginx-ingress: + enabled: false + global: + hosts: + externalIP: 127.0.0.1 pages: enabled: true gatewayApi: @@ -43,5 +48,9 @@ describe 'Gateway API configuration' do expect(kas_route).not_to be_nil expect(webservice_route).not_to be_nil end + + it 'picks up the static IP' do + expect(gateway["spec"]["addresses"]).to eq([{ "type" => "IPAddress", "value" => "127.0.0.1" }]) + end end end diff --git a/templates/gateway.yaml b/templates/gateway.yaml index 2c98351c7b..1373a5af59 100644 --- a/templates/gateway.yaml +++ b/templates/gateway.yaml @@ -12,8 +12,15 @@ metadata: {{- include "gitlab.gatewayApi.certmanager.annotations" . | nindent 4 }} spec: gatewayClassName: {{ include "gitlab.gatewayApi.class.name" . | quote }} + {{- $nginxEnabled := (index .Values "nginx-ingress" "enabled")}} + {{- if .Values.global.gatewayApi.addresses }} addresses: {{ .Values.global.gatewayApi.addresses | toYaml | nindent 4 }} + {{- else if (and (not $nginxEnabled) .Values.global.hosts.externalIP) }} + addresses: + - type: IPAddress + value: {{ .Values.global.hosts.externalIP }} + {{- end }} listeners: {{- $root := .Values.global.gatewayApi }} {{- $listeners := $root.listeners }} -- GitLab From b2fb4600a1b13b0abb1de3b462120d11b24f6eb5 Mon Sep 17 00:00:00 2001 From: Clemens Beck Date: Tue, 2 Dec 2025 12:50:09 +0100 Subject: [PATCH 4/7] Document external providers --- doc/charts/globals.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/charts/globals.md b/doc/charts/globals.md index 47f4792c2f..0329d09262 100644 --- a/doc/charts/globals.md +++ b/doc/charts/globals.md @@ -289,6 +289,30 @@ certmanager: Setting `configureCertmanager` configures the chart to render the relevant annotations to the Gateway manifest, and enables the creation of a HTTP01 Issuer configured for Gateway API. +### Using a external Gateway API provider + +The chart can be configured to use a external Gateway API provider, yet not every provider +meets the requirements to expose GitLab. + +Make sure your Gateway API provider does support `HTTPRoutes`, `TCPRoute` (for SSH), +and `GRPCRoutes` (for future KAS features). + +Note that we only test with the bundled Envoy Gateway chart. Support for other providers is +offered on a best-effort basis. We welcome any contributions that document working +configurations with other Gateway API providers. + +To configure GitLab chart to use an external GatewayClass, disable the bundled Envoy Gateway +and configure your custom class: + +```yaml +global: + gatewayApi: + enabled: true + class: + name: custom-class + installEnvoy: false +``` + ## GitLab Version {{< alert type="note" >}} -- GitLab From b12e81ffb63d9ef9d189713b25845bce9f576e5a Mon Sep 17 00:00:00 2001 From: Clemens Beck Date: Wed, 10 Dec 2025 09:35:04 +0100 Subject: [PATCH 5/7] spec: Merge Gateway API it blocks --- spec/configuration/gatewayapi_spec.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/configuration/gatewayapi_spec.rb b/spec/configuration/gatewayapi_spec.rb index 2b09e3b347..68b893e186 100644 --- a/spec/configuration/gatewayapi_spec.rb +++ b/spec/configuration/gatewayapi_spec.rb @@ -36,12 +36,14 @@ describe 'Gateway API configuration' do expect(template.exit_code).to eq(0), "Unexpected error code #{template.exit_code} -- #{template.stderr}" end - it 'creates Gateway and GatewayClass' do + it 'creates all expected Gateway API objects' do + expect(template.exit_code).to eq(0), "Unexpected error code #{template.exit_code} -- #{template.stderr}" + + # GatewayClass Object expect(gatewayclass).not_to be_nil + # Gateway Object expect(gateway).not_to be_nil - end - - it 'creates the routes' do + # Route objects expect(pages_route).not_to be_nil expect(registry_route).not_to be_nil expect(shell_route).not_to be_nil -- GitLab From d5ac80bd0221fe2de0aa30fea9ca2adfcae04241 Mon Sep 17 00:00:00 2001 From: Clemens Beck Date: Wed, 10 Dec 2025 10:02:38 +0100 Subject: [PATCH 6/7] Reorganize helper templates --- templates/_gateway.tpl | 45 +++++++++++++++++++++++++++++++++++ templates/_helpers.tpl | 34 -------------------------- templates/_kas.tpl | 9 +++++++ templates/_kas_workspaces.tpl | 15 ++++++++++++ templates/_pages.tpl | 9 +++++++ 5 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 templates/_kas_workspaces.tpl diff --git a/templates/_gateway.tpl b/templates/_gateway.tpl index c41bd64f77..190c1c86c9 100644 --- a/templates/_gateway.tpl +++ b/templates/_gateway.tpl @@ -1,15 +1,44 @@ +{{/* +Returns name of the Gateway class. Consumed by chart managed Gateway and GatewayClass. +*/}} {{- define "gitlab.gatewayApi.class.name" -}} {{- .Values.global.gatewayApi.class.name -}} {{- end -}} +{{/* +Returns the name of the EnvoyProxy resource. +*/}} {{- define "gitlab.gatewayApi.envoyProxy.config.name" -}} {{- printf "%s-envoy-proxy" .Release.Name -}} {{- end -}} +{{/* +Returns name of the managed Gateway resource. +*/}} {{- define "gitlab.gatewayApi.gateway" -}} {{ printf "%s-gw" .Release.Name }} {{- end -}} +{{/* +Renders a single listener configuration for the managed Gateway resource. + +Input parameters: +local: + name: Name of the listener + protocol: Protocol type (HTTPS, HTTP, TCP, or nil) + hostname: Domain name (e.g., example.com) + tls: + mode: TLS termination mode + certificateRefs: List of certificate references +root: + protocol: Default protocol (HTTPS or HTTP) + +The root protocol serves as a default when no local protocol is specified, +enabling centralized protocol configuration for all HTTP(S) workloads and +listeners through a single setting. + +Port assignment is automatically determined based on the selected protocol. +*/}} {{- define "gitlab.gatewayApi.gateway.listener" -}} {{- $name := .local.name }} {{- $protocol := .local.protocol | default .root.protocol }} @@ -35,10 +64,18 @@ {{- end }} {{- end -}} +{{/* +Renders the Gateway name referenced from a Route resource. +Defaults to the GitLab chart managed Gateway but can be overriden per Route. +*/}} {{- define "gitlab.gatewayApi.route.gateway" -}} {{ .Values.gatewayRoute.gatewayName | default (include "gitlab.gatewayApi.gateway" .) }} {{- end -}} +{{/* +Checks if a Route should be enabled. Defaults to global GatewayAPI toggle but can be +configured per Route by setting true/false explicitly. +*/}} {{- define "gitlab.gatewayApi.route.enabled" -}} {{- if not (eq nil .Values.gatewayRoute.enabled) -}} {{- .Values.gatewayRoute.enabled -}} @@ -47,10 +84,18 @@ {{- end -}} {{- end -}} +{{/* +Renders the name of the HTTP01 Issuer for managing certificates used by GatewayAPI. +Different from the Issuer used for Ingresses. +*/}} {{- define "gitlab.gatewayApi.certmanager.issuer" -}} {{- printf "%s-gw-issuer" .Release.Name -}} {{- end -}} +{{/* +Renders certmanager annotations for the Gateway resource. +https://cert-manager.io/docs/usage/gateway/ +*/}} {{- define "gitlab.gatewayApi.certmanager.annotations" -}} {{- if .Values.global.gatewayApi.configureCertmanager -}} cert-manager.io/issuer: {{ include "gitlab.gatewayApi.certmanager.issuer" . }} diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index 6a6a5d2036..219a8c19d1 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -757,37 +757,3 @@ Usage: {{ include "gitlab.topologyService.configureScript" $ | nindent 4 }} fi {{- end }} {{- end -}} - -{{/* -Returns the workspaces external hostname -*/}} -{{- define "gitlab.workspaces.hostname" -}} -{{- $hostname := $.Values.global.hosts.workspaces.name | required "Missing required workspaces host. Make sure to set `.Values.global.hosts.workspaces.name`" -}} -{{- $hostname -}} -{{- end -}} - -{{/* -Returns the workspaces wildcard hostname -*/}} -{{- define "gitlab.workspaces.wildcardHostname" -}} -{{- $hostname := include "gitlab.workspaces.hostname" . -}} -{{- print "*." $hostname -}} -{{- end -}} - -{{/* -Returns the KAS external hostname (for agentk connections) -If the hostname is set in `global.hosts.kas.name`, that will be returned, -otherwise the hostname will be assembed using `kas` as the prefix, and the `gitlab.assembleHost` function. -*/}} -{{- define "gitlab.kas.hostname" -}} -{{- coalesce $.Values.global.hosts.kas.name (include "gitlab.assembleHost" (dict "name" "kas" "context" . )) -}} -{{- end -}} - -{{/* -Returns the Pages hostname. -If the hostname is set in `global.hosts.pages.name`, that will be returned, -otherwise the hostname will be assembed using `pages` as the prefix, and the `gitlab.assembleHost` function. -*/}} -{{- define "gitlab.pages.hostname" -}} -{{- coalesce $.Values.global.pages.host $.Values.global.hosts.pages.name (include "gitlab.assembleHost" (dict "name" "pages" "context" . )) -}} -{{- end -}} diff --git a/templates/_kas.tpl b/templates/_kas.tpl index ad440bbc44..8e33d43522 100644 --- a/templates/_kas.tpl +++ b/templates/_kas.tpl @@ -83,3 +83,12 @@ Return the gitlab-kas AutoFlow Temporal Workflow data encryption secret {{- end -}} {{- default "kas_autoflow_temporal_workflow_data_encryption" $key | quote -}} {{- end -}} + +{{/* +Returns the KAS external hostname (for agentk connections) +If the hostname is set in `global.hosts.kas.name`, that will be returned, +otherwise the hostname will be assembed using `kas` as the prefix, and the `gitlab.assembleHost` function. +*/}} +{{- define "gitlab.kas.hostname" -}} +{{- coalesce $.Values.global.hosts.kas.name (include "gitlab.assembleHost" (dict "name" "kas" "context" . )) -}} +{{- end -}} diff --git a/templates/_kas_workspaces.tpl b/templates/_kas_workspaces.tpl new file mode 100644 index 0000000000..534e2bdf9a --- /dev/null +++ b/templates/_kas_workspaces.tpl @@ -0,0 +1,15 @@ +{{/* +Returns the KAS workspaces external hostname +*/}} +{{- define "gitlab.workspaces.hostname" -}} +{{- $hostname := $.Values.global.hosts.workspaces.name | required "Missing required workspaces host. Make sure to set `.Values.global.hosts.workspaces.name`" -}} +{{- $hostname -}} +{{- end -}} + +{{/* +Returns the KAS workspaces wildcard hostname +*/}} +{{- define "gitlab.workspaces.wildcardHostname" -}} +{{- $hostname := include "gitlab.workspaces.hostname" . -}} +{{- print "*." $hostname -}} +{{- end -}} diff --git a/templates/_pages.tpl b/templates/_pages.tpl index 7e16eac2c1..7b9c93f206 100644 --- a/templates/_pages.tpl +++ b/templates/_pages.tpl @@ -19,3 +19,12 @@ Return the gitlab-pages secret {{- define "gitlab.pages.authSecret.key" -}} {{ default "password" $.Values.global.pages.authSecret.key }} {{- end -}} + +{{/* +Returns the Pages hostname. +If the hostname is set in `global.hosts.pages.name`, that will be returned, +otherwise the hostname will be assembed using `pages` as the prefix, and the `gitlab.assembleHost` function. +*/}} +{{- define "gitlab.pages.hostname" -}} +{{- coalesce $.Values.global.pages.host $.Values.global.hosts.pages.name (include "gitlab.assembleHost" (dict "name" "pages" "context" . )) -}} +{{- end -}} -- GitLab From d0a4ae0087eff5c62bc82ff329824b96c8f93f16 Mon Sep 17 00:00:00 2001 From: Clemens Beck Date: Thu, 11 Dec 2025 13:09:56 +0100 Subject: [PATCH 7/7] Fix incorrect workspaces handling * Use correct path for section name. * Ensure hostname is quotes to render valid yaml with wildcard hostname. --- charts/gitlab/charts/kas/templates/httproute-workspaces.yaml | 2 +- templates/_gateway.tpl | 2 +- templates/envoypatchpolicy.yaml | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/charts/gitlab/charts/kas/templates/httproute-workspaces.yaml b/charts/gitlab/charts/kas/templates/httproute-workspaces.yaml index 0f3bfd291c..d80d25bd8b 100644 --- a/charts/gitlab/charts/kas/templates/httproute-workspaces.yaml +++ b/charts/gitlab/charts/kas/templates/httproute-workspaces.yaml @@ -13,7 +13,7 @@ metadata: spec: parentRefs: - name: {{ template "gitlab.gatewayApi.route.gateway" . }} - sectionName: {{ .gatewayApi.workspacesSectionName }} + sectionName: {{ .Values.gatewayRoute.workspacesSectionName }} hostnames: - {{ include "gitlab.workspaces.wildcardHostname" . | quote }} rules: diff --git a/templates/_gateway.tpl b/templates/_gateway.tpl index 190c1c86c9..ae22c2c75e 100644 --- a/templates/_gateway.tpl +++ b/templates/_gateway.tpl @@ -56,7 +56,7 @@ Port assignment is automatically determined based on the selected protocol. namespaces: from: Same {{- with .local.hostname }} - hostname: {{ . }} + hostname: {{ . | quote }} {{- end }} {{- with .local.tls }} tls: diff --git a/templates/envoypatchpolicy.yaml b/templates/envoypatchpolicy.yaml index d148e30a2f..1b1432a8ac 100644 --- a/templates/envoypatchpolicy.yaml +++ b/templates/envoypatchpolicy.yaml @@ -13,7 +13,6 @@ metadata: labels: {{- include "gitlab.standardLabels" . | nindent 4 }} {{- include "gitlab.commonLabels" . | nindent 4 }} - debug: {{ $gitlabWebProtocol }} spec: targetRef: group: gateway.networking.k8s.io -- GitLab