diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 85bc808dc9c..dc6b9d82ee8 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -236,6 +236,7 @@ func NewMainKubelet( resourceContainer: resourceContainer, os: osInterface, oomWatcher: oomWatcher, + runtimeHooks: newKubeletRuntimeHooks(recorder), } if plug, err := network.InitNetworkPlugin(networkPlugins, networkPluginName, &networkHost{klet}); err != nil { @@ -403,8 +404,14 @@ type Kubelet struct { // Name must be absolute. resourceContainer string - os kubecontainer.OSInterface + os kubecontainer.OSInterface + + // Watcher of out of memory events. oomWatcher OOMWatcher + + // TODO(vmarmol): Remove this when we only have to inject the hooks into the runtimes. + // Hooks injected into the container runtime. + runtimeHooks kubecontainer.RuntimeHooks } // getRootDir returns the full path to the directory under which kubelet can @@ -868,41 +875,25 @@ func parseResolvConf(reader io.Reader) (nameservers []string, searches []string, // Pull the image for the specified pod and container. func (kl *Kubelet) pullImage(pod *api.Pod, container *api.Container) error { - if container.ImagePullPolicy == api.PullNever { - return nil - } - - start := time.Now() - defer func() { - metrics.ImagePullLatency.Observe(metrics.SinceInMicroseconds(start)) - }() - - ref, err := kubecontainer.GenerateContainerRef(pod, container) - if err != nil { - glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err) - } present, err := kl.containerManager.IsImagePresent(container.Image) if err != nil { + ref, err := kubecontainer.GenerateContainerRef(pod, container) + if err != nil { + glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err) + } if ref != nil { kl.recorder.Eventf(ref, "failed", "Failed to inspect image %q: %v", container.Image, err) } return fmt.Errorf("failed to inspect image %q: %v", container.Image, err) } - if container.ImagePullPolicy == api.PullAlways || - (container.ImagePullPolicy == api.PullIfNotPresent && (!present)) { - if err := kl.containerManager.Pull(container.Image); err != nil { - if ref != nil { - kl.recorder.Eventf(ref, "failed", "Failed to pull image %q: %v", container.Image, err) - } - return err - } - if ref != nil { - kl.recorder.Eventf(ref, "pulled", "Successfully pulled image %q", container.Image) - } + if !kl.runtimeHooks.ShouldPullImage(pod, container, present) { + return nil } - return nil + err = kl.containerManager.Pull(container.Image) + kl.runtimeHooks.ReportImagePull(pod, container, err) + return err } // Kill all running containers in a pod (includes the pod infra container). diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index a04981cf796..442eb543400 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -123,6 +123,7 @@ func newTestKubelet(t *testing.T) *TestKubelet { kubelet.containerManager.Prober = kubelet.prober kubelet.handlerRunner = newHandlerRunner(&fakeHTTP{}, &fakeContainerCommandRunner{}, kubelet.containerManager) kubelet.volumeManager = newVolumeManager() + kubelet.runtimeHooks = newKubeletRuntimeHooks(kubelet.recorder) return &TestKubelet{kubelet, fakeDocker, mockCadvisor, fakeKubeClient, waitGroup, fakeMirrorClient} } diff --git a/pkg/kubelet/runonce_test.go b/pkg/kubelet/runonce_test.go index 6bcb39bb80d..c0d1084a380 100644 --- a/pkg/kubelet/runonce_test.go +++ b/pkg/kubelet/runonce_test.go @@ -90,6 +90,7 @@ func TestRunOnce(t *testing.T) { os: kubecontainer.FakeOS{}, volumeManager: newVolumeManager(), } + kb.runtimeHooks = newKubeletRuntimeHooks(kb.recorder) kb.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil)) if err := kb.setupDataDirs(); err != nil {