Skip to content

Commit

Permalink
Merge pull request kubernetes#16549 from dchen1107/automated-cherry-p…
Browse files Browse the repository at this point in the history
…ick-of-#15994-upstream-release-1.1

Automated cherry pick of kubernetes#15994 upstream release 1.1
  • Loading branch information
a-robinson committed Oct 30, 2015
2 parents d052c6f + 8937c0c commit 90bf6c2
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 9 deletions.
4 changes: 2 additions & 2 deletions cmd/integration/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func startComponents(firstManifestURL, secondManifestURL string) (string, string
testRootDir := makeTempDirOrDie("kubelet_integ_1.", "")
configFilePath := makeTempDirOrDie("config", testRootDir)
glog.Infof("Using %s as root dir for kubelet #1", testRootDir)
fakeDocker1.VersionInfo = docker.Env{"ApiVersion=1.15"}
fakeDocker1.VersionInfo = docker.Env{"ApiVersion=1.20"}

kcfg := kubeletapp.SimpleKubelet(
cl,
Expand Down Expand Up @@ -240,7 +240,7 @@ func startComponents(firstManifestURL, secondManifestURL string) (string, string
// have a place they can schedule.
testRootDir = makeTempDirOrDie("kubelet_integ_2.", "")
glog.Infof("Using %s as root dir for kubelet #2", testRootDir)
fakeDocker2.VersionInfo = docker.Env{"ApiVersion=1.15"}
fakeDocker2.VersionInfo = docker.Env{"ApiVersion=1.20"}

kcfg = kubeletapp.SimpleKubelet(
cl,
Expand Down
6 changes: 6 additions & 0 deletions pkg/kubelet/container/fake_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type FakeRuntime struct {
StartedContainers []string
KilledContainers []string
VersionInfo string
RuntimeType string
Err error
}

Expand Down Expand Up @@ -95,6 +96,7 @@ func (f *FakeRuntime) ClearCalls() {
f.StartedContainers = []string{}
f.KilledContainers = []string{}
f.VersionInfo = ""
f.RuntimeType = ""
f.Err = nil
}

Expand Down Expand Up @@ -136,6 +138,10 @@ func (f *FakeRuntime) AssertKilledContainers(containers []string) error {
return f.assertList(containers, f.KilledContainers)
}

func (f *FakeRuntime) Type() string {
return f.RuntimeType
}

func (f *FakeRuntime) Version() (Version, error) {
f.Lock()
defer f.Unlock()
Expand Down
2 changes: 2 additions & 0 deletions pkg/kubelet/container/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ type ImageSpec struct {
// by a container runtime.
// Thread safety is required from implementations of this interface.
type Runtime interface {
// Type returns the type of the container runtime.
Type() string
// Version returns the version information of the container runtime.
Version() (Version, error)
// GetPods returns a list containers group by pods. The boolean parameter
Expand Down
8 changes: 8 additions & 0 deletions pkg/kubelet/dockertools/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ import (
)

const (
DockerType = "docker"

MinimumDockerAPIVersion = "1.18"

maxReasonCacheEntries = 200

// ndots specifies the minimum number of dots that a domain name must contain for the resolver to consider it as FQDN (fully-qualified)
Expand Down Expand Up @@ -1021,6 +1025,10 @@ func (dv dockerVersion) Compare(other string) (int, error) {
return 0, nil
}

func (dm *DockerManager) Type() string {
return DockerType
}

func (dm *DockerManager) Version() (kubecontainer.Version, error) {
env, err := dm.client.Version()
if err != nil {
Expand Down
30 changes: 29 additions & 1 deletion pkg/kubelet/kubelet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2431,11 +2431,13 @@ func (kl *Kubelet) setNodeStatus(node *api.Node) error {
containerRuntimeUp := kl.containerRuntimeUp()
// Check whether network is configured properly
networkConfigured := kl.doneNetworkConfigure()
// Check whether runtime version meets the minimal requirements
containerRuntimeVersionRequirementMet := kl.containerRuntimeVersionRequirementMet()

currentTime := unversioned.Now()
var newNodeReadyCondition api.NodeCondition
var oldNodeReadyConditionStatus api.ConditionStatus
if containerRuntimeUp && networkConfigured {
if containerRuntimeUp && networkConfigured && containerRuntimeVersionRequirementMet {
newNodeReadyCondition = api.NodeCondition{
Type: api.NodeReady,
Status: api.ConditionTrue,
Expand All @@ -2452,6 +2454,9 @@ func (kl *Kubelet) setNodeStatus(node *api.Node) error {
if !networkConfigured {
messages = append(reasons, "network not configured correctly")
}
if !containerRuntimeVersionRequirementMet {
messages = append(messages, fmt.Sprintf("container runtime version is older than %s", dockertools.MinimumDockerAPIVersion))
}
newNodeReadyCondition = api.NodeCondition{
Type: api.NodeReady,
Status: api.ConditionFalse,
Expand Down Expand Up @@ -2563,6 +2568,29 @@ func (kl *Kubelet) doneNetworkConfigure() bool {
return kl.networkConfigured
}

func (kl *Kubelet) containerRuntimeVersionRequirementMet() bool {
switch kl.GetRuntime().Type() {
case "docker":
version, err := kl.GetContainerRuntimeVersion()
if err != nil {
return true
}
// Verify the docker version.
result, err := version.Compare(dockertools.MinimumDockerAPIVersion)
if err != nil {
glog.Errorf("Cannot compare current docker version %v with minimum support Docker version %q", version, dockertools.MinimumDockerAPIVersion)
return false
}
return (result >= 0)
case "rkt":
// TODO(dawnchen): Rkt support here
return true
default:
glog.Errorf("unsupported container runtime %s specified", kl.GetRuntime().Type())
return true
}
}

// tryUpdateNodeStatus tries to update node status to master. If ReconcileCBR0
// is set, this function will also confirm that cbr0 is configured correctly.
func (kl *Kubelet) tryUpdateNodeStatus() error {
Expand Down
137 changes: 137 additions & 0 deletions pkg/kubelet/kubelet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2627,6 +2627,143 @@ func TestUpdateNewNodeStatus(t *testing.T) {
}
}

func TestDockerRuntimeVersion(t *testing.T) {
testKubelet := newTestKubelet(t)
kubelet := testKubelet.kubelet
fakeRuntime := testKubelet.fakeRuntime
fakeRuntime.RuntimeType = "docker"
fakeRuntime.VersionInfo = "1.18"
kubeClient := testKubelet.fakeKubeClient
kubeClient.ReactionChain = testclient.NewSimpleFake(&api.NodeList{Items: []api.Node{
{ObjectMeta: api.ObjectMeta{Name: testKubeletHostname}},
}}).ReactionChain
machineInfo := &cadvisorApi.MachineInfo{
MachineID: "123",
SystemUUID: "abc",
BootID: "1b3",
NumCores: 2,
MemoryCapacity: 1024,
}
mockCadvisor := testKubelet.fakeCadvisor
mockCadvisor.On("MachineInfo").Return(machineInfo, nil)
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)
// Create a new DiskSpaceManager with a new policy. This new manager along with the mock
// FsInfo values added to Cadvisor should make the kubelet report that it has sufficient
// disk space.
dockerimagesFsInfo := cadvisorApiv2.FsInfo{Capacity: 500 * mb, Available: 200 * mb}
rootFsInfo := cadvisorApiv2.FsInfo{Capacity: 500 * mb, Available: 200 * mb}
mockCadvisor.On("DockerImagesFsInfo").Return(dockerimagesFsInfo, nil)
mockCadvisor.On("RootFsInfo").Return(rootFsInfo, nil)
dsp := DiskSpacePolicy{DockerFreeDiskMB: 100, RootFreeDiskMB: 100}
diskSpaceManager, err := newDiskSpaceManager(mockCadvisor, dsp)
if err != nil {
t.Fatalf("can't update disk space manager: %v", err)
}
diskSpaceManager.Unfreeze()
kubelet.diskSpaceManager = diskSpaceManager

expectedNode := &api.Node{
ObjectMeta: api.ObjectMeta{Name: testKubeletHostname},
Spec: api.NodeSpec{},
Status: api.NodeStatus{
Conditions: []api.NodeCondition{
{
Type: api.NodeReady,
Status: api.ConditionTrue,
Reason: "KubeletReady",
Message: fmt.Sprintf("kubelet is posting ready status"),
LastHeartbeatTime: unversioned.Time{},
LastTransitionTime: unversioned.Time{},
},
{
Type: api.NodeOutOfDisk,
Status: api.ConditionFalse,
Reason: "KubeletHasSufficientDisk",
Message: fmt.Sprintf("kubelet has sufficient disk space available"),
LastHeartbeatTime: unversioned.Time{},
LastTransitionTime: unversioned.Time{},
},
},
NodeInfo: api.NodeSystemInfo{
MachineID: "123",
SystemUUID: "abc",
BootID: "1b3",
KernelVersion: "3.16.0-0.bpo.4-amd64",
OsImage: "Debian GNU/Linux 7 (wheezy)",
ContainerRuntimeVersion: "docker://1.5.0",
KubeletVersion: version.Get().String(),
KubeProxyVersion: version.Get().String(),
},
Capacity: api.ResourceList{
api.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI),
api.ResourceMemory: *resource.NewQuantity(1024, resource.BinarySI),
api.ResourcePods: *resource.NewQuantity(0, resource.DecimalSI),
},
Addresses: []api.NodeAddress{
{Type: api.NodeLegacyHostIP, Address: "127.0.0.1"},
{Type: api.NodeInternalIP, Address: "127.0.0.1"},
},
},
}

kubelet.updateRuntimeUp()
if err := kubelet.updateNodeStatus(); err != nil {
t.Errorf("unexpected error: %v", err)
}
actions := kubeClient.Actions()
if len(actions) != 2 {
t.Fatalf("unexpected actions: %v", actions)
}
if !actions[1].Matches("update", "nodes") || actions[1].GetSubresource() != "status" {
t.Fatalf("unexpected actions: %v", actions)
}
updatedNode, ok := actions[1].(testclient.UpdateAction).GetObject().(*api.Node)
if !ok {
t.Errorf("unexpected object type")
}
for i, cond := range updatedNode.Status.Conditions {
if cond.LastHeartbeatTime.IsZero() {
t.Errorf("unexpected zero last probe timestamp")
}
if cond.LastTransitionTime.IsZero() {
t.Errorf("unexpected zero last transition timestamp")
}
updatedNode.Status.Conditions[i].LastHeartbeatTime = unversioned.Time{}
updatedNode.Status.Conditions[i].LastTransitionTime = unversioned.Time{}
}
if !reflect.DeepEqual(expectedNode, updatedNode) {
t.Errorf("unexpected objects: %s", util.ObjectDiff(expectedNode, updatedNode))
}

// Downgrade docker version, node should be NotReady
fakeRuntime.RuntimeType = "docker"
fakeRuntime.VersionInfo = "1.17"
kubelet.updateRuntimeUp()
if err := kubelet.updateNodeStatus(); err != nil {
t.Errorf("unexpected error: %v", err)
}
actions = kubeClient.Actions()
if len(actions) != 4 {
t.Fatalf("unexpected actions: %v", actions)
}
if !actions[1].Matches("update", "nodes") || actions[1].GetSubresource() != "status" {
t.Fatalf("unexpected actions: %v", actions)
}
updatedNode, ok = actions[3].(testclient.UpdateAction).GetObject().(*api.Node)
if !ok {
t.Errorf("unexpected object type")
}
if updatedNode.Status.Conditions[0].Reason != "KubeletNotReady" &&
!strings.Contains(updatedNode.Status.Conditions[0].Message, "container runtime version is older than") {
t.Errorf("unexpect NodeStatus due to container runtime version")
}
}

func TestUpdateExistingNodeStatus(t *testing.T) {
testKubelet := newTestKubelet(t)
kubelet := testKubelet.kubelet
Expand Down
10 changes: 8 additions & 2 deletions pkg/kubelet/rkt/rkt.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ const (
rktMinimumVersion = "0.8.1"
systemdMinimumVersion = "219"

RktType = "rkt"

systemdServiceDir = "/run/systemd/system"
rktDataDir = "/var/lib/rkt"
rktLocalConfigDir = "/etc/rkt"
Expand Down Expand Up @@ -513,7 +515,7 @@ func newUnitOption(section, name, value string) *unit.UnitOption {
// apiPodToruntimePod converts an api.Pod to kubelet/container.Pod.
// we save the this for later reconstruction of the kubelet/container.Pod
// such as in GetPods().
func apiPodToruntimePod(uuid string, pod *api.Pod) *kubecontainer.Pod {
func apiPodToRuntimePod(uuid string, pod *api.Pod) *kubecontainer.Pod {
p := &kubecontainer.Pod{
ID: pod.UID,
Name: pod.Name,
Expand Down Expand Up @@ -587,7 +589,7 @@ func (r *runtime) preparePod(pod *api.Pod, pullSecrets []api.Secret) (string, *k
glog.V(4).Infof("'rkt prepare' returns %q", uuid)

// Create systemd service file for the rkt pod.
runtimePod := apiPodToruntimePod(uuid, pod)
runtimePod := apiPodToRuntimePod(uuid, pod)
b, err := json.Marshal(runtimePod)
if err != nil {
return "", nil, err
Expand Down Expand Up @@ -846,6 +848,10 @@ func (r *runtime) GetPodStatus(pod *api.Pod) (*api.PodStatus, error) {
return r.getPodStatus(serviceName)
}

func (r *runtime) Type() string {
return RktType
}

// Version invokes 'rkt version' to get the version information of the rkt
// runtime on the machine.
// The return values are an int array containers the version number.
Expand Down
3 changes: 2 additions & 1 deletion pkg/kubelet/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"k8s.io/kubernetes/pkg/healthz"
"k8s.io/kubernetes/pkg/httplog"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
"k8s.io/kubernetes/pkg/kubelet/dockertools"
"k8s.io/kubernetes/pkg/kubelet/portforward"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util"
Expand Down Expand Up @@ -284,7 +285,7 @@ func (s *Server) dockerHealthCheck(req *http.Request) error {
return errors.New("unknown Docker version")
}
// Verify the docker version.
result, err := version.Compare("1.15")
result, err := version.Compare(dockertools.MinimumDockerAPIVersion)
if err != nil {
return err
}
Expand Down
9 changes: 6 additions & 3 deletions pkg/kubelet/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ type serverTestFramework struct {
func newServerTest() *serverTestFramework {
fw := &serverTestFramework{}
fw.fakeKubelet = &fakeKubelet{
containerVersionFunc: func() (kubecontainer.Version, error) {
return dockertools.NewVersion("1.18")
},
podByNameFunc: func(namespace, name string) (*api.Pod, bool) {
return &api.Pod{
ObjectMeta: api.ObjectMeta{
Expand Down Expand Up @@ -467,7 +470,7 @@ func TestServeRunInContainerWithUID(t *testing.T) {
func TestHealthCheck(t *testing.T) {
fw := newServerTest()
fw.fakeKubelet.containerVersionFunc = func() (kubecontainer.Version, error) {
return dockertools.NewVersion("1.15")
return dockertools.NewVersion("1.18")
}
fw.fakeKubelet.hostnameFunc = func() string {
return "127.0.0.1"
Expand All @@ -484,7 +487,7 @@ func TestHealthCheck(t *testing.T) {

//Test with old container runtime version
fw.fakeKubelet.containerVersionFunc = func() (kubecontainer.Version, error) {
return dockertools.NewVersion("1.1")
return dockertools.NewVersion("1.16")
}

assertHealthFails(t, fw.testHTTPServer.URL+"/healthz", http.StatusInternalServerError)
Expand All @@ -504,7 +507,7 @@ func assertHealthFails(t *testing.T, httpURL string, expectedErrorCode int) {
func TestSyncLoopCheck(t *testing.T) {
fw := newServerTest()
fw.fakeKubelet.containerVersionFunc = func() (kubecontainer.Version, error) {
return dockertools.NewVersion("1.15")
return dockertools.NewVersion("1.18")
}
fw.fakeKubelet.hostnameFunc = func() string {
return "127.0.0.1"
Expand Down

0 comments on commit 90bf6c2

Please sign in to comment.