Change:
"k8s.io/kubernetes/test/e2e_node/build" ) <del> // TODO(random-liu): Move this file to a separate package. var serverStartTimeout = flag.Duration("server-start-timeout", time.Second*120, "Time to wait for each server to become healthy.") </del> // E2EServices starts and stops e2e services in a separate process. The test // uses it to start and stop all e2e services. type E2EServices struct { <del> services *server </del> <ins> // monitorParent determines whether the sub-processes should watch and die with the current // process. monitorParent bool services      *server kubelet       *server logFiles      map[string]logFileData </ins> } <del> // NewE2EServices returns a new E2EServices instance. func NewE2EServices() *E2EServices { return &E2EServices{} </del> <ins> // logFileData holds data about logfiles to fetch with a journalctl command or // symlink from a node's file system. type logFileData struct { files             []string journalctlCommand []string </ins> } <del> // services.log is the combined log of all services const servicesLogFile = "services.log" </del> <ins> // NewE2EServices returns a new E2EServices instance. func NewE2EServices(monitorParent bool) *E2EServices { return &E2EServices{ monitorParent: monitorParent, // Special log files that need to be collected for additional debugging. logFiles: map[string]logFileData{ "kern.log":       {[]string{"/var/log/kern.log"}, []string{"-k"}}, "docker.log":     {[]string{"/var/log/docker.log", "/var/log/upstart/docker.log"}, []string{"-u", "docker"}}, "cloud-init.log": {[]string{"/var/log/cloud-init.log"}, []string{"-u", "cloud*"}}, }, } } </ins> // Start starts the e2e services in another process by calling back into the // test binary.  Returns when all e2e services are ready or an error. // // We want to statically link e2e services into the test binary, but we don't // want their glog output to pollute the test result. So we run the binary in <del> // run- services-mode to start e2e services in another process. </del> <ins> // run-services-mode to start e2e services in another process. // The function starts 2 processes: // * internal e2e services: services which statically linked in the test binary - apiserver, etcd and // namespace controller. // * kubelet: kubelet binary is outside. (We plan to move main kubelet start logic out when we have // standard kubelet launcher) </ins> func (e *E2EServices) Start() error { var err error <ins> // Start kubelet </ins> // Create the manifest path for kubelet. // TODO(random-liu): Remove related logic when we move kubelet starting logic out of the test. framework.TestContext.ManifestPath, err = ioutil.TempDir("", "node-e2e-pod") if err != nil { return fmt.Errorf("failed to create static pod manifest directory: %v", err) } <del> testBin, err := osext.Executable() </del> <ins> e.kubelet, err = e.startKubelet() </ins> if err != nil { <del> return fmt.Errorf("can't get current binary: %v", err) </del> <ins> return fmt.Errorf("failed to start kubelet: %v", err) </ins> } <del> // TODO(random-liu): Add sudo after we statically link apiserver and etcd, because apiserver needs // sudo. We can't add sudo now, because etcd may not be in PATH of root. startCmd := exec.Command(testBin, // TODO(mtaufen): Flags e.g. that target the TestContext need to be manually forwarded to the //                test binary when we start it up in run-services mode. This is not ideal. //                Very unintuitive because it prevents any falgs NOT manually forwarded here //                from being set via TEST_ARGS when running tests from the command line. "--run-services-mode", "--server-start-timeout", serverStartTimeout.String(), "--report-dir", framework.TestContext.ReportDir, // TODO(random-liu): Remove the following flags after we move kubelet starting logic // out of the test. "--node-name", framework.TestContext.NodeName, "--disable-kubenet="+strconv.FormatBool(framework.TestContext.DisableKubenet), // TODO: enable when flag is introduced in 1.5 // "--cgroups-per-qos="+strconv.FormatBool(framework.TestContext.CgroupsPerQOS), "--manifest-path", framework.TestContext.ManifestPath, "--eviction-hard", framework.TestContext.EvictionHard, "--feature-gates", framework.TestContext.FeatureGates, "--runtime-integration-type", framework.TestContext.RuntimeIntegrationType, "--logtostderr", "--vmodule=*=4", ) e.services = newServer("services", startCmd, nil, nil, getHealthCheckURLs(), servicesLogFile, false) return e.services.start() </del> <ins> e.services, err = e.startInternalServices() return err </ins> } // Stop stops the e2e services. <del> func (e *E2EServices) Stop() error { </del> <ins> func (e *E2EServices) Stop() { </ins> defer func() { <ins> // Collect log files. e.getLogFiles() </ins> // Cleanup the manifest path for kubelet. manifestPath := framework.TestContext.ManifestPath if manifestPath != "" {

Discussion:
In node e2e, we have the option to keep the services running after test for further debug. However, we set to for the services, which means that once the parent exits, they will receive and exit with the parent if they don't trap the signal. With this, option will never work. If we still need this feature, we should not set if is false. /cc
We still need this feature. It helps with debugging test failures by keeping all the daemons running upon failure. , Lantao Liu wrote: