runonce: list kubelet container between each iteration

pull/6/head
Johan Euphrosine 2014-10-08 22:28:41 -07:00
parent 14c5fd405d
commit dbb2342688
2 changed files with 40 additions and 59 deletions

View File

@ -20,7 +20,6 @@ import (
"fmt"
"time"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/dockertools"
"github.com/golang/glog"
)
@ -33,9 +32,8 @@ const (
)
type RunPodResult struct {
Pod *Pod
Info api.PodInfo
Err error
Pod *Pod
Err error
}
// RunOnce polls from one configuration update and run the associated pods.
@ -62,8 +60,8 @@ func (kl *Kubelet) runOnce(pods []Pod) (results []RunPodResult, err error) {
for i := range pods {
pod := pods[i] // Make a copy
go func() {
info, err := kl.runPod(pod)
ch <- RunPodResult{&pod, info, err}
err := kl.runPod(pod)
ch <- RunPodResult{&pod, err}
}()
}
@ -77,7 +75,7 @@ func (kl *Kubelet) runOnce(pods []Pod) (results []RunPodResult, err error) {
glog.Infof("failed to start pod %q: %v", res.Pod.Name, res.Err)
failedPods = append(failedPods, res.Pod.Name)
} else {
glog.Infof("started pod %q: %#v", res.Pod.Name, res.Info)
glog.Infof("started pod %q", res.Pod.Name)
}
}
if len(failedPods) > 0 {
@ -87,31 +85,29 @@ func (kl *Kubelet) runOnce(pods []Pod) (results []RunPodResult, err error) {
return results, err
}
// Run a single pod and wait until all containers are running.
func (kl *Kubelet) runPod(pod Pod) (api.PodInfo, error) {
dockerContainers, err := dockertools.GetKubeletDockerContainers(kl.dockerClient, false)
if err != nil {
return nil, fmt.Errorf("failed to get kubelet docker containers: %v", err)
}
// runPod runs a single pod and wait until all containers are running.
func (kl *Kubelet) runPod(pod Pod) error {
delay := RunOnceRetryDelay
retry := 0
for {
running, info, err := kl.isPodRunning(pod)
dockerContainers, err := dockertools.GetKubeletDockerContainers(kl.dockerClient, false)
if err != nil {
return nil, fmt.Errorf("error checking pod status: %v", err)
return fmt.Errorf("failed to get kubelet docker containers: %v", err)
}
running, err := kl.isPodRunning(pod, dockerContainers)
if err != nil {
return fmt.Errorf("error checking pod status: %v", err)
}
if running {
glog.Infof("pod %q containers running", pod.Name)
return info, nil
return nil
}
glog.Infof("pod %q containers not running: syncing", pod.Name)
err = kl.syncPod(&pod, dockerContainers)
if err != nil {
return nil, fmt.Errorf("error syncing pod: %v", err)
if err = kl.syncPod(&pod, dockerContainers); err != nil {
return fmt.Errorf("error syncing pod: %v", err)
}
if retry >= RunOnceMaxRetries {
return info, fmt.Errorf("timeout error: pod %q containers not running after %d retries", pod.Name, RunOnceMaxRetries)
return fmt.Errorf("timeout error: pod %q containers not running after %d retries", pod.Name, RunOnceMaxRetries)
}
// TODO(proppy): health checking would be better than waiting + checking the state at the next iteration.
glog.Infof("pod %q containers synced, waiting for %v", pod.Name, delay)
@ -121,31 +117,13 @@ func (kl *Kubelet) runPod(pod Pod) (api.PodInfo, error) {
}
}
// Check if all containers of a manifest are running.
func (kl *Kubelet) isPodRunning(pod Pod) (bool, api.PodInfo, error) {
info, err := kl.GetPodInfo(GetPodFullName(&pod), pod.Manifest.UUID)
if err != nil {
return false, nil, fmt.Errorf("error getting pod info: %v", err)
}
// isPodRunning returns true if all containers of a manifest are running.
func (kl *Kubelet) isPodRunning(pod Pod, dockerContainers dockertools.DockerContainers) (bool, error) {
for _, container := range pod.Manifest.Containers {
running := podInfo(info).isContainerRunning(container)
glog.Infof("container %q running: %v", container.Name, running)
if !running {
return false, info, nil
if dockerContainer, found, _ := dockerContainers.FindPodContainer(GetPodFullName(&pod), pod.Manifest.UUID, container.Name); !found || dockerContainer.Status != "running" {
glog.Infof("container %q not found (%v) or not running: %#v", container.Name, found, dockerContainer)
return false, nil
}
}
return true, info, nil
}
// Alias PodInfo for internal usage.
type podInfo api.PodInfo
func (info podInfo) isContainerRunning(container api.Container) bool {
for name, status := range info {
glog.Infof("container %q status: %#v", name, status)
if name == container.Name && status.State.Running != nil {
return true
}
}
return false
return true, nil
}

View File

@ -67,22 +67,25 @@ func (d *testDocker) InspectContainer(id string) (*docker.Container, error) {
func TestRunOnce(t *testing.T) {
kb := &Kubelet{}
container := api.Container{Name: "bar"}
podContainers := []docker.APIContainers{
{
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&api.Container{Name: "bar"}), 16) + "_foo.test"},
ID: "1234",
Status: "running",
},
{
Names: []string{"/k8s_net_foo.test_"},
ID: "9876",
Status: "running",
},
}
kb.dockerClient = &testDocker{
listContainersResults: []listContainersResult{
{label: "pre syncPod", containers: []docker.APIContainers{}},
{label: "syncPod #1", containers: []docker.APIContainers{}},
{label: "syncPod #2", containers: []docker.APIContainers{}},
{label: "post syncPod", containers: []docker.APIContainers{
{
Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo.test"},
ID: "1234",
},
{
Names: []string{"/k8s_net_foo.test_"},
ID: "9876",
},
}},
{label: "list pod container", containers: []docker.APIContainers{}},
{label: "syncPod", containers: []docker.APIContainers{}},
{label: "list pod container", containers: []docker.APIContainers{}},
{label: "syncPod", containers: podContainers},
{label: "list pod container", containers: podContainers},
},
inspectContainersResults: []inspectContainersResult{
{