mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Ensure terminal pods maintain terminal status
This commit is contained in:
parent
5ff6c2396d
commit
3005ef34f2
@ -1447,6 +1447,20 @@ func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.Po
|
|||||||
allStatus := append(append([]v1.ContainerStatus{}, s.ContainerStatuses...), s.InitContainerStatuses...)
|
allStatus := append(append([]v1.ContainerStatus{}, s.ContainerStatuses...), s.InitContainerStatuses...)
|
||||||
s.Phase = getPhase(&pod.Spec, allStatus)
|
s.Phase = getPhase(&pod.Spec, allStatus)
|
||||||
klog.V(4).InfoS("Got phase for pod", "pod", klog.KObj(pod), "oldPhase", oldPodStatus.Phase, "phase", s.Phase)
|
klog.V(4).InfoS("Got phase for pod", "pod", klog.KObj(pod), "oldPhase", oldPodStatus.Phase, "phase", s.Phase)
|
||||||
|
|
||||||
|
// Perform a three-way merge between the statuses from the status manager,
|
||||||
|
// runtime, and generated status to ensure terminal status is correctly set.
|
||||||
|
if s.Phase != v1.PodFailed && s.Phase != v1.PodSucceeded {
|
||||||
|
switch {
|
||||||
|
case oldPodStatus.Phase == v1.PodFailed || oldPodStatus.Phase == v1.PodSucceeded:
|
||||||
|
klog.V(4).InfoS("Status manager phase was terminal, updating phase to match", "pod", klog.KObj(pod), "phase", oldPodStatus.Phase)
|
||||||
|
s.Phase = oldPodStatus.Phase
|
||||||
|
case pod.Status.Phase == v1.PodFailed || pod.Status.Phase == v1.PodSucceeded:
|
||||||
|
klog.V(4).InfoS("API phase was terminal, updating phase to match", "pod", klog.KObj(pod), "phase", pod.Status.Phase)
|
||||||
|
s.Phase = pod.Status.Phase
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if s.Phase == oldPodStatus.Phase {
|
if s.Phase == oldPodStatus.Phase {
|
||||||
// preserve the reason and message which is associated with the phase
|
// preserve the reason and message which is associated with the phase
|
||||||
s.Reason = oldPodStatus.Reason
|
s.Reason = oldPodStatus.Reason
|
||||||
|
@ -2595,6 +2595,95 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "terminal phase from previous status must remain terminal, restartAlways",
|
||||||
|
pod: &v1.Pod{
|
||||||
|
Spec: desiredState,
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
Phase: v1.PodRunning,
|
||||||
|
ContainerStatuses: []v1.ContainerStatus{
|
||||||
|
runningState("containerA"),
|
||||||
|
runningState("containerB"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
currentStatus: &kubecontainer.PodStatus{},
|
||||||
|
previousStatus: v1.PodStatus{
|
||||||
|
Phase: v1.PodSucceeded,
|
||||||
|
ContainerStatuses: []v1.ContainerStatus{
|
||||||
|
runningState("containerA"),
|
||||||
|
runningState("containerB"),
|
||||||
|
},
|
||||||
|
// Reason and message should be preserved
|
||||||
|
Reason: "Test",
|
||||||
|
Message: "test",
|
||||||
|
},
|
||||||
|
expected: v1.PodStatus{
|
||||||
|
Phase: v1.PodSucceeded,
|
||||||
|
HostIP: "127.0.0.1",
|
||||||
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
||||||
|
{Type: v1.PodReady, Status: v1.ConditionFalse, Reason: "PodCompleted"},
|
||||||
|
{Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: "PodCompleted"},
|
||||||
|
{Type: v1.PodScheduled, Status: v1.ConditionTrue},
|
||||||
|
},
|
||||||
|
ContainerStatuses: []v1.ContainerStatus{
|
||||||
|
ready(waitingWithLastTerminationUnknown("containerA", 1)),
|
||||||
|
ready(waitingWithLastTerminationUnknown("containerB", 1)),
|
||||||
|
},
|
||||||
|
Reason: "Test",
|
||||||
|
Message: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "terminal phase from previous status must remain terminal, restartNever",
|
||||||
|
pod: &v1.Pod{
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
NodeName: "machine",
|
||||||
|
Containers: []v1.Container{
|
||||||
|
{Name: "containerA"},
|
||||||
|
{Name: "containerB"},
|
||||||
|
},
|
||||||
|
RestartPolicy: v1.RestartPolicyNever,
|
||||||
|
},
|
||||||
|
Status: v1.PodStatus{
|
||||||
|
Phase: v1.PodRunning,
|
||||||
|
ContainerStatuses: []v1.ContainerStatus{
|
||||||
|
runningState("containerA"),
|
||||||
|
runningState("containerB"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
currentStatus: &kubecontainer.PodStatus{},
|
||||||
|
previousStatus: v1.PodStatus{
|
||||||
|
Phase: v1.PodSucceeded,
|
||||||
|
ContainerStatuses: []v1.ContainerStatus{
|
||||||
|
succeededState("containerA"),
|
||||||
|
succeededState("containerB"),
|
||||||
|
},
|
||||||
|
// Reason and message should be preserved
|
||||||
|
Reason: "Test",
|
||||||
|
Message: "test",
|
||||||
|
},
|
||||||
|
expected: v1.PodStatus{
|
||||||
|
Phase: v1.PodSucceeded,
|
||||||
|
HostIP: "127.0.0.1",
|
||||||
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
|
Conditions: []v1.PodCondition{
|
||||||
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
||||||
|
{Type: v1.PodReady, Status: v1.ConditionFalse, Reason: "PodCompleted"},
|
||||||
|
{Type: v1.ContainersReady, Status: v1.ConditionFalse, Reason: "PodCompleted"},
|
||||||
|
{Type: v1.PodScheduled, Status: v1.ConditionTrue},
|
||||||
|
},
|
||||||
|
ContainerStatuses: []v1.ContainerStatus{
|
||||||
|
ready(succeededState("containerA")),
|
||||||
|
ready(succeededState("containerB")),
|
||||||
|
},
|
||||||
|
Reason: "Test",
|
||||||
|
Message: "test",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "running can revert to pending",
|
name: "running can revert to pending",
|
||||||
pod: &v1.Pod{
|
pod: &v1.Pod{
|
||||||
|
Loading…
Reference in New Issue
Block a user