Skip to content

Commit e5cb758

Browse files
Add feature flag treat-pod-as-always-schedulable
The feature flag allows to declare that Pods in the system will eventually all get scheduled and Revisions should therefore not be marked unschedulable
1 parent fea0e7a commit e5cb758

File tree

4 files changed

+51
-6
lines changed

4 files changed

+51
-6
lines changed

config/core/configmaps/features.yaml

+10-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ metadata:
2222
app.kubernetes.io/component: controller
2323
app.kubernetes.io/version: devel
2424
annotations:
25-
knative.dev/example-checksum: "632d47dd"
25+
knative.dev/example-checksum: "7b73abaa"
2626
data:
2727
_example: |-
2828
################################
@@ -216,3 +216,12 @@ data:
216216
217217
# Default queue proxy resource requests and limits to good values for most cases if set.
218218
queueproxy.resource-defaults: "disabled"
219+
220+
# treat-pod-as-always-schedulable can be used to define that Pods in the system will always be
221+
# scheduled, and a Revision should not be marked unschedulable.
222+
# Setting this to `enabled` makes sense if you have cluster-autoscaling set up for you cluster
223+
# where unschedulable Pods trigger the addition of a new Node and are therefore a short and
224+
# transient state.
225+
#
226+
# See https://github.com/knative/serving/issues/14862
227+
treat-pod-as-always-schedulable: "disabled"

pkg/apis/config/features.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func defaultFeaturesConfig() *Features {
7979
SecurePodDefaults: Disabled,
8080
TagHeaderBasedRouting: Disabled,
8181
AutoDetectHTTP2: Disabled,
82+
TreatPodAsAlwaysSchedulable: Disabled,
8283
}
8384
}
8485

@@ -112,7 +113,8 @@ func NewFeaturesConfigFromMap(data map[string]string) (*Features, error) {
112113
asFlag("tag-header-based-routing", &nc.TagHeaderBasedRouting),
113114
asFlag("queueproxy.resource-defaults", &nc.QueueProxyResourceDefaults),
114115
asFlag("queueproxy.mount-podinfo", &nc.QueueProxyMountPodInfo),
115-
asFlag("autodetect-http2", &nc.AutoDetectHTTP2)); err != nil {
116+
asFlag("autodetect-http2", &nc.AutoDetectHTTP2),
117+
asFlag("treat-pod-as-always-schedulable", &nc.TreatPodAsAlwaysSchedulable)); err != nil {
116118
return nil, err
117119
}
118120
return nc, nil
@@ -151,6 +153,7 @@ type Features struct {
151153
SecurePodDefaults Flag
152154
TagHeaderBasedRouting Flag
153155
AutoDetectHTTP2 Flag
156+
TreatPodAsAlwaysSchedulable Flag
154157
}
155158

156159
// asFlag parses the value at key as a Flag into the target, if it exists.

pkg/apis/config/features_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ func TestFeaturesConfiguration(t *testing.T) {
7777
SecurePodDefaults: Enabled,
7878
QueueProxyResourceDefaults: Enabled,
7979
TagHeaderBasedRouting: Enabled,
80+
TreatPodAsAlwaysSchedulable: Enabled,
8081
}),
8182
data: map[string]string{
8283
"multi-container": "Enabled",
@@ -97,6 +98,7 @@ func TestFeaturesConfiguration(t *testing.T) {
9798
"secure-pod-defaults": "Enabled",
9899
"queueproxy.resource-defaults": "Enabled",
99100
"tag-header-based-routing": "Enabled",
101+
"treat-pod-as-always-schedulable": "Enabled",
100102
},
101103
}, {
102104
name: "multi-container Allowed",
@@ -594,6 +596,33 @@ func TestFeaturesConfiguration(t *testing.T) {
594596
data: map[string]string{
595597
"kubernetes.podspec-dnsconfig": "Disabled",
596598
},
599+
}, {
600+
name: "treat-pod-as-always-schedulable Allowed",
601+
wantErr: false,
602+
wantFeatures: defaultWith(&Features{
603+
TreatPodAsAlwaysSchedulable: Allowed,
604+
}),
605+
data: map[string]string{
606+
"treat-pod-as-always-schedulable": "Allowed",
607+
},
608+
}, {
609+
name: "treat-pod-as-always-schedulable Enabled",
610+
wantErr: false,
611+
wantFeatures: defaultWith(&Features{
612+
TreatPodAsAlwaysSchedulable: Enabled,
613+
}),
614+
data: map[string]string{
615+
"treat-pod-as-always-schedulable": "Enabled",
616+
},
617+
}, {
618+
name: "treat-pod-as-always-schedulable Disabled",
619+
wantErr: false,
620+
wantFeatures: defaultWith(&Features{
621+
TreatPodAsAlwaysSchedulable: Disabled,
622+
}),
623+
data: map[string]string{
624+
"treat-pod-as-always-schedulable": "Disabled",
625+
},
597626
}}
598627

599628
for _, tt := range configTests {

pkg/reconciler/revision/reconcile_resources.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"knative.dev/pkg/kmp"
3737
"knative.dev/pkg/logging"
3838
"knative.dev/pkg/logging/logkey"
39+
apicfg "knative.dev/serving/pkg/apis/config"
3940
v1 "knative.dev/serving/pkg/apis/serving/v1"
4041
"knative.dev/serving/pkg/networking"
4142
"knative.dev/serving/pkg/reconciler/revision/config"
@@ -87,10 +88,13 @@ func (c *Reconciler) reconcileDeployment(ctx context.Context, rev *v1.Revision)
8788

8889
// Update the revision status if pod cannot be scheduled (possibly resource constraints)
8990
// If pod cannot be scheduled then we expect the container status to be empty.
90-
for _, cond := range pod.Status.Conditions {
91-
if cond.Type == corev1.PodScheduled && cond.Status == corev1.ConditionFalse {
92-
rev.Status.MarkResourcesAvailableFalse(cond.Reason, cond.Message)
93-
break
91+
treatPodAsAlwaysSchedulable := config.FromContext(ctx).Features.TreatPodAsAlwaysSchedulable
92+
if treatPodAsAlwaysSchedulable == apicfg.Disabled {
93+
for _, cond := range pod.Status.Conditions {
94+
if cond.Type == corev1.PodScheduled && cond.Status == corev1.ConditionFalse {
95+
rev.Status.MarkResourcesAvailableFalse(cond.Reason, cond.Message)
96+
break
97+
}
9498
}
9599
}
96100

0 commit comments

Comments
 (0)