mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-05 15:37:24 +00:00
Remove signal handler registration from pkg/kubelet
The goal of this change is to remove the registration of signal handling from pkg/kubelet. We now pass in a stop channel. If you register a signal handler in `main()` to aid in a controlled and deliberate exit then the handler registered in `pkg/kubelet` often wins and the process exits immediately. This means all other signal handler registrations are currently racy if `DockerServer.Start()` is directly or indirectly invoked. This change also removes another signal handler registration from `NewAPIServerCommand()`; a stop channel is now passed to this function.
This commit is contained in:
@@ -103,7 +103,7 @@ const (
|
||||
)
|
||||
|
||||
// NewKubeletCommand creates a *cobra.Command object with default parameters
|
||||
func NewKubeletCommand() *cobra.Command {
|
||||
func NewKubeletCommand(stopCh <-chan struct{}) *cobra.Command {
|
||||
cleanFlagSet := pflag.NewFlagSet(componentKubelet, pflag.ContinueOnError)
|
||||
cleanFlagSet.SetNormalizeFunc(flag.WordSepNormalizeFunc)
|
||||
kubeletFlags := options.NewKubeletFlags()
|
||||
@@ -248,14 +248,15 @@ HTTP server: The kubelet can also listen for HTTP and respond to a simple API
|
||||
|
||||
// start the experimental docker shim, if enabled
|
||||
if kubeletServer.KubeletFlags.ExperimentalDockershim {
|
||||
if err := RunDockershim(&kubeletServer.KubeletFlags, kubeletConfig); err != nil {
|
||||
if err := RunDockershim(&kubeletServer.KubeletFlags, kubeletConfig, stopCh); err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// run the kubelet
|
||||
glog.V(5).Infof("KubeletConfiguration: %#v", kubeletServer.KubeletConfiguration)
|
||||
if err := Run(kubeletServer, kubeletDeps); err != nil {
|
||||
if err := Run(kubeletServer, kubeletDeps, stopCh); err != nil {
|
||||
glog.Fatal(err)
|
||||
}
|
||||
},
|
||||
@@ -399,13 +400,13 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err
|
||||
// The kubeDeps argument may be nil - if so, it is initialized from the settings on KubeletServer.
|
||||
// Otherwise, the caller is assumed to have set up the Dependencies object and a default one will
|
||||
// not be generated.
|
||||
func Run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) error {
|
||||
func Run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan struct{}) error {
|
||||
// To help debugging, immediately log version
|
||||
glog.Infof("Version: %+v", version.Get())
|
||||
if err := initForOS(s.KubeletFlags.WindowsService); err != nil {
|
||||
return fmt.Errorf("failed OS init: %v", err)
|
||||
}
|
||||
if err := run(s, kubeDeps); err != nil {
|
||||
if err := run(s, kubeDeps, stopCh); err != nil {
|
||||
return fmt.Errorf("failed to run Kubelet: %v", err)
|
||||
}
|
||||
return nil
|
||||
@@ -462,7 +463,7 @@ func makeEventRecorder(kubeDeps *kubelet.Dependencies, nodeName types.NodeName)
|
||||
}
|
||||
}
|
||||
|
||||
func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) {
|
||||
func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan struct{}) (err error) {
|
||||
// Set global feature gates based on the value on the initial KubeletServer
|
||||
err = utilfeature.DefaultFeatureGate.SetFromMap(s.KubeletConfiguration.FeatureGates)
|
||||
if err != nil {
|
||||
@@ -717,7 +718,7 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) {
|
||||
glog.Warning(err)
|
||||
}
|
||||
|
||||
if err := RunKubelet(&s.KubeletFlags, &s.KubeletConfiguration, kubeDeps, s.RunOnce); err != nil {
|
||||
if err := RunKubelet(&s.KubeletFlags, &s.KubeletConfiguration, kubeDeps, s.RunOnce, stopCh); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -738,7 +739,13 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies) (err error) {
|
||||
// If systemd is used, notify it that we have started
|
||||
go daemon.SdNotify(false, "READY=1")
|
||||
|
||||
<-done
|
||||
select {
|
||||
case <-done:
|
||||
break
|
||||
case <-stopCh:
|
||||
break
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -877,7 +884,7 @@ func addChaosToClientConfig(s *options.KubeletServer, config *restclient.Config)
|
||||
// 2 Kubelet binary
|
||||
// 3 Standalone 'kubernetes' binary
|
||||
// Eventually, #2 will be replaced with instances of #3
|
||||
func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *kubelet.Dependencies, runOnce bool) error {
|
||||
func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *kubeletconfiginternal.KubeletConfiguration, kubeDeps *kubelet.Dependencies, runOnce bool, stopCh <-chan struct{}) error {
|
||||
hostname := nodeutil.GetHostname(kubeFlags.HostnameOverride)
|
||||
// Query the cloud provider for our node name, default to hostname if kubeDeps.Cloud == nil
|
||||
nodeName, err := getNodeName(kubeDeps.Cloud, hostname)
|
||||
@@ -950,7 +957,8 @@ func RunKubelet(kubeFlags *options.KubeletFlags, kubeCfg *kubeletconfiginternal.
|
||||
kubeFlags.KeepTerminatedPodVolumes,
|
||||
kubeFlags.NodeLabels,
|
||||
kubeFlags.SeccompProfileRoot,
|
||||
kubeFlags.BootstrapCheckpointPath)
|
||||
kubeFlags.BootstrapCheckpointPath,
|
||||
stopCh)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create kubelet: %v", err)
|
||||
}
|
||||
@@ -1034,7 +1042,8 @@ func CreateAndInitKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
||||
keepTerminatedPodVolumes bool,
|
||||
nodeLabels map[string]string,
|
||||
seccompProfileRoot string,
|
||||
bootstrapCheckpointPath string) (k kubelet.Bootstrap, err error) {
|
||||
bootstrapCheckpointPath string,
|
||||
stopCh <-chan struct{}) (k kubelet.Bootstrap, err error) {
|
||||
// TODO: block until all sources have delivered at least one update to the channel, or break the sync loop
|
||||
// up into "per source" synchronizations
|
||||
|
||||
@@ -1067,7 +1076,8 @@ func CreateAndInitKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
||||
keepTerminatedPodVolumes,
|
||||
nodeLabels,
|
||||
seccompProfileRoot,
|
||||
bootstrapCheckpointPath)
|
||||
bootstrapCheckpointPath,
|
||||
stopCh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1130,7 +1140,7 @@ func BootstrapKubeletConfigController(dynamicConfigDir string, transform dynamic
|
||||
|
||||
// RunDockershim only starts the dockershim in current process. This is only used for cri validate testing purpose
|
||||
// TODO(random-liu): Move this to a separate binary.
|
||||
func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConfiguration) error {
|
||||
func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConfiguration, stopCh <-chan struct{}) error {
|
||||
r := &f.ContainerRuntimeOptions
|
||||
|
||||
// Initialize docker client configuration.
|
||||
@@ -1167,11 +1177,23 @@ func RunDockershim(f *options.KubeletFlags, c *kubeletconfiginternal.KubeletConf
|
||||
}
|
||||
glog.V(2).Infof("Starting the GRPC server for the docker CRI shim.")
|
||||
server := dockerremote.NewDockerServer(f.RemoteRuntimeEndpoint, ds)
|
||||
if err := server.Start(); err != nil {
|
||||
if err := server.Start(stopCh); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
streamingServer := &http.Server{
|
||||
Addr: net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port))),
|
||||
Handler: ds,
|
||||
}
|
||||
|
||||
go func() {
|
||||
<-stopCh
|
||||
streamingServer.Shutdown(context.Background())
|
||||
}()
|
||||
|
||||
// Start the streaming server
|
||||
addr := net.JoinHostPort(c.Address, strconv.Itoa(int(c.Port)))
|
||||
return http.ListenAndServe(addr, ds)
|
||||
if err := streamingServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user