diff --git a/cmd/apiserver/apiserver.go b/cmd/apiserver/apiserver.go index 17c0efca0e..46fa835812 100644 --- a/cmd/apiserver/apiserver.go +++ b/cmd/apiserver/apiserver.go @@ -64,8 +64,9 @@ var ( corsAllowedOriginList util.StringList allowPrivileged = flag.Bool("allow_privileged", false, "If true, allow privileged containers.") // TODO: Discover these by pinging the host machines, and rip out these flags. - nodeMilliCPU = flag.Int("node_milli_cpu", 1000, "The amount of MilliCPU provisioned on each node") - nodeMemory = flag.Int("node_memory", 3*1024*1024*1024, "The amount of memory (in bytes) provisioned on each node") + nodeMilliCPU = flag.Int("node_milli_cpu", 1000, "The amount of MilliCPU provisioned on each node") + nodeMemory = flag.Int("node_memory", 3*1024*1024*1024, "The amount of memory (in bytes) provisioned on each node") + enableLogsSupport = flag.Bool("enable_logs_support", true, "Enables server endpoint for log collection") ) func init() { @@ -191,6 +192,9 @@ func main() { apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(mux, *apiPrefix+"/v1beta1") apiserver.NewAPIGroup(m.API_v1beta2()).InstallREST(mux, *apiPrefix+"/v1beta2") apiserver.InstallSupport(mux) + if *enableLogsSupport { + apiserver.InstallLogsSupport(mux) + } ui.InstallSupport(mux) handler := http.Handler(mux) diff --git a/cmd/integration/integration.go b/cmd/integration/integration.go index 9cd7a16bbc..d71f53d3c0 100644 --- a/cmd/integration/integration.go +++ b/cmd/integration/integration.go @@ -160,7 +160,7 @@ func startComponents(manifestURL string) (apiServerURL string) { myKubelet := kubelet.NewIntegrationTestKubelet(machineList[0], testRootDir, &fakeDocker1) go util.Forever(func() { myKubelet.Run(cfg1.Updates()) }, 0) go util.Forever(func() { - kubelet.ListenAndServeKubeletServer(myKubelet, cfg1.Channel("http"), net.ParseIP("127.0.0.1"), 10250) + kubelet.ListenAndServeKubeletServer(myKubelet, cfg1.Channel("http"), net.ParseIP("127.0.0.1"), 10250, true) }, 0) // Kubelet (machine) @@ -171,7 +171,7 @@ func startComponents(manifestURL string) (apiServerURL string) { otherKubelet := kubelet.NewIntegrationTestKubelet(machineList[1], testRootDir, &fakeDocker2) go util.Forever(func() { otherKubelet.Run(cfg2.Updates()) }, 0) go util.Forever(func() { - kubelet.ListenAndServeKubeletServer(otherKubelet, cfg2.Channel("http"), net.ParseIP("127.0.0.1"), 10251) + kubelet.ListenAndServeKubeletServer(otherKubelet, cfg2.Channel("http"), net.ParseIP("127.0.0.1"), 10251, true) }, 0) return apiServer.URL diff --git a/cmd/kubelet/kubelet.go b/cmd/kubelet/kubelet.go index f25b167765..0b2f1cf411 100644 --- a/cmd/kubelet/kubelet.go +++ b/cmd/kubelet/kubelet.go @@ -48,24 +48,25 @@ import ( const defaultRootDir = "/var/lib/kubelet" var ( - config = flag.String("config", "", "Path to the config file or directory of files") - syncFrequency = flag.Duration("sync_frequency", 10*time.Second, "Max period between synchronizing running containers and config") - fileCheckFrequency = flag.Duration("file_check_frequency", 20*time.Second, "Duration between checking config files for new data") - httpCheckFrequency = flag.Duration("http_check_frequency", 20*time.Second, "Duration between checking http for new data") - manifestURL = flag.String("manifest_url", "", "URL for accessing the container manifest") - enableServer = flag.Bool("enable_server", true, "Enable the info server") - address = util.IP(net.ParseIP("127.0.0.1")) - port = flag.Uint("port", master.KubeletPort, "The port for the info server to serve on") - hostnameOverride = flag.String("hostname_override", "", "If non-empty, will use this string as identification instead of the actual hostname.") - networkContainerImage = flag.String("network_container_image", kubelet.NetworkContainerImage, "The image that network containers in each pod will use.") - dockerEndpoint = flag.String("docker_endpoint", "", "If non-empty, use this for the docker endpoint to communicate with") - etcdServerList util.StringList - etcdConfigFile = flag.String("etcd_config", "", "The config file for the etcd client. Mutually exclusive with -etcd_servers") - rootDirectory = flag.String("root_dir", defaultRootDir, "Directory path for managing kubelet files (volume mounts,etc).") - allowPrivileged = flag.Bool("allow_privileged", false, "If true, allow containers to request privileged mode. [default=false]") - registryPullQPS = flag.Float64("registry_qps", 0.0, "If > 0, limit registry pull QPS to this value. If 0, unlimited. [default=0.0]") - registryBurst = flag.Int("registry_burst", 10, "Maximum size of a bursty pulls, temporarily allows pulls to burst to this number, while still not exceeding registry_qps. Only used if --registry_qps > 0") - runonce = flag.Bool("runonce", false, "If true, exit after spawning pods from local manifests or remote urls. Exclusive with --etcd_servers and --enable-server") + config = flag.String("config", "", "Path to the config file or directory of files") + syncFrequency = flag.Duration("sync_frequency", 10*time.Second, "Max period between synchronizing running containers and config") + fileCheckFrequency = flag.Duration("file_check_frequency", 20*time.Second, "Duration between checking config files for new data") + httpCheckFrequency = flag.Duration("http_check_frequency", 20*time.Second, "Duration between checking http for new data") + manifestURL = flag.String("manifest_url", "", "URL for accessing the container manifest") + enableServer = flag.Bool("enable_server", true, "Enable the info server") + address = util.IP(net.ParseIP("127.0.0.1")) + port = flag.Uint("port", master.KubeletPort, "The port for the info server to serve on") + hostnameOverride = flag.String("hostname_override", "", "If non-empty, will use this string as identification instead of the actual hostname.") + networkContainerImage = flag.String("network_container_image", kubelet.NetworkContainerImage, "The image that network containers in each pod will use.") + dockerEndpoint = flag.String("docker_endpoint", "", "If non-empty, use this for the docker endpoint to communicate with") + etcdServerList util.StringList + etcdConfigFile = flag.String("etcd_config", "", "The config file for the etcd client. Mutually exclusive with -etcd_servers") + rootDirectory = flag.String("root_dir", defaultRootDir, "Directory path for managing kubelet files (volume mounts,etc).") + allowPrivileged = flag.Bool("allow_privileged", false, "If true, allow containers to request privileged mode. [default=false]") + registryPullQPS = flag.Float64("registry_qps", 0.0, "If > 0, limit registry pull QPS to this value. If 0, unlimited. [default=0.0]") + registryBurst = flag.Int("registry_burst", 10, "Maximum size of a bursty pulls, temporarily allows pulls to burst to this number, while still not exceeding registry_qps. Only used if --registry_qps > 0") + runonce = flag.Bool("runonce", false, "If true, exit after spawning pods from local manifests or remote urls. Exclusive with --etcd_servers and --enable-server") + enableDebuggingHandlers = flag.Bool("enable_debugging_handlers", true, "Enables server endpoints for log collection and local running of containers and commands") ) func init() { @@ -217,7 +218,7 @@ func main() { // start the kubelet server if *enableServer { go util.Forever(func() { - kubelet.ListenAndServeKubeletServer(k, cfg.Channel("http"), net.IP(address), *port) + kubelet.ListenAndServeKubeletServer(k, cfg.Channel("http"), net.IP(address), *port, *enableDebuggingHandlers) }, 0) } diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index 7a8c9bda5d..5172da0a03 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -121,12 +121,16 @@ func (g *APIGroup) InstallREST(mux mux, paths ...string) { // InstallSupport registers the APIServer support functions into a mux. func InstallSupport(mux mux) { healthz.InstallHandler(mux) - mux.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/")))) mux.Handle("/proxy/minion/", http.StripPrefix("/proxy/minion", http.HandlerFunc(handleProxyMinion))) mux.HandleFunc("/version", handleVersion) mux.HandleFunc("/", handleIndex) } +// InstallLogsSupport registers the APIServer log support function into a mux. +func InstallLogsSupport(mux mux) { + mux.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/")))) +} + // handleVersion writes the server's version information. func handleVersion(w http.ResponseWriter, req *http.Request) { writeRawJSON(http.StatusOK, version.Get(), w) diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index 75b05fc547..0fdf1a8678 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -47,9 +47,9 @@ type Server struct { } // ListenAndServeKubeletServer initializes a server to respond to HTTP network requests on the Kubelet. -func ListenAndServeKubeletServer(host HostInterface, updates chan<- interface{}, address net.IP, port uint) { +func ListenAndServeKubeletServer(host HostInterface, updates chan<- interface{}, address net.IP, port uint, enableDebuggingHandlers bool) { glog.V(1).Infof("Starting to listen on %s:%d", address, port) - handler := NewServer(host, updates) + handler := NewServer(host, updates, enableDebuggingHandlers) s := &http.Server{ Addr: net.JoinHostPort(address.String(), strconv.FormatUint(uint64(port), 10)), Handler: &handler, @@ -73,26 +73,35 @@ type HostInterface interface { } // NewServer initializes and configures a kubelet.Server object to handle HTTP requests. -func NewServer(host HostInterface, updates chan<- interface{}) Server { +func NewServer(host HostInterface, updates chan<- interface{}, enableDebuggingHandlers bool) Server { server := Server{ host: host, updates: updates, mux: http.NewServeMux(), } server.InstallDefaultHandlers() + if enableDebuggingHandlers { + server.InstallDebuggingHandlers() + } return server } -// InstallDefaultHandlers registers the set of supported HTTP request patterns with the mux. +// InstallDefaultHandlers registers the default set of supported HTTP request patterns with the mux. func (s *Server) InstallDefaultHandlers() { healthz.InstallHandler(s.mux) - s.mux.HandleFunc("/container", s.handleContainer) - s.mux.HandleFunc("/containers", s.handleContainers) s.mux.HandleFunc("/podInfo", s.handlePodInfo) s.mux.HandleFunc("/stats/", s.handleStats) - s.mux.HandleFunc("/logs/", s.handleLogs) s.mux.HandleFunc("/spec/", s.handleSpec) +} + +// InstallDeguggingHandlers registers the HTTP request patterns that serve logs or run commands/containers +func (s *Server) InstallDebuggingHandlers() { + // ToDo: /container, /run, and /containers aren't debugging options, should probably be handled separately + s.mux.HandleFunc("/container", s.handleContainer) + s.mux.HandleFunc("/containers", s.handleContainers) s.mux.HandleFunc("/run/", s.handleRun) + + s.mux.HandleFunc("/logs/", s.handleLogs) s.mux.HandleFunc("/containerLogs/", s.handleContainerLogs) } diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index be9f3c5d4b..91a742fbea 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -86,7 +86,7 @@ func newServerTest() *serverTestFramework { } fw.updateReader = startReading(fw.updateChan) fw.fakeKubelet = &fakeKubelet{} - server := NewServer(fw.fakeKubelet, fw.updateChan) + server := NewServer(fw.fakeKubelet, fw.updateChan, true) fw.serverUnderTest = &server fw.testHTTPServer = httptest.NewServer(fw.serverUnderTest) return fw