From c0b686e3be024106c8f0b6af417f38bf78f54a90 Mon Sep 17 00:00:00 2001 From: James DeFelice Date: Fri, 12 Jun 2015 21:07:29 +0000 Subject: [PATCH 1/4] resolve pod readiness issue see https://github.com/mesosphere/kubernetes-mesos/issues/342 xref #9710 --- contrib/mesos/pkg/executor/executor.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/contrib/mesos/pkg/executor/executor.go b/contrib/mesos/pkg/executor/executor.go index 6a024fddb93..520c882f980 100644 --- a/contrib/mesos/pkg/executor/executor.go +++ b/contrib/mesos/pkg/executor/executor.go @@ -490,7 +490,18 @@ func (k *KubernetesExecutor) launchTask(driver bindings.ExecutorDriver, taskId s // Delay reporting 'task running' until container is up. psf := podStatusFunc(func() (*api.PodStatus, error) { - return k.podStatusFunc(k.kl, pod) + status, err := k.podStatusFunc(k.kl, pod) + if err != nil { + return nil, err + } + status.Phase = kubelet.GetPhase(&pod.Spec, status.ContainerStatuses) + hostIP, err := k.kl.GetHostIP() + if err != nil { + log.Errorf("Cannot get host IP: %v", err) + } else { + status.HostIP = hostIP.String() + } + return status, nil }) go k._launchTask(driver, taskId, podFullName, psf) From eca5a2ac883d63d6f3ea0636edfe9c42ac495d5b Mon Sep 17 00:00:00 2001 From: James DeFelice Date: Fri, 12 Jun 2015 21:10:16 +0000 Subject: [PATCH 2/4] lower container poll freq to something more sane --- contrib/mesos/pkg/executor/executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/mesos/pkg/executor/executor.go b/contrib/mesos/pkg/executor/executor.go index 520c882f980..526d823f6f7 100644 --- a/contrib/mesos/pkg/executor/executor.go +++ b/contrib/mesos/pkg/executor/executor.go @@ -42,7 +42,7 @@ import ( ) const ( - containerPollTime = 300 * time.Millisecond + containerPollTime = 1 * time.Second launchGracePeriod = 5 * time.Minute ) From 5e4992aa5e1d82eea88f43f48b05238a3e9db902 Mon Sep 17 00:00:00 2001 From: James DeFelice Date: Sun, 14 Jun 2015 03:38:29 +0000 Subject: [PATCH 3/4] fix broken TestExecutorLaunchAndKillTask unit test --- contrib/mesos/pkg/executor/executor.go | 14 ++++++++++---- contrib/mesos/pkg/executor/executor_test.go | 18 ++++++++++++++++-- contrib/mesos/pkg/executor/service/service.go | 4 ++-- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/contrib/mesos/pkg/executor/executor.go b/contrib/mesos/pkg/executor/executor.go index 526d823f6f7..62c2bba44bd 100644 --- a/contrib/mesos/pkg/executor/executor.go +++ b/contrib/mesos/pkg/executor/executor.go @@ -19,6 +19,7 @@ package executor import ( "encoding/json" "fmt" + "net" "strings" "sync" "sync/atomic" @@ -97,10 +98,15 @@ type suicideWatcher interface { type podStatusFunc func() (*api.PodStatus, error) +// KubeletInterface consists of the kubelet.Kubelet API's that we actually use +type KubeletInterface interface { + GetHostIP() (net.IP, error) +} + // KubernetesExecutor is an mesos executor that runs pods // in a minion machine. type KubernetesExecutor struct { - kl *kubelet.Kubelet // the kubelet instance. + kl KubeletInterface // the kubelet instance. updateChan chan<- interface{} // to send pod config updates to the kubelet state stateType tasks map[string]*kuberTask @@ -118,11 +124,11 @@ type KubernetesExecutor struct { kubeletFinished <-chan struct{} // signals that kubelet Run() died initialRegistration sync.Once exitFunc func(int) - podStatusFunc func(*kubelet.Kubelet, *api.Pod) (*api.PodStatus, error) + podStatusFunc func(KubeletInterface, *api.Pod) (*api.PodStatus, error) } type Config struct { - Kubelet *kubelet.Kubelet + Kubelet KubeletInterface Updates chan<- interface{} // to send pod config updates to the kubelet SourceName string APIClient *client.Client @@ -132,7 +138,7 @@ type Config struct { SuicideTimeout time.Duration KubeletFinished <-chan struct{} // signals that kubelet Run() died ExitFunc func(int) - PodStatusFunc func(*kubelet.Kubelet, *api.Pod) (*api.PodStatus, error) + PodStatusFunc func(KubeletInterface, *api.Pod) (*api.PodStatus, error) } func (k *KubernetesExecutor) isConnected() bool { diff --git a/contrib/mesos/pkg/executor/executor_test.go b/contrib/mesos/pkg/executor/executor_test.go index 0954454422d..faa79372bc7 100644 --- a/contrib/mesos/pkg/executor/executor_test.go +++ b/contrib/mesos/pkg/executor/executor_test.go @@ -18,6 +18,7 @@ package executor import ( "fmt" + "net" "net/http" "net/http/httptest" "reflect" @@ -285,6 +286,15 @@ func TestExecutorReregister(t *testing.T) { mockDriver.AssertExpectations(t) } +type fakeKubelet struct { + *kubelet.Kubelet + hostIP net.IP +} + +func (kl *fakeKubelet) GetHostIP() (net.IP, error) { + return kl.hostIP, nil +} + // TestExecutorLaunchAndKillTask ensures that the executor is able to launch // and kill tasks while properly bookkeping its tasks. func TestExecutorLaunchAndKillTask(t *testing.T) { @@ -304,8 +314,11 @@ func TestExecutorLaunchAndKillTask(t *testing.T) { Host: testApiServer.server.URL, Version: testapi.Version(), }), - Kubelet: &kubelet.Kubelet{}, - PodStatusFunc: func(kl *kubelet.Kubelet, pod *api.Pod) (*api.PodStatus, error) { + Kubelet: &fakeKubelet{ + Kubelet: &kubelet.Kubelet{}, + hostIP: net.IPv4(127, 0, 0, 1), + }, + PodStatusFunc: func(kl KubeletInterface, pod *api.Pod) (*api.PodStatus, error) { return &api.PodStatus{ ContainerStatuses: []api.ContainerStatus{ { @@ -331,6 +344,7 @@ func TestExecutorLaunchAndKillTask(t *testing.T) { } pod := NewTestPod(1) + pod.Spec.Containers[0].Name = "foo" podTask, err := podtask.New(api.NewDefaultContext(), "", *pod, &mesosproto.ExecutorInfo{}) assert.Equal(t, nil, err, "must be able to create a task from a pod") diff --git a/contrib/mesos/pkg/executor/service/service.go b/contrib/mesos/pkg/executor/service/service.go index be3335c0dc9..dc8ba9beabe 100644 --- a/contrib/mesos/pkg/executor/service/service.go +++ b/contrib/mesos/pkg/executor/service/service.go @@ -376,8 +376,8 @@ func (ks *KubeletExecutorServer) createAndInitKubelet( } }, ExitFunc: os.Exit, - PodStatusFunc: func(kl *kubelet.Kubelet, pod *api.Pod) (*api.PodStatus, error) { - return kl.GetRuntime().GetPodStatus(pod) + PodStatusFunc: func(_ executor.KubeletInterface, pod *api.Pod) (*api.PodStatus, error) { + return klet.GetRuntime().GetPodStatus(pod) }, }) From f956f23d3780ce92ab6f7e778040e4b0305e93f4 Mon Sep 17 00:00:00 2001 From: James DeFelice Date: Mon, 15 Jun 2015 14:30:48 +0000 Subject: [PATCH 4/4] move the container name fix to NewTestPod to avoid breakage in other unit tests in the future --- contrib/mesos/pkg/executor/executor_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/mesos/pkg/executor/executor_test.go b/contrib/mesos/pkg/executor/executor_test.go index faa79372bc7..b94deaee182 100644 --- a/contrib/mesos/pkg/executor/executor_test.go +++ b/contrib/mesos/pkg/executor/executor_test.go @@ -344,7 +344,6 @@ func TestExecutorLaunchAndKillTask(t *testing.T) { } pod := NewTestPod(1) - pod.Spec.Containers[0].Name = "foo" podTask, err := podtask.New(api.NewDefaultContext(), "", *pod, &mesosproto.ExecutorInfo{}) assert.Equal(t, nil, err, "must be able to create a task from a pod") @@ -503,6 +502,7 @@ func NewTestPod(i int) *api.Pod { Spec: api.PodSpec{ Containers: []api.Container{ { + Name: "foo", Ports: []api.ContainerPort{ { ContainerPort: 8000 + i,