Change:
In autoscaling tests, we verify that when a node suddenly disappears from the cluster, Cluster Autoscaler will add another one to replace it. With TaintNodesByCondition (enabled by default in ), this is now failing: https://k8s- Every time a node disappears, a subset of pods become NodeLost and aren't rescheduled on a new node. /cc /sig node
I can work on this.
just got merged. Let's check result of autoscaling testings tomorrow: https://k8s-
latest autoscaling testing is green. I think we can close this issue.
Thanks for fixing this!

Discussion:
Effect: v1.TaintEffectNoExecute, } <del> nodeConditionToTaintKeyStatusMap = map[v1.NodeConditionType]struct { taintKey string // noScheduleStatus is the condition under which the node should be tainted as not schedulable for this // NodeConditionType noScheduleStatus v1.ConditionStatus }{ </del> <ins> // map {NodeConditionType: {ConditionStatus: TaintKey}} // represents which NodeConditionType under which ConditionStatus should be // tainted with which TaintKey // for certain NodeConditionType, there are multiple {ConditionStatus,TaintKey} pairs nodeConditionToTaintKeyStatusMap = map[v1.NodeConditionType]map[v1.ConditionStatus]string{ </ins> v1.NodeReady: { <del> taintKey:         algorithm.TaintNodeNotReady, noScheduleStatus: v1.ConditionFalse, </del> <ins> v1.ConditionFalse:   algorithm.TaintNodeNotReady, v1.ConditionUnknown: algorithm.TaintNodeUnreachable, </ins> }, v1.NodeMemoryPressure: { <del> taintKey:         algorithm.TaintNodeMemoryPressure, noScheduleStatus: v1.ConditionTrue, </del> <ins> v1.ConditionTrue: algorithm.TaintNodeMemoryPressure, </ins> }, v1.NodeOutOfDisk: { <del> taintKey:         algorithm.TaintNodeOutOfDisk, noScheduleStatus: v1.ConditionTrue, </del> <ins> v1.ConditionTrue: algorithm.TaintNodeOutOfDisk, </ins> }, v1.NodeDiskPressure: { <del> taintKey:         algorithm.TaintNodeDiskPressure, noScheduleStatus: v1.ConditionTrue, </del> <ins> v1.ConditionTrue: algorithm.TaintNodeDiskPressure, </ins> }, v1.NodeNetworkUnavailable: { <del> taintKey:         algorithm.TaintNodeNetworkUnavailable, noScheduleStatus: v1.ConditionTrue, </del> <ins> v1.ConditionTrue: algorithm.TaintNodeNetworkUnavailable, </ins> }, v1.NodePIDPressure: { <del> taintKey:         algorithm.TaintNodePIDPressure, noScheduleStatus: v1.ConditionTrue, </del> <ins> v1.ConditionTrue: algorithm.TaintNodePIDPressure, </ins> }, } taintKeyToNodeConditionMap = map[string]v1.NodeConditionType{ algorithm.TaintNodeNotReady:           v1.NodeReady, <ins> algorithm.TaintNodeUnreachable:        v1.NodeReady, </ins> algorithm.TaintNodeNetworkUnavailable: v1.NodeNetworkUnavailable, algorithm.TaintNodeMemoryPressure:     v1.NodeMemoryPressure, algorithm.TaintNodeOutOfDisk:          v1.NodeOutOfDisk,

// Map node's condition to Taints. var taints []v1.Taint for _, condition := range node.Status.Conditions { <del> if taint, found := nodeConditionToTaintKeyStatusMap[condition.Type]; found { if condition.Status == taint.noScheduleStatus { </del> <ins> if taintMap, found := nodeConditionToTaintKeyStatusMap[condition.Type]; found { if taintKey, found := taintMap[condition.Status]; found { </ins> taints = append(taints, v1.Taint{ <del> Key:    taint.taintKey, </del> <ins> Key:    taintKey, </ins> Effect: v1.TaintEffectNoSchedule, }) }

// Get exist taints of node. nodeTaints := taintutils.TaintSetFilter(node.Spec.Taints, func(t *v1.Taint) bool { <ins> // only NoSchedule taints are candidates to be compared with "taints" later if t.Effect != v1.TaintEffectNoSchedule { return false } </ins> // Find unschedulable taint of node. if t.Key == algorithm.TaintNodeUnschedulable { return true

Key:    algorithm.TaintNodeNotReady, Effect: v1.TaintEffectNoSchedule, } <ins> unreachableTaint := &v1.Taint{ Key:    algorithm.TaintNodeUnreachable, Effect: v1.TaintEffectNoSchedule, } </ins> tests := []struct { Name           string

}, ExpectedTaints: []*v1.Taint{notReadyTaint}, }, <ins> { Name: "Ready is unknown", Node: &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name:              "node0", CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), Labels: map[string]string{ kubeletapis.LabelZoneRegion:        "region1", kubeletapis.LabelZoneFailureDomain: "zone1", }, }, Status: v1.NodeStatus{ Conditions: []v1.NodeCondition{ { Type:               v1.NodeReady, Status:             v1.ConditionUnknown, LastHeartbeatTime:  metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC), }, }, }, }, ExpectedTaints: []*v1.Taint{unreachableTaint}, }, </ins> } for _, test := range tests {

__EOF__ # taint/untaint <del> # Pre-condition: node has no taints kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.taints}}" '<no value>' </del> <ins> # Pre-condition: node doesn't have dedicated=foo:PreferNoSchedule taint kube::test::get_object_assert "nodes 127.0.0.1" '{{range .spec.taints}}{{if eq .key "dedicated"}}{{.key}}={{.value}}:{{.effect}}{{end}}{{end}}' "" # expect no output </ins> # taint can add a taint kubectl taint node 127.0.0.1 dedicated=foo:PreferNoSchedule <del> kube::test::get_object_assert "nodes 127.0.0.1" '{{range .spec.taints}}{{.effect}}{{end}}' 'PreferNoSchedule' </del> <ins> kube::test::get_object_assert "nodes 127.0.0.1" '{{range .spec.taints}}{{if eq .key "dedicated"}}{{.key}}={{.value}}:{{.effect}}{{end}}{{end}}' "dedicated=foo:PreferNoSchedule" </ins> # taint can remove a taint kubectl taint node 127.0.0.1 dedicated- <del> # Post-condition: node has no taints kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.taints}}" '<no value>' </del> <ins> # Post-condition: node doesn't have dedicated=foo:PreferNoSchedule taint kube::test::get_object_assert "nodes 127.0.0.1" '{{range .spec.taints}}{{if eq .key "dedicated"}}{{.key}}={{.value}}:{{.effect}}{{end}}{{end}}' "" # expect no output </ins> ### kubectl cordon update with --dry-run does not mark node unschedulable # Pre-condition: node is schedulable