mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-06 10:43:56 +00:00
Merge pull request #20020 from apcera/cleanup-docker-engine-check
kubelet: Update engine version parsing to handle semantic versioning
This commit is contained in:
commit
8e1ca68760
@ -275,7 +275,7 @@ func getDockerClient(dockerEndpoint string) (*docker.Client, error) {
|
|||||||
func ConnectToDockerOrDie(dockerEndpoint string) DockerInterface {
|
func ConnectToDockerOrDie(dockerEndpoint string) DockerInterface {
|
||||||
if dockerEndpoint == "fake://" {
|
if dockerEndpoint == "fake://" {
|
||||||
return &FakeDockerClient{
|
return &FakeDockerClient{
|
||||||
VersionInfo: docker.Env{"ApiVersion=1.18"},
|
VersionInfo: docker.Env{"ApiVersion=1.18", "Version=1.6.0"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client, err := getDockerClient(dockerEndpoint)
|
client, err := getDockerClient(dockerEndpoint)
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/coreos/go-semver/semver"
|
||||||
docker "github.com/fsouza/go-dockerclient"
|
docker "github.com/fsouza/go-dockerclient"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/golang/groupcache/lru"
|
"github.com/golang/groupcache/lru"
|
||||||
@ -945,18 +946,47 @@ func (dm *DockerManager) podInfraContainerChanged(pod *api.Pod, podInfraContaine
|
|||||||
return podInfraContainerStatus.Hash != kubecontainer.HashContainer(expectedPodInfraContainer), nil
|
return podInfraContainerStatus.Hash != kubecontainer.HashContainer(expectedPodInfraContainer), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerVersion docker.APIVersion
|
// dockerVersion implementes kubecontainer.Version interface by implementing
|
||||||
|
// Compare() and String() (which is implemented by the underlying semver.Version)
|
||||||
func NewVersion(input string) (dockerVersion, error) {
|
// TODO: this code is the same as rktVersion and may make sense to be moved to
|
||||||
version, err := docker.NewAPIVersion(input)
|
// somewhere shared.
|
||||||
return dockerVersion(version), err
|
type dockerVersion struct {
|
||||||
|
*semver.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dv dockerVersion) String() string {
|
func newDockerVersion(version string) (dockerVersion, error) {
|
||||||
|
sem, err := semver.NewVersion(version)
|
||||||
|
if err != nil {
|
||||||
|
return dockerVersion{}, err
|
||||||
|
}
|
||||||
|
return dockerVersion{sem}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r dockerVersion) Compare(other string) (int, error) {
|
||||||
|
v, err := semver.NewVersion(other)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.LessThan(*v) {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
if v.LessThan(*r.Version) {
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dockerVersion implementes kubecontainer.Version interface by implementing
|
||||||
|
// Compare() and String() on top og go-dockerclient's APIVersion. This version
|
||||||
|
// string doesn't conform to semantic versioning, as it is only "x.y"
|
||||||
|
type dockerAPIVersion docker.APIVersion
|
||||||
|
|
||||||
|
func (dv dockerAPIVersion) String() string {
|
||||||
return docker.APIVersion(dv).String()
|
return docker.APIVersion(dv).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dv dockerVersion) Compare(other string) (int, error) {
|
func (dv dockerAPIVersion) Compare(other string) (int, error) {
|
||||||
a := docker.APIVersion(dv)
|
a := docker.APIVersion(dv)
|
||||||
b, err := docker.NewAPIVersion(other)
|
b, err := docker.NewAPIVersion(other)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -982,12 +1012,12 @@ func (dm *DockerManager) Version() (kubecontainer.Version, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
engineVersion := env.Get("Version")
|
engineVersion := env.Get("Version")
|
||||||
version, err := docker.NewAPIVersion(engineVersion)
|
version, err := newDockerVersion(engineVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorf("docker: failed to parse docker server version %q: %v", engineVersion, err)
|
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 nil, fmt.Errorf("docker: failed to parse docker server version %q: %v", engineVersion, err)
|
||||||
}
|
}
|
||||||
return dockerVersion(version), nil
|
return version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dm *DockerManager) APIVersion() (kubecontainer.Version, error) {
|
func (dm *DockerManager) APIVersion() (kubecontainer.Version, error) {
|
||||||
@ -1002,7 +1032,7 @@ func (dm *DockerManager) APIVersion() (kubecontainer.Version, error) {
|
|||||||
glog.Errorf("docker: failed to parse docker api 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 nil, fmt.Errorf("docker: failed to parse docker api version %q: %v", apiVersion, err)
|
||||||
}
|
}
|
||||||
return dockerVersion(version), nil
|
return dockerAPIVersion(version), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first version of docker that supports exec natively is 1.3.0 == API 1.15
|
// The first version of docker that supports exec natively is 1.3.0 == API 1.15
|
||||||
|
@ -2719,26 +2719,59 @@ func TestUpdateNewNodeOutOfDiskStatusWithTransitionFrequency(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Enable me..
|
func TestDockerRuntimeVersion(t *testing.T) {
|
||||||
func testDockerRuntimeVersion(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
testKubelet := newTestKubelet(t)
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
fakeRuntime := testKubelet.fakeRuntime
|
fakeRuntime := testKubelet.fakeRuntime
|
||||||
fakeRuntime.RuntimeType = "docker"
|
fakeRuntime.RuntimeType = "docker"
|
||||||
fakeRuntime.VersionInfo = "1.5.0"
|
fakeRuntime.VersionInfo = "1.10.0-rc1-fc24"
|
||||||
fakeRuntime.APIVersionInfo = "1.18"
|
fakeRuntime.APIVersionInfo = "1.22"
|
||||||
kubeClient := testKubelet.fakeKubeClient
|
kubeClient := testKubelet.fakeKubeClient
|
||||||
kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{
|
kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{
|
||||||
{ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}},
|
{
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: testKubeletHostname},
|
||||||
|
Spec: api.NodeSpec{},
|
||||||
|
Status: api.NodeStatus{
|
||||||
|
Conditions: []api.NodeCondition{
|
||||||
|
{
|
||||||
|
Type: api.NodeOutOfDisk,
|
||||||
|
Status: api.ConditionFalse,
|
||||||
|
Reason: "KubeletHasSufficientDisk",
|
||||||
|
Message: fmt.Sprintf("kubelet has sufficient disk space available"),
|
||||||
|
LastHeartbeatTime: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
LastTransitionTime: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: api.NodeReady,
|
||||||
|
Status: api.ConditionTrue,
|
||||||
|
Reason: "KubeletReady",
|
||||||
|
Message: fmt.Sprintf("kubelet is posting ready status"),
|
||||||
|
LastHeartbeatTime: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
LastTransitionTime: unversioned.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Capacity: api.ResourceList{
|
||||||
|
api.ResourceCPU: *resource.NewMilliQuantity(3000, resource.DecimalSI),
|
||||||
|
api.ResourceMemory: *resource.NewQuantity(20E9, resource.BinarySI),
|
||||||
|
api.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
Allocatable: api.ResourceList{
|
||||||
|
api.ResourceCPU: *resource.NewMilliQuantity(2800, resource.DecimalSI),
|
||||||
|
api.ResourceMemory: *resource.NewQuantity(19900E6, resource.BinarySI),
|
||||||
|
api.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}}).ReactionChain
|
}}).ReactionChain
|
||||||
|
mockCadvisor := testKubelet.fakeCadvisor
|
||||||
|
mockCadvisor.On("Start").Return(nil)
|
||||||
machineInfo := &cadvisorapi.MachineInfo{
|
machineInfo := &cadvisorapi.MachineInfo{
|
||||||
MachineID: "123",
|
MachineID: "123",
|
||||||
SystemUUID: "abc",
|
SystemUUID: "abc",
|
||||||
BootID: "1b3",
|
BootID: "1b3",
|
||||||
NumCores: 2,
|
NumCores: 2,
|
||||||
MemoryCapacity: 1024,
|
MemoryCapacity: 20E9,
|
||||||
}
|
}
|
||||||
mockCadvisor := testKubelet.fakeCadvisor
|
|
||||||
mockCadvisor.On("MachineInfo").Return(machineInfo, nil)
|
mockCadvisor.On("MachineInfo").Return(machineInfo, nil)
|
||||||
versionInfo := &cadvisorapi.VersionInfo{
|
versionInfo := &cadvisorapi.VersionInfo{
|
||||||
KernelVersion: "3.16.0-0.bpo.4-amd64",
|
KernelVersion: "3.16.0-0.bpo.4-amd64",
|
||||||
@ -2779,13 +2812,18 @@ func testDockerRuntimeVersion(t *testing.T) {
|
|||||||
BootID: "1b3",
|
BootID: "1b3",
|
||||||
KernelVersion: "3.16.0-0.bpo.4-amd64",
|
KernelVersion: "3.16.0-0.bpo.4-amd64",
|
||||||
OSImage: "Debian GNU/Linux 7 (wheezy)",
|
OSImage: "Debian GNU/Linux 7 (wheezy)",
|
||||||
ContainerRuntimeVersion: "docker://1.5.0",
|
ContainerRuntimeVersion: "docker://1.10.0-rc1-fc24",
|
||||||
KubeletVersion: version.Get().String(),
|
KubeletVersion: version.Get().String(),
|
||||||
KubeProxyVersion: version.Get().String(),
|
KubeProxyVersion: version.Get().String(),
|
||||||
},
|
},
|
||||||
Capacity: api.ResourceList{
|
Capacity: api.ResourceList{
|
||||||
api.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI),
|
api.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI),
|
||||||
api.ResourceMemory: *resource.NewQuantity(1024, resource.BinarySI),
|
api.ResourceMemory: *resource.NewQuantity(20E9, resource.BinarySI),
|
||||||
|
api.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI),
|
||||||
|
},
|
||||||
|
Allocatable: api.ResourceList{
|
||||||
|
api.ResourceCPU: *resource.NewMilliQuantity(1800, resource.DecimalSI),
|
||||||
|
api.ResourceMemory: *resource.NewQuantity(19900E6, resource.BinarySI),
|
||||||
api.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI),
|
api.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI),
|
||||||
},
|
},
|
||||||
Addresses: []api.NodeAddress{
|
Addresses: []api.NodeAddress{
|
||||||
@ -2805,6 +2843,7 @@ func testDockerRuntimeVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kubelet.runtimeState = newRuntimeState(maxWaitForContainerRuntime, false, "", kubelet.isContainerRuntimeVersionCompatible)
|
||||||
kubelet.updateRuntimeUp()
|
kubelet.updateRuntimeUp()
|
||||||
if err := kubelet.updateNodeStatus(); err != nil {
|
if err := kubelet.updateNodeStatus(); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
@ -2836,13 +2875,14 @@ func testDockerRuntimeVersion(t *testing.T) {
|
|||||||
t.Errorf("unexpected node condition order. NodeReady should be last.")
|
t.Errorf("unexpected node condition order. NodeReady should be last.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(expectedNode, updatedNode) {
|
if !api.Semantic.DeepEqual(expectedNode, updatedNode) {
|
||||||
t.Errorf("unexpected objects: %s", util.ObjectDiff(expectedNode, updatedNode))
|
t.Errorf("expected \n%v\n, got \n%v", expectedNode, updatedNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Downgrade docker version, node should be NotReady
|
// Downgrade docker version, node should be NotReady
|
||||||
fakeRuntime.RuntimeType = "docker"
|
fakeRuntime.RuntimeType = "docker"
|
||||||
fakeRuntime.VersionInfo = "1.17"
|
fakeRuntime.VersionInfo = "1.5.0"
|
||||||
|
fakeRuntime.APIVersionInfo = "1.17"
|
||||||
kubelet.updateRuntimeUp()
|
kubelet.updateRuntimeUp()
|
||||||
if err := kubelet.updateNodeStatus(); err != nil {
|
if err := kubelet.updateNodeStatus(); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
@ -2858,8 +2898,8 @@ func testDockerRuntimeVersion(t *testing.T) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("unexpected object type")
|
t.Errorf("unexpected object type")
|
||||||
}
|
}
|
||||||
if updatedNode.Status.Conditions[0].Reason != "KubeletNotReady" &&
|
if updatedNode.Status.Conditions[1].Reason != "KubeletNotReady" &&
|
||||||
!strings.Contains(updatedNode.Status.Conditions[0].Message, "container runtime version is older than") {
|
!strings.Contains(updatedNode.Status.Conditions[1].Message, "container runtime version is older than") {
|
||||||
t.Errorf("unexpect NodeStatus due to container runtime version")
|
t.Errorf("unexpect NodeStatus due to container runtime version")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user