// EnsureImageExists pulls the image for the specified pod and container, and returns // (imageRef, error message, error). func (m *imageManager) EnsureImageExists(pod *v1.Pod, container *v1.Container, pullSecrets []v1.Secret) (string, string, error) { logPrefix := fmt.Sprintf("%s/%s", pod.Name, container.Image) ref, err := kubecontainer.GenerateContainerRef(pod, container) if err != nil { glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err) } // If the image contains no tag or digest, a default tag should be applied. image, err := applyDefaultImageTag(container.Image) if err != nil { msg := fmt.Sprintf("Failed to apply default image tag %q: %v", container.Image, err) m.logIt(ref, v1.EventTypeWarning, events.FailedToInspectImage, logPrefix, msg, glog.Warning) return "", msg, ErrInvalidImageName } spec := kubecontainer.ImageSpec{Image: image} imageRef, err := m.imageService.GetImageRef(spec) if err != nil { msg := fmt.Sprintf("Failed to inspect image %q: %v", container.Image, err) m.logIt(ref, v1.EventTypeWarning, events.FailedToInspectImage, logPrefix, msg, glog.Warning) return "", msg, ErrImageInspect } present := imageRef != "" if !shouldPullImage(container, present) { if present { msg := fmt.Sprintf("Container image %q already present on machine", container.Image) m.logIt(ref, v1.EventTypeNormal, events.PulledImage, logPrefix, msg, glog.Info) return imageRef, "", nil } else { msg := fmt.Sprintf("Container image %q is not present with pull policy of Never", container.Image) m.logIt(ref, v1.EventTypeWarning, events.ErrImageNeverPullPolicy, logPrefix, msg, glog.Warning) return "", msg, ErrImageNeverPull } } backOffKey := fmt.Sprintf("%s_%s", pod.UID, container.Image) if m.backOff.IsInBackOffSinceUpdate(backOffKey, m.backOff.Clock.Now()) { msg := fmt.Sprintf("Back-off pulling image %q", container.Image) m.logIt(ref, v1.EventTypeNormal, events.BackOffPullImage, logPrefix, msg, glog.Info) return "", msg, ErrImagePullBackOff } m.logIt(ref, v1.EventTypeNormal, events.PullingImage, logPrefix, fmt.Sprintf("pulling image %q", container.Image), glog.Info) pullChan := make(chan pullResult) m.puller.pullImage(spec, pullSecrets, pullChan) imagePullResult := <-pullChan if imagePullResult.err != nil { m.logIt(ref, v1.EventTypeWarning, events.FailedToPullImage, logPrefix, fmt.Sprintf("Failed to pull image %q: %v", container.Image, imagePullResult.err), glog.Warning) m.backOff.Next(backOffKey, m.backOff.Clock.Now()) if imagePullResult.err == RegistryUnavailable { msg := fmt.Sprintf("image pull failed for %s because the registry is unavailable.", container.Image) return "", msg, imagePullResult.err } return "", imagePullResult.err.Error(), ErrImagePull } m.logIt(ref, v1.EventTypeNormal, events.PulledImage, logPrefix, fmt.Sprintf("Successfully pulled image %q", container.Image), glog.Info) m.backOff.GC() return imagePullResult.imageRef, "", nil }
// If a container is still in backoff, the function will return a brief backoff error and // a detailed error message. func (m *kubeGenericRuntimeManager) doBackOff(pod *api.Pod, container *api.Container, podStatus *kubecontainer.PodStatus, backOff *flowcontrol.Backoff) (bool, string, error) { var cStatus *kubecontainer.ContainerStatus for _, c := range podStatus.ContainerStatuses { if c.Name == container.Name && c.State == kubecontainer.ContainerStateExited { cStatus = c break } } if cStatus == nil { return false, "", nil } glog.Infof("checking backoff for container %q in pod %q", container.Name, format.Pod(pod)) // Use the finished time of the latest exited container as the start point to calculate whether to do back-off. ts := cStatus.FinishedAt // backOff requires a unique key to identify the container. key := getStableKey(pod, container) if backOff.IsInBackOffSince(key, ts) { if ref, err := kubecontainer.GenerateContainerRef(pod, container); err == nil { m.recorder.Eventf(ref, api.EventTypeWarning, events.BackOffStartContainer, "Back-off restarting failed container") } err := fmt.Errorf("Back-off %s restarting failed container=%s pod=%s", backOff.Get(key), container.Name, format.Pod(pod)) glog.Infof("%s", err.Error()) return true, err.Error(), kubecontainer.ErrCrashLoopBackOff } backOff.Next(key, ts) return false, "", nil }
func (kr *kubeletRuntimeHooks) ReportImagePulling(pod *api.Pod, container *api.Container) { ref, err := kubecontainer.GenerateContainerRef(pod, container) if err != nil { glog.Errorf("Couldn't make a ref to pod %q, container %q: '%v'", pod.Name, container.Name, err) return } kr.recorder.Eventf(ref, "Pulling", "Pulling image %q", container.Image) }
// PullImage pulls the image for the specified pod and container. func (puller *serializedImagePuller) pullImage(pod *api.Pod, container *api.Container, pullSecrets []api.Secret) (error, string) { logPrefix := fmt.Sprintf("%s/%s", pod.Name, container.Image) ref, err := kubecontainer.GenerateContainerRef(pod, container) if err != nil { glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err) } spec := kubecontainer.ImageSpec{Image: container.Image} present, err := puller.runtime.IsImagePresent(spec) if err != nil { msg := fmt.Sprintf("Failed to inspect image %q: %v", container.Image, err) puller.logIt(ref, api.EventTypeWarning, events.FailedToInspectImage, logPrefix, msg, glog.Warning) return ErrImageInspect, msg } if !shouldPullImage(container, present) { if present { msg := fmt.Sprintf("Container image %q already present on machine", container.Image) puller.logIt(ref, api.EventTypeNormal, events.PulledImage, logPrefix, msg, glog.Info) return nil, "" } else { msg := fmt.Sprintf("Container image %q is not present with pull policy of Never", container.Image) puller.logIt(ref, api.EventTypeWarning, events.ErrImageNeverPullPolicy, logPrefix, msg, glog.Warning) return ErrImageNeverPull, msg } } backOffKey := fmt.Sprintf("%s_%s", pod.UID, container.Image) if puller.backOff.IsInBackOffSinceUpdate(backOffKey, puller.backOff.Clock.Now()) { msg := fmt.Sprintf("Back-off pulling image %q", container.Image) puller.logIt(ref, api.EventTypeNormal, events.BackOffPullImage, logPrefix, msg, glog.Info) return ErrImagePullBackOff, msg } // enqueue image pull request and wait for response. returnChan := make(chan error) puller.pullRequests <- &imagePullRequest{ spec: spec, container: container, pullSecrets: pullSecrets, logPrefix: logPrefix, ref: ref, returnChan: returnChan, } if err = <-returnChan; err != nil { puller.logIt(ref, api.EventTypeWarning, events.FailedToPullImage, logPrefix, fmt.Sprintf("Failed to pull image %q: %v", container.Image, err), glog.Warning) puller.backOff.Next(backOffKey, puller.backOff.Clock.Now()) if err == RegistryUnavailable { msg := fmt.Sprintf("image pull failed for %s because the registry is unavailable.", container.Image) return err, msg } else { return ErrImagePull, err.Error() } } puller.logIt(ref, api.EventTypeNormal, events.PulledImage, logPrefix, fmt.Sprintf("Successfully pulled image %q", container.Image), glog.Info) puller.backOff.GC() return nil, "" }
func (kr *kubeletRuntimeHooks) ReportImagePulled(pod *api.Pod, container *api.Container, pullError error) { ref, err := kubecontainer.GenerateContainerRef(pod, container) if err != nil { glog.Errorf("Couldn't make a ref to pod %q, container %q: '%v'", pod.Name, container.Name, err) return } if pullError != nil { kr.recorder.Eventf(ref, "Failed", "Failed to pull image %q: %v", container.Image, pullError) } else { kr.recorder.Eventf(ref, "Pulled", "Successfully pulled image %q", container.Image) } }
// EnsureImageExists pulls the image for the specified pod and container. func (m *imageManager) EnsureImageExists(pod *api.Pod, container *api.Container, pullSecrets []api.Secret) (error, string) { logPrefix := fmt.Sprintf("%s/%s", pod.Name, container.Image) ref, err := kubecontainer.GenerateContainerRef(pod, container) if err != nil { glog.Errorf("Couldn't make a ref to pod %v, container %v: '%v'", pod.Name, container.Name, err) } spec := kubecontainer.ImageSpec{Image: container.Image} present, err := m.imageService.IsImagePresent(spec) if err != nil { msg := fmt.Sprintf("Failed to inspect image %q: %v", container.Image, err) m.logIt(ref, api.EventTypeWarning, events.FailedToInspectImage, logPrefix, msg, glog.Warning) return ErrImageInspect, msg } if !shouldPullImage(container, present) { if present { msg := fmt.Sprintf("Container image %q already present on machine", container.Image) m.logIt(ref, api.EventTypeNormal, events.PulledImage, logPrefix, msg, glog.Info) return nil, "" } else { msg := fmt.Sprintf("Container image %q is not present with pull policy of Never", container.Image) m.logIt(ref, api.EventTypeWarning, events.ErrImageNeverPullPolicy, logPrefix, msg, glog.Warning) return ErrImageNeverPull, msg } } backOffKey := fmt.Sprintf("%s_%s", pod.UID, container.Image) if m.backOff.IsInBackOffSinceUpdate(backOffKey, m.backOff.Clock.Now()) { msg := fmt.Sprintf("Back-off pulling image %q", container.Image) m.logIt(ref, api.EventTypeNormal, events.BackOffPullImage, logPrefix, msg, glog.Info) return ErrImagePullBackOff, msg } m.logIt(ref, api.EventTypeNormal, events.PullingImage, logPrefix, fmt.Sprintf("pulling image %q", container.Image), glog.Info) errChan := make(chan error) m.puller.pullImage(spec, pullSecrets, errChan) if err := <-errChan; err != nil { m.logIt(ref, api.EventTypeWarning, events.FailedToPullImage, logPrefix, fmt.Sprintf("Failed to pull image %q: %v", container.Image, err), glog.Warning) m.backOff.Next(backOffKey, m.backOff.Clock.Now()) if err == RegistryUnavailable { msg := fmt.Sprintf("image pull failed for %s because the registry is unavailable.", container.Image) return err, msg } else { return ErrImagePull, err.Error() } } m.logIt(ref, api.EventTypeNormal, events.PulledImage, logPrefix, fmt.Sprintf("Successfully pulled image %q", container.Image), glog.Info) m.backOff.GC() return nil, "" }
// RunPod first creates the unit file for a pod, and then // starts the unit over d-bus. func (r *Runtime) RunPod(pod *api.Pod, pullSecrets []api.Secret) error { glog.V(4).Infof("Rkt starts to run pod: name %q.", format.Pod(pod)) name, runtimePod, prepareErr := r.preparePod(pod, pullSecrets) // Set container references and generate events. // If preparedPod fails, then send out 'failed' events for each container. // Otherwise, store the container references so we can use them later to send events. for i, c := range pod.Spec.Containers { ref, err := kubecontainer.GenerateContainerRef(pod, &c) if err != nil { glog.Errorf("Couldn't make a ref to pod %q, container %v: '%v'", format.Pod(pod), c.Name, err) continue } if prepareErr != nil { r.recorder.Eventf(ref, api.EventTypeWarning, kubecontainer.FailedToCreateContainer, "Failed to create rkt container with error: %v", prepareErr) continue } containerID := runtimePod.Containers[i].ID r.containerRefManager.SetRef(containerID, ref) } if prepareErr != nil { return prepareErr } r.generateEvents(runtimePod, "Created", nil) // RestartUnit has the same effect as StartUnit if the unit is not running, besides it can restart // a unit if the unit file is changed and reloaded. reschan := make(chan string) _, err := r.systemd.RestartUnit(name, "replace", reschan) if err != nil { r.generateEvents(runtimePod, "Failed", err) return err } res := <-reschan if res != "done" { err := fmt.Errorf("Failed to restart unit %q: %s", name, res) r.generateEvents(runtimePod, "Failed", err) return err } r.generateEvents(runtimePod, "Started", nil) return nil }
// RunPod first creates the unit file for a pod, and then // starts the unit over d-bus. func (r *runtime) RunPod(pod *api.Pod, pullSecrets []api.Secret) error { glog.V(4).Infof("Rkt starts to run pod: name %q.", kubeletUtil.FormatPodName(pod)) name, runtimePod, prepareErr := r.preparePod(pod, pullSecrets) // Set container references and generate events. // If preparedPod fails, then send out 'failed' events for each container. // Otherwise, store the container references so we can use them later to send events. for i, c := range pod.Spec.Containers { ref, err := kubecontainer.GenerateContainerRef(pod, &c) if err != nil { glog.Errorf("Couldn't make a ref to pod %q, container %v: '%v'", kubeletUtil.FormatPodName(pod), c.Name, err) continue } if prepareErr != nil { r.recorder.Eventf(ref, "Failed", "Failed to create rkt container with error: %v", prepareErr) continue } containerID := string(runtimePod.Containers[i].ID) r.containerRefManager.SetRef(containerID, ref) } if prepareErr != nil { return prepareErr } r.generateEvents(runtimePod, "Created", nil) // TODO(yifan): This is the old version of go-systemd. Should update when libcontainer updates // its version of go-systemd. // RestartUnit has the same effect as StartUnit if the unit is not running, besides it can restart // a unit if the unit file is changed and reloaded. if _, err := r.systemd.RestartUnit(name, "replace"); err != nil { r.generateEvents(runtimePod, "Failed", err) return err } r.generateEvents(runtimePod, "Started", nil) return nil }
// startContainer starts a container and returns a message indicates why it is failed on error. // It starts the container through the following steps: // * pull the image // * create the container // * start the container // * run the post start lifecycle hooks (if applicable) func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandboxConfig *runtimeapi.PodSandboxConfig, container *v1.Container, pod *v1.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []v1.Secret, podIP string) (string, error) { // Step 1: pull the image. err, msg := m.imagePuller.EnsureImageExists(pod, container, pullSecrets) if err != nil { return msg, err } // Step 2: create the container. ref, err := kubecontainer.GenerateContainerRef(pod, container) if err != nil { glog.Errorf("Can't make a ref to pod %q, container %v: %v", format.Pod(pod), container.Name, err) } glog.V(4).Infof("Generating ref for container %s: %#v", container.Name, ref) // For a new container, the RestartCount should be 0 restartCount := 0 containerStatus := podStatus.FindContainerStatusByName(container.Name) if containerStatus != nil { restartCount = containerStatus.RestartCount + 1 } containerConfig, err := m.generateContainerConfig(container, pod, restartCount, podIP) if err != nil { m.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedToCreateContainer, "Failed to create container with error: %v", err) return "Generate Container Config Failed", err } containerID, err := m.runtimeService.CreateContainer(podSandboxID, containerConfig, podSandboxConfig) if err != nil { m.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedToCreateContainer, "Failed to create container with error: %v", err) return "Create Container Failed", err } m.recorder.Eventf(ref, v1.EventTypeNormal, events.CreatedContainer, "Created container with id %v", containerID) if ref != nil { m.containerRefManager.SetRef(kubecontainer.ContainerID{ Type: m.runtimeName, ID: containerID, }, ref) } // Step 3: start the container. err = m.runtimeService.StartContainer(containerID) if err != nil { m.recorder.Eventf(ref, v1.EventTypeWarning, events.FailedToStartContainer, "Failed to start container with id %v with error: %v", containerID, err) return "Start Container Failed", err } m.recorder.Eventf(ref, v1.EventTypeNormal, events.StartedContainer, "Started container with id %v", containerID) // Symlink container logs to the legacy container log location for cluster logging // support. // TODO(random-liu): Remove this after cluster logging supports CRI container log path. containerMeta := containerConfig.GetMetadata() sandboxMeta := podSandboxConfig.GetMetadata() legacySymlink := legacyLogSymlink(containerID, containerMeta.GetName(), sandboxMeta.GetName(), sandboxMeta.GetNamespace()) containerLog := filepath.Join(podSandboxConfig.GetLogDirectory(), containerConfig.GetLogPath()) if err := m.osInterface.Symlink(containerLog, legacySymlink); err != nil { glog.Errorf("Failed to create legacy symbolic link %q to container %q log %q: %v", legacySymlink, containerID, containerLog, err) } // Step 4: execute the post start hook. if container.Lifecycle != nil && container.Lifecycle.PostStart != nil { kubeContainerID := kubecontainer.ContainerID{ Type: m.runtimeName, ID: containerID, } msg, handlerErr := m.runner.Run(kubeContainerID, pod, container, container.Lifecycle.PostStart) if handlerErr != nil { err := fmt.Errorf("PostStart handler: %v", handlerErr) m.generateContainerEvent(kubeContainerID, v1.EventTypeWarning, events.FailedPostStartHook, msg) m.killContainer(pod, kubeContainerID, container.Name, "FailedPostStartHook", nil) return "PostStart Hook Failed", err } } return "", nil }
// startContainer starts a container and returns a message indicates why it is failed on error. // It starts the container through the following steps: // * pull the image // * create the container // * start the container // * run the post start lifecycle hooks (if applicable) func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandboxConfig *runtimeApi.PodSandboxConfig, container *api.Container, pod *api.Pod, podStatus *kubecontainer.PodStatus, pullSecrets []api.Secret, podIP string) (string, error) { // Step 1: pull the image. err, msg := m.imagePuller.EnsureImageExists(pod, container, pullSecrets) if err != nil { return msg, err } // Step 2: create the container. ref, err := kubecontainer.GenerateContainerRef(pod, container) if err != nil { glog.Errorf("Can't make a ref to pod %q, container %v: %v", format.Pod(pod), container.Name, err) } glog.V(4).Infof("Generating ref for container %s: %#v", container.Name, ref) // For a new container, the RestartCount should be 0 restartCount := 0 containerStatus := podStatus.FindContainerStatusByName(container.Name) if containerStatus != nil { restartCount = containerStatus.RestartCount + 1 } containerConfig, err := m.generateContainerConfig(container, pod, restartCount, podIP) if err != nil { m.recorder.Eventf(ref, api.EventTypeWarning, events.FailedToCreateContainer, "Failed to create container with error: %v", err) return "Generate Container Config Failed", err } containerID, err := m.runtimeService.CreateContainer(podSandboxID, containerConfig, podSandboxConfig) if err != nil { m.recorder.Eventf(ref, api.EventTypeWarning, events.FailedToCreateContainer, "Failed to create container with error: %v", err) return "Create Container Failed", err } m.recorder.Eventf(ref, api.EventTypeNormal, events.CreatedContainer, "Created container with id %v", containerID) if ref != nil { m.containerRefManager.SetRef(kubecontainer.ContainerID{ Type: m.runtimeName, ID: containerID, }, ref) } // Step 3: start the container. err = m.runtimeService.StartContainer(containerID) if err != nil { m.recorder.Eventf(ref, api.EventTypeWarning, events.FailedToStartContainer, "Failed to start container with id %v with error: %v", containerID, err) return "Start Container Failed", err } m.recorder.Eventf(ref, api.EventTypeNormal, events.StartedContainer, "Started container with id %v", containerID) // Step 4: execute the post start hook. if container.Lifecycle != nil && container.Lifecycle.PostStart != nil { kubeContainerID := kubecontainer.ContainerID{ Type: m.runtimeName, ID: containerID, } msg, handlerErr := m.runner.Run(kubeContainerID, pod, container, container.Lifecycle.PostStart) if handlerErr != nil { err := fmt.Errorf("PostStart handler: %v", handlerErr) m.generateContainerEvent(kubeContainerID, api.EventTypeWarning, events.FailedPostStartHook, msg) m.killContainer(pod, kubeContainerID, container.Name, "FailedPostStartHook", nil) return "PostStart Hook Failed", err } } return "", nil }
func (r *runtime) RunPod(pod *api.Pod, restartCount int, pullSecrets []api.Secret) error { var ( err error podData []byte podFullName string podID string podStatus *kubecontainer.PodStatus ) podData, err = r.buildHyperPod(pod, restartCount, pullSecrets) if err != nil { glog.Errorf("Hyper: buildHyperPod failed, error: %v", err) return err } podFullName = kubecontainer.BuildPodFullName(pod.Name, pod.Namespace) err = r.savePodSpec(string(podData), podFullName) if err != nil { glog.Errorf("Hyper: savePodSpec failed, error: %v", err) return err } defer func() { if err != nil { specFileName := path.Join(hyperPodSpecDir, podFullName) _, err = os.Stat(specFileName) if err == nil { e := os.Remove(specFileName) if e != nil { glog.Warningf("Hyper: delete spec file for %s failed, error: %v", podFullName, e) } } if podID != "" { destroyErr := r.hyperClient.RemovePod(podID) if destroyErr != nil { glog.Errorf("Hyper: destory pod %s (ID:%s) failed: %v", pod.Name, podID, destroyErr) } } tearDownError := r.networkPlugin.TearDownPod(pod.Namespace, pod.Name, kubecontainer.ContainerID{}, "hyper") if tearDownError != nil { glog.Warningf("Hyper: networkPlugin.TearDownPod failed: %v, kubelet will continue to rm pod %s", tearDownError, pod.Name) } } }() // Setup pod's network by network plugin err = r.networkPlugin.SetUpPod(pod.Namespace, pod.Name, kubecontainer.ContainerID{}, "hyper") if err != nil { glog.Errorf("Hyper: networkPlugin.SetUpPod %s failed, error: %v", pod.Name, err) return err } // Create and start hyper pod specData, err := r.getPodSpec(podFullName) if err != nil { glog.Errorf("Hyper: create pod %s failed, error: %v", podFullName, err) return err } var podSpec grpctypes.UserPod err = json.Unmarshal([]byte(specData), &podSpec) if err != nil { glog.Errorf("Hyper: marshal pod %s from specData error: %v", podFullName, err) } podID, err = r.hyperClient.CreatePod(&podSpec) if err != nil { glog.Errorf("Hyper: create pod %s failed, error: %v", podData, err) return err } err = r.hyperClient.StartPod(podID) if err != nil { glog.Errorf("Hyper: start pod %s (ID:%s) failed, error: %v", pod.Name, podID, err) return err } podStatus, err = r.GetPodStatus(pod.UID, pod.Name, pod.Namespace) if err != nil { return err } runningPod := kubecontainer.ConvertPodStatusToRunningPod(podStatus) for _, container := range pod.Spec.Containers { var containerID kubecontainer.ContainerID for _, runningContainer := range runningPod.Containers { if container.Name == runningContainer.Name { containerID = runningContainer.ID } } // Update container references ref, err := kubecontainer.GenerateContainerRef(pod, &container) if err != nil { glog.Errorf("Couldn't make a ref to pod %q, container %v: '%v'", pod.Name, container.Name, err) } else { r.containerRefManager.SetRef(containerID, ref) } // Create a symbolic link to the Hyper container log file using a name // which captures the full pod name, the container name and the // container ID. Cluster level logging will capture these symbolic // filenames which can be used for search terms in Elasticsearch or for // labels for Cloud Logging. containerLogFile := path.Join(hyperLogsDir, podID, fmt.Sprintf("%s-json.log", containerID.ID)) symlinkFile := LogSymlink(r.containerLogsDir, podFullName, container.Name, containerID.ID) if err = r.os.Symlink(containerLogFile, symlinkFile); err != nil { glog.Errorf("Failed to create symbolic link to the log file of pod %q container %q: %v", podFullName, container.Name, err) } if container.Lifecycle != nil && container.Lifecycle.PostStart != nil { msg, handlerErr := r.runner.Run(containerID, pod, &container, container.Lifecycle.PostStart) if handlerErr != nil { err = fmt.Errorf("PostStart handler: %v, error msg is: %v", handlerErr, msg) if e := r.KillPod(pod, runningPod, nil); e != nil { glog.Errorf("KillPod %v failed: %v", podFullName, e) } return err } } } return nil }
func (r *runtime) RunPod(pod *api.Pod, restartCount int, pullSecrets []api.Secret) error { podFullName := kubecontainer.BuildPodFullName(pod.Name, pod.Namespace) podData, err := r.buildHyperPod(pod, restartCount, pullSecrets) if err != nil { glog.Errorf("Hyper: buildHyperPod failed, error: %v", err) return err } err = r.savePodSpec(string(podData), podFullName) if err != nil { glog.Errorf("Hyper: savePodSpec failed, error: %v", err) return err } // Setup pod's network by network plugin err = r.networkPlugin.SetUpPod(pod.Namespace, pod.Name, "", "hyper") if err != nil { glog.Errorf("Hyper: networkPlugin.SetUpPod %s failed, error: %v", pod.Name, err) return err } // Create and start hyper pod podSpec, err := r.getPodSpec(podFullName) if err != nil { glog.Errorf("Hyper: create pod %s failed, error: %v", podFullName, err) return err } result, err := r.hyperClient.CreatePod(podSpec) if err != nil { glog.Errorf("Hyper: create pod %s failed, error: %v", podData, err) return err } podID := string(result["ID"].(string)) err = r.hyperClient.StartPod(podID) if err != nil { glog.Errorf("Hyper: start pod %s (ID:%s) failed, error: %v", pod.Name, podID, err) destroyErr := r.hyperClient.RemovePod(podID) if destroyErr != nil { glog.Errorf("Hyper: destory pod %s (ID:%s) failed: %v", pod.Name, podID, destroyErr) } return err } podStatus, err := r.GetPodStatus(pod.UID, pod.Name, pod.Namespace) if err != nil { return err } runningPod := kubecontainer.ConvertPodStatusToRunningPod(podStatus) for _, container := range pod.Spec.Containers { var containerID kubecontainer.ContainerID for _, runningContainer := range runningPod.Containers { if container.Name == runningContainer.Name { containerID = runningContainer.ID } } // Update container references ref, err := kubecontainer.GenerateContainerRef(pod, &container) if err != nil { glog.Errorf("Couldn't make a ref to pod %q, container %v: '%v'", pod.Name, container.Name, err) } else { r.containerRefManager.SetRef(containerID, ref) } // Create a symbolic link to the Hyper container log file using a name // which captures the full pod name, the container name and the // container ID. Cluster level logging will capture these symbolic // filenames which can be used for search terms in Elasticsearch or for // labels for Cloud Logging. containerLogFile := path.Join(hyperLogsDir, podID, fmt.Sprintf("%s-json.log", containerID.ID)) symlinkFile := LogSymlink(r.containerLogsDir, podFullName, container.Name, containerID.ID) if err = r.os.Symlink(containerLogFile, symlinkFile); err != nil { glog.Errorf("Failed to create symbolic link to the log file of pod %q container %q: %v", podFullName, container.Name, err) } if container.Lifecycle != nil && container.Lifecycle.PostStart != nil { handlerErr := r.runner.Run(containerID, pod, &container, container.Lifecycle.PostStart) if handlerErr != nil { err := fmt.Errorf("PostStart handler: %v", handlerErr) if e := r.KillPod(pod, runningPod); e != nil { glog.Errorf("KillPod %v failed: %v", podFullName, e) } return err } } } return nil }