This is an automated email from the ASF dual-hosted git repository.

ronething pushed a commit to branch feat/webhook_server
in repository https://gitbox.apache.org/repos/asf/apisix-helm-chart.git

commit ac35b4ffb5a2cfdd55e2ad1e5aca9a7056816b03
Author: Ashing Zheng <[email protected]>
AuthorDate: Fri Oct 17 10:47:26 2025 +0800

    feat: support webhook server for ingress
    
    Signed-off-by: Ashing Zheng <[email protected]>
---
 charts/apisix-ingress-controller/README.md         |   5 +
 .../templates/_helpers.tpl                         |  20 ++
 .../templates/cluster_role.yaml                    |  25 +-
 .../templates/configmap.yaml                       |   8 +
 .../templates/deployment.yaml                      |  15 ++
 .../templates/webhook.yaml                         | 254 +++++++++++++++++++++
 charts/apisix-ingress-controller/values.yaml       |  18 ++
 7 files changed, 330 insertions(+), 15 deletions(-)

diff --git a/charts/apisix-ingress-controller/README.md 
b/charts/apisix-ingress-controller/README.md
index 886ada1..3251406 100644
--- a/charts/apisix-ingress-controller/README.md
+++ b/charts/apisix-ingress-controller/README.md
@@ -158,3 +158,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..4f77554 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,6 +104,7 @@ rules:
   resources:
   - gatewayclasses/status
   - gateways/status
+  - grpcroutes/status
   - httproutes/status
   - referencegrants/status
   verbs:
@@ -113,23 +113,19 @@ rules:
 - apiGroups:
   - gateway.networking.k8s.io
   resources:
+  - gateways
+  - grpcroutes
   - httproutes
-  verbs:
-  - get
-  - list
-  - watch
-- apiGroups:
-  - gateway.networking.k8s.io
-  resources:
   - referencegrants
   verbs:
+  - get
   - list
-  - update
   - watch
 - apiGroups:
   - networking.k8s.io
   resources:
   - ingressclasses
+  - ingresses
   verbs:
   - get
   - list
@@ -137,19 +133,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..946cba5
--- /dev/null
+++ b/charts/apisix-ingress-controller/templates/webhook.yaml
@@ -0,0 +1,254 @@
+#
+# 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"]
+
+---
+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 ec68e3a..be41799 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: ""
+
 gatewayProxy:
   createDefault: false
   provider:

Reply via email to