kubelet: Mark ready condition as false explicitly for terminal pods

Terminal pods may continue to report a ready condition of true because
there is a delay in reconciling the ready condition of the containers
from the runtime with the pod status. It should be invalid for kubelet
to report a terminal phase with a true ready condition. To fix the
issue, explicitly override the ready condition to false for terminal
pods during status updates.

Signed-off-by: David Porter <david@porter.me>
This commit is contained in:
David Porter
2022-05-27 13:21:20 -07:00
committed by David Porter
parent b6fb5a2878
commit 7811d84fef
5 changed files with 165 additions and 7 deletions

View File

@@ -317,6 +317,12 @@ func IsPodReadyConditionTrue(status v1.PodStatus) bool {
return condition != nil && condition.Status == v1.ConditionTrue
}
// IsContainersReadyConditionTrue returns true if a pod is ready; false otherwise.
func IsContainersReadyConditionTrue(status v1.PodStatus) bool {
condition := GetContainersReadyCondition(status)
return condition != nil && condition.Status == v1.ConditionTrue
}
// GetPodReadyCondition extracts the pod ready condition from the given status and returns that.
// Returns nil if the condition is not present.
func GetPodReadyCondition(status v1.PodStatus) *v1.PodCondition {
@@ -324,6 +330,13 @@ func GetPodReadyCondition(status v1.PodStatus) *v1.PodCondition {
return condition
}
// GetContainersReadyCondition extracts the containers ready condition from the given status and returns that.
// Returns nil if the condition is not present.
func GetContainersReadyCondition(status v1.PodStatus) *v1.PodCondition {
_, condition := GetPodCondition(&status, v1.ContainersReady)
return condition
}
// GetPodCondition extracts the provided condition from the given status and returns that.
// Returns nil and -1 if the condition is not present, and the index of the located condition.
func GetPodCondition(status *v1.PodStatus, conditionType v1.PodConditionType) (int, *v1.PodCondition) {

View File

@@ -904,3 +904,97 @@ func TestUpdatePodCondition(t *testing.T) {
assert.Equal(t, test.expected, resultStatus, test.desc)
}
}
func TestGetContainersReadyCondition(t *testing.T) {
time := metav1.Now()
containersReadyCondition := v1.PodCondition{
Type: v1.ContainersReady,
Status: v1.ConditionTrue,
Reason: "successfully",
Message: "sync pod successfully",
LastProbeTime: time,
LastTransitionTime: metav1.NewTime(time.Add(1000)),
}
tests := []struct {
desc string
podStatus v1.PodStatus
expectedCondition *v1.PodCondition
}{
{
desc: "containers ready condition exists",
podStatus: v1.PodStatus{
Conditions: []v1.PodCondition{containersReadyCondition},
},
expectedCondition: &containersReadyCondition,
},
{
desc: "containers ready condition does not exist",
podStatus: v1.PodStatus{
Conditions: []v1.PodCondition{},
},
expectedCondition: nil,
},
}
for _, test := range tests {
containersReadyCondition := GetContainersReadyCondition(test.podStatus)
assert.Equal(t, test.expectedCondition, containersReadyCondition, test.desc)
}
}
func TestIsContainersReadyConditionTrue(t *testing.T) {
time := metav1.Now()
tests := []struct {
desc string
podStatus v1.PodStatus
expected bool
}{
{
desc: "containers ready condition is true",
podStatus: v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.ContainersReady,
Status: v1.ConditionTrue,
Reason: "successfully",
Message: "sync pod successfully",
LastProbeTime: time,
LastTransitionTime: metav1.NewTime(time.Add(1000)),
},
},
},
expected: true,
},
{
desc: "containers ready condition is false",
podStatus: v1.PodStatus{
Conditions: []v1.PodCondition{
{
Type: v1.ContainersReady,
Status: v1.ConditionFalse,
Reason: "successfully",
Message: "sync pod successfully",
LastProbeTime: time,
LastTransitionTime: metav1.NewTime(time.Add(1000)),
},
},
},
expected: false,
},
{
desc: "containers ready condition is empty",
podStatus: v1.PodStatus{
Conditions: []v1.PodCondition{},
},
expected: false,
},
}
for _, test := range tests {
isContainersReady := IsContainersReadyConditionTrue(test.podStatus)
assert.Equal(t, test.expected, isContainersReady, test.desc)
}
}