// SetVolumeOwnership modifies the given volume to be owned by // fsGroup, and sets SetGid so that newly created files are owned by // fsGroup. If fsGroup is nil nothing is done. func SetVolumeOwnership(mounter Mounter, fsGroup *int64) error { if fsGroup == nil { return nil } chownRunner := chown.New() chmodRunner := chmod.New() return filepath.Walk(mounter.GetPath(), func(path string, info os.FileInfo, err error) error { if err != nil { return err } // chown and chmod pass through to the underlying file for symlinks. // Symlinks have a mode of 777 but this really doesn't mean anything. // The permissions of the underlying file are what matter. // However, if one reads the mode of a symlink then chmods the symlink // with that mode, it changes the mode of the underlying file, overridden // the defaultMode and permissions initialized by the volume plugin, which // is not what we want; thus, we skip chown/chmod for symlinks. if info.Mode()&os.ModeSymlink != 0 { return nil } stat, ok := info.Sys().(*syscall.Stat_t) if !ok { return nil } if stat == nil { glog.Errorf("Got nil stat_t for path %v while setting ownership of volume", path) return nil } err = chownRunner.Chown(path, int(stat.Uid), int(*fsGroup)) if err != nil { glog.Errorf("Chown failed on %v: %v", path, err) } mask := rwMask if mounter.GetAttributes().ReadOnly { mask = roMask } if info.IsDir() { mask |= os.ModeSetgid } err = chmodRunner.Chmod(path, info.Mode()|mask) if err != nil { glog.Errorf("Chmod failed on %v: %v", path, err) } return nil }) }
// SetVolumeOwnership modifies the given volume to be owned by // fsGroup, and sets SetGid so that newly created files are owned by // fsGroup. If fsGroup is nil nothing is done. func SetVolumeOwnership(mounter Mounter, fsGroup *int64) error { if fsGroup == nil { return nil } chownRunner := chown.New() chmodRunner := chmod.New() return filepath.Walk(mounter.GetPath(), func(path string, info os.FileInfo, err error) error { if err != nil { return err } stat, ok := info.Sys().(*syscall.Stat_t) if !ok { return nil } if stat == nil { glog.Errorf("Got nil stat_t for path %v while setting ownership of volume", path) return nil } err = chownRunner.Chown(path, int(stat.Uid), int(*fsGroup)) if err != nil { glog.Errorf("Chown failed on %v: %v", path, err) } mask := rwMask if mounter.GetAttributes().ReadOnly { mask = roMask } if info.IsDir() { mask |= os.ModeSetgid } err = chmodRunner.Chmod(path, info.Mode()|mask) if err != nil { glog.Errorf("Chmod failed on %v: %v", path, err) } return nil }) }
// SimpleRunKubelet is a simple way to start a Kubelet talking to dockerEndpoint, using an API Client. // Under the hood it calls RunKubelet (below) func SimpleKubelet(client *client.Client, dockerClient dockertools.DockerInterface, hostname, rootDir, manifestURL, address string, port uint, readOnlyPort uint, masterServiceNamespace string, volumePlugins []volume.VolumePlugin, tlsOptions *server.TLSOptions, cadvisorInterface cadvisor.Interface, configFilePath string, cloud cloudprovider.Interface, osInterface kubecontainer.OSInterface, fileCheckFrequency, httpCheckFrequency, minimumGCAge, nodeStatusUpdateFrequency, syncFrequency, outOfDiskTransitionFrequency time.Duration, maxPods int, containerManager cm.ContainerManager, clusterDNS net.IP) *KubeletConfig { imageGCPolicy := kubelet.ImageGCPolicy{ HighThresholdPercent: 90, LowThresholdPercent: 80, } diskSpacePolicy := kubelet.DiskSpacePolicy{ DockerFreeDiskMB: 256, RootFreeDiskMB: 256, } kcfg := KubeletConfig{ Address: net.ParseIP(address), CAdvisorInterface: cadvisorInterface, CgroupRoot: "", Cloud: cloud, ClusterDNS: clusterDNS, ConfigFile: configFilePath, ContainerManager: containerManager, ContainerRuntime: "docker", CPUCFSQuota: false, DiskSpacePolicy: diskSpacePolicy, DockerClient: dockerClient, DockerDaemonContainer: "/docker-daemon", DockerExecHandler: &dockertools.NativeExecHandler{}, EnableDebuggingHandlers: true, EnableServer: true, FileCheckFrequency: fileCheckFrequency, HostnameOverride: hostname, HTTPCheckFrequency: httpCheckFrequency, ImageGCPolicy: imageGCPolicy, KubeClient: client, ManifestURL: manifestURL, MasterServiceNamespace: masterServiceNamespace, MaxContainerCount: 100, MaxOpenFiles: 1024, MaxPerPodContainerCount: 2, MaxPods: maxPods, MinimumGCAge: minimumGCAge, Mounter: mount.New(), ChownRunner: chown.New(), ChmodRunner: chmod.New(), NodeStatusUpdateFrequency: nodeStatusUpdateFrequency, OOMAdjuster: oom.NewFakeOOMAdjuster(), OSInterface: osInterface, PodInfraContainerImage: kubetypes.PodInfraContainerImage, Port: port, ReadOnlyPort: readOnlyPort, RegisterNode: true, RegisterSchedulable: true, RegistryBurst: 10, RegistryPullQPS: 5.0, ResolverConfig: kubetypes.ResolvConfDefault, ResourceContainer: "/kubelet", RootDirectory: rootDir, SerializeImagePulls: true, SyncFrequency: syncFrequency, SystemContainer: "", TLSOptions: tlsOptions, VolumePlugins: volumePlugins, Writer: &io.StdWriter{}, OutOfDiskTransitionFrequency: outOfDiskTransitionFrequency, } return &kcfg }
// UnsecuredKubeletConfig returns a KubeletConfig suitable for being run, or an error if the server setup // is not valid. It will not start any background processes, and does not include authentication/authorization func UnsecuredKubeletConfig(s *options.KubeletServer) (*KubeletConfig, error) { hostNetworkSources, err := kubetypes.GetValidatedSources(strings.Split(s.HostNetworkSources, ",")) if err != nil { return nil, err } hostPIDSources, err := kubetypes.GetValidatedSources(strings.Split(s.HostPIDSources, ",")) if err != nil { return nil, err } hostIPCSources, err := kubetypes.GetValidatedSources(strings.Split(s.HostIPCSources, ",")) if err != nil { return nil, err } mounter := mount.New() var writer io.Writer = &io.StdWriter{} if s.Containerized { glog.V(2).Info("Running kubelet in containerized mode (experimental)") mounter = mount.NewNsenterMounter() writer = &io.NsenterWriter{} } chmodRunner := chmod.New() chownRunner := chown.New() tlsOptions, err := InitializeTLS(s) if err != nil { 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{ HighThresholdPercent: s.ImageGCHighThresholdPercent, LowThresholdPercent: s.ImageGCLowThresholdPercent, } diskSpacePolicy := kubelet.DiskSpacePolicy{ DockerFreeDiskMB: s.LowDiskSpaceThresholdMB, RootFreeDiskMB: s.LowDiskSpaceThresholdMB, } manifestURLHeader := make(http.Header) if s.ManifestURLHeader != "" { pieces := strings.Split(s.ManifestURLHeader, ":") if len(pieces) != 2 { return nil, fmt.Errorf("manifest-url-header must have a single ':' key-value separator, got %q", s.ManifestURLHeader) } manifestURLHeader.Set(pieces[0], pieces[1]) } reservation, err := parseReservation(s.KubeReserved, s.SystemReserved) if err != nil { return nil, err } return &KubeletConfig{ Address: s.Address, AllowPrivileged: s.AllowPrivileged, Auth: nil, // default does not enforce auth[nz] CAdvisorInterface: nil, // launches background processes, not set here CgroupRoot: s.CgroupRoot, Cloud: nil, // cloud provider might start background processes ClusterDNS: s.ClusterDNS, ClusterDomain: s.ClusterDomain, ConfigFile: s.Config, ConfigureCBR0: s.ConfigureCBR0, ContainerManager: nil, ContainerRuntime: s.ContainerRuntime, CPUCFSQuota: s.CPUCFSQuota, DiskSpacePolicy: diskSpacePolicy, DockerClient: dockertools.ConnectToDockerOrDie(s.DockerEndpoint), DockerDaemonContainer: s.DockerDaemonContainer, DockerExecHandler: dockerExecHandler, EnableDebuggingHandlers: s.EnableDebuggingHandlers, EnableServer: s.EnableServer, EventBurst: s.EventBurst, EventRecordQPS: s.EventRecordQPS, FileCheckFrequency: s.FileCheckFrequency, HostnameOverride: s.HostnameOverride, HostNetworkSources: hostNetworkSources, HostPIDSources: hostPIDSources, HostIPCSources: hostIPCSources, HTTPCheckFrequency: s.HTTPCheckFrequency, ImageGCPolicy: imageGCPolicy, KubeClient: nil, ManifestURL: s.ManifestURL, ManifestURLHeader: manifestURLHeader, MasterServiceNamespace: s.MasterServiceNamespace, MaxContainerCount: s.MaxContainerCount, MaxOpenFiles: s.MaxOpenFiles, MaxPerPodContainerCount: s.MaxPerPodContainerCount, MaxPods: s.MaxPods, MinimumGCAge: s.MinimumGCAge, Mounter: mounter, ChownRunner: chownRunner, ChmodRunner: chmodRunner, NetworkPluginName: s.NetworkPluginName, NetworkPlugins: ProbeNetworkPlugins(s.NetworkPluginDir), NodeLabels: s.NodeLabels, NodeStatusUpdateFrequency: s.NodeStatusUpdateFrequency, OOMAdjuster: oom.NewOOMAdjuster(), OSInterface: kubecontainer.RealOS{}, PodCIDR: s.PodCIDR, ReconcileCIDR: s.ReconcileCIDR, PodInfraContainerImage: s.PodInfraContainerImage, Port: s.Port, ReadOnlyPort: s.ReadOnlyPort, RegisterNode: s.RegisterNode, RegisterSchedulable: s.RegisterSchedulable, RegistryBurst: s.RegistryBurst, RegistryPullQPS: s.RegistryPullQPS, ResolverConfig: s.ResolverConfig, Reservation: *reservation, ResourceContainer: s.ResourceContainer, RktPath: s.RktPath, RktStage1Image: s.RktStage1Image, RootDirectory: s.RootDirectory, Runonce: s.RunOnce, SerializeImagePulls: s.SerializeImagePulls, StandaloneMode: (len(s.APIServerList) == 0), StreamingConnectionIdleTimeout: s.StreamingConnectionIdleTimeout, SyncFrequency: s.SyncFrequency, SystemContainer: s.SystemContainer, TLSOptions: tlsOptions, Writer: writer, VolumePlugins: ProbeVolumePlugins(s.VolumePluginDir), OutOfDiskTransitionFrequency: s.OutOfDiskTransitionFrequency, ExperimentalFlannelOverlay: s.ExperimentalFlannelOverlay, NodeIP: s.NodeIP, }, nil }