[PodSecurity] Avoid the LegcayRegistry for metrics serving

This commit is contained in:
Tim Allclair 2021-10-26 18:49:13 -07:00
parent 21692e1683
commit 6c273020d3
4 changed files with 31 additions and 27 deletions

View File

@ -43,6 +43,7 @@ import (
"k8s.io/client-go/kubernetes"
corev1listers "k8s.io/client-go/listers/core/v1"
"k8s.io/component-base/featuregate"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch"
@ -83,6 +84,20 @@ var _ admission.ValidationInterface = &Plugin{}
var _ genericadmissioninit.WantsExternalKubeInformerFactory = &Plugin{}
var _ genericadmissioninit.WantsExternalKubeClientSet = &Plugin{}
var (
defaultRecorder *metrics.PrometheusRecorder
defaultRecorderInit sync.Once
)
func getDefaultRecorder() metrics.Recorder {
// initialize and register to legacy metrics once
defaultRecorderInit.Do(func() {
defaultRecorder = metrics.NewPrometheusRecorder(podsecurityadmissionapi.GetAPIVersion())
defaultRecorder.MustRegister(legacyregistry.MustRegister)
})
return defaultRecorder
}
// newPlugin creates a new admission plugin.
func newPlugin(reader io.Reader) (*Plugin, error) {
config, err := podsecurityconfigloader.LoadFromReader(reader)
@ -94,14 +109,13 @@ func newPlugin(reader io.Reader) (*Plugin, error) {
if err != nil {
return nil, fmt.Errorf("could not create PodSecurityRegistry: %w", err)
}
metrics.LegacyMustRegister()
return &Plugin{
Handler: admission.NewHandler(admission.Create, admission.Update),
delegate: &podsecurityadmission.Admission{
Configuration: config,
Evaluator: evaluator,
Metrics: metrics.DefaultRecorder(),
Metrics: getDefaultRecorder(),
PodSpecExtractor: podsecurityadmission.DefaultPodSpecExtractor{},
},
}, nil

View File

@ -41,7 +41,6 @@ import (
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
compbasemetrics "k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/component-base/version/verflag"
"k8s.io/klog/v2"
"k8s.io/pod-security-admission/admission"
@ -107,6 +106,8 @@ type Server struct {
informerFactory kubeinformers.SharedInformerFactory
delegate *admission.Admission
metricsRegistry compbasemetrics.KubeRegistry
}
func (s *Server) Start(ctx context.Context) error {
@ -119,10 +120,9 @@ func (s *Server) Start(ctx context.Context) error {
// debugging or proxy purposes. The API server will not connect to an http webhook.
mux.HandleFunc("/", s.HandleValidate)
// Serve the global metrics registry.
metrics.LegacyMustRegister()
// Serve the metrics.
mux.Handle("/metrics",
compbasemetrics.HandlerFor(legacyregistry.DefaultGatherer, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}))
compbasemetrics.HandlerFor(s.metricsRegistry, compbasemetrics.HandlerOpts{ErrorHandling: compbasemetrics.ContinueOnError}))
if s.insecureServing != nil {
if err := s.insecureServing.Serve(mux, 0, ctx.Done()); err != nil {
@ -279,11 +279,14 @@ func Setup(c *Config) (*Server, error) {
if err != nil {
return nil, fmt.Errorf("could not create PodSecurityRegistry: %w", err)
}
metrics := metrics.NewPrometheusRecorder(api.GetAPIVersion())
s.metricsRegistry = compbasemetrics.NewKubeRegistry()
metrics.MustRegister(s.metricsRegistry.MustRegister)
s.delegate = &admission.Admission{
Configuration: c.PodSecurityConfig,
Evaluator: evaluator,
Metrics: metrics.DefaultRecorder(),
Metrics: metrics,
PodSpecExtractor: admission.DefaultPodSpecExtractor{},
PodLister: admission.PodListerFromClient(client),
NamespaceGetter: admission.NamespaceGetterFromListerAndClient(namespaceLister, client),

View File

@ -19,13 +19,11 @@ package metrics
import (
"strconv"
"strings"
"sync"
admissionv1 "k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/component-base/metrics"
"k8s.io/component-base/metrics/legacyregistry"
"k8s.io/pod-security-admission/api"
)
@ -46,25 +44,12 @@ type Recorder interface {
RecordError(fatal bool, attrs api.Attributes)
}
var defaultRecorder = NewPrometheusRecorder(api.GetAPIVersion())
func DefaultRecorder() Recorder {
return defaultRecorder
}
// MustRegister registers the global DefaultMetrics against the legacy registry.
func LegacyMustRegister() {
defaultRecorder.MustRegister(legacyregistry.MustRegister)
}
type PrometheusRecorder struct {
apiVersion api.Version
evaluationsCounter *metrics.CounterVec
exemptionsCounter *metrics.CounterVec
errorsCounter *metrics.CounterVec
registerOnce sync.Once
}
var _ Recorder = &PrometheusRecorder{}
@ -104,11 +89,9 @@ func NewPrometheusRecorder(version api.Version) *PrometheusRecorder {
}
func (r *PrometheusRecorder) MustRegister(registerFunc func(...metrics.Registerable)) {
r.registerOnce.Do(func() {
registerFunc(r.evaluationsCounter)
registerFunc(r.exemptionsCounter)
registerFunc(r.errorsCounter)
})
registerFunc(r.evaluationsCounter)
registerFunc(r.exemptionsCounter)
registerFunc(r.errorsCounter)
}
func (r *PrometheusRecorder) Reset() {

View File

@ -342,4 +342,8 @@ func validateMetrics(t *testing.T, rawMetrics []byte) {
"decision", "policy_level", "policy_version", "mode", "request_operation", "resource", "subresource"); err != nil {
t.Errorf("Metric validation failed: %v", err)
}
if err := testutil.ValidateMetrics(metrics, "pod_security_exemptions_total",
"request_operation", "resource", "subresource"); err != nil {
t.Errorf("Metric validation failed: %v", err)
}
}