This is an automated email from the ASF dual-hosted git repository.
ronething pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-helm-chart.git
The following commit(s) were added to refs/heads/master by this push:
new 7fd5bd2 feat: support webhook server for ingress (#888)
7fd5bd2 is described below
commit 7fd5bd2a422fb8182c1d170c3d3641ba7d0156a6
Author: Ashing Zheng <[email protected]>
AuthorDate: Fri Oct 17 16:29:12 2025 +0800
feat: support webhook server for ingress (#888)
Signed-off-by: Ashing Zheng <[email protected]>
---
charts/apisix-ingress-controller/README.md | 5 +
.../templates/_helpers.tpl | 20 ++
.../templates/cluster_role.yaml | 31 +-
.../templates/configmap.yaml | 8 +
.../templates/deployment.yaml | 15 +
.../templates/webhook.yaml | 342 +++++++++++++++++++++
charts/apisix-ingress-controller/values.yaml | 18 ++
7 files changed, 424 insertions(+), 15 deletions(-)
diff --git a/charts/apisix-ingress-controller/README.md
b/charts/apisix-ingress-controller/README.md
index bf3dd3e..ab13f08 100644
--- a/charts/apisix-ingress-controller/README.md
+++ b/charts/apisix-ingress-controller/README.md
@@ -166,3 +166,8 @@ The same for container level, you need to set:
| serviceMonitor.labels | object | `{}` | @param serviceMonitor.labels
ServiceMonitor extra labels |
| serviceMonitor.metricRelabelings | object | `{}` | @param
serviceMonitor.metricRelabelings MetricRelabelConfigs to apply to samples
before ingestion. ref:
https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs
|
| serviceMonitor.namespace | string | `"monitoring"` | @param
serviceMonitor.namespace Namespace in which to create the ServiceMonitor |
+| webhook.certificate.provided | bool | `false` | Set to true if you want to
provide your own certificate |
+| webhook.enabled | bool | `true` | Enable or disable admission webhook |
+| webhook.failurePolicy | string | `"Fail"` | Failure policy for the webhook
(Fail or Ignore) |
+| webhook.port | int | `9443` | The port for the webhook server to listen on |
+| webhook.timeoutSeconds | int | `10` | Timeout in seconds for the webhook |
diff --git a/charts/apisix-ingress-controller/templates/_helpers.tpl
b/charts/apisix-ingress-controller/templates/_helpers.tpl
index fdba6f4..cf34bd7 100644
--- a/charts/apisix-ingress-controller/templates/_helpers.tpl
+++ b/charts/apisix-ingress-controller/templates/_helpers.tpl
@@ -67,3 +67,23 @@ app.kubernetes.io/name: {{ include
"apisix-ingress-controller-manager.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- end }}
+
+{{/*
+Webhook service name - ensure it stays within 63 character limit
+*/}}
+{{- define "apisix-ingress-controller-manager.webhook.serviceName" -}}
+{{- $suffix := "-webhook-svc" -}}
+{{- $maxLen := sub 63 (len $suffix) | int -}}
+{{- $baseName := include "apisix-ingress-controller-manager.name.fullname" . |
trunc $maxLen | trimSuffix "-" -}}
+{{- printf "%s%s" $baseName $suffix -}}
+{{- end }}
+
+{{/*
+Webhook secret name - ensure it stays within 63 character limit
+*/}}
+{{- define "apisix-ingress-controller-manager.webhook.secretName" -}}
+{{- $suffix := "-webhook-cert" -}}
+{{- $maxLen := sub 63 (len $suffix) | int -}}
+{{- $baseName := include "apisix-ingress-controller-manager.name.fullname" . |
trunc $maxLen | trimSuffix "-" -}}
+{{- printf "%s%s" $baseName $suffix -}}
+{{- end }}
diff --git a/charts/apisix-ingress-controller/templates/cluster_role.yaml
b/charts/apisix-ingress-controller/templates/cluster_role.yaml
index d3149bc..649ce80 100644
--- a/charts/apisix-ingress-controller/templates/cluster_role.yaml
+++ b/charts/apisix-ingress-controller/templates/cluster_role.yaml
@@ -94,7 +94,6 @@ rules:
- gateway.networking.k8s.io
resources:
- gatewayclasses
- - gateways
verbs:
- get
- list
@@ -105,7 +104,11 @@ rules:
resources:
- gatewayclasses/status
- gateways/status
+ - grpcroutes/status
- httproutes/status
+ - tcproutes/status
+ - udproutes/status
+ - tlsroutes/status
- referencegrants/status
verbs:
- get
@@ -113,23 +116,22 @@ rules:
- apiGroups:
- gateway.networking.k8s.io
resources:
+ - gateways
+ - grpcroutes
- httproutes
- verbs:
- - get
- - list
- - watch
-- apiGroups:
- - gateway.networking.k8s.io
- resources:
+ - tcproutes
+ - udproutes
+ - tlsroutes
- referencegrants
verbs:
+ - get
- list
- - update
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
+ - ingresses
verbs:
- get
- list
@@ -137,19 +139,18 @@ rules:
- apiGroups:
- networking.k8s.io
resources:
- - ingresses
+ - ingresses/status
verbs:
- get
- - list
- update
- - watch
- apiGroups:
- - networking.k8s.io
+ - ""
resources:
- - ingresses/status
+ - endpoints
verbs:
- get
- - update
+ - list
+ - watch
---
apiVersion: rbac.authorization.k8s.io/v1
diff --git a/charts/apisix-ingress-controller/templates/configmap.yaml
b/charts/apisix-ingress-controller/templates/configmap.yaml
index 6495559..82a6da6 100644
--- a/charts/apisix-ingress-controller/templates/configmap.yaml
+++ b/charts/apisix-ingress-controller/templates/configmap.yaml
@@ -38,3 +38,11 @@ data:
type: {{ .Values.config.provider.type | default "apisix" }}
sync_period: {{ .Values.config.provider.syncPeriod | default "1s" }}
init_sync_delay: {{ .Values.config.provider.initSyncDelay | default
"20m" }}
+ {{- if .Values.webhook.enabled }}
+ webhook:
+ enable: true
+ port: {{ .Values.webhook.port }}
+ tls_cert_file: "tls.crt"
+ tls_key_file: "tls.key"
+ tls_cert_dir: "/certs"
+ {{- end }}
diff --git a/charts/apisix-ingress-controller/templates/deployment.yaml
b/charts/apisix-ingress-controller/templates/deployment.yaml
index ac61846..7a0f506 100644
--- a/charts/apisix-ingress-controller/templates/deployment.yaml
+++ b/charts/apisix-ingress-controller/templates/deployment.yaml
@@ -58,10 +58,20 @@ spec:
- containerPort: {{ splitList ":" .Values.config.metricsAddr | last |
int }}
name: metrics
protocol: TCP
+ {{- if .Values.webhook.enabled }}
+ - containerPort: {{ .Values.webhook.port }}
+ name: webhook
+ protocol: TCP
+ {{- end }}
volumeMounts:
- name: {{ .Release.Name }}-ingress-config
mountPath: /app/conf/config.yaml
subPath: config.yaml
+ {{- if .Values.webhook.enabled }}
+ - name: webhook-certs
+ mountPath: /certs
+ readOnly: true
+ {{- end }}
livenessProbe:
httpGet:
path: /healthz
@@ -136,6 +146,11 @@ spec:
- name: {{ .Release.Name }}-ingress-config
configMap:
name: {{ .Release.Name }}-ingress-config
+ {{- if .Values.webhook.enabled }}
+ - name: webhook-certs
+ secret:
+ secretName: {{ include
"apisix-ingress-controller-manager.webhook.secretName" . }}
+ {{- end }}
securityContext:
runAsNonRoot: false
serviceAccountName: {{ .Release.Name }}
diff --git a/charts/apisix-ingress-controller/templates/webhook.yaml
b/charts/apisix-ingress-controller/templates/webhook.yaml
new file mode 100644
index 0000000..3d00aff
--- /dev/null
+++ b/charts/apisix-ingress-controller/templates/webhook.yaml
@@ -0,0 +1,342 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+{{- if .Values.webhook.enabled }}
+{{- $certCert := "" -}}
+{{- $certKey := "" -}}
+{{- $caCert := "" -}}
+{{- if not .Values.webhook.certificate.provided }}
+{{- $cn := printf "%s.%s.svc" (include
"apisix-ingress-controller-manager.webhook.serviceName" .) .Release.Namespace
-}}
+{{- $ca := genCA "apisix-ingress-webhook-ca" 3650 -}}
+{{- $cert := genSignedCert $cn nil (list $cn) 3650 $ca -}}
+{{- $certCert = $cert.Cert -}}
+{{- $certKey = $cert.Key -}}
+{{- $caCert = $ca.Cert -}}
+
+{{- $certSecret := (lookup "v1" "Secret" .Release.Namespace (include
"apisix-ingress-controller-manager.webhook.secretName" .)) -}}
+{{- if $certSecret }}
+{{- $certCert = (b64dec (get $certSecret.data "tls.crt")) -}}
+{{- $certKey = (b64dec (get $certSecret.data "tls.key")) -}}
+{{- $caCert = (b64dec (get $certSecret.data "ca.crt")) -}}
+{{- end }}
+{{- end }}
+
+---
+apiVersion: admissionregistration.k8s.io/v1
+kind: ValidatingWebhookConfiguration
+metadata:
+ name: {{ include "apisix-ingress-controller-manager.name.fullname" .
}}-webhook
+ labels:
+ {{- include "apisix-ingress-controller-manager.labels" . | nindent 4 }}
+webhooks:
+- name: vapisixroute-v2.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-apisix-apache-org-v2-apisixroute
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["apisix.apache.org"]
+ apiVersions: ["v2"]
+ resources: ["apisixroutes"]
+- name: vapisixconsumer-v2.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-apisix-apache-org-v2-apisixconsumer
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["apisix.apache.org"]
+ apiVersions: ["v2"]
+ resources: ["apisixconsumers"]
+- name: vapisixtls-v2.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-apisix-apache-org-v2-apisixtls
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["apisix.apache.org"]
+ apiVersions: ["v2"]
+ resources: ["apisixtlses"]
+- name: vconsumer-v1alpha1.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-apisix-apache-org-v1alpha1-consumer
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["apisix.apache.org"]
+ apiVersions: ["v1alpha1"]
+ resources: ["consumers"]
+- name: vgatewayproxy-v1alpha1.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-apisix-apache-org-v1alpha1-gatewayproxy
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["apisix.apache.org"]
+ apiVersions: ["v1alpha1"]
+ resources: ["gatewayproxies"]
+- name: vingress-v1.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-networking-k8s-io-v1-ingress
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["networking.k8s.io"]
+ apiVersions: ["v1"]
+ resources: ["ingresses"]
+- name: vingressclass-v1.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-networking-k8s-io-v1-ingressclass
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["networking.k8s.io"]
+ apiVersions: ["v1"]
+ resources: ["ingressclasses"]
+- name: vgateway-v1.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-gateway-networking-k8s-io-v1-gateway
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["gateway.networking.k8s.io"]
+ apiVersions: ["v1"]
+ resources: ["gateways"]
+- name: vgrpcroute-v1.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-gateway-networking-k8s-io-v1-grpcroute
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["gateway.networking.k8s.io"]
+ apiVersions: ["v1"]
+ resources: ["grpcroutes"]
+- name: vhttproute-v1.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-gateway-networking-k8s-io-v1-httproute
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["gateway.networking.k8s.io"]
+ apiVersions: ["v1"]
+ resources: ["httproutes"]
+- name: vtcproute-v1alpha2.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-gateway-networking-k8s-io-v1alpha2-tcproute
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["gateway.networking.k8s.io"]
+ apiVersions: ["v1alpha2"]
+ resources: ["tcproutes"]
+- name: vudproute-v1alpha2.kb.io
+ admissionReviewVersions: ["v1"]
+ clientConfig:
+ {{- if not .Values.webhook.certificate.provided }}
+ caBundle: {{ b64enc $caCert }}
+ {{- else }}
+ caBundle: {{ .Values.webhook.certificate.caBundle }}
+ {{- end }}
+ service:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName"
. }}
+ namespace: {{ .Release.Namespace }}
+ path: /validate-gateway-networking-k8s-io-v1alpha2-udproute
+ failurePolicy: {{ .Values.webhook.failurePolicy }}
+ {{- with .Values.webhook.timeoutSeconds }}
+ timeoutSeconds: {{ . }}
+ {{- end }}
+ sideEffects: None
+ rules:
+ - operations: ["CREATE", "UPDATE"]
+ apiGroups: ["gateway.networking.k8s.io"]
+ apiVersions: ["v1alpha2"]
+ resources: ["udproutes"]
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "apisix-ingress-controller-manager.webhook.serviceName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "apisix-ingress-controller-manager.labels" . | nindent 4 }}
+spec:
+ ports:
+ - name: webhook
+ port: 443
+ protocol: TCP
+ targetPort: webhook
+ selector:
+ {{- include "apisix-ingress-controller-manager.selectorLabels" . | nindent
4 }}
+
+{{- if not .Values.webhook.certificate.provided }}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ include "apisix-ingress-controller-manager.webhook.secretName" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ {{- include "apisix-ingress-controller-manager.labels" . | nindent 4 }}
+type: kubernetes.io/tls
+data:
+ tls.crt: {{ b64enc $certCert }}
+ tls.key: {{ b64enc $certKey }}
+ ca.crt: {{ b64enc $caCert }}
+{{- end }}
+{{- end }}
diff --git a/charts/apisix-ingress-controller/values.yaml
b/charts/apisix-ingress-controller/values.yaml
index 6703473..c180c12 100644
--- a/charts/apisix-ingress-controller/values.yaml
+++ b/charts/apisix-ingress-controller/values.yaml
@@ -94,6 +94,24 @@ config:
ingressClass: apisix
defaultIngressClass: false
+# Admission webhook configuration
+webhook:
+ # -- Enable or disable admission webhook
+ enabled: true
+ # -- The port for the webhook server to listen on
+ port: 9443
+ # -- Failure policy for the webhook (Fail or Ignore)
+ failurePolicy: Fail
+ # -- Timeout in seconds for the webhook
+ timeoutSeconds: 10
+ certificate:
+ # -- Set to true if you want to provide your own certificate
+ provided: false
+ # -- Secret name containing the certificate (required if provided is true)
+ # secretName: "my-webhook-cert"
+ # -- CA bundle in base64 format (required if provided is true)
+ # caBundle: ""
+
# The GatewayProxy resource configures gateway proxy instances including
networking,
# provider connection, global plugins, and plugin metadata.
gatewayProxy: