// InitializeTLS checks for a configured TLSCertFile and TLSPrivateKeyFile: if unspecified a new self-signed // certificate and key file are generated. Returns a configured server.TLSOptions object. func InitializeTLS(kc *componentconfig.KubeletConfiguration) (*server.TLSOptions, error) { if kc.TLSCertFile == "" && kc.TLSPrivateKeyFile == "" { kc.TLSCertFile = path.Join(kc.CertDirectory, "kubelet.crt") kc.TLSPrivateKeyFile = path.Join(kc.CertDirectory, "kubelet.key") if !certutil.CanReadCertOrKey(kc.TLSCertFile, kc.TLSPrivateKeyFile) { if err := certutil.GenerateSelfSignedCert(nodeutil.GetHostname(kc.HostnameOverride), kc.TLSCertFile, kc.TLSPrivateKeyFile, nil, nil); err != nil { return nil, fmt.Errorf("unable to generate self signed cert: %v", err) } glog.V(4).Infof("Using self-signed cert (%s, %s)", kc.TLSCertFile, kc.TLSPrivateKeyFile) } } tlsOptions := &server.TLSOptions{ Config: &tls.Config{ // Can't use SSLv3 because of POODLE and BEAST // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher // Can't use TLSv1.1 because of RC4 cipher usage MinVersion: tls.VersionTLS12, }, CertFile: kc.TLSCertFile, KeyFile: kc.TLSPrivateKeyFile, } if len(kc.Authentication.X509.ClientCAFile) > 0 { clientCAs, err := cert.NewPool(kc.Authentication.X509.ClientCAFile) if err != nil { return nil, fmt.Errorf("unable to load client CA file %s: %v", kc.Authentication.X509.ClientCAFile, err) } // Specify allowed CAs for client certificates tlsOptions.Config.ClientCAs = clientCAs // Populate PeerCertificates in requests, but don't reject connections without verified certificates tlsOptions.Config.ClientAuth = tls.RequestClientCert } return tlsOptions, nil }
// InitializeTLS checks for a configured TLSCertFile and TLSPrivateKeyFile: if unspecified a new self-signed // certificate and key file are generated. Returns a configured server.TLSOptions object. func InitializeTLS(s *options.KubeletServer) (*server.TLSOptions, error) { if s.TLSCertFile == "" && s.TLSPrivateKeyFile == "" { s.TLSCertFile = path.Join(s.CertDirectory, "kubelet.crt") s.TLSPrivateKeyFile = path.Join(s.CertDirectory, "kubelet.key") if crypto.ShouldGenSelfSignedCerts(s.TLSCertFile, s.TLSPrivateKeyFile) { if err := crypto.GenerateSelfSignedCert(nodeutil.GetHostname(s.HostnameOverride), s.TLSCertFile, s.TLSPrivateKeyFile, nil, nil); err != nil { return nil, fmt.Errorf("unable to generate self signed cert: %v", err) } glog.V(4).Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile) } } tlsOptions := &server.TLSOptions{ Config: &tls.Config{ // Can't use SSLv3 because of POODLE and BEAST // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher // Can't use TLSv1.1 because of RC4 cipher usage MinVersion: tls.VersionTLS12, // Populate PeerCertificates in requests, but don't yet reject connections without certificates. ClientAuth: tls.RequestClientCert, }, CertFile: s.TLSCertFile, KeyFile: s.TLSPrivateKeyFile, } return tlsOptions, nil }
// RunKubelet is responsible for setting up and running a kubelet. It is used in three different applications: // 1 Integration tests // 2 Kubelet binary // 3 Standalone 'kubernetes' binary // Eventually, #2 will be replaced with instances of #3 func RunKubelet(kcfg *KubeletConfig, builder KubeletBuilder) error { kcfg.Hostname = nodeutil.GetHostname(kcfg.HostnameOverride) if len(kcfg.NodeName) == 0 { // Query the cloud provider for our node name, default to Hostname nodeName := kcfg.Hostname if kcfg.Cloud != nil { var err error instances, ok := kcfg.Cloud.Instances() if !ok { return fmt.Errorf("failed to get instances from cloud provider") } nodeName, err = instances.CurrentNodeName(kcfg.Hostname) if err != nil { return fmt.Errorf("error fetching current instance name from cloud provider: %v", err) } glog.V(2).Infof("cloud provider determined current node name to be %s", nodeName) } kcfg.NodeName = nodeName } eventBroadcaster := record.NewBroadcaster() kcfg.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "kubelet", Host: kcfg.NodeName}) eventBroadcaster.StartLogging(glog.V(3).Infof) if kcfg.KubeClient != nil { glog.V(4).Infof("Sending events to api server.") eventBroadcaster.StartRecordingToSink(kcfg.KubeClient.Events("")) } else { glog.Warning("No api server defined - no events will be sent to API server.") } capabilities.Setup(kcfg.AllowPrivileged, kcfg.HostNetworkSources, 0) credentialprovider.SetPreferredDockercfgPath(kcfg.RootDirectory) if builder == nil { builder = createAndInitKubelet } if kcfg.OSInterface == nil { kcfg.OSInterface = kubecontainer.RealOS{} } k, podCfg, err := builder(kcfg) if err != nil { return fmt.Errorf("failed to create kubelet: %v", err) } // process pods and exit. if kcfg.Runonce { if _, err := k.RunOnce(podCfg.Updates()); err != nil { return fmt.Errorf("runonce failed: %v", err) } glog.Infof("Started kubelet as runonce") } else { startKubelet(k, podCfg, kcfg) glog.Infof("Started kubelet") } return nil }
func (hc HostnameCheck) Check() (warnings, errors []error) { errors = []error{} hostname := node.GetHostname("") for _, msg := range validation.ValidateNodeName(hostname, false) { errors = append(errors, fmt.Errorf("hostname \"%s\" %s", hostname, msg)) } return nil, errors }
// Tries to download the kubelet-<node-name> configmap from "kube-system" namespace via the API server and returns a JSON string or error func getRemoteKubeletConfig(s *options.KubeletServer, kubeDeps *kubelet.KubeletDeps) (string, error) { // TODO(mtaufen): should probably cache clientset and pass into this function rather than regenerate on every request kubeClient, err := getKubeClient(s) if err != nil { return "", err } configmap, err := func() (*v1.ConfigMap, error) { var nodename types.NodeName hostname := nodeutil.GetHostname(s.HostnameOverride) if kubeDeps != nil && kubeDeps.Cloud != nil { instances, ok := kubeDeps.Cloud.Instances() if !ok { err = fmt.Errorf("failed to get instances from cloud provider, can't determine nodename.") return nil, err } nodename, err = instances.CurrentNodeName(hostname) if err != nil { err = fmt.Errorf("error fetching current instance name from cloud provider: %v", err) return nil, err } // look for kubelet-<node-name> configmap from "kube-system" configmap, err := kubeClient.CoreV1Client.ConfigMaps("kube-system").Get(fmt.Sprintf("kubelet-%s", nodename)) if err != nil { return nil, err } return configmap, nil } // No cloud provider yet, so can't get the nodename via Cloud.Instances().CurrentNodeName(hostname), try just using the hostname configmap, err := kubeClient.CoreV1Client.ConfigMaps("kube-system").Get(fmt.Sprintf("kubelet-%s", hostname)) if err != nil { return nil, fmt.Errorf("cloud provider was nil, and attempt to use hostname to find config resulted in: %v", err) } return configmap, nil }() if err != nil { return "", err } // When we create the KubeletConfiguration configmap, we put a json string // representation of the config in a `kubelet.config` key. jsonstr, ok := configmap.Data["kubelet.config"] if !ok { return "", fmt.Errorf("KubeletConfiguration configmap did not contain a value with key `kubelet.config`") } return jsonstr, nil }
func newCinderDiskUtil(cinderConfigFile string, isNoMountSupported bool) *CinderDiskUtil { result := &CinderDiskUtil{} if cinderConfigFile != "" { cinderClient, err := newCinderClient(cinderConfigFile) if err != nil { glog.Warningf("Init cinder client failed: %v", err) } else { result.cinderBaremetalUtil = &CinderBaremetalUtil{ client: cinderClient, hostname: node.GetHostname(""), isNoMountSupported: isNoMountSupported, } } } else { glog.V(4).Info("Cinder volume configure is not provided") } return result }
// InitializeTLS checks for a configured TLSCertFile and TLSPrivateKeyFile: if unspecified a new self-signed // certificate and key file are generated. Returns a configured kubelet.TLSOptions object. func (s *KubeletServer) InitializeTLS() (*kubelet.TLSOptions, error) { if s.TLSCertFile == "" && s.TLSPrivateKeyFile == "" { s.TLSCertFile = path.Join(s.CertDirectory, "kubelet.crt") s.TLSPrivateKeyFile = path.Join(s.CertDirectory, "kubelet.key") if err := util.GenerateSelfSignedCert(nodeutil.GetHostname(s.HostnameOverride), s.TLSCertFile, s.TLSPrivateKeyFile, nil, nil); err != nil { return nil, fmt.Errorf("unable to generate self signed cert: %v", err) } glog.V(4).Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile) } tlsOptions := &kubelet.TLSOptions{ Config: &tls.Config{ // Change default from SSLv3 to TLSv1.0 (because of POODLE vulnerability). MinVersion: tls.VersionTLS10, // Populate PeerCertificates in requests, but don't yet reject connections without certificates. ClientAuth: tls.RequestClientCert, }, CertFile: s.TLSCertFile, KeyFile: s.TLSPrivateKeyFile, } return tlsOptions, nil }
// Run runs the specified ProxyServer. This should never exit. func (s *ProxyServer) Run(_ []string) error { // TODO(vmarmol): Use container config for this. oomAdjuster := oom.NewOomAdjuster() if err := oomAdjuster.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil { glog.V(2).Info(err) } // Run in its own container. if err := util.RunInResourceContainer(s.ResourceContainer); err != nil { glog.Warningf("Failed to start in resource-only container %q: %v", s.ResourceContainer, err) } else { glog.V(2).Infof("Running in resource-only container %q", s.ResourceContainer) } // define api config source if s.Kubeconfig == "" && s.Master == "" { glog.Warningf("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.") } // This creates a client, first loading any specified kubeconfig // file, and then overriding the Master flag, if non-empty. kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( &clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Kubeconfig}, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: s.Master}}).ClientConfig() if err != nil { return err } client, err := client.New(kubeconfig) if err != nil { glog.Fatalf("Invalid API configuration: %v", err) } // Add event recorder Hostname := nodeutil.GetHostname(s.HostnameOverride) eventBroadcaster := record.NewBroadcaster() s.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: Hostname}) eventBroadcaster.StartRecordingToSink(client.Events("")) s.nodeRef = &api.ObjectReference{ Kind: "Node", Name: Hostname, UID: types.UID(Hostname), Namespace: "", } // Birth Cry s.birthCry() serviceConfig := config.NewServiceConfig() endpointsConfig := config.NewEndpointsConfig() protocol := iptables.ProtocolIpv4 if s.BindAddress.To4() == nil { protocol = iptables.ProtocolIpv6 } loadBalancer := userspace.NewLoadBalancerRR() proxier, err := userspace.NewProxier(loadBalancer, s.BindAddress, iptables.New(exec.New(), protocol), s.PortRange) if err != nil { glog.Fatalf("Unable to create proxer: %v", err) } // Wire proxier to handle changes to services serviceConfig.RegisterHandler(proxier) // And wire loadBalancer to handle changes to endpoints to services endpointsConfig.RegisterHandler(loadBalancer) // Note: RegisterHandler() calls need to happen before creation of Sources because sources // only notify on changes, and the initial update (on process start) may be lost if no handlers // are registered yet. config.NewSourceAPI( client, 30*time.Second, serviceConfig.Channel("api"), endpointsConfig.Channel("api"), ) if s.HealthzPort > 0 { go util.Forever(func() { err := http.ListenAndServe(s.HealthzBindAddress.String()+":"+strconv.Itoa(s.HealthzPort), nil) if err != nil { glog.Errorf("Starting health server failed: %v", err) } }, 5*time.Second) } // Just loop forever for now... proxier.SyncLoop() return nil }
// NewProxyServerDefault creates a new ProxyServer object with default parameters. func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, error) { if c, err := configz.New("componentconfig"); err == nil { c.Set(config.KubeProxyConfiguration) } else { glog.Errorf("unable to register configz: %s", err) } protocol := utiliptables.ProtocolIpv4 if net.ParseIP(config.BindAddress).To4() == nil { protocol = utiliptables.ProtocolIpv6 } // Create a iptables utils. execer := exec.New() dbus := utildbus.New() iptInterface := utiliptables.New(execer, dbus, protocol) // We omit creation of pretty much everything if we run in cleanup mode if config.CleanupAndExit { return &ProxyServer{ Config: config, IptInterface: iptInterface, }, nil } // TODO(vmarmol): Use container config for this. var oomAdjuster *oom.OOMAdjuster if config.OOMScoreAdj != nil { oomAdjuster = oom.NewOOMAdjuster() if err := oomAdjuster.ApplyOOMScoreAdj(0, int(*config.OOMScoreAdj)); err != nil { glog.V(2).Info(err) } } if config.ResourceContainer != "" { // Run in its own container. if err := resourcecontainer.RunInResourceContainer(config.ResourceContainer); err != nil { glog.Warningf("Failed to start in resource-only container %q: %v", config.ResourceContainer, err) } else { glog.V(2).Infof("Running in resource-only container %q", config.ResourceContainer) } } // Create a Kube Client // define api config source if config.Kubeconfig == "" && config.Master == "" { glog.Warningf("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.") } // This creates a client, first loading any specified kubeconfig // file, and then overriding the Master flag, if non-empty. kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( &clientcmd.ClientConfigLoadingRules{ExplicitPath: config.Kubeconfig}, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: config.Master}}).ClientConfig() if err != nil { return nil, err } kubeconfig.ContentType = config.ContentType // Override kubeconfig qps/burst settings from flags kubeconfig.QPS = config.KubeAPIQPS kubeconfig.Burst = int(config.KubeAPIBurst) client, err := clientset.NewForConfig(kubeconfig) if err != nil { glog.Fatalf("Invalid API configuration: %v", err) } // Create event recorder hostname := nodeutil.GetHostname(config.HostnameOverride) eventBroadcaster := record.NewBroadcaster() recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: hostname}) var proxier proxy.ProxyProvider var endpointsHandler proxyconfig.EndpointsConfigHandler proxyMode := getProxyMode(string(config.Mode), client.Core().Nodes(), hostname, iptInterface, iptables.LinuxKernelCompatTester{}) if proxyMode == proxyModeIPTables { glog.V(0).Info("Using iptables Proxier.") if config.IPTablesMasqueradeBit == nil { // IPTablesMasqueradeBit must be specified or defaulted. return nil, fmt.Errorf("Unable to read IPTablesMasqueradeBit from config") } proxierIPTables, err := iptables.NewProxier(iptInterface, utilsysctl.New(), execer, config.IPTablesSyncPeriod.Duration, config.MasqueradeAll, int(*config.IPTablesMasqueradeBit), config.ClusterCIDR, hostname, getNodeIP(client, hostname)) if err != nil { glog.Fatalf("Unable to create proxier: %v", err) } proxier = proxierIPTables endpointsHandler = proxierIPTables // No turning back. Remove artifacts that might still exist from the userspace Proxier. glog.V(0).Info("Tearing down userspace rules.") userspace.CleanupLeftovers(iptInterface) } else { glog.V(0).Info("Using userspace Proxier.") // This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for // our config.EndpointsConfigHandler. loadBalancer := userspace.NewLoadBalancerRR() // set EndpointsConfigHandler to our loadBalancer endpointsHandler = loadBalancer proxierUserspace, err := userspace.NewProxier( loadBalancer, net.ParseIP(config.BindAddress), iptInterface, *utilnet.ParsePortRangeOrDie(config.PortRange), config.IPTablesSyncPeriod.Duration, config.UDPIdleTimeout.Duration, ) if err != nil { glog.Fatalf("Unable to create proxier: %v", err) } proxier = proxierUserspace // Remove artifacts from the pure-iptables Proxier. glog.V(0).Info("Tearing down pure-iptables proxy rules.") iptables.CleanupLeftovers(iptInterface) } iptInterface.AddReloadFunc(proxier.Sync) // Create configs (i.e. Watches for Services and Endpoints) // Note: RegisterHandler() calls need to happen before creation of Sources because sources // only notify on changes, and the initial update (on process start) may be lost if no handlers // are registered yet. serviceConfig := proxyconfig.NewServiceConfig() serviceConfig.RegisterHandler(proxier) endpointsConfig := proxyconfig.NewEndpointsConfig() endpointsConfig.RegisterHandler(endpointsHandler) proxyconfig.NewSourceAPI( client.Core().RESTClient(), config.ConfigSyncPeriod, serviceConfig.Channel("api"), endpointsConfig.Channel("api"), ) config.NodeRef = &api.ObjectReference{ Kind: "Node", Name: hostname, UID: types.UID(hostname), Namespace: "", } conntracker := realConntracker{} return NewProxyServer(client, config, iptInterface, proxier, eventBroadcaster, recorder, conntracker, proxyMode) }
func (util *RBDUtil) rbdLock(b rbdBuilder, lock bool) error { var err error var output, locker string var cmd []byte var secret_opt []string if b.Secret != "" { secret_opt = []string{"--key=" + b.Secret} } else { secret_opt = []string{"-k", b.Keyring} } // construct lock id using host name and a magic prefix lock_id := "kubelet_lock_magic_" + node.GetHostname("") l := len(b.Mon) // avoid mount storm, pick a host randomly start := rand.Int() % l // iterate all hosts until mount succeeds. for i := start; i < start+l; i++ { mon := b.Mon[i%l] // cmd "rbd lock list" serves two purposes: // for fencing, check if lock already held for this host // this edge case happens if host crashes in the middle of acquiring lock and mounting rbd // for defencing, get the locker name, something like "client.1234" cmd, err = b.plugin.execCommand("rbd", append([]string{"lock", "list", b.Image, "--pool", b.Pool, "--id", b.Id, "-m", mon}, secret_opt...)) output = string(cmd) if err != nil { continue } if lock { // check if lock is already held for this host by matching lock_id and rbd lock id if strings.Contains(output, lock_id) { // this host already holds the lock, exit glog.V(1).Infof("rbd: lock already held for %s", lock_id) return nil } // hold a lock: rbd lock add cmd, err = b.plugin.execCommand("rbd", append([]string{"lock", "add", b.Image, lock_id, "--pool", b.Pool, "--id", b.Id, "-m", mon}, secret_opt...)) } else { // defencing, find locker name ind := strings.LastIndex(output, lock_id) - 1 for i := ind; i >= 0; i-- { if output[i] == '\n' { locker = output[(i + 1):ind] break } } // remove a lock: rbd lock remove cmd, err = b.plugin.execCommand("rbd", append([]string{"lock", "remove", b.Image, lock_id, locker, "--pool", b.Pool, "--id", b.Id, "-m", mon}, secret_opt...)) } if err == nil { //lock is acquired break } } return err }
func run(s *options.KubeletServer, kubeDeps *kubelet.KubeletDeps) (err error) { // TODO: this should be replaced by a --standalone flag standaloneMode := (len(s.APIServerList) == 0 && !s.RequireKubeConfig) if s.ExitOnLockContention && s.LockFilePath == "" { return errors.New("cannot exit on lock file contention: no lock file specified") } done := make(chan struct{}) if s.LockFilePath != "" { glog.Infof("acquiring file lock on %q", s.LockFilePath) if err := flock.Acquire(s.LockFilePath); err != nil { return fmt.Errorf("unable to acquire file lock on %q: %v", s.LockFilePath, err) } if s.ExitOnLockContention { glog.Infof("watching for inotify events for: %v", s.LockFilePath) if err := watchForLockfileContention(s.LockFilePath, done); err != nil { return err } } } // Set feature gates based on the value in KubeletConfiguration err = utilconfig.DefaultFeatureGate.Set(s.KubeletConfiguration.FeatureGates) if err != nil { return err } // Register current configuration with /configz endpoint cfgz, cfgzErr := initConfigz(&s.KubeletConfiguration) if utilconfig.DefaultFeatureGate.DynamicKubeletConfig() { // Look for config on the API server. If it exists, replace s.KubeletConfiguration // with it and continue. initKubeletConfigSync also starts the background thread that checks for new config. // Don't do dynamic Kubelet configuration in runonce mode if s.RunOnce == false { remoteKC, err := initKubeletConfigSync(s) if err == nil { // Update s (KubeletServer) with new config from API server s.KubeletConfiguration = *remoteKC // Ensure that /configz is up to date with the new config if cfgzErr != nil { glog.Errorf("was unable to register configz before due to %s, will not be able to set now", cfgzErr) } else { setConfigz(cfgz, &s.KubeletConfiguration) } // Update feature gates from the new config err = utilconfig.DefaultFeatureGate.Set(s.KubeletConfiguration.FeatureGates) if err != nil { return err } } } } if kubeDeps == nil { var kubeClient, eventClient *clientset.Clientset var cloud cloudprovider.Interface if s.CloudProvider != componentconfigv1alpha1.AutoDetectCloudProvider { cloud, err = cloudprovider.InitCloudProvider(s.CloudProvider, s.CloudConfigFile) if err != nil { return err } if cloud == nil { glog.V(2).Infof("No cloud provider specified: %q from the config file: %q\n", s.CloudProvider, s.CloudConfigFile) } else { glog.V(2).Infof("Successfully initialized cloud provider: %q from the config file: %q\n", s.CloudProvider, s.CloudConfigFile) } } if s.BootstrapKubeconfig != "" { nodeName, err := getNodeName(cloud, nodeutil.GetHostname(s.HostnameOverride)) if err != nil { return err } if err := bootstrapClientCert(s.KubeConfig.Value(), s.BootstrapKubeconfig, s.CertDirectory, nodeName); err != nil { return err } } clientConfig, err := CreateAPIServerClientConfig(s) if err == nil { kubeClient, err = clientset.NewForConfig(clientConfig) if err != nil { glog.Warningf("New kubeClient from clientConfig error: %v", err) } // make a separate client for events eventClientConfig := *clientConfig eventClientConfig.QPS = float32(s.EventRecordQPS) eventClientConfig.Burst = int(s.EventBurst) eventClient, err = clientset.NewForConfig(&eventClientConfig) } else { if s.RequireKubeConfig { return fmt.Errorf("invalid kubeconfig: %v", err) } if standaloneMode { glog.Warningf("No API client: %v", err) } } kubeDeps, err = UnsecuredKubeletDeps(s) if err != nil { return err } kubeDeps.Cloud = cloud kubeDeps.KubeClient = kubeClient kubeDeps.EventClient = eventClient } if kubeDeps.Auth == nil { nodeName, err := getNodeName(kubeDeps.Cloud, nodeutil.GetHostname(s.HostnameOverride)) if err != nil { return err } auth, err := buildAuth(nodeName, kubeDeps.KubeClient, s.KubeletConfiguration) if err != nil { return err } kubeDeps.Auth = auth } if kubeDeps.CAdvisorInterface == nil { kubeDeps.CAdvisorInterface, err = cadvisor.New(uint(s.CAdvisorPort), s.ContainerRuntime, s.RootDirectory) if err != nil { return err } } if kubeDeps.ContainerManager == nil { if s.SystemCgroups != "" && s.CgroupRoot == "" { return fmt.Errorf("invalid configuration: system container was specified and cgroup root was not specified") } kubeDeps.ContainerManager, err = cm.NewContainerManager( kubeDeps.Mounter, kubeDeps.CAdvisorInterface, cm.NodeConfig{ RuntimeCgroupsName: s.RuntimeCgroups, SystemCgroupsName: s.SystemCgroups, KubeletCgroupsName: s.KubeletCgroups, ContainerRuntime: s.ContainerRuntime, CgroupsPerQOS: s.ExperimentalCgroupsPerQOS, CgroupRoot: s.CgroupRoot, CgroupDriver: s.CgroupDriver, ProtectKernelDefaults: s.ProtectKernelDefaults, EnableCRI: s.EnableCRI, }, s.ExperimentalFailSwapOn) if err != nil { return err } } if err := checkPermissions(); err != nil { glog.Error(err) } utilruntime.ReallyCrash = s.ReallyCrashForTesting rand.Seed(time.Now().UTC().UnixNano()) // TODO(vmarmol): Do this through container config. oomAdjuster := kubeDeps.OOMAdjuster if err := oomAdjuster.ApplyOOMScoreAdj(0, int(s.OOMScoreAdj)); err != nil { glog.Warning(err) } if err := RunKubelet(&s.KubeletConfiguration, kubeDeps, s.RunOnce, standaloneMode); err != nil { return err } if s.HealthzPort > 0 { healthz.DefaultHealthz() go wait.Until(func() { err := http.ListenAndServe(net.JoinHostPort(s.HealthzBindAddress, strconv.Itoa(int(s.HealthzPort))), nil) if err != nil { glog.Errorf("Starting health server failed: %v", err) } }, 5*time.Second, wait.NeverStop) } if s.RunOnce { return nil } <-done return nil }
// RunKubelet is responsible for setting up and running a kubelet. It is used in three different applications: // 1 Integration tests // 2 Kubelet binary // 3 Standalone 'kubernetes' binary // Eventually, #2 will be replaced with instances of #3 func RunKubelet(kubeCfg *componentconfig.KubeletConfiguration, kubeDeps *kubelet.KubeletDeps, runOnce bool, standaloneMode bool) error { hostname := nodeutil.GetHostname(kubeCfg.HostnameOverride) // Query the cloud provider for our node name, default to hostname if kcfg.Cloud == nil nodeName, err := getNodeName(kubeDeps.Cloud, hostname) if err != nil { return err } eventBroadcaster := record.NewBroadcaster() kubeDeps.Recorder = eventBroadcaster.NewRecorder(v1.EventSource{Component: "kubelet", Host: string(nodeName)}) eventBroadcaster.StartLogging(glog.V(3).Infof) if kubeDeps.EventClient != nil { glog.V(4).Infof("Sending events to api server.") eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: kubeDeps.EventClient.Events("")}) } else { glog.Warning("No api server defined - no events will be sent to API server.") } // TODO(mtaufen): I moved the validation of these fields here, from UnsecuredKubeletConfig, // so that I could remove the associated fields from KubeletConfig. I would // prefer this to be done as part of an independent validation step on the // KubeletConfiguration. But as far as I can tell, we don't have an explicit // place for validation of the KubeletConfiguration yet. hostNetworkSources, err := kubetypes.GetValidatedSources(kubeCfg.HostNetworkSources) if err != nil { return err } hostPIDSources, err := kubetypes.GetValidatedSources(kubeCfg.HostPIDSources) if err != nil { return err } hostIPCSources, err := kubetypes.GetValidatedSources(kubeCfg.HostIPCSources) if err != nil { return err } privilegedSources := capabilities.PrivilegedSources{ HostNetworkSources: hostNetworkSources, HostPIDSources: hostPIDSources, HostIPCSources: hostIPCSources, } capabilities.Setup(kubeCfg.AllowPrivileged, privilegedSources, 0) credentialprovider.SetPreferredDockercfgPath(kubeCfg.RootDirectory) glog.V(2).Infof("Using root directory: %v", kubeCfg.RootDirectory) builder := kubeDeps.Builder if builder == nil { builder = CreateAndInitKubelet } if kubeDeps.OSInterface == nil { kubeDeps.OSInterface = kubecontainer.RealOS{} } k, err := builder(kubeCfg, kubeDeps, standaloneMode) if err != nil { return fmt.Errorf("failed to create kubelet: %v", err) } // NewMainKubelet should have set up a pod source config if one didn't exist // when the builder was run. This is just a precaution. if kubeDeps.PodConfig == nil { return fmt.Errorf("failed to create kubelet, pod source config was nil!") } podCfg := kubeDeps.PodConfig rlimit.RlimitNumFiles(uint64(kubeCfg.MaxOpenFiles)) // TODO(dawnchen): remove this once we deprecated old debian containervm images. // This is a workaround for issue: https://github.com/opencontainers/runc/issues/726 // The current chosen number is consistent with most of other os dist. const maxkeysPath = "/proc/sys/kernel/keys/root_maxkeys" const minKeys uint64 = 1000000 key, err := ioutil.ReadFile(maxkeysPath) if err != nil { glog.Errorf("Cannot read keys quota in %s", maxkeysPath) } else { fields := strings.Fields(string(key)) nkey, _ := strconv.ParseUint(fields[0], 10, 64) if nkey < minKeys { glog.Infof("Setting keys quota in %s to %d", maxkeysPath, minKeys) err = ioutil.WriteFile(maxkeysPath, []byte(fmt.Sprintf("%d", uint64(minKeys))), 0644) if err != nil { glog.Warningf("Failed to update %s: %v", maxkeysPath, err) } } } const maxbytesPath = "/proc/sys/kernel/keys/root_maxbytes" const minBytes uint64 = 25000000 bytes, err := ioutil.ReadFile(maxbytesPath) if err != nil { glog.Errorf("Cannot read keys bytes in %s", maxbytesPath) } else { fields := strings.Fields(string(bytes)) nbyte, _ := strconv.ParseUint(fields[0], 10, 64) if nbyte < minBytes { glog.Infof("Setting keys bytes in %s to %d", maxbytesPath, minBytes) err = ioutil.WriteFile(maxbytesPath, []byte(fmt.Sprintf("%d", uint64(minBytes))), 0644) if err != nil { glog.Warningf("Failed to update %s: %v", maxbytesPath, err) } } } // process pods and exit. if runOnce { if _, err := k.RunOnce(podCfg.Updates()); err != nil { return fmt.Errorf("runonce failed: %v", err) } glog.Infof("Started kubelet %s as runonce", version.Get().String()) } else { startKubelet(k, podCfg, kubeCfg, kubeDeps) glog.Infof("Started kubelet %s", version.Get().String()) } return nil }
// NewProxyServerDefault creates a new ProxyServer object with default parameters. func NewProxyServerDefault(config *ProxyServerConfig) (*ProxyServer, error) { protocol := utiliptables.ProtocolIpv4 if config.BindAddress.To4() == nil { protocol = utiliptables.ProtocolIpv6 } // Create a iptables utils. execer := exec.New() dbus := utildbus.New() iptInterface := utiliptables.New(execer, dbus, protocol) // We ommit creation of pretty much everything if we run in cleanup mode if config.CleanupAndExit { return &ProxyServer{ Config: config, IptInterface: iptInterface, }, nil } // TODO(vmarmol): Use container config for this. var oomAdjuster *oom.OOMAdjuster if config.OOMScoreAdj != 0 { oomAdjuster = oom.NewOOMAdjuster() if err := oomAdjuster.ApplyOOMScoreAdj(0, config.OOMScoreAdj); err != nil { glog.V(2).Info(err) } } if config.ResourceContainer != "" { // Run in its own container. if err := util.RunInResourceContainer(config.ResourceContainer); err != nil { glog.Warningf("Failed to start in resource-only container %q: %v", config.ResourceContainer, err) } else { glog.V(2).Infof("Running in resource-only container %q", config.ResourceContainer) } } // Create a Kube Client // define api config source if config.Kubeconfig == "" && config.Master == "" { glog.Warningf("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.") } // This creates a client, first loading any specified kubeconfig // file, and then overriding the Master flag, if non-empty. kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( &clientcmd.ClientConfigLoadingRules{ExplicitPath: config.Kubeconfig}, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: config.Master}}).ClientConfig() if err != nil { return nil, err } // Override kubeconfig qps/burst settings from flags kubeconfig.QPS = config.KubeApiQps kubeconfig.Burst = config.KubeApiBurst client, err := kubeclient.New(kubeconfig) if err != nil { glog.Fatalf("Invalid API configuration: %v", err) } // Create event recorder hostname := nodeutil.GetHostname(config.HostnameOverride) eventBroadcaster := record.NewBroadcaster() recorder := eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: hostname}) eventBroadcaster.StartRecordingToSink(client.Events("")) var proxier proxy.ProxyProvider var endpointsHandler proxyconfig.EndpointsConfigHandler useIptablesProxy := false if mayTryIptablesProxy(config.ProxyMode, client.Nodes(), hostname) { var err error // guaranteed false on error, error only necessary for debugging useIptablesProxy, err = iptables.ShouldUseIptablesProxier() if err != nil { glog.Errorf("Can't determine whether to use iptables proxy, using userspace proxier: %v", err) } } if useIptablesProxy { glog.V(2).Info("Using iptables Proxier.") proxierIptables, err := iptables.NewProxier(iptInterface, execer, config.IptablesSyncPeriod, config.MasqueradeAll) if err != nil { glog.Fatalf("Unable to create proxier: %v", err) } proxier = proxierIptables endpointsHandler = proxierIptables // No turning back. Remove artifacts that might still exist from the userspace Proxier. glog.V(2).Info("Tearing down userspace rules. Errors here are acceptable.") userspace.CleanupLeftovers(iptInterface) } else { glog.V(2).Info("Using userspace Proxier.") // This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for // our config.EndpointsConfigHandler. loadBalancer := userspace.NewLoadBalancerRR() // set EndpointsConfigHandler to our loadBalancer endpointsHandler = loadBalancer proxierUserspace, err := userspace.NewProxier(loadBalancer, config.BindAddress, iptInterface, config.PortRange, config.IptablesSyncPeriod) if err != nil { glog.Fatalf("Unable to create proxier: %v", err) } proxier = proxierUserspace // Remove artifacts from the pure-iptables Proxier. glog.V(2).Info("Tearing down pure-iptables proxy rules. Errors here are acceptable.") iptables.CleanupLeftovers(iptInterface) } iptInterface.AddReloadFunc(proxier.Sync) // Create configs (i.e. Watches for Services and Endpoints) // Note: RegisterHandler() calls need to happen before creation of Sources because sources // only notify on changes, and the initial update (on process start) may be lost if no handlers // are registered yet. serviceConfig := proxyconfig.NewServiceConfig() serviceConfig.RegisterHandler(proxier) endpointsConfig := proxyconfig.NewEndpointsConfig() endpointsConfig.RegisterHandler(endpointsHandler) proxyconfig.NewSourceAPI( client, config.ConfigSyncPeriod, serviceConfig.Channel("api"), endpointsConfig.Channel("api"), ) config.nodeRef = &api.ObjectReference{ Kind: "Node", Name: hostname, UID: types.UID(hostname), Namespace: "", } return NewProxyServer(config, iptInterface, proxier, recorder) }
func run(s *options.KubeletServer, kcfg *KubeletConfig) (err error) { if s.ExitOnLockContention && s.LockFilePath == "" { return errors.New("cannot exit on lock file contention: no lock file specified") } done := make(chan struct{}) if s.LockFilePath != "" { glog.Infof("acquiring lock on %q", s.LockFilePath) if err := flock.Acquire(s.LockFilePath); err != nil { return fmt.Errorf("unable to acquire file lock on %q: %v", s.LockFilePath, err) } if s.ExitOnLockContention { glog.Infof("watching for inotify events for: %v", s.LockFilePath) if err := watchForLockfileContention(s.LockFilePath, done); err != nil { return err } } } if c, err := configz.New("componentconfig"); err == nil { c.Set(s.KubeletConfiguration) } else { glog.Errorf("unable to register configz: %s", err) } if kcfg == nil { var kubeClient, eventClient *clientset.Clientset var autoDetectCloudProvider bool var cloud cloudprovider.Interface if s.CloudProvider == kubeExternal.AutoDetectCloudProvider { autoDetectCloudProvider = true } else { cloud, err = cloudprovider.InitCloudProvider(s.CloudProvider, s.CloudConfigFile) if err != nil { return err } if cloud == nil { glog.V(2).Infof("No cloud provider specified: %q from the config file: %q\n", s.CloudProvider, s.CloudConfigFile) } else { glog.V(2).Infof("Successfully initialized cloud provider: %q from the config file: %q\n", s.CloudProvider, s.CloudConfigFile) } } if s.BootstrapKubeconfig != "" { nodeName, err := getNodeName(cloud, nodeutil.GetHostname(s.HostnameOverride)) if err != nil { return err } if err := bootstrapClientCert(s.KubeConfig.Value(), s.BootstrapKubeconfig, s.CertDirectory, nodeName); err != nil { return err } } clientConfig, err := CreateAPIServerClientConfig(s) if err == nil { kubeClient, err = clientset.NewForConfig(clientConfig) // make a separate client for events eventClientConfig := *clientConfig eventClientConfig.QPS = float32(s.EventRecordQPS) eventClientConfig.Burst = int(s.EventBurst) eventClient, err = clientset.NewForConfig(&eventClientConfig) } if err != nil { if s.RequireKubeConfig { return fmt.Errorf("invalid kubeconfig: %v", err) } // TODO: this should be replaced by a --standalone flag if len(s.APIServerList) > 0 { glog.Warningf("No API client: %v", err) } } cfg, err := UnsecuredKubeletConfig(s) if err != nil { return err } kcfg = cfg kcfg.AutoDetectCloudProvider = autoDetectCloudProvider kcfg.Cloud = cloud kcfg.KubeClient = kubeClient kcfg.EventClient = eventClient } if kcfg.CAdvisorInterface == nil { kcfg.CAdvisorInterface, err = cadvisor.New(uint(s.CAdvisorPort), kcfg.ContainerRuntime) if err != nil { return err } } if kcfg.ContainerManager == nil { if kcfg.SystemCgroups != "" && kcfg.CgroupRoot == "" { return fmt.Errorf("invalid configuration: system container was specified and cgroup root was not specified") } kcfg.ContainerManager, err = cm.NewContainerManager(kcfg.Mounter, kcfg.CAdvisorInterface, cm.NodeConfig{ RuntimeCgroupsName: kcfg.RuntimeCgroups, SystemCgroupsName: kcfg.SystemCgroups, KubeletCgroupsName: kcfg.KubeletCgroups, ContainerRuntime: kcfg.ContainerRuntime, CgroupsPerQOS: kcfg.CgroupsPerQOS, CgroupRoot: kcfg.CgroupRoot, ProtectKernelDefaults: kcfg.ProtectKernelDefaults, }) if err != nil { return err } } if err := checkPermissions(); err != nil { glog.Error(err) } runtime.ReallyCrash = s.ReallyCrashForTesting rand.Seed(time.Now().UTC().UnixNano()) // TODO(vmarmol): Do this through container config. oomAdjuster := kcfg.OOMAdjuster if err := oomAdjuster.ApplyOOMScoreAdj(0, int(s.OOMScoreAdj)); err != nil { glog.Warning(err) } if err := RunKubelet(kcfg); err != nil { return err } if s.HealthzPort > 0 { healthz.DefaultHealthz() go wait.Until(func() { err := http.ListenAndServe(net.JoinHostPort(s.HealthzBindAddress, strconv.Itoa(int(s.HealthzPort))), nil) if err != nil { glog.Errorf("Starting health server failed: %v", err) } }, 5*time.Second, wait.NeverStop) } if s.RunOnce { return nil } <-done return nil }
// RunKubelet is responsible for setting up and running a kubelet. It is used in three different applications: // 1 Integration tests // 2 Kubelet binary // 3 Standalone 'kubernetes' binary // Eventually, #2 will be replaced with instances of #3 func RunKubelet(kcfg *KubeletConfig) error { kcfg.Hostname = nodeutil.GetHostname(kcfg.HostnameOverride) if len(kcfg.NodeName) == 0 { // Query the cloud provider for our node name, default to Hostname nodeName := kcfg.Hostname if kcfg.Cloud != nil { var err error instances, ok := kcfg.Cloud.Instances() if !ok { return fmt.Errorf("failed to get instances from cloud provider") } nodeName, err = instances.CurrentNodeName(kcfg.Hostname) if err != nil { return fmt.Errorf("error fetching current instance name from cloud provider: %v", err) } glog.V(2).Infof("cloud provider determined current node name to be %s", nodeName) } kcfg.NodeName = nodeName } eventBroadcaster := record.NewBroadcaster() kcfg.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "kubelet", Host: kcfg.NodeName}) eventBroadcaster.StartLogging(glog.V(3).Infof) if kcfg.EventClient != nil { glog.V(4).Infof("Sending events to api server.") eventBroadcaster.StartRecordingToSink(&unversionedcore.EventSinkImpl{Interface: kcfg.EventClient.Events("")}) } else { glog.Warning("No api server defined - no events will be sent to API server.") } privilegedSources := capabilities.PrivilegedSources{ HostNetworkSources: kcfg.HostNetworkSources, HostPIDSources: kcfg.HostPIDSources, HostIPCSources: kcfg.HostIPCSources, } capabilities.Setup(kcfg.AllowPrivileged, privilegedSources, 0) credentialprovider.SetPreferredDockercfgPath(kcfg.RootDirectory) glog.V(2).Infof("Using root directory: %v", kcfg.RootDirectory) builder := kcfg.Builder if builder == nil { builder = CreateAndInitKubelet } if kcfg.OSInterface == nil { kcfg.OSInterface = kubecontainer.RealOS{} } k, podCfg, err := builder(kcfg) if err != nil { return fmt.Errorf("failed to create kubelet: %v", err) } rlimit.RlimitNumFiles(kcfg.MaxOpenFiles) // TODO(dawnchen): remove this once we deprecated old debian containervm images. // This is a workaround for issue: https://github.com/opencontainers/runc/issues/726 // The current chosen number is consistent with most of other os dist. const maxkeysPath = "/proc/sys/kernel/keys/root_maxkeys" const minKeys uint64 = 1000000 key, err := ioutil.ReadFile(maxkeysPath) if err != nil { glog.Errorf("Cannot read keys quota in %s", maxkeysPath) } else { fields := strings.Fields(string(key)) nkey, _ := strconv.ParseUint(fields[0], 10, 64) if nkey < minKeys { glog.Infof("Setting keys quota in %s to %d", maxkeysPath, minKeys) err = ioutil.WriteFile(maxkeysPath, []byte(fmt.Sprintf("%d", uint64(minKeys))), 0644) if err != nil { glog.Warningf("Failed to update %s: %v", maxkeysPath, err) } } } const maxbytesPath = "/proc/sys/kernel/keys/root_maxbytes" const minBytes uint64 = 25000000 bytes, err := ioutil.ReadFile(maxbytesPath) if err != nil { glog.Errorf("Cannot read keys bytes in %s", maxbytesPath) } else { fields := strings.Fields(string(bytes)) nbyte, _ := strconv.ParseUint(fields[0], 10, 64) if nbyte < minBytes { glog.Infof("Setting keys bytes in %s to %d", maxbytesPath, minBytes) err = ioutil.WriteFile(maxbytesPath, []byte(fmt.Sprintf("%d", uint64(minBytes))), 0644) if err != nil { glog.Warningf("Failed to update %s: %v", maxbytesPath, err) } } } // process pods and exit. if kcfg.Runonce { if _, err := k.RunOnce(podCfg.Updates()); err != nil { return fmt.Errorf("runonce failed: %v", err) } glog.Infof("Started kubelet %s as runonce", version.Get().String()) } else { startKubelet(k, podCfg, kcfg) glog.Infof("Started kubelet %s", version.Get().String()) } return nil }
// RunProxy starts the proxy func (c *NodeConfig) RunProxy() { protocol := utiliptables.ProtocolIpv4 bindAddr := net.ParseIP(c.ProxyConfig.BindAddress) if bindAddr.To4() == nil { protocol = utiliptables.ProtocolIpv6 } portRange := utilnet.ParsePortRangeOrDie(c.ProxyConfig.PortRange) hostname := utilnode.GetHostname(c.KubeletServer.HostnameOverride) eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartRecordingToSink(c.Client.Events("")) recorder := eventBroadcaster.NewRecorder(kapi.EventSource{Component: "kube-proxy", Host: hostname}) execer := kexec.New() dbus := utildbus.New() iptInterface := utiliptables.New(execer, dbus, protocol) var proxier proxy.ProxyProvider var endpointsHandler pconfig.EndpointsConfigHandler switch c.ProxyConfig.Mode { case componentconfig.ProxyModeIPTables: glog.V(0).Info("Using iptables Proxier.") if c.ProxyConfig.IPTablesMasqueradeBit == nil { // IPTablesMasqueradeBit must be specified or defaulted. glog.Fatalf("Unable to read IPTablesMasqueradeBit from config") } proxierIptables, err := iptables.NewProxier( iptInterface, utilsysctl.New(), execer, c.ProxyConfig.IPTablesSyncPeriod.Duration, c.ProxyConfig.MasqueradeAll, int(*c.ProxyConfig.IPTablesMasqueradeBit), c.ProxyConfig.ClusterCIDR, hostname, getNodeIP(c.Client, hostname), ) if err != nil { if c.Containerized { glog.Fatalf("error: Could not initialize Kubernetes Proxy: %v\n When running in a container, you must run the container in the host network namespace with --net=host and with --privileged", err) } else { glog.Fatalf("error: Could not initialize Kubernetes Proxy. You must run this process as root to use the service proxy: %v", err) } } proxier = proxierIptables endpointsHandler = proxierIptables // No turning back. Remove artifacts that might still exist from the userspace Proxier. glog.V(0).Info("Tearing down userspace rules.") userspace.CleanupLeftovers(iptInterface) case componentconfig.ProxyModeUserspace: glog.V(0).Info("Using userspace Proxier.") // This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for // our config.EndpointsConfigHandler. loadBalancer := userspace.NewLoadBalancerRR() // set EndpointsConfigHandler to our loadBalancer endpointsHandler = loadBalancer proxierUserspace, err := userspace.NewProxier( loadBalancer, bindAddr, iptInterface, *portRange, c.ProxyConfig.IPTablesSyncPeriod.Duration, c.ProxyConfig.UDPIdleTimeout.Duration, ) if err != nil { if c.Containerized { glog.Fatalf("error: Could not initialize Kubernetes Proxy: %v\n When running in a container, you must run the container in the host network namespace with --net=host and with --privileged", err) } else { glog.Fatalf("error: Could not initialize Kubernetes Proxy. You must run this process as root to use the service proxy: %v", err) } } proxier = proxierUserspace // Remove artifacts from the pure-iptables Proxier. glog.V(0).Info("Tearing down pure-iptables proxy rules.") iptables.CleanupLeftovers(iptInterface) default: glog.Fatalf("Unknown proxy mode %q", c.ProxyConfig.Mode) } // Create configs (i.e. Watches for Services and Endpoints) // Note: RegisterHandler() calls need to happen before creation of Sources because sources // only notify on changes, and the initial update (on process start) may be lost if no handlers // are registered yet. serviceConfig := pconfig.NewServiceConfig() if c.EnableUnidling { unidlingLoadBalancer := ouserspace.NewLoadBalancerRR() signaler := unidler.NewEventSignaler(recorder) unidlingUserspaceProxy, err := unidler.NewUnidlerProxier(unidlingLoadBalancer, bindAddr, iptInterface, execer, *portRange, c.ProxyConfig.IPTablesSyncPeriod.Duration, c.ProxyConfig.UDPIdleTimeout.Duration, signaler) if err != nil { if c.Containerized { glog.Fatalf("error: Could not initialize Kubernetes Proxy: %v\n When running in a container, you must run the container in the host network namespace with --net=host and with --privileged", err) } else { glog.Fatalf("error: Could not initialize Kubernetes Proxy. You must run this process as root to use the service proxy: %v", err) } } hybridProxier, err := hybrid.NewHybridProxier(unidlingLoadBalancer, unidlingUserspaceProxy, endpointsHandler, proxier, c.ProxyConfig.IPTablesSyncPeriod.Duration, serviceConfig) if err != nil { if c.Containerized { glog.Fatalf("error: Could not initialize Kubernetes Proxy: %v\n When running in a container, you must run the container in the host network namespace with --net=host and with --privileged", err) } else { glog.Fatalf("error: Could not initialize Kubernetes Proxy. You must run this process as root to use the service proxy: %v", err) } } endpointsHandler = hybridProxier proxier = hybridProxier } iptInterface.AddReloadFunc(proxier.Sync) serviceConfig.RegisterHandler(proxier) endpointsConfig := pconfig.NewEndpointsConfig() // customized handling registration that inserts a filter if needed if c.FilteringEndpointsHandler != nil { if err := c.FilteringEndpointsHandler.Start(endpointsHandler); err != nil { glog.Fatalf("error: node proxy plugin startup failed: %v", err) } endpointsHandler = c.FilteringEndpointsHandler } endpointsConfig.RegisterHandler(endpointsHandler) c.ServiceStore = pconfig.NewServiceStore(c.ServiceStore, serviceConfig.Channel("api")) c.EndpointsStore = pconfig.NewEndpointsStore(c.EndpointsStore, endpointsConfig.Channel("api")) // will be started by RunServiceStores recorder.Eventf(c.ProxyConfig.NodeRef, kapi.EventTypeNormal, "Starting", "Starting kube-proxy.") // periodically sync k8s iptables rules go utilwait.Forever(proxier.SyncLoop, 0) glog.Infof("Started Kubernetes Proxy on %s", c.ProxyConfig.BindAddress) }
// Run runs the specified ProxyServer. This should never exit (unless CleanupAndExit is set). func (s *ProxyServer) Run(_ []string) error { protocol := utiliptables.ProtocolIpv4 if s.BindAddress.To4() == nil { protocol = utiliptables.ProtocolIpv6 } // remove iptables rules and exit if s.CleanupAndExit { execer := exec.New() ipt := utiliptables.New(execer, protocol) encounteredError := userspace.CleanupLeftovers(ipt) encounteredError = iptables.CleanupLeftovers(ipt) || encounteredError if encounteredError { return errors.New("Encountered an error while tearing down rules.") } return nil } // TODO(vmarmol): Use container config for this. oomAdjuster := oom.NewOomAdjuster() if err := oomAdjuster.ApplyOomScoreAdj(0, s.OOMScoreAdj); err != nil { glog.V(2).Info(err) } // Run in its own container. if err := util.RunInResourceContainer(s.ResourceContainer); err != nil { glog.Warningf("Failed to start in resource-only container %q: %v", s.ResourceContainer, err) } else { glog.V(2).Infof("Running in resource-only container %q", s.ResourceContainer) } // define api config source if s.Kubeconfig == "" && s.Master == "" { glog.Warningf("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.") } // This creates a client, first loading any specified kubeconfig // file, and then overriding the Master flag, if non-empty. kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig( &clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Kubeconfig}, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: s.Master}}).ClientConfig() if err != nil { return err } client, err := client.New(kubeconfig) if err != nil { glog.Fatalf("Invalid API configuration: %v", err) } // Add event recorder Hostname := nodeutil.GetHostname(s.HostnameOverride) eventBroadcaster := record.NewBroadcaster() s.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "kube-proxy", Host: Hostname}) eventBroadcaster.StartRecordingToSink(client.Events("")) s.nodeRef = &api.ObjectReference{ Kind: "Node", Name: Hostname, UID: types.UID(Hostname), Namespace: "", } // Birth Cry s.birthCry() serviceConfig := config.NewServiceConfig() endpointsConfig := config.NewEndpointsConfig() var proxier proxy.ProxyProvider var endpointsHandler config.EndpointsConfigHandler // guaranteed false on error, error only necessary for debugging shouldUseIptables, err := iptables.ShouldUseIptablesProxier() if err != nil { glog.Errorf("Can't determine whether to use iptables or userspace, using userspace proxier: %v", err) } if !s.ForceUserspaceProxy && shouldUseIptables { glog.V(2).Info("Using iptables Proxier.") execer := exec.New() ipt := utiliptables.New(execer, protocol) proxierIptables, err := iptables.NewProxier(ipt, execer, s.SyncPeriod, s.MasqueradeAll) if err != nil { glog.Fatalf("Unable to create proxier: %v", err) } proxier = proxierIptables endpointsHandler = proxierIptables // No turning back. Remove artifacts that might still exist from the userspace Proxier. glog.V(2).Info("Tearing down userspace rules. Errors here are acceptable.") userspace.CleanupLeftovers(ipt) } else { glog.V(2).Info("Using userspace Proxier.") // This is a proxy.LoadBalancer which NewProxier needs but has methods we don't need for // our config.EndpointsConfigHandler. loadBalancer := userspace.NewLoadBalancerRR() // set EndpointsConfigHandler to our loadBalancer endpointsHandler = loadBalancer execer := exec.New() ipt := utiliptables.New(execer, protocol) proxierUserspace, err := userspace.NewProxier(loadBalancer, s.BindAddress, ipt, s.PortRange, s.SyncPeriod) if err != nil { glog.Fatalf("Unable to create proxer: %v", err) } proxier = proxierUserspace // Remove artifacts from the pure-iptables Proxier. glog.V(2).Info("Tearing down pure-iptables proxy rules. Errors here are acceptable.") iptables.CleanupLeftovers(ipt) } // Wire proxier to handle changes to services serviceConfig.RegisterHandler(proxier) // And wire endpointsHandler to handle changes to endpoints to services endpointsConfig.RegisterHandler(endpointsHandler) // Note: RegisterHandler() calls need to happen before creation of Sources because sources // only notify on changes, and the initial update (on process start) may be lost if no handlers // are registered yet. config.NewSourceAPI( client, 30*time.Second, serviceConfig.Channel("api"), endpointsConfig.Channel("api"), ) if s.HealthzPort > 0 { go util.Until(func() { err := http.ListenAndServe(s.HealthzBindAddress.String()+":"+strconv.Itoa(s.HealthzPort), nil) if err != nil { glog.Errorf("Starting health server failed: %v", err) } }, 5*time.Second, util.NeverStop) } // Just loop forever for now... proxier.SyncLoop() return nil }