diff --git a/pkg/kubelet/container/fake_runtime.go b/pkg/kubelet/container/fake_runtime.go index ac10dbebd7..a684b3ad29 100644 --- a/pkg/kubelet/container/fake_runtime.go +++ b/pkg/kubelet/container/fake_runtime.go @@ -43,6 +43,7 @@ type FakeRuntime struct { StartedContainers []string KilledContainers []string VersionInfo string + APIVersionInfo string RuntimeType string Err error InspectErr error @@ -154,6 +155,14 @@ func (f *FakeRuntime) Version() (Version, error) { return &FakeVersion{Version: f.VersionInfo}, f.Err } +func (f *FakeRuntime) APIVersion() (Version, error) { + f.Lock() + defer f.Unlock() + + f.CalledFunctions = append(f.CalledFunctions, "APIVersion") + return &FakeVersion{Version: f.APIVersionInfo}, f.Err +} + func (f *FakeRuntime) GetPods(all bool) ([]*Pod, error) { f.Lock() defer f.Unlock() diff --git a/pkg/kubelet/container/runtime.go b/pkg/kubelet/container/runtime.go index ec215654d1..4ae4c0dfb3 100644 --- a/pkg/kubelet/container/runtime.go +++ b/pkg/kubelet/container/runtime.go @@ -82,6 +82,9 @@ type Runtime interface { // Version returns the version information of the container runtime. Version() (Version, error) + // APIVersion returns the API version information of the container + // runtime. This may be different from the runtime engine's version. + APIVersion() (Version, error) // GetPods returns a list containers group by pods. The boolean parameter // specifies whether the runtime returns all containers including those already // exited and dead containers (used for garbage collection). diff --git a/pkg/kubelet/container/runtime_mock.go b/pkg/kubelet/container/runtime_mock.go index 1cc9298b16..fd5ddad88d 100644 --- a/pkg/kubelet/container/runtime_mock.go +++ b/pkg/kubelet/container/runtime_mock.go @@ -47,6 +47,11 @@ func (r *Mock) Version() (Version, error) { return args.Get(0).(Version), args.Error(1) } +func (r *Mock) APIVersion() (Version, error) { + args := r.Called() + return args.Get(0).(Version), args.Error(1) +} + func (r *Mock) GetPods(all bool) ([]*Pod, error) { args := r.Called(all) return args.Get(0).([]*Pod), args.Error(1) diff --git a/pkg/kubelet/dockertools/docker_test.go b/pkg/kubelet/dockertools/docker_test.go index 6249038d25..569e40ac43 100644 --- a/pkg/kubelet/dockertools/docker_test.go +++ b/pkg/kubelet/dockertools/docker_test.go @@ -160,7 +160,16 @@ func TestVersion(t *testing.T) { if err != nil { t.Errorf("got error while getting docker server version - %s", err) } - expectedVersion, _ := docker.NewAPIVersion("1.15") + expectedVersion, _ := docker.NewAPIVersion("1.1.3") + if e, a := expectedVersion.String(), version.String(); e != a { + t.Errorf("invalid docker server version. expected: %v, got: %v", e, a) + } + + version, err = manager.APIVersion() + if err != nil { + t.Errorf("got error while getting docker server version - %s", err) + } + expectedVersion, _ = docker.NewAPIVersion("1.15") if e, a := expectedVersion.String(), version.String(); e != a { t.Errorf("invalid docker server version. expected: %v, got: %v", e, a) } diff --git a/pkg/kubelet/dockertools/manager.go b/pkg/kubelet/dockertools/manager.go index 2f64966ed7..45c8af8682 100644 --- a/pkg/kubelet/dockertools/manager.go +++ b/pkg/kubelet/dockertools/manager.go @@ -980,11 +980,26 @@ func (dm *DockerManager) Version() (kubecontainer.Version, error) { return nil, fmt.Errorf("docker: failed to get docker version: %v", err) } + engineVersion := env.Get("Version") + version, err := docker.NewAPIVersion(engineVersion) + if err != nil { + glog.Errorf("docker: failed to parse docker server version %q: %v", engineVersion, err) + return nil, fmt.Errorf("docker: failed to parse docker server version %q: %v", engineVersion, err) + } + return dockerVersion(version), nil +} + +func (dm *DockerManager) APIVersion() (kubecontainer.Version, error) { + env, err := dm.client.Version() + if err != nil { + return nil, fmt.Errorf("docker: failed to get docker version: %v", err) + } + apiVersion := env.Get("ApiVersion") version, err := docker.NewAPIVersion(apiVersion) if err != nil { - glog.Errorf("docker: failed to parse docker server version %q: %v", apiVersion, err) - return nil, fmt.Errorf("docker: failed to parse docker server version %q: %v", apiVersion, err) + glog.Errorf("docker: failed to parse docker api version %q: %v", apiVersion, err) + return nil, fmt.Errorf("docker: failed to parse docker api version %q: %v", apiVersion, err) } return dockerVersion(version), nil } @@ -993,7 +1008,7 @@ func (dm *DockerManager) Version() (kubecontainer.Version, error) { var dockerAPIVersionWithExec = "1.15" func (dm *DockerManager) nativeExecSupportExists() (bool, error) { - version, err := dm.Version() + version, err := dm.APIVersion() if err != nil { return false, err } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index d5bbf795b3..dc8a659e8f 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -2438,14 +2438,6 @@ func (kl *Kubelet) LatestLoopEntryTime() time.Time { return val.(time.Time) } -// Returns the container runtime version for this Kubelet. -func (kl *Kubelet) GetContainerRuntimeVersion() (kubecontainer.Version, error) { - if kl.containerRuntime == nil { - return nil, fmt.Errorf("no container runtime") - } - return kl.containerRuntime.Version() -} - func (kl *Kubelet) validatePodPhase(podStatus *api.PodStatus) error { switch podStatus.Phase { case api.PodRunning, api.PodSucceeded, api.PodFailed: @@ -2768,8 +2760,13 @@ func (kl *Kubelet) setNodeStatusVersionInfo(node *api.Node) { } else { node.Status.NodeInfo.KernelVersion = verinfo.KernelVersion node.Status.NodeInfo.OSImage = verinfo.ContainerOsVersion - // TODO: Determine the runtime is docker or rocket - node.Status.NodeInfo.ContainerRuntimeVersion = "docker://" + verinfo.DockerVersion + + runtimeVersion := "Unknown" + if runtimeVer, err := kl.containerRuntime.Version(); err == nil { + runtimeVersion = runtimeVer.String() + } + node.Status.NodeInfo.ContainerRuntimeVersion = fmt.Sprintf("%s://%s", kl.containerRuntime.Type(), runtimeVersion) + node.Status.NodeInfo.KubeletVersion = version.Get().String() // TODO: kube-proxy might be different version from kubelet in the future node.Status.NodeInfo.KubeProxyVersion = version.Get().String() @@ -2959,7 +2956,7 @@ func (kl *Kubelet) setNodeStatus(node *api.Node) error { func (kl *Kubelet) isContainerRuntimeVersionCompatible() error { switch kl.GetRuntime().Type() { case "docker": - version, err := kl.GetContainerRuntimeVersion() + version, err := kl.GetRuntime().APIVersion() if err != nil { return nil } diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index fdcb6280b1..0831c6de6f 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -2521,6 +2521,9 @@ func updateDiskSpacePolicy(kubelet *Kubelet, mockCadvisor *cadvisor.Mock, rootCa func TestUpdateNewNodeStatus(t *testing.T) { testKubelet := newTestKubelet(t) kubelet := testKubelet.kubelet + fakeRuntime := testKubelet.fakeRuntime + fakeRuntime.RuntimeType = "docker" + fakeRuntime.VersionInfo = "1.5.0" kubeClient := testKubelet.fakeKubeClient kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ {ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}}, @@ -2538,7 +2541,6 @@ func TestUpdateNewNodeStatus(t *testing.T) { versionInfo := &cadvisorapi.VersionInfo{ KernelVersion: "3.16.0-0.bpo.4-amd64", ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", - DockerVersion: "1.5.0", } mockCadvisor.On("VersionInfo").Return(versionInfo, nil) @@ -2662,7 +2664,6 @@ func TestUpdateNewNodeOutOfDiskStatusWithTransitionFrequency(t *testing.T) { versionInfo := &cadvisorapi.VersionInfo{ KernelVersion: "3.16.0-0.bpo.4-amd64", ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", - DockerVersion: "1.5.0", } mockCadvisor.On("VersionInfo").Return(versionInfo, nil) @@ -2724,7 +2725,8 @@ func testDockerRuntimeVersion(t *testing.T) { kubelet := testKubelet.kubelet fakeRuntime := testKubelet.fakeRuntime fakeRuntime.RuntimeType = "docker" - fakeRuntime.VersionInfo = "1.18" + fakeRuntime.VersionInfo = "1.5.0" + fakeRuntime.APIVersionInfo = "1.18" kubeClient := testKubelet.fakeKubeClient kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ {ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}}, @@ -2741,7 +2743,6 @@ func testDockerRuntimeVersion(t *testing.T) { versionInfo := &cadvisorapi.VersionInfo{ KernelVersion: "3.16.0-0.bpo.4-amd64", ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", - DockerVersion: "1.5.0", } mockCadvisor.On("VersionInfo").Return(versionInfo, nil) @@ -2866,6 +2867,9 @@ func testDockerRuntimeVersion(t *testing.T) { func TestUpdateExistingNodeStatus(t *testing.T) { testKubelet := newTestKubelet(t) kubelet := testKubelet.kubelet + fakeRuntime := testKubelet.fakeRuntime + fakeRuntime.RuntimeType = "docker" + fakeRuntime.VersionInfo = "1.5.0" kubeClient := testKubelet.fakeKubeClient kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ { @@ -2916,7 +2920,6 @@ func TestUpdateExistingNodeStatus(t *testing.T) { versionInfo := &cadvisorapi.VersionInfo{ KernelVersion: "3.16.0-0.bpo.4-amd64", ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", - DockerVersion: "1.5.0", } mockCadvisor.On("VersionInfo").Return(versionInfo, nil) @@ -3179,10 +3182,8 @@ func TestUpdateNodeStatusWithoutContainerRuntime(t *testing.T) { kubelet := testKubelet.kubelet kubeClient := testKubelet.fakeKubeClient fakeRuntime := testKubelet.fakeRuntime - // This causes returning an error from GetContainerRuntimeVersion() which - // simulates that container runtime is down. - fakeRuntime.VersionInfo = "" - + fakeRuntime.RuntimeType = "docker" + fakeRuntime.VersionInfo = "1.5.0" kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{ {ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}}, }}).ReactionChain @@ -3199,7 +3200,6 @@ func TestUpdateNodeStatusWithoutContainerRuntime(t *testing.T) { versionInfo := &cadvisorapi.VersionInfo{ KernelVersion: "3.16.0-0.bpo.4-amd64", ContainerOsVersion: "Debian GNU/Linux 7 (wheezy)", - DockerVersion: "1.5.0", } mockCadvisor.On("VersionInfo").Return(versionInfo, nil) diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index c2859f9373..b9e149ce09 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -971,6 +971,10 @@ func (r *Runtime) Version() (kubecontainer.Version, error) { return r.binVersion, nil } +func (r *Runtime) APIVersion() (kubecontainer.Version, error) { + return r.binVersion, nil +} + // SyncPod syncs the running pod to match the specified desired pod. func (r *Runtime) SyncPod(pod *api.Pod, podStatus api.PodStatus, internalPodStatus *kubecontainer.PodStatus, pullSecrets []api.Secret, backOff *util.Backoff) error { // TODO: (random-liu) Stop using running pod in SyncPod()