Merge pull request #7182 from wallrj/7065-webhook-metrics

[VC-34401] Add a metrics server to the webhook
This commit is contained in:
cert-manager-prow[bot] 2024-07-23 08:26:08 +00:00 committed by GitHub
commit e1c19274c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 240 additions and 43 deletions

View File

@ -373,14 +373,14 @@ config:
StableCertificateRequestName: true StableCertificateRequestName: true
UseCertificateRequestBasicConstraints: true UseCertificateRequestBasicConstraints: true
ValidateCAA: true ValidateCAA: true
# Configure the metrics server for TLS
# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
metricsTLSConfig: metricsTLSConfig:
dynamic: dynamic:
secretNamespace: "cert-manager" secretNamespace: "cert-manager"
secretName: "cert-manager-metrics-ca" secretName: "cert-manager-metrics-ca"
dnsNames: dnsNames:
- cert-manager-metrics - cert-manager-metrics
- cert-manager-metrics.cert-manager
- cert-manager-metrics.cert-manager.svc
``` ```
#### **dns01RecursiveNameservers** ~ `string` #### **dns01RecursiveNameservers** ~ `string`
> Default value: > Default value:
@ -660,9 +660,9 @@ enableServiceLinks indicates whether information about services should be inject
> true > true
> ``` > ```
Enable Prometheus monitoring for the cert-manager controller to use with the. Prometheus Operator. If this option is enabled without enabling `prometheus.servicemonitor.enabled` or Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a
`prometheus.podmonitor.enabled`, 'prometheus.io' annotations are added to the cert-manager Deployment ServiceMonitor resource.
resources. Additionally, a service is created which can be used together with your own ServiceMonitor (managed outside of this Helm chart). Otherwise, a ServiceMonitor/ PodMonitor is created. Otherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in a error.
#### **prometheus.servicemonitor.enabled** ~ `bool` #### **prometheus.servicemonitor.enabled** ~ `bool`
> Default value: > Default value:
> ```yaml > ```yaml
@ -828,6 +828,15 @@ endpointAdditionalProperties:
sourceLabels: sourceLabels:
- __meta_kubernetes_pod_node_name - __meta_kubernetes_pod_node_name
targetLabel: instance targetLabel: instance
# Configure the PodMonitor for TLS connections
# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
scheme: https
tlsConfig:
serverName: cert-manager-metrics
ca:
secret:
name: cert-manager-metrics-ca
key: "tls.crt"
``` ```
@ -878,6 +887,14 @@ kind: WebhookConfiguration
# This should be uncommented and set as a default by the chart once # This should be uncommented and set as a default by the chart once
# the apiVersion of WebhookConfiguration graduates beyond v1alpha1. # the apiVersion of WebhookConfiguration graduates beyond v1alpha1.
securePort: 10250 securePort: 10250
# Configure the metrics server for TLS
# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
metricsTLSConfig:
dynamic:
secretNamespace: "cert-manager"
secretName: "cert-manager-metrics-ca"
dnsNames:
- cert-manager-metrics
``` ```
#### **webhook.strategy** ~ `object` #### **webhook.strategy** ~ `object`
> Default value: > Default value:

View File

@ -29,10 +29,21 @@ metadata:
spec: spec:
jobLabel: {{ template "cert-manager.fullname" . }} jobLabel: {{ template "cert-manager.fullname" . }}
selector: selector:
matchLabels: matchExpressions:
app.kubernetes.io/name: {{ template "cert-manager.name" . }} - key: app.kubernetes.io/name
app.kubernetes.io/instance: {{ .Release.Name }} operator: In
app.kubernetes.io/component: "controller" values:
- {{ template "cert-manager.name" . }}
- {{ include "webhook.name" . }}
- key: app.kubernetes.io/instance
operator: In
values:
- {{ .Release.Name }}
- key: app.kubernetes.io/component
operator: In
values:
- controller
- webhook
{{- if .Values.prometheus.podmonitor.namespace }} {{- if .Values.prometheus.podmonitor.namespace }}
namespaceSelector: namespaceSelector:
matchNames: matchNames:

View File

@ -29,10 +29,21 @@ metadata:
spec: spec:
jobLabel: {{ template "cert-manager.fullname" . }} jobLabel: {{ template "cert-manager.fullname" . }}
selector: selector:
matchLabels: matchExpressions:
app.kubernetes.io/name: {{ template "cert-manager.name" . }} - key: app.kubernetes.io/name
app.kubernetes.io/instance: {{ .Release.Name }} operator: In
app.kubernetes.io/component: "controller" values:
- {{ template "cert-manager.name" . }}
- {{ include "webhook.name" . }}
- key: app.kubernetes.io/instance
operator: In
values:
- {{ .Release.Name }}
- key: app.kubernetes.io/component
operator: In
values:
- controller
- webhook
{{- if .Values.prometheus.servicemonitor.namespace }} {{- if .Values.prometheus.servicemonitor.namespace }}
namespaceSelector: namespaceSelector:
matchNames: matchNames:

View File

@ -43,6 +43,14 @@ spec:
annotations: annotations:
{{- toYaml . | nindent 8 }} {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
{{- if and .Values.prometheus.enabled (not (or .Values.prometheus.servicemonitor.enabled .Values.prometheus.podmonitor.enabled)) }}
{{- if not .Values.podAnnotations }}
annotations:
{{- end }}
prometheus.io/path: "/metrics"
prometheus.io/scrape: 'true'
prometheus.io/port: '9402'
{{- end }}
spec: spec:
serviceAccountName: {{ template "webhook.serviceAccountName" . }} serviceAccountName: {{ template "webhook.serviceAccountName" . }}
{{- if hasKey .Values.webhook "automountServiceAccountToken" }} {{- if hasKey .Values.webhook "automountServiceAccountToken" }}
@ -95,6 +103,9 @@ spec:
{{- with .Values.webhook.extraArgs }} {{- with .Values.webhook.extraArgs }}
{{- toYaml . | nindent 10 }} {{- toYaml . | nindent 10 }}
{{- end }} {{- end }}
{{- if not .Values.prometheus.enabled }}
- --metrics-listen-address=0
{{- end }}
ports: ports:
- name: https - name: https
protocol: TCP protocol: TCP
@ -112,6 +123,11 @@ spec:
{{- else }} {{- else }}
containerPort: 6080 containerPort: 6080
{{- end }} {{- end }}
{{- if .Values.prometheus.enabled }}
- containerPort: 9402
name: http-metrics
protocol: TCP
{{- end }}
livenessProbe: livenessProbe:
httpGet: httpGet:
path: /livez path: /livez

View File

@ -15,6 +15,15 @@ rules:
resources: ["secrets"] resources: ["secrets"]
resourceNames: resourceNames:
- '{{ template "webhook.fullname" . }}-ca' - '{{ template "webhook.fullname" . }}-ca'
{{- $certmanagerNamespace := include "cert-manager.namespace" . }}
{{- with (.Values.webhook.config.metricsTLSConfig).dynamic }}
{{- if $certmanagerNamespace | eq .secretNamespace }}
# Allow webhook to read and update the metrics CA Secret when dynamic TLS is
# enabled for the metrics server and if the Secret is configured to be in the
# same namespace as cert-manager.
- {{ .secretName | quote }}
{{- end }}
{{- end }}
verbs: ["get", "list", "watch", "update"] verbs: ["get", "list", "watch", "update"]
# It's not possible to grant CREATE permission on a single resourceName. # It's not possible to grant CREATE permission on a single resourceName.
- apiGroups: [""] - apiGroups: [""]

View File

@ -32,6 +32,12 @@ spec:
port: 443 port: 443
protocol: TCP protocol: TCP
targetPort: "https" targetPort: "https"
{{- if and .Values.prometheus.enabled (not .Values.prometheus.podmonitor.enabled) }}
- name: metrics
port: 9402
protocol: TCP
targetPort: "http-metrics"
{{- end }}
selector: selector:
app.kubernetes.io/name: {{ include "webhook.name" . }} app.kubernetes.io/name: {{ include "webhook.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/instance: {{ .Release.Name }}

View File

@ -554,7 +554,7 @@
}, },
"helm-values.config": { "helm-values.config": {
"default": {}, "default": {},
"description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n featureGates:\n AdditionalCertificateOutputFormats: true\n DisallowInsecureCSRUsageDefinition: true\n ExperimentalCertificateSigningRequestControllers: true\n ExperimentalGatewayAPISupport: true\n LiteralCertificateSubject: true\n SecretsFilteredCaching: true\n ServerSideApply: true\n StableCertificateRequestName: true\n UseCertificateRequestBasicConstraints: true\n ValidateCAA: true\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics\n - cert-manager-metrics.cert-manager\n - cert-manager-metrics.cert-manager.svc", "description": "This property is used to configure options for the controller pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `controller.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\nconfig:\n apiVersion: controller.config.cert-manager.io/v1alpha1\n kind: ControllerConfiguration\n logging:\n verbosity: 2\n format: text\n leaderElectionConfig:\n namespace: kube-system\n kubernetesAPIQPS: 9000\n kubernetesAPIBurst: 9000\n numberOfConcurrentWorkers: 200\n featureGates:\n AdditionalCertificateOutputFormats: true\n DisallowInsecureCSRUsageDefinition: true\n ExperimentalCertificateSigningRequestControllers: true\n ExperimentalGatewayAPISupport: true\n LiteralCertificateSubject: true\n SecretsFilteredCaching: true\n ServerSideApply: true\n StableCertificateRequestName: true\n UseCertificateRequestBasicConstraints: true\n ValidateCAA: true\n # Configure the metrics server for TLS\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n metricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics",
"type": "object" "type": "object"
}, },
"helm-values.containerSecurityContext": { "helm-values.containerSecurityContext": {
@ -976,7 +976,7 @@
}, },
"helm-values.prometheus.enabled": { "helm-values.prometheus.enabled": {
"default": true, "default": true,
"description": "Enable Prometheus monitoring for the cert-manager controller to use with the. Prometheus Operator. If this option is enabled without enabling `prometheus.servicemonitor.enabled` or\n`prometheus.podmonitor.enabled`, 'prometheus.io' annotations are added to the cert-manager Deployment\nresources. Additionally, a service is created which can be used together with your own ServiceMonitor (managed outside of this Helm chart). Otherwise, a ServiceMonitor/ PodMonitor is created.", "description": "Enable Prometheus monitoring for the cert-manager controller and webhook. If you use the Prometheus Operator, set prometheus.podmonitor.enabled or prometheus.servicemonitor.enabled, to create a PodMonitor or a\nServiceMonitor resource.\nOtherwise, 'prometheus.io' annotations are added to the cert-manager and cert-manager-webhook Deployments. Note that you can not enable both PodMonitor and ServiceMonitor as they are mutually exclusive. Enabling both will result in a error.",
"type": "boolean" "type": "boolean"
}, },
"helm-values.prometheus.podmonitor": { "helm-values.prometheus.podmonitor": {
@ -1027,7 +1027,7 @@
}, },
"helm-values.prometheus.podmonitor.endpointAdditionalProperties": { "helm-values.prometheus.podmonitor.endpointAdditionalProperties": {
"default": {}, "default": {},
"description": "EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc.\n\nFor example:\nendpointAdditionalProperties:\n relabelings:\n - action: replace\n sourceLabels:\n - __meta_kubernetes_pod_node_name\n targetLabel: instance", "description": "EndpointAdditionalProperties allows setting additional properties on the endpoint such as relabelings, metricRelabelings etc.\n\nFor example:\nendpointAdditionalProperties:\n relabelings:\n - action: replace\n sourceLabels:\n - __meta_kubernetes_pod_node_name\n targetLabel: instance\n # Configure the PodMonitor for TLS connections\n # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\n scheme: https\n tlsConfig:\n serverName: cert-manager-metrics\n ca:\n secret:\n name: cert-manager-metrics-ca\n key: \"tls.crt\"",
"type": "object" "type": "object"
}, },
"helm-values.prometheus.podmonitor.honorLabels": { "helm-values.prometheus.podmonitor.honorLabels": {
@ -1683,7 +1683,7 @@
}, },
"helm-values.webhook.config": { "helm-values.webhook.config": {
"default": {}, "default": {},
"description": "This is used to configure options for the webhook pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\napiVersion: webhook.config.cert-manager.io/v1alpha1\nkind: WebhookConfiguration\n# The port that the webhook listens on for requests.\n# In GKE private clusters, by default Kubernetes apiservers are allowed to\n# talk to the cluster nodes only on 443 and 10250. Configuring\n# securePort: 10250 therefore will work out-of-the-box without needing to add firewall\n# rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000.\n# This should be uncommented and set as a default by the chart once\n# the apiVersion of WebhookConfiguration graduates beyond v1alpha1.\nsecurePort: 10250", "description": "This is used to configure options for the webhook pod. This allows setting options that would usually be provided using flags.\n\nIf `apiVersion` and `kind` are unspecified they default to the current latest version (currently `webhook.config.cert-manager.io/v1alpha1`). You can pin the version by specifying the `apiVersion` yourself.\n\nFor example:\napiVersion: webhook.config.cert-manager.io/v1alpha1\nkind: WebhookConfiguration\n# The port that the webhook listens on for requests.\n# In GKE private clusters, by default Kubernetes apiservers are allowed to\n# talk to the cluster nodes only on 443 and 10250. Configuring\n# securePort: 10250 therefore will work out-of-the-box without needing to add firewall\n# rules or requiring NET_BIND_SERVICE capabilities to bind port numbers < 1000.\n# This should be uncommented and set as a default by the chart once\n# the apiVersion of WebhookConfiguration graduates beyond v1alpha1.\nsecurePort: 10250\n# Configure the metrics server for TLS\n# See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls\nmetricsTLSConfig:\n dynamic:\n secretNamespace: \"cert-manager\"\n secretName: \"cert-manager-metrics-ca\"\n dnsNames:\n - cert-manager-metrics",
"type": "object" "type": "object"
}, },
"helm-values.webhook.containerSecurityContext": { "helm-values.webhook.containerSecurityContext": {

View File

@ -236,14 +236,14 @@ enableCertificateOwnerRef: false
# StableCertificateRequestName: true # StableCertificateRequestName: true
# UseCertificateRequestBasicConstraints: true # UseCertificateRequestBasicConstraints: true
# ValidateCAA: true # ValidateCAA: true
# # Configure the metrics server for TLS
# # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
# metricsTLSConfig: # metricsTLSConfig:
# dynamic: # dynamic:
# secretNamespace: "cert-manager" # secretNamespace: "cert-manager"
# secretName: "cert-manager-metrics-ca" # secretName: "cert-manager-metrics-ca"
# dnsNames: # dnsNames:
# - cert-manager-metrics # - cert-manager-metrics
# - cert-manager-metrics.cert-manager
# - cert-manager-metrics.cert-manager.svc
config: {} config: {}
# Setting Nameservers for DNS01 Self Check. # Setting Nameservers for DNS01 Self Check.
@ -482,12 +482,14 @@ enableServiceLinks: false
# +docs:section=Prometheus # +docs:section=Prometheus
prometheus: prometheus:
# Enable Prometheus monitoring for the cert-manager controller to use with the # Enable Prometheus monitoring for the cert-manager controller and webhook.
# Prometheus Operator. If this option is enabled without enabling `prometheus.servicemonitor.enabled` or # If you use the Prometheus Operator, set prometheus.podmonitor.enabled or
# `prometheus.podmonitor.enabled`, 'prometheus.io' annotations are added to the cert-manager Deployment # prometheus.servicemonitor.enabled, to create a PodMonitor or a
# resources. Additionally, a service is created which can be used together # ServiceMonitor resource.
# with your own ServiceMonitor (managed outside of this Helm chart). # Otherwise, 'prometheus.io' annotations are added to the cert-manager and
# Otherwise, a ServiceMonitor/ PodMonitor is created. # cert-manager-webhook Deployments.
# Note that you can not enable both PodMonitor and ServiceMonitor as they are
# mutually exclusive. Enabling both will result in a error.
enabled: true enabled: true
servicemonitor: servicemonitor:
@ -583,6 +585,15 @@ prometheus:
# sourceLabels: # sourceLabels:
# - __meta_kubernetes_pod_node_name # - __meta_kubernetes_pod_node_name
# targetLabel: instance # targetLabel: instance
# # Configure the PodMonitor for TLS connections
# # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
# scheme: https
# tlsConfig:
# serverName: cert-manager-metrics
# ca:
# secret:
# name: cert-manager-metrics-ca
# key: "tls.crt"
# #
# +docs:property # +docs:property
endpointAdditionalProperties: {} endpointAdditionalProperties: {}
@ -632,6 +643,14 @@ webhook:
# # This should be uncommented and set as a default by the chart once # # This should be uncommented and set as a default by the chart once
# # the apiVersion of WebhookConfiguration graduates beyond v1alpha1. # # the apiVersion of WebhookConfiguration graduates beyond v1alpha1.
# securePort: 10250 # securePort: 10250
# # Configure the metrics server for TLS
# # See https://cert-manager.io/docs/devops-tips/prometheus-metrics/#tls
# metricsTLSConfig:
# dynamic:
# secretNamespace: "cert-manager"
# secretName: "cert-manager-metrics-ca"
# dnsNames:
# - cert-manager-metrics
config: {} config: {}
# The update strategy for the cert-manager webhook deployment. # The update strategy for the cert-manager webhook deployment.

View File

@ -33,6 +33,9 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
if s.PprofAddress == "" { if s.PprofAddress == "" {
s.PprofAddress = "something:1234" s.PprofAddress = "something:1234"
} }
if s.MetricsListenAddress == "" {
s.MetricsListenAddress = "something:1234"
}
logsapi.SetRecommendedLoggingConfiguration(&s.Logging) logsapi.SetRecommendedLoggingConfiguration(&s.Logging)
}, },

View File

@ -62,4 +62,12 @@ type WebhookConfiguration struct {
// featureGates is a map of feature names to bools that enable or disable experimental // featureGates is a map of feature names to bools that enable or disable experimental
// features. // features.
FeatureGates map[string]bool FeatureGates map[string]bool
// The host and port that the metrics endpoint should listen on.
// The value "0" disables the metrics server.
// Defaults to '0.0.0.0:9402'.
MetricsListenAddress string
// Metrics endpoint TLS config
MetricsTLSConfig shared.TLSConfig
} }

View File

@ -24,6 +24,8 @@ import (
"github.com/cert-manager/cert-manager/pkg/apis/config/webhook/v1alpha1" "github.com/cert-manager/cert-manager/pkg/apis/config/webhook/v1alpha1"
) )
const defaultPrometheusMetricsServerAddress = "0.0.0.0:9402"
func addDefaultingFuncs(scheme *runtime.Scheme) error { func addDefaultingFuncs(scheme *runtime.Scheme) error {
return RegisterDefaults(scheme) return RegisterDefaults(scheme)
} }
@ -39,5 +41,9 @@ func SetDefaults_WebhookConfiguration(obj *v1alpha1.WebhookConfiguration) {
obj.PprofAddress = "localhost:6060" obj.PprofAddress = "localhost:6060"
} }
if obj.MetricsListenAddress == "" {
obj.MetricsListenAddress = defaultPrometheusMetricsServerAddress
}
logsapi.SetRecommendedLoggingConfiguration(&obj.Logging) logsapi.SetRecommendedLoggingConfiguration(&obj.Logging)
} }

View File

@ -21,5 +21,12 @@
"infoBufferSize": "0" "infoBufferSize": "0"
} }
} }
},
"metricsListenAddress": "0.0.0.0:9402",
"metricsTLSConfig": {
"filesystem": {},
"dynamic": {
"leafDuration": "168h0m0s"
}
} }
} }

View File

@ -68,6 +68,10 @@ func autoConvert_v1alpha1_WebhookConfiguration_To_webhook_WebhookConfiguration(i
out.PprofAddress = in.PprofAddress out.PprofAddress = in.PprofAddress
out.Logging = in.Logging out.Logging = in.Logging
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.MetricsListenAddress = in.MetricsListenAddress
if err := sharedv1alpha1.Convert_v1alpha1_TLSConfig_To_shared_TLSConfig(&in.MetricsTLSConfig, &out.MetricsTLSConfig, s); err != nil {
return err
}
return nil return nil
} }
@ -92,6 +96,10 @@ func autoConvert_webhook_WebhookConfiguration_To_v1alpha1_WebhookConfiguration(i
out.PprofAddress = in.PprofAddress out.PprofAddress = in.PprofAddress
out.Logging = in.Logging out.Logging = in.Logging
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates)) out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.MetricsListenAddress = in.MetricsListenAddress
if err := sharedv1alpha1.Convert_shared_TLSConfig_To_v1alpha1_TLSConfig(&in.MetricsTLSConfig, &out.MetricsTLSConfig, s); err != nil {
return err
}
return nil return nil
} }

View File

@ -38,4 +38,5 @@ func RegisterDefaults(scheme *runtime.Scheme) error {
func SetObjectDefaults_WebhookConfiguration(in *v1alpha1.WebhookConfiguration) { func SetObjectDefaults_WebhookConfiguration(in *v1alpha1.WebhookConfiguration) {
SetDefaults_WebhookConfiguration(in) SetDefaults_WebhookConfiguration(in)
sharedv1alpha1.SetDefaults_DynamicServingConfig(&in.TLSConfig.Dynamic) sharedv1alpha1.SetDefaults_DynamicServingConfig(&in.TLSConfig.Dynamic)
sharedv1alpha1.SetDefaults_DynamicServingConfig(&in.MetricsTLSConfig.Dynamic)
} }

View File

@ -38,6 +38,7 @@ func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
(*out)[key] = val (*out)[key] = val
} }
} }
in.MetricsTLSConfig.DeepCopyInto(&out.MetricsTLSConfig)
return return
} }

View File

@ -81,6 +81,10 @@ func NewCertManagerWebhookServer(log logr.Logger, opts config.WebhookConfigurati
MinTLSVersion: opts.TLSConfig.MinTLSVersion, MinTLSVersion: opts.TLSConfig.MinTLSVersion,
ValidationWebhook: admissionHandler, ValidationWebhook: admissionHandler,
MutationWebhook: admissionHandler, MutationWebhook: admissionHandler,
MetricsListenAddress: opts.MetricsListenAddress,
MetricsCertificateSource: buildCertificateSource(log, opts.MetricsTLSConfig, restcfg),
MetricsCipherSuites: opts.MetricsTLSConfig.CipherSuites,
MetricsMinTLSVersion: opts.MetricsTLSConfig.MinTLSVersion,
} }
for _, fn := range optionFunctions { for _, fn := range optionFunctions {
fn(s) fn(s)

View File

@ -64,4 +64,12 @@ type WebhookConfiguration struct {
// features. // features.
// +optional // +optional
FeatureGates map[string]bool `json:"featureGates,omitempty"` FeatureGates map[string]bool `json:"featureGates,omitempty"`
// The host and port that the metrics endpoint should listen on.
// The value "0" disables the metrics server.
// Defaults to '0.0.0.0:9402'.
MetricsListenAddress string `json:"metricsListenAddress,omitempty"`
// metricsTLSConfig is used to configure the metrics server TLS settings.
MetricsTLSConfig sharedv1alpha1.TLSConfig `json:"metricsTLSConfig"`
} }

View File

@ -48,6 +48,7 @@ func (in *WebhookConfiguration) DeepCopyInto(out *WebhookConfiguration) {
(*out)[key] = val (*out)[key] = val
} }
} }
in.MetricsTLSConfig.DeepCopyInto(&out.MetricsTLSConfig)
return return
} }

View File

@ -81,6 +81,8 @@ func WebhookConfigurationPathRefs(cfg *config.WebhookConfiguration) ([]*string,
return []*string{ return []*string{
&cfg.TLSConfig.Filesystem.KeyFile, &cfg.TLSConfig.Filesystem.KeyFile,
&cfg.TLSConfig.Filesystem.CertFile, &cfg.TLSConfig.Filesystem.CertFile,
&cfg.MetricsTLSConfig.Filesystem.KeyFile,
&cfg.MetricsTLSConfig.Filesystem.CertFile,
&cfg.KubeConfig, &cfg.KubeConfig,
}, nil }, nil
} }

View File

@ -90,4 +90,20 @@ func AddConfigFlags(fs *pflag.FlagSet, c *config.WebhookConfiguration) {
"Options are:\n"+strings.Join(utilfeature.DefaultFeatureGate.KnownFeatures(), "\n")) "Options are:\n"+strings.Join(utilfeature.DefaultFeatureGate.KnownFeatures(), "\n"))
logf.AddFlags(&c.Logging, fs) logf.AddFlags(&c.Logging, fs)
fs.StringVar(&c.MetricsListenAddress, "metrics-listen-address", c.MetricsListenAddress, "The host and port that the metrics endpoint should listen on. The value '0' disables the metrics server")
fs.StringVar(&c.MetricsTLSConfig.Filesystem.CertFile, "metrics-tls-cert-file", c.MetricsTLSConfig.Filesystem.CertFile, "path to the file containing the TLS certificate to serve metrics with")
fs.StringVar(&c.MetricsTLSConfig.Filesystem.KeyFile, "metrics-tls-private-key-file", c.MetricsTLSConfig.Filesystem.KeyFile, "path to the file containing the TLS private key to serve metrics with")
fs.DurationVar(&c.MetricsTLSConfig.Dynamic.LeafDuration, "metrics-dynamic-serving-leaf-duration", c.MetricsTLSConfig.Dynamic.LeafDuration, "leaf duration of metrics serving certificates")
fs.StringVar(&c.MetricsTLSConfig.Dynamic.SecretNamespace, "metrics-dynamic-serving-ca-secret-namespace", c.MetricsTLSConfig.Dynamic.SecretNamespace, "namespace of the secret used to store the CA that signs metrics serving certificates")
fs.StringVar(&c.MetricsTLSConfig.Dynamic.SecretName, "metrics-dynamic-serving-ca-secret-name", c.MetricsTLSConfig.Dynamic.SecretName, "name of the secret used to store the CA that signs serving certificates")
fs.StringSliceVar(&c.MetricsTLSConfig.Dynamic.DNSNames, "metrics-dynamic-serving-dns-names", c.MetricsTLSConfig.Dynamic.DNSNames, "DNS names that should be present on certificates generated by the metrics dynamic serving CA")
fs.StringSliceVar(&c.MetricsTLSConfig.CipherSuites, "metrics-tls-cipher-suites", c.MetricsTLSConfig.CipherSuites,
"Comma-separated list of cipher suites for the metrics server. "+
"If omitted, the default Go cipher suites will be used. "+
"Possible values: "+strings.Join(tlsCipherPossibleValues, ","))
fs.StringVar(&c.MetricsTLSConfig.MinTLSVersion, "metrics-tls-min-version", c.MetricsTLSConfig.MinTLSVersion,
"Minimum TLS version supported by the metrics server. If omitted, the default Go minimum version will be used. "+
"Possible values: "+strings.Join(tlsPossibleVersions, ", "))
} }

View File

@ -86,6 +86,21 @@ type Server struct {
// MinTLSVersion is the minimum TLS version supported. // MinTLSVersion is the minimum TLS version supported.
// Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). // Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants).
MinTLSVersion string MinTLSVersion string
// The host and port that the metrics endpoint should listen on.
MetricsListenAddress string
// If specified, the metrics server will listen with TLS using certificates
// provided by this CertificateSource.
MetricsCertificateSource servertls.CertificateSource
// MetricsCipherSuites is the list of allowed cipher suites for the server.
// Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants).
MetricsCipherSuites []string
// MetricsMinTLSVersion is the minimum TLS version supported.
// Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants).
MetricsMinTLSVersion string
} }
func (s *Server) Run(ctx context.Context) error { func (s *Server) Run(ctx context.Context) error {
@ -104,6 +119,15 @@ func (s *Server) Run(ctx context.Context) error {
return err return err
} }
metricsCipherSuites, err := ciphers.TLSCipherSuites(s.MetricsCipherSuites)
if err != nil {
return err
}
metricsMinVersion, err := ciphers.TLSVersion(s.MetricsMinTLSVersion)
if err != nil {
return err
}
if s.ListenAddr == 0 { if s.ListenAddr == 0 {
webhookPort, err := freePort() webhookPort, err := freePort()
if err != nil { if err != nil {
@ -119,7 +143,17 @@ func (s *Server) Run(ctx context.Context) error {
Scheme: s.ResourceScheme, Scheme: s.ResourceScheme,
Logger: log, Logger: log,
LeaderElection: false, // The webhook component does not need to perform leader election LeaderElection: false, // The webhook component does not need to perform leader election
Metrics: metricsserver.Options{BindAddress: "0"}, Metrics: metricsserver.Options{
BindAddress: s.MetricsListenAddress,
SecureServing: s.MetricsCertificateSource != nil,
TLSOpts: []func(*tls.Config){
func(cfg *tls.Config) {
cfg.CipherSuites = metricsCipherSuites
cfg.MinVersion = metricsMinVersion
cfg.GetCertificate = s.MetricsCertificateSource.GetCertificate
},
},
},
WebhookServer: webhook.NewServer(webhook.Options{ WebhookServer: webhook.NewServer(webhook.Options{
Port: int(s.ListenAddr), Port: int(s.ListenAddr),
TLSOpts: []func(*tls.Config){ TLSOpts: []func(*tls.Config){
@ -139,6 +173,12 @@ func (s *Server) Run(ctx context.Context) error {
return err return err
} }
if s.MetricsCertificateSource != nil {
if err := mgr.Add(s.MetricsCertificateSource); err != nil {
return err
}
}
// if a HealthzAddr is provided, start the healthz listener // if a HealthzAddr is provided, start the healthz listener
if s.HealthzAddr != nil { if s.HealthzAddr != nil {
healthzListener, err := net.Listen("tcp", fmt.Sprintf(":%d", *s.HealthzAddr)) healthzListener, err := net.Listen("tcp", fmt.Sprintf(":%d", *s.HealthzAddr))

View File

@ -100,7 +100,10 @@ func RunControlPlane(t *testing.T, ctx context.Context, optionFunctions ...RunCo
} }
webhookOpts, stopWebhook := webhooktesting.StartWebhookServer( webhookOpts, stopWebhook := webhooktesting.StartWebhookServer(
t, ctx, []string{"--kubeconfig", f.Name()}, // Disable the metrics server to avoid multiple webhook servers
// attempting to listen on metrics port 9402 when tests are running in
// parallel.
t, ctx, []string{"--kubeconfig", f.Name(), "--metrics-listen-address=0"},
) )
crds := readCustomResourcesAtPath(t, *options.crdsDir) crds := readCustomResourcesAtPath(t, *options.crdsDir)