Commit bb79365e authored by Clayton Coleman's avatar Clayton Coleman

Split kubelet server initialization into two parts

First is initializing a KubeletConfig that starts no background processes. Second is running the config. Provide a legacy path that won't impact older callers while making it easier to customize the interfaces passed to the Kubelet. Used by OpenShift to inject some custom interfaces to the Kubelet for config management.
parent 5b216d8a
...@@ -32,8 +32,8 @@ func NewKubelet() *Server { ...@@ -32,8 +32,8 @@ func NewKubelet() *Server {
queries Docker to see what is currently running. It synchronizes the queries Docker to see what is currently running. It synchronizes the
configuration data, with the running set of containers by starting or stopping configuration data, with the running set of containers by starting or stopping
Docker containers.`, Docker containers.`,
Run: func(_ *Server, args []string) error { Run: func(_ *Server, _ []string) error {
return s.Run(args) return s.Run(nil)
}, },
} }
s.AddFlags(hks.Flags()) s.AddFlags(hks.Flags())
......
...@@ -254,32 +254,34 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) { ...@@ -254,32 +254,34 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&s.Containerized, "containerized", s.Containerized, "Experimental support for running kubelet in a container. Intended for testing. [default=false]") fs.BoolVar(&s.Containerized, "containerized", s.Containerized, "Experimental support for running kubelet in a container. Intended for testing. [default=false]")
} }
// Run runs the specified KubeletServer. This should never exit. // KubeletConfig returns a KubeletConfig suitable for being run, or an error if the server setup
func (s *KubeletServer) Run(_ []string) error { // is not valid. It will not start any background processes.
util.ReallyCrash = s.ReallyCrashForTesting func (s *KubeletServer) KubeletConfig() (*KubeletConfig, error) {
rand.Seed(time.Now().UTC().UnixNano()) hostNetworkSources, err := kubelet.GetValidatedSources(strings.Split(s.HostNetworkSources, ","))
if err != nil {
// TODO(vmarmol): Do this through container config. return nil, err
if err := util.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil {
glog.Warning(err)
} }
var apiclient *client.Client mounter := mount.New()
clientConfig, err := s.CreateAPIServerClientConfig() if s.Containerized {
if err == nil { glog.V(2).Info("Running kubelet in containerized mode (experimental)")
apiclient, err = client.New(clientConfig) mounter = mount.NewNsenterMounter()
}
if err != nil && len(s.APIServerList) > 0 {
glog.Warningf("No API client: %v", err)
} }
glog.V(2).Infof("Using root directory: %v", s.RootDirectory) tlsOptions, err := s.InitializeTLS()
credentialprovider.SetPreferredDockercfgPath(s.RootDirectory)
cadvisorInterface, err := cadvisor.New(s.CadvisorPort)
if err != nil { if err != nil {
return err return nil, err
}
var dockerExecHandler dockertools.ExecHandler
switch s.DockerExecHandlerName {
case "native":
dockerExecHandler = &dockertools.NativeExecHandler{}
case "nsenter":
dockerExecHandler = &dockertools.NsenterExecHandler{}
default:
glog.Warningf("Unknown Docker exec handler %q; defaulting to native", s.DockerExecHandlerName)
dockerExecHandler = &dockertools.NativeExecHandler{}
} }
imageGCPolicy := kubelet.ImageGCPolicy{ imageGCPolicy := kubelet.ImageGCPolicy{
...@@ -291,49 +293,17 @@ func (s *KubeletServer) Run(_ []string) error { ...@@ -291,49 +293,17 @@ func (s *KubeletServer) Run(_ []string) error {
DockerFreeDiskMB: s.LowDiskSpaceThresholdMB, DockerFreeDiskMB: s.LowDiskSpaceThresholdMB,
RootFreeDiskMB: s.LowDiskSpaceThresholdMB, RootFreeDiskMB: s.LowDiskSpaceThresholdMB,
} }
cloud, err := cloudprovider.InitCloudProvider(s.CloudProvider, s.CloudConfigFile)
if err != nil {
return err
}
glog.V(2).Infof("Successfully initialized cloud provider: %q from the config file: %q\n", s.CloudProvider, s.CloudConfigFile)
manifestURLHeader := make(http.Header) manifestURLHeader := make(http.Header)
if s.ManifestURLHeader != "" { if s.ManifestURLHeader != "" {
pieces := strings.Split(s.ManifestURLHeader, ":") pieces := strings.Split(s.ManifestURLHeader, ":")
if len(pieces) != 2 { if len(pieces) != 2 {
return fmt.Errorf("manifest-url-header must have a single ':' key-value separator, got %q", s.ManifestURLHeader) return nil, fmt.Errorf("manifest-url-header must have a single ':' key-value separator, got %q", s.ManifestURLHeader)
} }
manifestURLHeader.Set(pieces[0], pieces[1]) manifestURLHeader.Set(pieces[0], pieces[1])
} }
hostNetworkSources, err := kubelet.GetValidatedSources(strings.Split(s.HostNetworkSources, ",")) return &KubeletConfig{
if err != nil {
return err
}
tlsOptions, err := s.InitializeTLS()
if err != nil {
return err
}
mounter := mount.New()
if s.Containerized {
glog.V(2).Info("Running kubelet in containerized mode (experimental)")
mounter = mount.NewNsenterMounter()
}
var dockerExecHandler dockertools.ExecHandler
switch s.DockerExecHandlerName {
case "native":
dockerExecHandler = &dockertools.NativeExecHandler{}
case "nsenter":
dockerExecHandler = &dockertools.NsenterExecHandler{}
default:
glog.Warningf("Unknown Docker exec handler %q; defaulting to native", s.DockerExecHandlerName)
dockerExecHandler = &dockertools.NativeExecHandler{}
}
kcfg := KubeletConfig{
Address: s.Address, Address: s.Address,
AllowPrivileged: s.AllowPrivileged, AllowPrivileged: s.AllowPrivileged,
HostNetworkSources: hostNetworkSources, HostNetworkSources: hostNetworkSources,
...@@ -358,11 +328,11 @@ func (s *KubeletServer) Run(_ []string) error { ...@@ -358,11 +328,11 @@ func (s *KubeletServer) Run(_ []string) error {
Runonce: s.RunOnce, Runonce: s.RunOnce,
Port: s.Port, Port: s.Port,
ReadOnlyPort: s.ReadOnlyPort, ReadOnlyPort: s.ReadOnlyPort,
CadvisorInterface: cadvisorInterface, CadvisorInterface: nil, // launches background processes, not set here
EnableServer: s.EnableServer, EnableServer: s.EnableServer,
EnableDebuggingHandlers: s.EnableDebuggingHandlers, EnableDebuggingHandlers: s.EnableDebuggingHandlers,
DockerClient: dockertools.ConnectToDockerOrDie(s.DockerEndpoint), DockerClient: dockertools.ConnectToDockerOrDie(s.DockerEndpoint),
KubeClient: apiclient, KubeClient: nil,
MasterServiceNamespace: s.MasterServiceNamespace, MasterServiceNamespace: s.MasterServiceNamespace,
VolumePlugins: ProbeVolumePlugins(), VolumePlugins: ProbeVolumePlugins(),
NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir), NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir),
...@@ -371,7 +341,7 @@ func (s *KubeletServer) Run(_ []string) error { ...@@ -371,7 +341,7 @@ func (s *KubeletServer) Run(_ []string) error {
TLSOptions: tlsOptions, TLSOptions: tlsOptions,
ImageGCPolicy: imageGCPolicy, ImageGCPolicy: imageGCPolicy,
DiskSpacePolicy: diskSpacePolicy, DiskSpacePolicy: diskSpacePolicy,
Cloud: cloud, Cloud: nil, // cloud provider might start background processes
NodeStatusUpdateFrequency: s.NodeStatusUpdateFrequency, NodeStatusUpdateFrequency: s.NodeStatusUpdateFrequency,
ResourceContainer: s.ResourceContainer, ResourceContainer: s.ResourceContainer,
CgroupRoot: s.CgroupRoot, CgroupRoot: s.CgroupRoot,
...@@ -383,9 +353,58 @@ func (s *KubeletServer) Run(_ []string) error { ...@@ -383,9 +353,58 @@ func (s *KubeletServer) Run(_ []string) error {
PodCIDR: s.PodCIDR, PodCIDR: s.PodCIDR,
MaxPods: s.MaxPods, MaxPods: s.MaxPods,
DockerExecHandler: dockerExecHandler, DockerExecHandler: dockerExecHandler,
}, nil
}
// Run runs the specified KubeletServer for the given KubeletConfig. This should never exit.
// The kcfg argument may be nil - if so, it is initialized from the settings on KubeletServer.
// Otherwise, the caller is assumed to have set up the KubeletConfig object and all defaults
// will be ignored.
func (s *KubeletServer) Run(kcfg *KubeletConfig) error {
if kcfg == nil {
cfg, err := s.KubeletConfig()
if err != nil {
return err
}
kcfg = cfg
clientConfig, err := s.CreateAPIServerClientConfig()
if err == nil {
kcfg.KubeClient, err = client.New(clientConfig)
}
if err != nil && len(s.APIServerList) > 0 {
glog.Warningf("No API client: %v", err)
}
cloud, err := cloudprovider.InitCloudProvider(s.CloudProvider, s.CloudConfigFile)
if err != nil {
return err
}
glog.V(2).Infof("Successfully initialized cloud provider: %q from the config file: %q\n", s.CloudProvider, s.CloudConfigFile)
kcfg.Cloud = cloud
}
if kcfg.CadvisorInterface == nil {
ca, err := cadvisor.New(s.CadvisorPort)
if err != nil {
return err
}
kcfg.CadvisorInterface = ca
}
util.ReallyCrash = s.ReallyCrashForTesting
rand.Seed(time.Now().UTC().UnixNano())
credentialprovider.SetPreferredDockercfgPath(s.RootDirectory)
glog.V(2).Infof("Using root directory: %v", s.RootDirectory)
// TODO(vmarmol): Do this through container config.
if err := util.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil {
glog.Warning(err)
} }
if err := RunKubelet(&kcfg, nil); err != nil { if err := RunKubelet(kcfg, nil); err != nil {
return err return err
} }
......
...@@ -43,7 +43,7 @@ func main() { ...@@ -43,7 +43,7 @@ func main() {
verflag.PrintAndExitIfRequested() verflag.PrintAndExitIfRequested()
if err := s.Run(pflag.CommandLine.Args()); err != nil { if err := s.Run(nil); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err) fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1) os.Exit(1)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment