Merge pull request #5619 from vmarmol/rate

Spread out pod status updates to apiserver.
This commit is contained in:
Dawn Chen 2015-03-18 17:26:02 -07:00
commit 52e1ee9d5b
2 changed files with 66 additions and 35 deletions

View File

@ -51,6 +51,7 @@ type KubeletServer struct {
FileCheckFrequency time.Duration FileCheckFrequency time.Duration
HTTPCheckFrequency time.Duration HTTPCheckFrequency time.Duration
StatusUpdateFrequency time.Duration StatusUpdateFrequency time.Duration
PodStatusUpdateFrequency time.Duration
ManifestURL string ManifestURL string
EnableServer bool EnableServer bool
Address util.IP Address util.IP
@ -83,13 +84,14 @@ type KubeletServer struct {
// NewKubeletServer will create a new KubeletServer with default values. // NewKubeletServer will create a new KubeletServer with default values.
func NewKubeletServer() *KubeletServer { func NewKubeletServer() *KubeletServer {
return &KubeletServer{ return &KubeletServer{
SyncFrequency: 10 * time.Second, SyncFrequency: 10 * time.Second,
FileCheckFrequency: 20 * time.Second, FileCheckFrequency: 20 * time.Second,
HTTPCheckFrequency: 20 * time.Second, HTTPCheckFrequency: 20 * time.Second,
StatusUpdateFrequency: 20 * time.Second, StatusUpdateFrequency: 20 * time.Second,
EnableServer: true, PodStatusUpdateFrequency: 2 * time.Minute,
Address: util.IP(net.ParseIP("127.0.0.1")), EnableServer: true,
Port: ports.KubeletPort, Address: util.IP(net.ParseIP("127.0.0.1")),
Port: ports.KubeletPort,
PodInfraContainerImage: kubelet.PodInfraContainerImage, PodInfraContainerImage: kubelet.PodInfraContainerImage,
RootDirectory: defaultRootDir, RootDirectory: defaultRootDir,
RegistryBurst: 10, RegistryBurst: 10,
@ -110,6 +112,7 @@ func (s *KubeletServer) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.Config, "config", s.Config, "Path to the config file or directory of files") fs.StringVar(&s.Config, "config", s.Config, "Path to the config file or directory of files")
fs.DurationVar(&s.SyncFrequency, "sync_frequency", s.SyncFrequency, "Max period between synchronizing running containers and config") fs.DurationVar(&s.SyncFrequency, "sync_frequency", s.SyncFrequency, "Max period between synchronizing running containers and config")
fs.DurationVar(&s.StatusUpdateFrequency, "status_update_frequency", s.StatusUpdateFrequency, "Duration between posting node status to master") fs.DurationVar(&s.StatusUpdateFrequency, "status_update_frequency", s.StatusUpdateFrequency, "Duration between posting node status to master")
fs.DurationVar(&s.PodStatusUpdateFrequency, "pod_status_update_frequency", s.PodStatusUpdateFrequency, "Duration between posting pod status updates to the master")
fs.DurationVar(&s.FileCheckFrequency, "file_check_frequency", s.FileCheckFrequency, "Duration between checking config files for new data") fs.DurationVar(&s.FileCheckFrequency, "file_check_frequency", s.FileCheckFrequency, "Duration between checking config files for new data")
fs.DurationVar(&s.HTTPCheckFrequency, "http_check_frequency", s.HTTPCheckFrequency, "Duration between checking http for new data") fs.DurationVar(&s.HTTPCheckFrequency, "http_check_frequency", s.HTTPCheckFrequency, "Duration between checking http for new data")
fs.StringVar(&s.ManifestURL, "manifest_url", s.ManifestURL, "URL for accessing the container manifest") fs.StringVar(&s.ManifestURL, "manifest_url", s.ManifestURL, "URL for accessing the container manifest")
@ -176,6 +179,7 @@ func (s *KubeletServer) Run(_ []string) error {
ConfigFile: s.Config, ConfigFile: s.Config,
ManifestURL: s.ManifestURL, ManifestURL: s.ManifestURL,
StatusUpdateFrequency: s.StatusUpdateFrequency, StatusUpdateFrequency: s.StatusUpdateFrequency,
PodStatusUpdateFrequency: s.PodStatusUpdateFrequency,
FileCheckFrequency: s.FileCheckFrequency, FileCheckFrequency: s.FileCheckFrequency,
HTTPCheckFrequency: s.HTTPCheckFrequency, HTTPCheckFrequency: s.HTTPCheckFrequency,
PodInfraContainerImage: s.PodInfraContainerImage, PodInfraContainerImage: s.PodInfraContainerImage,
@ -273,21 +277,22 @@ func SimpleRunKubelet(client *client.Client,
RootDirectory: rootDir, RootDirectory: rootDir,
ManifestURL: manifestURL, ManifestURL: manifestURL,
PodInfraContainerImage: kubelet.PodInfraContainerImage, PodInfraContainerImage: kubelet.PodInfraContainerImage,
Port: port, Port: port,
Address: util.IP(net.ParseIP(address)), Address: util.IP(net.ParseIP(address)),
EnableServer: true, EnableServer: true,
EnableDebuggingHandlers: true, EnableDebuggingHandlers: true,
StatusUpdateFrequency: 3 * time.Second, StatusUpdateFrequency: 3 * time.Second,
SyncFrequency: 3 * time.Second, PodStatusUpdateFrequency: 2 * time.Minute,
MinimumGCAge: 10 * time.Second, SyncFrequency: 3 * time.Second,
MaxPerPodContainerCount: 5, MinimumGCAge: 10 * time.Second,
MaxContainerCount: 100, MaxPerPodContainerCount: 5,
MasterServiceNamespace: masterServiceNamespace, MaxContainerCount: 100,
VolumePlugins: volumePlugins, MasterServiceNamespace: masterServiceNamespace,
TLSOptions: tlsOptions, VolumePlugins: volumePlugins,
CadvisorInterface: cadvisorInterface, TLSOptions: tlsOptions,
ConfigFile: configFilePath, CadvisorInterface: cadvisorInterface,
ImageGCPolicy: imageGCPolicy, ConfigFile: configFilePath,
ImageGCPolicy: imageGCPolicy,
} }
RunKubelet(&kcfg) RunKubelet(&kcfg)
} }
@ -373,6 +378,7 @@ type KubeletConfig struct {
ConfigFile string ConfigFile string
ManifestURL string ManifestURL string
StatusUpdateFrequency time.Duration StatusUpdateFrequency time.Duration
PodStatusUpdateFrequency time.Duration
FileCheckFrequency time.Duration FileCheckFrequency time.Duration
HTTPCheckFrequency time.Duration HTTPCheckFrequency time.Duration
Hostname string Hostname string
@ -435,6 +441,7 @@ func createAndInitKubelet(kc *KubeletConfig, pc *config.PodConfig) (*kubelet.Kub
kc.Recorder, kc.Recorder,
kc.CadvisorInterface, kc.CadvisorInterface,
kc.StatusUpdateFrequency, kc.StatusUpdateFrequency,
kc.PodStatusUpdateFrequency,
kc.ImageGCPolicy) kc.ImageGCPolicy)
if err != nil { if err != nil {

View File

@ -122,6 +122,7 @@ func NewMainKubelet(
recorder record.EventRecorder, recorder record.EventRecorder,
cadvisorInterface cadvisor.Interface, cadvisorInterface cadvisor.Interface,
statusUpdateFrequency time.Duration, statusUpdateFrequency time.Duration,
podStatusUpdateFrequency time.Duration,
imageGCPolicy ImageGCPolicy) (*Kubelet, error) { imageGCPolicy ImageGCPolicy) (*Kubelet, error) {
if rootDirectory == "" { if rootDirectory == "" {
return nil, fmt.Errorf("invalid root directory %q", rootDirectory) return nil, fmt.Errorf("invalid root directory %q", rootDirectory)
@ -129,6 +130,9 @@ func NewMainKubelet(
if resyncInterval <= 0 { if resyncInterval <= 0 {
return nil, fmt.Errorf("invalid sync frequency %d", resyncInterval) return nil, fmt.Errorf("invalid sync frequency %d", resyncInterval)
} }
if podStatusUpdateFrequency <= 0 {
return nil, fmt.Errorf("invalid status update frequency %d", podStatusUpdateFrequency)
}
dockerClient = metrics.NewInstrumentedDockerInterface(dockerClient) dockerClient = metrics.NewInstrumentedDockerInterface(dockerClient)
// Wait for the Docker daemon to be up (with a timeout). // Wait for the Docker daemon to be up (with a timeout).
@ -179,6 +183,7 @@ func NewMainKubelet(
rootDirectory: rootDirectory, rootDirectory: rootDirectory,
statusUpdateFrequency: statusUpdateFrequency, statusUpdateFrequency: statusUpdateFrequency,
resyncInterval: resyncInterval, resyncInterval: resyncInterval,
podStatusUpdateFrequency: podStatusUpdateFrequency,
podInfraContainerImage: podInfraContainerImage, podInfraContainerImage: podInfraContainerImage,
containerIDToRef: map[string]*api.ObjectReference{}, containerIDToRef: map[string]*api.ObjectReference{},
runner: dockertools.NewDockerContainerCommandRunner(dockerClient), runner: dockertools.NewDockerContainerCommandRunner(dockerClient),
@ -232,16 +237,17 @@ type serviceLister interface {
// Kubelet is the main kubelet implementation. // Kubelet is the main kubelet implementation.
type Kubelet struct { type Kubelet struct {
hostname string hostname string
dockerClient dockertools.DockerInterface dockerClient dockertools.DockerInterface
dockerCache dockertools.DockerCache dockerCache dockertools.DockerCache
kubeClient client.Interface kubeClient client.Interface
rootDirectory string rootDirectory string
podInfraContainerImage string podInfraContainerImage string
podWorkers *podWorkers podWorkers *podWorkers
statusUpdateFrequency time.Duration statusUpdateFrequency time.Duration
resyncInterval time.Duration resyncInterval time.Duration
sourcesReady SourcesReadyFn podStatusUpdateFrequency time.Duration
sourcesReady SourcesReadyFn
// Protects the pods array // Protects the pods array
// We make complete array copies out of this while locked, which is OK because once added to this array, // We make complete array copies out of this while locked, which is OK because once added to this array,
@ -507,7 +513,11 @@ func (kl *Kubelet) Run(updates <-chan PodUpdate) {
glog.Warning("No api server defined - no node status update will be sent.") glog.Warning("No api server defined - no node status update will be sent.")
} }
go kl.syncNodeStatus() go kl.syncNodeStatus()
go util.Forever(kl.syncStatus, kl.resyncInterval)
// syncStatus handles its own frequency and throttling, run it always.
go util.Forever(func() {
kl.syncStatus(kl.podStatusUpdateFrequency)
}, 0)
kl.syncLoop(updates, kl) kl.syncLoop(updates, kl)
} }
@ -1673,12 +1683,25 @@ func (kl *Kubelet) syncLoop(updates <-chan PodUpdate, handler SyncHandler) {
} }
} }
// syncStatus syncs pods statuses with the apiserver. // syncStatus syncs pods statuses with the apiserver. Spread the updates over the specified deadline.
func (kl *Kubelet) syncStatus() { func (kl *Kubelet) syncStatus(deadline time.Duration) {
start := time.Now()
glog.V(3).Infof("Syncing pods status") glog.V(3).Infof("Syncing pods status")
pods, _ := kl.GetPods() pods, _ := kl.GetPods()
if len(pods) == 0 {
// No pods, sleep the rest of our deadline.
time.Sleep(deadline - time.Since(start))
return
}
// TODO(vmarmol): Enhance util.RateLimiter for our use here.
singleDeadline := time.Duration(deadline.Nanoseconds() / int64(len(pods)))
t := time.NewTicker(singleDeadline)
for _, pod := range pods { for _, pod := range pods {
// Don't hit the api server too hard, wait for the next time slot.
<-t.C
status, err := kl.GetPodStatus(GetPodFullName(&pod), pod.UID) status, err := kl.GetPodStatus(GetPodFullName(&pod), pod.UID)
if err != nil { if err != nil {
glog.Warningf("Error getting pod %q status: %v, retry later", pod.Name, err) glog.Warningf("Error getting pod %q status: %v, retry later", pod.Name, err)
@ -1691,6 +1714,7 @@ func (kl *Kubelet) syncStatus() {
glog.V(3).Infof("Status for pod %q updated successfully: %s", pod.Name, pod) glog.V(3).Infof("Status for pod %q updated successfully: %s", pod.Name, pod)
} }
} }
t.Stop()
} }
// Update the Kubelet's internal pods with those provided by the update. // Update the Kubelet's internal pods with those provided by the update.