Skip to content

Commit b7433df

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 77c7e1d commit b7433df

File tree

5 files changed

+54
-6
lines changed

5 files changed

+54
-6
lines changed

config/core/configmaps/features.yaml

Lines changed: 10 additions & 1 deletion
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: "9ff569ad"
25+
knative.dev/example-checksum: "e2b4e75b"
2626
data:
2727
_example: |-
2828
################################
@@ -234,3 +234,12 @@ data:
234234
235235
# Default queue proxy resource requests and limits to good values for most cases if set.
236236
queueproxy.resource-defaults: "disabled"
237+
238+
# treat-pod-as-always-schedulable can be used to define that Pods in the system will always be
239+
# scheduled, and a Revision should not be marked unschedulable.
240+
# Setting this to `enabled` makes sense if you have cluster-autoscaling set up for you cluster
241+
# where unschedulable Pods trigger the addition of a new Node and are therefore a short and
242+
# transient state.
243+
#
244+
# See https://github.com/knative/serving/issues/14862
245+
treat-pod-as-always-schedulable: "disabled"

pkg/apis/config/features.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ func defaultFeaturesConfig() *Features {
8282
SecurePodDefaults: Disabled,
8383
TagHeaderBasedRouting: Disabled,
8484
AutoDetectHTTP2: Disabled,
85+
TreatPodAsAlwaysSchedulable: Disabled,
8586
}
8687
}
8788

@@ -119,7 +120,8 @@ func NewFeaturesConfigFromMap(data map[string]string) (*Features, error) {
119120
asFlag("tag-header-based-routing", &nc.TagHeaderBasedRouting),
120121
asFlag("queueproxy.resource-defaults", &nc.QueueProxyResourceDefaults),
121122
asFlag("queueproxy.mount-podinfo", &nc.QueueProxyMountPodInfo),
122-
asFlag("autodetect-http2", &nc.AutoDetectHTTP2)); err != nil {
123+
asFlag("autodetect-http2", &nc.AutoDetectHTTP2),
124+
asFlag("treat-pod-as-always-schedulable", &nc.TreatPodAsAlwaysSchedulable)); err != nil {
123125
return nil, err
124126
}
125127
return nc, nil
@@ -161,6 +163,7 @@ type Features struct {
161163
SecurePodDefaults Flag
162164
TagHeaderBasedRouting Flag
163165
AutoDetectHTTP2 Flag
166+
TreatPodAsAlwaysSchedulable Flag
164167
}
165168

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

pkg/apis/config/features_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func TestFeaturesConfiguration(t *testing.T) {
8080
SecurePodDefaults: Enabled,
8181
QueueProxyResourceDefaults: Enabled,
8282
TagHeaderBasedRouting: Enabled,
83+
TreatPodAsAlwaysSchedulable: Enabled,
8384
}),
8485
data: map[string]string{
8586
"multi-container": "Enabled",
@@ -103,6 +104,7 @@ func TestFeaturesConfiguration(t *testing.T) {
103104
"secure-pod-defaults": "Enabled",
104105
"queueproxy.resource-defaults": "Enabled",
105106
"tag-header-based-routing": "Enabled",
107+
"treat-pod-as-always-schedulable": "Enabled",
106108
},
107109
}, {
108110
name: "multi-container Allowed",
@@ -654,6 +656,33 @@ func TestFeaturesConfiguration(t *testing.T) {
654656
data: map[string]string{
655657
"kubernetes.podspec-hostnetwork": "Disabled",
656658
},
659+
}, {
660+
name: "treat-pod-as-always-schedulable Allowed",
661+
wantErr: false,
662+
wantFeatures: defaultWith(&Features{
663+
TreatPodAsAlwaysSchedulable: Allowed,
664+
}),
665+
data: map[string]string{
666+
"treat-pod-as-always-schedulable": "Allowed",
667+
},
668+
}, {
669+
name: "treat-pod-as-always-schedulable Enabled",
670+
wantErr: false,
671+
wantFeatures: defaultWith(&Features{
672+
TreatPodAsAlwaysSchedulable: Enabled,
673+
}),
674+
data: map[string]string{
675+
"treat-pod-as-always-schedulable": "Enabled",
676+
},
677+
}, {
678+
name: "treat-pod-as-always-schedulable Disabled",
679+
wantErr: false,
680+
wantFeatures: defaultWith(&Features{
681+
TreatPodAsAlwaysSchedulable: Disabled,
682+
}),
683+
data: map[string]string{
684+
"treat-pod-as-always-schedulable": "Disabled",
685+
},
657686
}}
658687

659688
for _, tt := range configTests {

pkg/reconciler/revision/reconcile_resources.go

Lines changed: 8 additions & 4 deletions
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

pkg/reconciler/revision/table_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@ func TestReconcile(t *testing.T) {
615615
Object: pa("foo", "pod-schedule-error", WithReachabilityUnreachable),
616616
}},
617617
Key: "foo/pod-schedule-error",
618+
Ctx: defaultconfig.ToContext(context.Background(), &defaultconfig.Config{Features: &defaultconfig.Features{
619+
TreatPodAsAlwaysSchedulable: defaultconfig.Disabled,
620+
}}),
618621
}, {
619622
Name: "ready steady state",
620623
// Test the transition that Reconcile makes when Endpoints become ready on the

0 commit comments

Comments
 (0)