diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index edca51a5714ef..4cb510bcf7276 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -178,7 +178,7 @@ cluster's shared state through which all other components interact.`, return utilerrors.NewAggregate(errs) } - return Run(completedOptions, genericapiserver.SetupSignalHandler()) + return Run(completedOptions, genericapiserver.SetupSignalHandler(false)) }, Args: func(cmd *cobra.Command, args []string) error { for _, arg := range args { diff --git a/cmd/kube-controller-manager/app/controllermanager.go b/cmd/kube-controller-manager/app/controllermanager.go index 9a933d9b3d3a4..9a3d04c734995 100644 --- a/cmd/kube-controller-manager/app/controllermanager.go +++ b/cmd/kube-controller-manager/app/controllermanager.go @@ -126,7 +126,7 @@ controller, and serviceaccounts controller.`, os.Exit(1) } - stopCh := server.SetupSignalHandler() + stopCh := server.SetupSignalHandler(true) if err := Run(c.Complete(), stopCh); err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) diff --git a/cmd/kube-scheduler/app/server.go b/cmd/kube-scheduler/app/server.go index 4b03016f7ada9..0da62b9bac06f 100644 --- a/cmd/kube-scheduler/app/server.go +++ b/cmd/kube-scheduler/app/server.go @@ -124,7 +124,7 @@ func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Op ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { - stopCh := server.SetupSignalHandler() + stopCh := server.SetupSignalHandler(true) <-stopCh cancel() }() diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index ff7e05feec125..8594ad293bc67 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -261,7 +261,7 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API kubeletDeps.KubeletConfigController = kubeletConfigController // set up signal context here in order to be reused by kubelet and docker shim - ctx := genericapiserver.SetupSignalContext() + ctx := genericapiserver.SetupSignalContext(true) // run the kubelet klog.V(5).Infof("KubeletConfiguration: %#v", kubeletServer.KubeletConfiguration) diff --git a/staging/src/k8s.io/apiextensions-apiserver/main.go b/staging/src/k8s.io/apiextensions-apiserver/main.go index a4784e14ff475..fb6d946171c85 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/main.go +++ b/staging/src/k8s.io/apiextensions-apiserver/main.go @@ -31,7 +31,7 @@ func main() { logs.InitLogs() defer logs.FlushLogs() - stopCh := genericapiserver.SetupSignalHandler() + stopCh := genericapiserver.SetupSignalHandler(true) cmd := server.NewServerCommand(os.Stdout, os.Stderr, stopCh) cmd.Flags().AddGoFlagSet(flag.CommandLine) if err := cmd.Execute(); err != nil { diff --git a/staging/src/k8s.io/apiserver/pkg/server/signal.go b/staging/src/k8s.io/apiserver/pkg/server/signal.go index e5334ae4c15f5..89cc4ce8f6b59 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/signal.go +++ b/staging/src/k8s.io/apiserver/pkg/server/signal.go @@ -20,6 +20,8 @@ import ( "context" "os" "os/signal" + + "k8s.io/klog/v2" ) var onlyOneSignalHandler = make(chan struct{}) @@ -30,14 +32,14 @@ var shutdownHandler chan os.Signal // is terminated with exit code 1. // Only one of SetupSignalContext and SetupSignalHandler should be called, and only can // be called once. -func SetupSignalHandler() <-chan struct{} { - return SetupSignalContext().Done() +func SetupSignalHandler(exitOnSecondSignal bool) <-chan struct{} { + return SetupSignalContext(exitOnSecondSignal).Done() } // SetupSignalContext is same as SetupSignalHandler, but a context.Context is returned. // Only one of SetupSignalContext and SetupSignalHandler should be called, and only can // be called once. -func SetupSignalContext() context.Context { +func SetupSignalContext(exitOnSecondSignal bool) context.Context { close(onlyOneSignalHandler) // panics when called twice shutdownHandler = make(chan os.Signal, 2) @@ -47,8 +49,15 @@ func SetupSignalContext() context.Context { go func() { <-shutdownHandler cancel() - <-shutdownHandler - os.Exit(1) // second signal. Exit directly. + if exitOnSecondSignal { + <-shutdownHandler + os.Exit(1) + } else { + for { + <-shutdownHandler + klog.Infof("Termination signal has been received already. Ignoring signal.") + } + } }() return ctx diff --git a/staging/src/k8s.io/kube-aggregator/main.go b/staging/src/k8s.io/kube-aggregator/main.go index e7575e96d0cf8..4e8a5c489e472 100644 --- a/staging/src/k8s.io/kube-aggregator/main.go +++ b/staging/src/k8s.io/kube-aggregator/main.go @@ -38,7 +38,7 @@ func main() { logs.InitLogs() defer logs.FlushLogs() - stopCh := genericapiserver.SetupSignalHandler() + stopCh := genericapiserver.SetupSignalHandler(true) options := server.NewDefaultOptions(os.Stdout, os.Stderr) cmd := server.NewCommandStartAggregator(options, stopCh) cmd.Flags().AddGoFlagSet(flag.CommandLine)