Skip to content

Commit a022e64

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 Signed-off-by: Sascha Schwarze <schwarzs@de.ibm.com>
1 parent db2721f commit a022e64

File tree

4 files changed

+50
-5
lines changed

4 files changed

+50
-5
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: "63a13754"
25+
knative.dev/example-checksum: "0ac06704"
2626
data:
2727
_example: |-
2828
################################
@@ -242,3 +242,12 @@ data:
242242
243243
# Default queue proxy resource requests and limits to good values for most cases if set.
244244
queueproxy.resource-defaults: "disabled"
245+
246+
# treat-pod-as-always-schedulable can be used to define that Pods in the system will always be
247+
# scheduled, and a Revision should not be marked unschedulable.
248+
# Setting this to `enabled` makes sense if you have cluster-autoscaling set up for you cluster
249+
# where unschedulable Pods trigger the addition of a new Node and are therefore a short and
250+
# transient state.
251+
#
252+
# See https://github.com/knative/serving/issues/14862
253+
treat-pod-as-always-schedulable: "disabled"

pkg/apis/config/features.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ func defaultFeaturesConfig() *Features {
109109
SecurePodDefaults: Disabled,
110110
TagHeaderBasedRouting: Disabled,
111111
AutoDetectHTTP2: Disabled,
112+
TreatPodAsAlwaysSchedulable: Disabled,
112113
}
113114
}
114115

@@ -126,6 +127,7 @@ func NewFeaturesConfigFromMap(data map[string]string) (*Features, error) {
126127
asFlag("queueproxy.resource-defaults", &nc.QueueProxyResourceDefaults),
127128
asFlag("secure-pod-defaults", &nc.SecurePodDefaults),
128129
asFlag("tag-header-based-routing", &nc.TagHeaderBasedRouting),
130+
asFlag("treat-pod-as-always-schedulable", &nc.TreatPodAsAlwaysSchedulable),
129131
asFlag(FeatureContainerSpecAddCapabilities, &nc.ContainerSpecAddCapabilities),
130132
asFlag(FeaturePodSpecAffinity, &nc.PodSpecAffinity),
131133
asFlag(FeaturePodSpecDNSConfig, &nc.PodSpecDNSConfig),
@@ -191,6 +193,7 @@ type Features struct {
191193
SecurePodDefaults Flag
192194
TagHeaderBasedRouting Flag
193195
AutoDetectHTTP2 Flag
196+
TreatPodAsAlwaysSchedulable Flag
194197
}
195198

196199
// 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",
@@ -672,6 +674,33 @@ func TestFeaturesConfiguration(t *testing.T) {
672674
data: map[string]string{
673675
"kubernetes.podspec-hostnetwork": "Disabled",
674676
},
677+
}, {
678+
name: "treat-pod-as-always-schedulable Allowed",
679+
wantErr: false,
680+
wantFeatures: defaultWith(&Features{
681+
TreatPodAsAlwaysSchedulable: Allowed,
682+
}),
683+
data: map[string]string{
684+
"treat-pod-as-always-schedulable": "Allowed",
685+
},
686+
}, {
687+
name: "treat-pod-as-always-schedulable Enabled",
688+
wantErr: false,
689+
wantFeatures: defaultWith(&Features{
690+
TreatPodAsAlwaysSchedulable: Enabled,
691+
}),
692+
data: map[string]string{
693+
"treat-pod-as-always-schedulable": "Enabled",
694+
},
695+
}, {
696+
name: "treat-pod-as-always-schedulable Disabled",
697+
wantErr: false,
698+
wantFeatures: defaultWith(&Features{
699+
TreatPodAsAlwaysSchedulable: Disabled,
700+
}),
701+
data: map[string]string{
702+
"treat-pod-as-always-schedulable": "Disabled",
703+
},
675704
}}
676705

677706
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.Enabled {
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)