Skip to content

Commit

Permalink
Add support for disabling /logs endpoint in kubelet
Browse files Browse the repository at this point in the history
  • Loading branch information
SaranBalaji90 committed Jul 6, 2020
1 parent 205d5c5 commit 05240c9
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 35 deletions.
3 changes: 2 additions & 1 deletion cmd/kubelet/app/server.go
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions pkg/kubelet/apis/config/fuzzer/fuzzer.go
Expand Up @@ -103,6 +103,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
if obj.Logging.Format == "" {
obj.Logging.Format = "text"
}
obj.EnableSystemLogHandler = true
},
}
}
1 change: 1 addition & 0 deletions pkg/kubelet/apis/config/helpers_test.go
Expand Up @@ -166,6 +166,7 @@ var (
"EnableControllerAttachDetach",
"EnableDebuggingHandlers",
"EnableServer",
"EnableSystemLogHandler",
"EnforceNodeAllocatable[*]",
"EventBurst",
"EventRecordQPS",
Expand Down
Expand Up @@ -25,6 +25,7 @@ cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enableServer: true
enableSystemLogHandler: true
enforceNodeAllocatable:
- pods
eventBurst: 10
Expand Down
Expand Up @@ -25,6 +25,7 @@ cpuManagerReconcilePeriod: 10s
enableControllerAttachDetach: true
enableDebuggingHandlers: true
enableServer: true
enableSystemLogHandler: true
enforceNodeAllocatable:
- pods
eventBurst: 10
Expand Down
2 changes: 2 additions & 0 deletions pkg/kubelet/apis/config/types.go
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions pkg/kubelet/apis/config/v1beta1/defaults.go
Expand Up @@ -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)
}
}
6 changes: 6 additions & 0 deletions pkg/kubelet/apis/config/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions pkg/kubelet/kubelet.go
Expand Up @@ -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)
Expand Down Expand Up @@ -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.
Expand Down
48 changes: 31 additions & 17 deletions pkg/kubelet/server/server.go
Expand Up @@ -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,
Expand All @@ -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)),
Expand Down Expand Up @@ -222,7 +223,8 @@ func NewServer(
enableCAdvisorJSONEndpoints,
enableDebuggingHandlers,
enableContentionProfiling,
redirectContainerStreaming bool,
redirectContainerStreaming,
enableSystemLogHandler bool,
criHandler http.Handler) Server {
server := Server{
host: host,
Expand All @@ -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)
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
47 changes: 33 additions & 14 deletions pkg/kubelet/server/server_test.go
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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{
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions staging/src/k8s.io/kubelet/config/v1beta1/types.go
Expand Up @@ -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
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 05240c9

Please sign in to comment.