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:
