Skip to content

Commit eabb362

Browse files
committed
log tls handshake error at trace level to avoid error flooding, and add
metric to count such errors
1 parent 4b9b9ab commit eabb362

File tree

4 files changed

+47
-0
lines changed

4 files changed

+47
-0
lines changed

staging/src/k8s.io/apiserver/pkg/endpoints/metrics/metrics.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ var (
113113
},
114114
[]string{"requestKind"},
115115
)
116+
// TLSHandshakeErrors is a number of requests dropped with 'TLS handshake error from' error
117+
TLSHandshakeErrors = compbasemetrics.NewCounter(
118+
&compbasemetrics.CounterOpts{
119+
Name: "apiserver_tls_handshake_errors_total",
120+
Help: "Number of requests dropped with 'TLS handshake error from' error",
121+
StabilityLevel: compbasemetrics.ALPHA,
122+
},
123+
)
116124
// RegisteredWatchers is a number of currently registered watchers splitted by resource.
117125
RegisteredWatchers = compbasemetrics.NewGaugeVec(
118126
&compbasemetrics.GaugeOpts{
@@ -166,6 +174,7 @@ var (
166174
requestLatencies,
167175
responseSizes,
168176
DroppedRequests,
177+
TLSHandshakeErrors,
169178
RegisteredWatchers,
170179
WatchEvents,
171180
WatchEventsSizes,

staging/src/k8s.io/apiserver/pkg/server/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ go_library(
102102
"//staging/src/k8s.io/apiserver/pkg/endpoints/discovery:go_default_library",
103103
"//staging/src/k8s.io/apiserver/pkg/endpoints/filters:go_default_library",
104104
"//staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters:go_default_library",
105+
"//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library",
105106
"//staging/src/k8s.io/apiserver/pkg/endpoints/openapi:go_default_library",
106107
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
107108
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",

staging/src/k8s.io/apiserver/pkg/server/secure_serving.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,20 @@ import (
2020
"context"
2121
"crypto/tls"
2222
"fmt"
23+
"io"
24+
"log"
2325
"net"
2426
"net/http"
27+
"os"
28+
"strings"
2529
"time"
2630

2731
"golang.org/x/net/http2"
2832
"k8s.io/component-base/cli/flag"
2933
"k8s.io/klog/v2"
3034

3135
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
36+
"k8s.io/apiserver/pkg/endpoints/metrics"
3237
"k8s.io/apiserver/pkg/server/dynamiccertificates"
3338
)
3439

@@ -184,6 +189,11 @@ func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Dur
184189
}
185190
}
186191

192+
// use tlsHandshakeErrorWriter to handle messages of tls handshake error
193+
tlsErrorWriter := &tlsHandshakeErrorWriter{os.Stderr}
194+
tlsErrorLogger := log.New(tlsErrorWriter, "", 0)
195+
secureServer.ErrorLog = tlsErrorLogger
196+
187197
klog.Infof("Serving securely on %s", secureServer.Addr)
188198
return RunServer(secureServer, s.Listener, shutdownTimeout, stopCh)
189199
}
@@ -256,3 +266,22 @@ func (ln tcpKeepAliveListener) Accept() (net.Conn, error) {
256266
tc.SetKeepAlivePeriod(defaultKeepAlivePeriod)
257267
return tc, nil
258268
}
269+
270+
// tlsHandshakeErrorWriter writes TLS handshake errors to klog with
271+
// trace level - V(5), to avoid flooding of tls handshake errors.
272+
type tlsHandshakeErrorWriter struct {
273+
out io.Writer
274+
}
275+
276+
const tlsHandshakeErrorPrefix = "http: TLS handshake error"
277+
278+
func (w *tlsHandshakeErrorWriter) Write(p []byte) (int, error) {
279+
if strings.Contains(string(p), tlsHandshakeErrorPrefix) {
280+
klog.V(5).Info(string(p))
281+
metrics.TLSHandshakeErrors.Inc()
282+
return len(p), nil
283+
}
284+
285+
// for non tls handshake error, log it as usual
286+
return w.out.Write(p)
287+
}

staging/src/k8s.io/component-base/metrics/counter.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ func NewCounter(opts *CounterOpts) *Counter {
4545
return kc
4646
}
4747

48+
// Reset resets the underlying prometheus Counter to start counting from 0 again
49+
func (c *Counter) Reset() {
50+
if !c.IsCreated() {
51+
return
52+
}
53+
c.setPrometheusCounter(prometheus.NewCounter(c.CounterOpts.toPromCounterOpts()))
54+
}
55+
4856
// setPrometheusCounter sets the underlying CounterMetric object, i.e. the thing that does the measurement.
4957
func (c *Counter) setPrometheusCounter(counter prometheus.Counter) {
5058
c.CounterMetric = counter

0 commit comments

Comments
 (0)