mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-06 18:54:06 +00:00
Merge pull request #27415 from caesarxuchao/fix-oldrc
Automatic merge from submit-queue fix updatePod() of RS and RC controllers Fix updatePod of replication controller manager and replica set controller to handle pod label updates that match no RC or RS. Fix #27405
This commit is contained in:
commit
646a872f15
@ -326,12 +326,8 @@ func (rsc *ReplicaSetController) updatePod(old, cur interface{}) {
|
|||||||
}
|
}
|
||||||
curPod := cur.(*api.Pod)
|
curPod := cur.(*api.Pod)
|
||||||
oldPod := old.(*api.Pod)
|
oldPod := old.(*api.Pod)
|
||||||
glog.V(4).Infof("Pod %s updated %+v -> %+v.", curPod.Name, oldPod, curPod)
|
glog.V(4).Infof("Pod %s updated, objectMeta %+v -> %+v.", curPod.Name, oldPod.ObjectMeta, curPod.ObjectMeta)
|
||||||
rs := rsc.getPodReplicaSet(curPod)
|
labelChanged := !reflect.DeepEqual(curPod.Labels, oldPod.Labels)
|
||||||
if rs == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if curPod.DeletionTimestamp != nil {
|
if curPod.DeletionTimestamp != nil {
|
||||||
// when a pod is deleted gracefully it's deletion timestamp is first modified to reflect a grace period,
|
// when a pod is deleted gracefully it's deletion timestamp is first modified to reflect a grace period,
|
||||||
// and after such time has passed, the kubelet actually deletes it from the store. We receive an update
|
// and after such time has passed, the kubelet actually deletes it from the store. We receive an update
|
||||||
@ -339,11 +335,17 @@ func (rsc *ReplicaSetController) updatePod(old, cur interface{}) {
|
|||||||
// until the kubelet actually deletes the pod. This is different from the Phase of a pod changing, because
|
// until the kubelet actually deletes the pod. This is different from the Phase of a pod changing, because
|
||||||
// an rs never initiates a phase change, and so is never asleep waiting for the same.
|
// an rs never initiates a phase change, and so is never asleep waiting for the same.
|
||||||
rsc.deletePod(curPod)
|
rsc.deletePod(curPod)
|
||||||
|
if labelChanged {
|
||||||
|
// we don't need to check the oldPod.DeletionTimestamp because DeletionTimestamp cannot be unset.
|
||||||
|
rsc.deletePod(oldPod)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rs := rsc.getPodReplicaSet(curPod); rs != nil {
|
||||||
rsc.enqueueReplicaSet(rs)
|
rsc.enqueueReplicaSet(rs)
|
||||||
if !reflect.DeepEqual(curPod.Labels, oldPod.Labels) {
|
}
|
||||||
|
if labelChanged {
|
||||||
// If the old and new ReplicaSet are the same, the first one that syncs
|
// If the old and new ReplicaSet are the same, the first one that syncs
|
||||||
// will set expectations preventing any damage from the second.
|
// will set expectations preventing any damage from the second.
|
||||||
if oldRS := rsc.getPodReplicaSet(oldPod); oldRS != nil {
|
if oldRS := rsc.getPodReplicaSet(oldPod); oldRS != nil {
|
||||||
|
@ -547,15 +547,13 @@ func TestUpdatePods(t *testing.T) {
|
|||||||
testRSSpec2.Name = "barfoo"
|
testRSSpec2.Name = "barfoo"
|
||||||
manager.rsStore.Store.Add(&testRSSpec2)
|
manager.rsStore.Store.Add(&testRSSpec2)
|
||||||
|
|
||||||
// Put one pod in the podStore
|
// case 1: We put in the podStore a pod with labels matching testRSSpec1,
|
||||||
|
// then update its labels to match testRSSpec2. We expect to receive a sync
|
||||||
|
// request for both replica sets.
|
||||||
pod1 := newPodList(manager.podStore.Indexer, 1, api.PodRunning, labelMap1, testRSSpec1, "pod").Items[0]
|
pod1 := newPodList(manager.podStore.Indexer, 1, api.PodRunning, labelMap1, testRSSpec1, "pod").Items[0]
|
||||||
pod2 := pod1
|
pod2 := pod1
|
||||||
pod2.Labels = labelMap2
|
pod2.Labels = labelMap2
|
||||||
|
|
||||||
// Send an update of the same pod with modified labels, and confirm we get a sync request for
|
|
||||||
// both controllers
|
|
||||||
manager.updatePod(&pod1, &pod2)
|
manager.updatePod(&pod1, &pod2)
|
||||||
|
|
||||||
expected := sets.NewString(testRSSpec1.Name, testRSSpec2.Name)
|
expected := sets.NewString(testRSSpec1.Name, testRSSpec2.Name)
|
||||||
for _, name := range expected.List() {
|
for _, name := range expected.List() {
|
||||||
t.Logf("Expecting update for %+v", name)
|
t.Logf("Expecting update for %+v", name)
|
||||||
@ -568,6 +566,24 @@ func TestUpdatePods(t *testing.T) {
|
|||||||
t.Errorf("Expected update notifications for replica sets within 100ms each")
|
t.Errorf("Expected update notifications for replica sets within 100ms each")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// case 2: pod1 in the podStore has labels matching testRSSpec1. We update
|
||||||
|
// its labels to match no replica set. We expect to receive a sync request
|
||||||
|
// for testRSSpec1.
|
||||||
|
pod2.Labels = make(map[string]string)
|
||||||
|
manager.updatePod(&pod1, &pod2)
|
||||||
|
expected = sets.NewString(testRSSpec1.Name)
|
||||||
|
for _, name := range expected.List() {
|
||||||
|
t.Logf("Expecting update for %+v", name)
|
||||||
|
select {
|
||||||
|
case got := <-received:
|
||||||
|
if !expected.Has(got) {
|
||||||
|
t.Errorf("Expected keys %#v got %v", expected, got)
|
||||||
|
}
|
||||||
|
case <-time.After(wait.ForeverTestTimeout):
|
||||||
|
t.Errorf("Expected update notifications for replica sets within 100ms each")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestControllerUpdateRequeue(t *testing.T) {
|
func TestControllerUpdateRequeue(t *testing.T) {
|
||||||
|
@ -353,12 +353,9 @@ func (rm *ReplicationManager) updatePod(old, cur interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
curPod := cur.(*api.Pod)
|
curPod := cur.(*api.Pod)
|
||||||
rc := rm.getPodController(curPod)
|
|
||||||
if rc == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
oldPod := old.(*api.Pod)
|
oldPod := old.(*api.Pod)
|
||||||
|
glog.V(4).Infof("Pod %s updated, objectMeta %+v -> %+v.", curPod.Name, oldPod.ObjectMeta, curPod.ObjectMeta)
|
||||||
|
labelChanged := !reflect.DeepEqual(curPod.Labels, oldPod.Labels)
|
||||||
if curPod.DeletionTimestamp != nil {
|
if curPod.DeletionTimestamp != nil {
|
||||||
// when a pod is deleted gracefully it's deletion timestamp is first modified to reflect a grace period,
|
// when a pod is deleted gracefully it's deletion timestamp is first modified to reflect a grace period,
|
||||||
// and after such time has passed, the kubelet actually deletes it from the store. We receive an update
|
// and after such time has passed, the kubelet actually deletes it from the store. We receive an update
|
||||||
@ -366,11 +363,18 @@ func (rm *ReplicationManager) updatePod(old, cur interface{}) {
|
|||||||
// until the kubelet actually deletes the pod. This is different from the Phase of a pod changing, because
|
// until the kubelet actually deletes the pod. This is different from the Phase of a pod changing, because
|
||||||
// an rc never initiates a phase change, and so is never asleep waiting for the same.
|
// an rc never initiates a phase change, and so is never asleep waiting for the same.
|
||||||
rm.deletePod(curPod)
|
rm.deletePod(curPod)
|
||||||
|
if labelChanged {
|
||||||
|
// we don't need to check the oldPod.DeletionTimestamp because DeletionTimestamp cannot be unset.
|
||||||
|
rm.deletePod(oldPod)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rc := rm.getPodController(curPod); rc != nil {
|
||||||
rm.enqueueController(rc)
|
rm.enqueueController(rc)
|
||||||
|
}
|
||||||
// Only need to get the old controller if the labels changed.
|
// Only need to get the old controller if the labels changed.
|
||||||
if !reflect.DeepEqual(curPod.Labels, oldPod.Labels) {
|
if labelChanged {
|
||||||
// If the old and new rc are the same, the first one that syncs
|
// If the old and new rc are the same, the first one that syncs
|
||||||
// will set expectations preventing any damage from the second.
|
// will set expectations preventing any damage from the second.
|
||||||
if oldRC := rm.getPodController(oldPod); oldRC != nil {
|
if oldRC := rm.getPodController(oldPod); oldRC != nil {
|
||||||
|
@ -531,15 +531,13 @@ func TestUpdatePods(t *testing.T) {
|
|||||||
testControllerSpec2.Name = "barfoo"
|
testControllerSpec2.Name = "barfoo"
|
||||||
manager.rcStore.Indexer.Add(&testControllerSpec2)
|
manager.rcStore.Indexer.Add(&testControllerSpec2)
|
||||||
|
|
||||||
// Put one pod in the podStore
|
// case 1: We put in the podStore a pod with labels matching
|
||||||
|
// testControllerSpec1, then update its labels to match testControllerSpec2.
|
||||||
|
// We expect to receive a sync request for both controllers.
|
||||||
pod1 := newPodList(manager.podStore.Indexer, 1, api.PodRunning, testControllerSpec1, "pod").Items[0]
|
pod1 := newPodList(manager.podStore.Indexer, 1, api.PodRunning, testControllerSpec1, "pod").Items[0]
|
||||||
pod2 := pod1
|
pod2 := pod1
|
||||||
pod2.Labels = testControllerSpec2.Spec.Selector
|
pod2.Labels = testControllerSpec2.Spec.Selector
|
||||||
|
|
||||||
// Send an update of the same pod with modified labels, and confirm we get a sync request for
|
|
||||||
// both controllers
|
|
||||||
manager.updatePod(&pod1, &pod2)
|
manager.updatePod(&pod1, &pod2)
|
||||||
|
|
||||||
expected := sets.NewString(testControllerSpec1.Name, testControllerSpec2.Name)
|
expected := sets.NewString(testControllerSpec1.Name, testControllerSpec2.Name)
|
||||||
for _, name := range expected.List() {
|
for _, name := range expected.List() {
|
||||||
t.Logf("Expecting update for %+v", name)
|
t.Logf("Expecting update for %+v", name)
|
||||||
@ -552,6 +550,24 @@ func TestUpdatePods(t *testing.T) {
|
|||||||
t.Errorf("Expected update notifications for controllers within 100ms each")
|
t.Errorf("Expected update notifications for controllers within 100ms each")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// case 2: pod1 in the podStore has labels matching testControllerSpec1.
|
||||||
|
// We update its labels to match no replication controller. We expect to
|
||||||
|
// receive a sync request for testControllerSpec1.
|
||||||
|
pod2.Labels = make(map[string]string)
|
||||||
|
manager.updatePod(&pod1, &pod2)
|
||||||
|
expected = sets.NewString(testControllerSpec1.Name)
|
||||||
|
for _, name := range expected.List() {
|
||||||
|
t.Logf("Expecting update for %+v", name)
|
||||||
|
select {
|
||||||
|
case got := <-received:
|
||||||
|
if !expected.Has(got) {
|
||||||
|
t.Errorf("Expected keys %#v got %v", expected, got)
|
||||||
|
}
|
||||||
|
case <-time.After(wait.ForeverTestTimeout):
|
||||||
|
t.Errorf("Expected update notifications for controllers within 100ms each")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestControllerUpdateRequeue(t *testing.T) {
|
func TestControllerUpdateRequeue(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user