mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 21:17:23 +00:00
add metrics for insecure backend proxy
This commit is contained in:
parent
e765ab2e7e
commit
782a7a5426
@ -10,6 +10,7 @@ go_library(
|
|||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"log.go",
|
"log.go",
|
||||||
|
"metrics.go",
|
||||||
"subresources.go",
|
"subresources.go",
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/pkg/registry/core/pod/rest",
|
importpath = "k8s.io/kubernetes/pkg/registry/core/pod/rest",
|
||||||
@ -25,11 +26,14 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/proxy:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/proxy:go_default_library",
|
||||||
|
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/features:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic/rest:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/generic/rest:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||||
|
"//staging/src/k8s.io/component-base/metrics:go_default_library",
|
||||||
|
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||||
@ -70,10 +72,16 @@ func (r *LogREST) ProducesObject(verb string) interface{} {
|
|||||||
|
|
||||||
// Get retrieves a runtime.Object that will stream the contents of the pod log
|
// Get retrieves a runtime.Object that will stream the contents of the pod log
|
||||||
func (r *LogREST) Get(ctx context.Context, name string, opts runtime.Object) (runtime.Object, error) {
|
func (r *LogREST) Get(ctx context.Context, name string, opts runtime.Object) (runtime.Object, error) {
|
||||||
|
// register the metrics if the context is used. This assumes sync.Once is fast. If it's not, it could be an init block.
|
||||||
|
registerMetrics()
|
||||||
|
|
||||||
logOpts, ok := opts.(*api.PodLogOptions)
|
logOpts, ok := opts.(*api.PodLogOptions)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("invalid options object: %#v", opts)
|
return nil, fmt.Errorf("invalid options object: %#v", opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we must do this before forcing the insecure flag if the feature is disabled
|
||||||
|
countSkipTLSMetric(logOpts.InsecureSkipTLSVerifyBackend)
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.AllowInsecureBackendProxy) {
|
if !utilfeature.DefaultFeatureGate.Enabled(features.AllowInsecureBackendProxy) {
|
||||||
logOpts.InsecureSkipTLSVerifyBackend = false
|
logOpts.InsecureSkipTLSVerifyBackend = false
|
||||||
}
|
}
|
||||||
@ -86,15 +94,34 @@ func (r *LogREST) Get(ctx context.Context, name string, opts runtime.Object) (ru
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &genericrest.LocationStreamer{
|
return &genericrest.LocationStreamer{
|
||||||
Location: location,
|
Location: location,
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
ContentType: "text/plain",
|
ContentType: "text/plain",
|
||||||
Flush: logOpts.Follow,
|
Flush: logOpts.Follow,
|
||||||
ResponseChecker: genericrest.NewGenericHttpResponseChecker(api.Resource("pods/log"), name),
|
ResponseChecker: genericrest.NewGenericHttpResponseChecker(api.Resource("pods/log"), name),
|
||||||
RedirectChecker: genericrest.PreventRedirects,
|
RedirectChecker: genericrest.PreventRedirects,
|
||||||
|
TLSVerificationErrorCounter: podLogsTLSFailure,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func countSkipTLSMetric(insecureSkipTLSVerifyBackend bool) {
|
||||||
|
usageType := usageEnforce
|
||||||
|
if insecureSkipTLSVerifyBackend {
|
||||||
|
if utilfeature.DefaultFeatureGate.Enabled(features.AllowInsecureBackendProxy) {
|
||||||
|
usageType = usageSkipAllowed
|
||||||
|
} else {
|
||||||
|
usageType = usageSkipDenied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
counter, err := podLogsUsage.GetMetricWithLabelValues(usageType)
|
||||||
|
if err != nil {
|
||||||
|
utilruntime.HandleError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
counter.Inc()
|
||||||
|
}
|
||||||
|
|
||||||
// NewGetOptions creates a new options object
|
// NewGetOptions creates a new options object
|
||||||
func (r *LogREST) NewGetOptions() (runtime.Object, bool, string) {
|
func (r *LogREST) NewGetOptions() (runtime.Object, bool, string) {
|
||||||
return &api.PodLogOptions{}, false, ""
|
return &api.PodLogOptions{}, false, ""
|
||||||
|
67
pkg/registry/core/pod/rest/metrics.go
Normal file
67
pkg/registry/core/pod/rest/metrics.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package rest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"k8s.io/component-base/metrics"
|
||||||
|
"k8s.io/component-base/metrics/legacyregistry"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
namespace = "kube_apiserver"
|
||||||
|
subsystem = "pod_logs"
|
||||||
|
|
||||||
|
usageEnforce = "enforce_tls"
|
||||||
|
usageSkipAllowed = "skip_tls_allowed"
|
||||||
|
usageSkipDenied = "skip_tls_denied"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// podLogsUsage counts and categorizes how the insecure backend skip TLS option is used and allowed.
|
||||||
|
podLogsUsage = metrics.NewCounterVec(
|
||||||
|
&metrics.CounterOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: subsystem,
|
||||||
|
Name: "pods_logs_insecure_backend_total",
|
||||||
|
Help: "Total number of requests for pods/logs sliced by usage type: enforce_tls, skip_tls_allowed, skip_tls_denied",
|
||||||
|
StabilityLevel: metrics.ALPHA,
|
||||||
|
},
|
||||||
|
[]string{"usage"},
|
||||||
|
)
|
||||||
|
|
||||||
|
// podLogsTLSFailure counts how many attempts to get pod logs fail on tls verification
|
||||||
|
podLogsTLSFailure = metrics.NewCounter(
|
||||||
|
&metrics.CounterOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Subsystem: subsystem,
|
||||||
|
Name: "pods_logs_backend_tls_failure_total",
|
||||||
|
Help: "Total number of requests for pods/logs that failed due to kubelet server TLS verification",
|
||||||
|
StabilityLevel: metrics.ALPHA,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
var registerMetricsOnce sync.Once
|
||||||
|
|
||||||
|
func registerMetrics() {
|
||||||
|
registerMetricsOnce.Do(func() {
|
||||||
|
legacyregistry.MustRegister(podLogsUsage)
|
||||||
|
legacyregistry.MustRegister(podLogsTLSFailure)
|
||||||
|
})
|
||||||
|
}
|
@ -30,6 +30,10 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CounterMetric interface {
|
||||||
|
Inc()
|
||||||
|
}
|
||||||
|
|
||||||
// LocationStreamer is a resource that streams the contents of a particular
|
// LocationStreamer is a resource that streams the contents of a particular
|
||||||
// location URL.
|
// location URL.
|
||||||
type LocationStreamer struct {
|
type LocationStreamer struct {
|
||||||
@ -39,6 +43,9 @@ type LocationStreamer struct {
|
|||||||
Flush bool
|
Flush bool
|
||||||
ResponseChecker HttpResponseChecker
|
ResponseChecker HttpResponseChecker
|
||||||
RedirectChecker func(req *http.Request, via []*http.Request) error
|
RedirectChecker func(req *http.Request, via []*http.Request) error
|
||||||
|
// TLSVerificationErrorCounter is an optional value that will Inc every time a TLS error is encountered. This can
|
||||||
|
// be wired a single prometheus counter instance to get counts overall.
|
||||||
|
TLSVerificationErrorCounter CounterMetric
|
||||||
}
|
}
|
||||||
|
|
||||||
// a LocationStreamer must implement a rest.ResourceStreamer
|
// a LocationStreamer must implement a rest.ResourceStreamer
|
||||||
@ -77,6 +84,10 @@ func (s *LocationStreamer) InputStream(ctx context.Context, apiVersion, acceptHe
|
|||||||
|
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// TODO prefer segregate TLS errors more reliably, but we do want to increment a count
|
||||||
|
if strings.Contains(err.Error(), "x509:") && s.TLSVerificationErrorCounter != nil {
|
||||||
|
s.TLSVerificationErrorCounter.Inc()
|
||||||
|
}
|
||||||
return nil, false, "", err
|
return nil, false, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user