From 05240c9218e84a3bfeb2ced62824b33b0b23efe5 Mon Sep 17 00:00:00 2001 From: Sri Saran Balaji Vellore Rajakumar Date: Wed, 15 Jan 2020 20:37:39 -0800 Subject: [PATCH] Add support for disabling /logs endpoint in kubelet --- cmd/kubelet/app/server.go | 3 +- pkg/kubelet/apis/config/fuzzer/fuzzer.go | 1 + pkg/kubelet/apis/config/helpers_test.go | 1 + .../KubeletConfiguration/after/v1beta1.yaml | 1 + .../roundtrip/default/v1beta1.yaml | 1 + pkg/kubelet/apis/config/types.go | 2 + pkg/kubelet/apis/config/v1beta1/defaults.go | 3 ++ .../config/v1beta1/zz_generated.conversion.go | 6 +++ pkg/kubelet/kubelet.go | 6 +-- pkg/kubelet/server/server.go | 48 ++++++++++++------- pkg/kubelet/server/server_test.go | 47 ++++++++++++------ .../k8s.io/kubelet/config/v1beta1/types.go | 4 ++ .../config/v1beta1/zz_generated.deepcopy.go | 5 ++ 13 files changed, 93 insertions(+), 35 deletions(-) diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 0c2dbc11074..d9bcb8fce8a 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -1155,7 +1155,8 @@ func startKubelet(k kubelet.Bootstrap, podCfg *config.PodConfig, kubeCfg *kubele // start the kubelet server if enableServer { - go k.ListenAndServe(net.ParseIP(kubeCfg.Address), uint(kubeCfg.Port), kubeDeps.TLSOptions, kubeDeps.Auth, enableCAdvisorJSONEndpoints, kubeCfg.EnableDebuggingHandlers, kubeCfg.EnableContentionProfiling) + go k.ListenAndServe(net.ParseIP(kubeCfg.Address), uint(kubeCfg.Port), kubeDeps.TLSOptions, kubeDeps.Auth, + enableCAdvisorJSONEndpoints, kubeCfg.EnableDebuggingHandlers, kubeCfg.EnableContentionProfiling, kubeCfg.EnableSystemLogHandler) } if kubeCfg.ReadOnlyPort > 0 { diff --git a/pkg/kubelet/apis/config/fuzzer/fuzzer.go b/pkg/kubelet/apis/config/fuzzer/fuzzer.go index 2c68c3596e7..3a05dae926f 100644 --- a/pkg/kubelet/apis/config/fuzzer/fuzzer.go +++ b/pkg/kubelet/apis/config/fuzzer/fuzzer.go @@ -103,6 +103,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { if obj.Logging.Format == "" { obj.Logging.Format = "text" } + obj.EnableSystemLogHandler = true }, } } diff --git a/pkg/kubelet/apis/config/helpers_test.go b/pkg/kubelet/apis/config/helpers_test.go index 115ec8150ce..c75d4d289d3 100644 --- a/pkg/kubelet/apis/config/helpers_test.go +++ b/pkg/kubelet/apis/config/helpers_test.go @@ -166,6 +166,7 @@ var ( "EnableControllerAttachDetach", "EnableDebuggingHandlers", "EnableServer", + "EnableSystemLogHandler", "EnforceNodeAllocatable[*]", "EventBurst", "EventRecordQPS", diff --git a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml index c97e66665ce..9321e8b00ee 100644 --- a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml +++ b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/after/v1beta1.yaml @@ -25,6 +25,7 @@ cpuManagerReconcilePeriod: 10s enableControllerAttachDetach: true enableDebuggingHandlers: true enableServer: true +enableSystemLogHandler: true enforceNodeAllocatable: - pods eventBurst: 10 diff --git a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml index c97e66665ce..9321e8b00ee 100644 --- a/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml +++ b/pkg/kubelet/apis/config/scheme/testdata/KubeletConfiguration/roundtrip/default/v1beta1.yaml @@ -25,6 +25,7 @@ cpuManagerReconcilePeriod: 10s enableControllerAttachDetach: true enableDebuggingHandlers: true enableServer: true +enableSystemLogHandler: true enforceNodeAllocatable: - pods eventBurst: 10 diff --git a/pkg/kubelet/apis/config/types.go b/pkg/kubelet/apis/config/types.go index bead9bad55e..a7e2d5e1b23 100644 --- a/pkg/kubelet/apis/config/types.go +++ b/pkg/kubelet/apis/config/types.go @@ -361,6 +361,8 @@ type KubeletConfiguration struct { // Logging specifies the options of logging. // Refer [Logs Options](https://github.com/kubernetes/component-base/blob/master/logs/options.go) for more information. Logging componentbaseconfig.LoggingConfiguration + // EnableSystemLogHandler enables /logs handler. + EnableSystemLogHandler bool } // KubeletAuthorizationMode denotes the authorization mode for the kubelet diff --git a/pkg/kubelet/apis/config/v1beta1/defaults.go b/pkg/kubelet/apis/config/v1beta1/defaults.go index 79005ccdcd7..5cf26ad7a0d 100644 --- a/pkg/kubelet/apis/config/v1beta1/defaults.go +++ b/pkg/kubelet/apis/config/v1beta1/defaults.go @@ -236,4 +236,7 @@ func SetDefaults_KubeletConfiguration(obj *kubeletconfigv1beta1.KubeletConfigura } // Use the Default LoggingConfiguration option componentbaseconfigv1alpha1.RecommendedLoggingConfiguration(&obj.Logging) + if obj.EnableSystemLogHandler == nil { + obj.EnableSystemLogHandler = utilpointer.BoolPtr(true) + } } diff --git a/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go b/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go index f8f4c947616..e0b7608745b 100644 --- a/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go +++ b/pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go @@ -346,6 +346,9 @@ func autoConvert_v1beta1_KubeletConfiguration_To_config_KubeletConfiguration(in if err := v1alpha1.Convert_v1alpha1_LoggingConfiguration_To_config_LoggingConfiguration(&in.Logging, &out.Logging, s); err != nil { return err } + if err := v1.Convert_Pointer_bool_To_bool(&in.EnableSystemLogHandler, &out.EnableSystemLogHandler, s); err != nil { + return err + } return nil } @@ -493,6 +496,9 @@ func autoConvert_config_KubeletConfiguration_To_v1beta1_KubeletConfiguration(in if err := v1alpha1.Convert_config_LoggingConfiguration_To_v1alpha1_LoggingConfiguration(&in.Logging, &out.Logging, s); err != nil { return err } + if err := v1.Convert_bool_To_Pointer_bool(&in.EnableSystemLogHandler, &out.EnableSystemLogHandler, s); err != nil { + return err + } return nil } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 45bb2915bcb..bcd9b972931 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -196,7 +196,7 @@ type Bootstrap interface { GetConfiguration() kubeletconfiginternal.KubeletConfiguration BirthCry() StartGarbageCollection() - ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling bool) + ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, enableSystemLogHandler bool) ListenAndServeReadOnly(address net.IP, port uint, enableCAdvisorJSONEndpoints bool) ListenAndServePodResources() Run(<-chan kubetypes.PodUpdate) @@ -2153,8 +2153,8 @@ func (kl *Kubelet) ResyncInterval() time.Duration { } // ListenAndServe runs the kubelet HTTP server. -func (kl *Kubelet) ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling bool) { - server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, kl.redirectContainerStreaming, kl.criHandler) +func (kl *Kubelet) ListenAndServe(address net.IP, port uint, tlsOptions *server.TLSOptions, auth server.AuthInterface, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, enableSystemLogHandler bool) { + server.ListenAndServeKubeletServer(kl, kl.resourceAnalyzer, address, port, tlsOptions, auth, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, kl.redirectContainerStreaming, enableSystemLogHandler, kl.criHandler) } // ListenAndServeReadOnly runs the kubelet HTTP server in read-only mode. diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index ed86b630cac..d8cf0175e54 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -143,10 +143,11 @@ func ListenAndServeKubeletServer( enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, - redirectContainerStreaming bool, + redirectContainerStreaming, + enableSystemLogHandler bool, criHandler http.Handler) { klog.Infof("Starting to listen on %s:%d", address, port) - handler := NewServer(host, resourceAnalyzer, auth, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, redirectContainerStreaming, criHandler) + handler := NewServer(host, resourceAnalyzer, auth, enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, redirectContainerStreaming, enableSystemLogHandler, criHandler) s := &http.Server{ Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), Handler: &handler, @@ -168,7 +169,7 @@ func ListenAndServeKubeletServer( // ListenAndServeKubeletReadOnlyServer initializes a server to respond to HTTP network requests on the Kubelet. func ListenAndServeKubeletReadOnlyServer(host HostInterface, resourceAnalyzer stats.ResourceAnalyzer, address net.IP, port uint, enableCAdvisorJSONEndpoints bool) { klog.V(1).Infof("Starting to listen read-only on %s:%d", address, port) - s := NewServer(host, resourceAnalyzer, nil, enableCAdvisorJSONEndpoints, false, false, false, nil) + s := NewServer(host, resourceAnalyzer, nil, enableCAdvisorJSONEndpoints, false, false, false, false, nil) server := &http.Server{ Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), @@ -222,7 +223,8 @@ func NewServer( enableCAdvisorJSONEndpoints, enableDebuggingHandlers, enableContentionProfiling, - redirectContainerStreaming bool, + redirectContainerStreaming, + enableSystemLogHandler bool, criHandler http.Handler) Server { server := Server{ host: host, @@ -239,6 +241,9 @@ func NewServer( server.InstallDefaultHandlers(enableCAdvisorJSONEndpoints) if enableDebuggingHandlers { server.InstallDebuggingHandlers(criHandler) + // To maintain backward compatibility serve logs only when enableDebuggingHandlers is also enabled + // see https://github.com/kubernetes/kubernetes/pull/87273 + server.InstallSystemLogHandler(enableSystemLogHandler) if enableContentionProfiling { goruntime.SetBlockProfileRate(1) } @@ -470,19 +475,6 @@ func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) { Operation("getPortForward")) s.restfulCont.Add(ws) - s.addMetricsBucketMatcher("logs") - ws = new(restful.WebService) - ws. - Path(logsPath) - ws.Route(ws.GET(""). - To(s.getLogs). - Operation("getLogs")) - ws.Route(ws.GET("/{logpath:*}"). - To(s.getLogs). - Operation("getLogs"). - Param(ws.PathParameter("logpath", "path to the log").DataType("string"))) - s.restfulCont.Add(ws) - s.addMetricsBucketMatcher("containerLogs") ws = new(restful.WebService) ws. @@ -561,6 +553,28 @@ func (s *Server) InstallDebuggingDisabledHandlers() { } } +// InstallSystemLogHandler registers the HTTP request patterns for logs endpoint. +func (s *Server) InstallSystemLogHandler(enableSystemLogHandler bool) { + s.addMetricsBucketMatcher("logs") + if enableSystemLogHandler { + ws := new(restful.WebService) + ws.Path(logsPath) + ws.Route(ws.GET(""). + To(s.getLogs). + Operation("getLogs")) + ws.Route(ws.GET("/{logpath:*}"). + To(s.getLogs). + Operation("getLogs"). + Param(ws.PathParameter("logpath", "path to the log").DataType("string"))) + s.restfulCont.Add(ws) + } else { + h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "logs endpoint is disabled.", http.StatusMethodNotAllowed) + }) + s.restfulCont.Handle(logsPath, h) + } +} + // Checks if kubelet's sync loop that updates containers is working. func (s *Server) syncLoopHealthCheck(req *http.Request) error { duration := s.host.ResyncInterval() * 2 diff --git a/pkg/kubelet/server/server_test.go b/pkg/kubelet/server/server_test.go index 4e63df323d7..fa55abb56ff 100644 --- a/pkg/kubelet/server/server_test.go +++ b/pkg/kubelet/server/server_test.go @@ -301,6 +301,11 @@ func newServerTest() *serverTestFramework { } func newServerTestWithDebug(enableDebugging, redirectContainerStreaming bool, streamingServer streaming.Server) *serverTestFramework { + return newServerTestWithDebuggingHandlers(enableDebugging, enableDebugging, redirectContainerStreaming, streamingServer) +} + +func newServerTestWithDebuggingHandlers(enableDebugging, enableSystemLogHandler, redirectContainerStreaming bool, + streamingServer streaming.Server) *serverTestFramework { fw := &serverTestFramework{} fw.fakeKubelet = &fakeKubelet{ hostnameFunc: func() string { @@ -340,6 +345,7 @@ func newServerTestWithDebug(enableDebugging, redirectContainerStreaming bool, st enableDebugging, false, redirectContainerStreaming, + enableSystemLogHandler, fw.criHandler) fw.serverUnderTest = &server fw.testHTTPServer = httptest.NewServer(fw.serverUnderTest) @@ -1544,7 +1550,9 @@ func TestMetricMethodBuckets(t *testing.T) { } func TestDebuggingDisabledHandlers(t *testing.T) { - fw := newServerTestWithDebug(false, false, nil) + // for backward compatibility even if enablesystemLogHandler is set but not enableDebuggingHandler then /logs + //shouldn't be served. + fw := newServerTestWithDebuggingHandlers(false, true, false, nil) defer fw.testHTTPServer.Close() paths := []string{ @@ -1554,19 +1562,7 @@ func TestDebuggingDisabledHandlers(t *testing.T) { } for _, p := range paths { - resp, err := http.Get(fw.testHTTPServer.URL + p) - require.NoError(t, err) - assert.Equal(t, http.StatusMethodNotAllowed, resp.StatusCode) - body, err := ioutil.ReadAll(resp.Body) - require.NoError(t, err) - assert.Equal(t, "Debug endpoints are disabled.\n", string(body)) - - resp, err = http.Post(fw.testHTTPServer.URL+p, "", nil) - require.NoError(t, err) - assert.Equal(t, http.StatusMethodNotAllowed, resp.StatusCode) - body, err = ioutil.ReadAll(resp.Body) - require.NoError(t, err) - assert.Equal(t, "Debug endpoints are disabled.\n", string(body)) + verifyEndpointResponse(t, fw, p, "Debug endpoints are disabled.\n") } // test some other paths, make sure they're working @@ -1599,6 +1595,14 @@ func TestDebuggingDisabledHandlers(t *testing.T) { } +func TestDisablingSystemLogHandler(t *testing.T) { + fw := newServerTestWithDebuggingHandlers(true, false, false, nil) + defer fw.testHTTPServer.Close() + + // verify logs endpoint is disabled + verifyEndpointResponse(t, fw, "/logs/kubelet.log", "logs endpoint is disabled.\n") +} + func TestFailedParseParamsSummaryHandler(t *testing.T) { fw := newServerTest() defer fw.testHTTPServer.Close() @@ -1610,7 +1614,22 @@ func TestFailedParseParamsSummaryHandler(t *testing.T) { assert.NoError(t, err) assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) assert.Contains(t, string(v), "parse form failed") +} +func verifyEndpointResponse(t *testing.T, fw *serverTestFramework, path string, expectedResponse string) { + resp, err := http.Get(fw.testHTTPServer.URL + path) + require.NoError(t, err) + assert.Equal(t, http.StatusMethodNotAllowed, resp.StatusCode) + body, err := ioutil.ReadAll(resp.Body) + require.NoError(t, err) + assert.Equal(t, expectedResponse, string(body)) + + resp, err = http.Post(fw.testHTTPServer.URL+path, "", nil) + require.NoError(t, err) + assert.Equal(t, http.StatusMethodNotAllowed, resp.StatusCode) + body, err = ioutil.ReadAll(resp.Body) + require.NoError(t, err) + assert.Equal(t, expectedResponse, string(body)) } func TestTrimURLPath(t *testing.T) { diff --git a/staging/src/k8s.io/kubelet/config/v1beta1/types.go b/staging/src/k8s.io/kubelet/config/v1beta1/types.go index 254a3e1fec9..49e848077d7 100644 --- a/staging/src/k8s.io/kubelet/config/v1beta1/types.go +++ b/staging/src/k8s.io/kubelet/config/v1beta1/types.go @@ -800,6 +800,10 @@ type KubeletConfiguration struct { // Format: text // + optional Logging componentbaseconfigv1alpha1.LoggingConfiguration `json:"logging,omitempty"` + // enableSystemLogHandler enables system logs via web interface host:port/logs/ + // Default: true + // +optional + EnableSystemLogHandler *bool `json:"enableSystemLogHandler,omitempty"` } type KubeletAuthorizationMode string diff --git a/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go b/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go index 4f998494ce7..fd478f82050 100644 --- a/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/kubelet/config/v1beta1/zz_generated.deepcopy.go @@ -296,6 +296,11 @@ func (in *KubeletConfiguration) DeepCopyInto(out *KubeletConfiguration) { copy(*out, *in) } out.Logging = in.Logging + if in.EnableSystemLogHandler != nil { + in, out := &in.EnableSystemLogHandler, &out.EnableSystemLogHandler + *out = new(bool) + **out = **in + } return }