Skip to content

Commit b3a7a3b

Browse files
committed
perf: move lbp configuration up to the annotation level
1 parent 8a7e201 commit b3a7a3b

File tree

11 files changed

+63
-90
lines changed

11 files changed

+63
-90
lines changed

config/core/300-resources/configuration.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,12 +1027,6 @@ spec:
10271027
description: This is accessible behind a feature flag - kubernetes.podspec-init-containers
10281028
type: object
10291029
x-kubernetes-preserve-unknown-fields: true
1030-
loadBalancingPolicy:
1031-
description: |-
1032-
LoadBalancingPolicy is the load balancing algorithm used by the
1033-
activator to route requests to application pods. If unspecified,
1034-
a suggested default is applied depending on ContainerConcurrency
1035-
type: string
10361030
nodeSelector:
10371031
description: |-
10381032
This is accessible behind a feature flag - kubernetes.podspec-nodeselector

config/core/300-resources/revision.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,12 +1003,6 @@ spec:
10031003
description: This is accessible behind a feature flag - kubernetes.podspec-init-containers
10041004
type: object
10051005
x-kubernetes-preserve-unknown-fields: true
1006-
loadBalancingPolicy:
1007-
description: |-
1008-
LoadBalancingPolicy is the load balancing algorithm used by the
1009-
activator to route requests to application pods. If unspecified,
1010-
a suggested default is applied depending on ContainerConcurrency
1011-
type: string
10121006
nodeSelector:
10131007
description: |-
10141008
This is accessible behind a feature flag - kubernetes.podspec-nodeselector

config/core/300-resources/service.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,12 +1045,6 @@ spec:
10451045
description: This is accessible behind a feature flag - kubernetes.podspec-init-containers
10461046
type: object
10471047
x-kubernetes-preserve-unknown-fields: true
1048-
loadBalancingPolicy:
1049-
description: |-
1050-
LoadBalancingPolicy is the load balancing algorithm used by the
1051-
activator to route requests to application pods. If unspecified,
1052-
a suggested default is applied depending on ContainerConcurrency
1053-
type: string
10541048
nodeSelector:
10551049
description: |-
10561050
This is accessible behind a feature flag - kubernetes.podspec-nodeselector

docs/serving-api.md

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -948,20 +948,6 @@ to stay open while not receiving any bytes from the user’s application. If
948948
unspecified, a system default will be provided.</p>
949949
</td>
950950
</tr>
951-
<tr>
952-
<td>
953-
<code>loadBalancingPolicy</code><br/>
954-
<em>
955-
string
956-
</em>
957-
</td>
958-
<td>
959-
<em>(Optional)</em>
960-
<p>LoadBalancingPolicy is the load balancing algorithm used by the
961-
activator to route requests to application pods. If unspecified,
962-
a suggested default is applied depending on ContainerConcurrency</p>
963-
</td>
964-
</tr>
965951
</table>
966952
</td>
967953
</tr>
@@ -1452,20 +1438,6 @@ to stay open while not receiving any bytes from the user&rsquo;s application. If
14521438
unspecified, a system default will be provided.</p>
14531439
</td>
14541440
</tr>
1455-
<tr>
1456-
<td>
1457-
<code>loadBalancingPolicy</code><br/>
1458-
<em>
1459-
string
1460-
</em>
1461-
</td>
1462-
<td>
1463-
<em>(Optional)</em>
1464-
<p>LoadBalancingPolicy is the load balancing algorithm used by the
1465-
activator to route requests to application pods. If unspecified,
1466-
a suggested default is applied depending on ContainerConcurrency</p>
1467-
</td>
1468-
</tr>
14691441
</tbody>
14701442
</table>
14711443
<h3 id="serving.knative.dev/v1.RevisionStatus">RevisionStatus
@@ -1694,20 +1666,6 @@ to stay open while not receiving any bytes from the user&rsquo;s application. If
16941666
unspecified, a system default will be provided.</p>
16951667
</td>
16961668
</tr>
1697-
<tr>
1698-
<td>
1699-
<code>loadBalancingPolicy</code><br/>
1700-
<em>
1701-
string
1702-
</em>
1703-
</td>
1704-
<td>
1705-
<em>(Optional)</em>
1706-
<p>LoadBalancingPolicy is the load balancing algorithm used by the
1707-
activator to route requests to application pods. If unspecified,
1708-
a suggested default is applied depending on ContainerConcurrency</p>
1709-
</td>
1710-
</tr>
17111669
</table>
17121670
</td>
17131671
</tr>

pkg/activator/net/throttler.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,9 +601,14 @@ func (t *Throttler) getOrCreateRevisionThrottler(revID types.NamespacedName) (*r
601601
if err != nil {
602602
return nil, err
603603
}
604+
// Get load balancing policy from annotation
605+
var lbPolicy *string
606+
if _, v, ok := serving.LoadBalancingPolicyAnnotation.Get(rev.GetAnnotations()); ok && v != "" {
607+
lbPolicy = &v
608+
}
604609
revThrottler = newRevisionThrottler(
605610
revID,
606-
rev.Spec.LoadBalancingPolicy,
611+
lbPolicy,
607612
int(rev.Spec.GetContainerConcurrency()),
608613
pkgnet.ServicePortName(rev.GetProtocol()),
609614
queue.BreakerParams{QueueDepth: breakerQueueDepth, MaxConcurrency: revisionMaxConcurrency},
@@ -626,12 +631,17 @@ func (t *Throttler) revisionUpdated(obj any) {
626631
t.logger.Errorw("Failed to get revision throttler for revision",
627632
zap.Error(err), zap.String(logkey.Key, revID.String()))
628633
} else if rt != nil {
629-
// Update the lbPolicy dynamically if the revision's spec policy changed
634+
// Update the lbPolicy dynamically if the revision's annotation policy changed
630635
containerConcurrency := rev.Spec.GetContainerConcurrency()
631636
if containerConcurrency < 0 {
632637
containerConcurrency = 0
633638
}
634-
newPolicy, name := pickLBPolicy(rev.Spec.LoadBalancingPolicy, nil, int(containerConcurrency), t.logger)
639+
// Get load balancing policy from annotation
640+
var lbPolicy *string
641+
if _, v, ok := serving.LoadBalancingPolicyAnnotation.Get(rev.GetAnnotations()); ok && v != "" {
642+
lbPolicy = &v
643+
}
644+
newPolicy, name := pickLBPolicy(lbPolicy, nil, int(containerConcurrency), t.logger)
635645
// Use atomic store for lock-free access in the hot request path
636646
rt.lbPolicy.Store(newPolicy)
637647
// Safe conversion: containerConcurrency is guaranteed to be non-negative after the check above

pkg/activator/net/throttler_test.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,9 +1222,11 @@ func TestThrottlerUsesRevisionLoadBalancingPolicy(t *testing.T) {
12221222
ObjectMeta: metav1.ObjectMeta{
12231223
Name: "test-revision-rc2",
12241224
Namespace: "test-namespace",
1225+
Annotations: map[string]string{
1226+
"serving.knative.dev/load-balancing-policy": "random-choice-2",
1227+
},
12251228
},
12261229
Spec: v1.RevisionSpec{
1227-
LoadBalancingPolicy: stringPtr("random-choice-2"),
12281230
ContainerConcurrency: ptr.Int64(10),
12291231
},
12301232
},
@@ -1235,9 +1237,11 @@ func TestThrottlerUsesRevisionLoadBalancingPolicy(t *testing.T) {
12351237
ObjectMeta: metav1.ObjectMeta{
12361238
Name: "test-revision-rr",
12371239
Namespace: "test-namespace",
1240+
Annotations: map[string]string{
1241+
"serving.knative.dev/load-balancing-policy": "round-robin",
1242+
},
12381243
},
12391244
Spec: v1.RevisionSpec{
1240-
LoadBalancingPolicy: stringPtr("round-robin"),
12411245
ContainerConcurrency: ptr.Int64(10),
12421246
},
12431247
},
@@ -1248,9 +1252,11 @@ func TestThrottlerUsesRevisionLoadBalancingPolicy(t *testing.T) {
12481252
ObjectMeta: metav1.ObjectMeta{
12491253
Name: "test-revision-lc",
12501254
Namespace: "test-namespace",
1255+
Annotations: map[string]string{
1256+
"serving.knative.dev/load-balancing-policy": "least-connections",
1257+
},
12511258
},
12521259
Spec: v1.RevisionSpec{
1253-
LoadBalancingPolicy: stringPtr("least-connections"),
12541260
ContainerConcurrency: ptr.Int64(10),
12551261
},
12561262
},
@@ -1354,9 +1360,12 @@ func TestDynamicLoadBalancingPolicyUpdate(t *testing.T) {
13541360
t.Fatalf("Unexpected distribution before update: %v", selections)
13551361
}
13561362

1357-
// Update the revision to set round-robin via spec and invoke revisionUpdated
1363+
// Update the revision to set round-robin via annotation and invoke revisionUpdated
13581364
rev = rev.DeepCopy()
1359-
rev.Spec.LoadBalancingPolicy = stringPtr("round-robin")
1365+
if rev.Annotations == nil {
1366+
rev.Annotations = make(map[string]string)
1367+
}
1368+
rev.Annotations["serving.knative.dev/load-balancing-policy"] = "round-robin"
13601369
// Update informer store and call revisionUpdated
13611370
revisions.Informer().GetIndexer().Update(rev)
13621371
throttler.revisionUpdated(rev)

pkg/apis/serving/register.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ const (
144144

145145
// ProgressDeadlineAnnotationKey is the label key for the per revision progress deadline to set for the deployment
146146
ProgressDeadlineAnnotationKey = GroupName + "/progress-deadline"
147+
148+
// LoadBalancingPolicyKey is the annotation key for specifying the load balancing algorithm
149+
// used by the activator to route requests to application pods.
150+
LoadBalancingPolicyKey = GroupName + "/load-balancing-policy"
147151
)
148152

149153
var (
@@ -202,4 +206,7 @@ var (
202206
ProgressDeadlineAnnotation = kmap.KeyPriority{
203207
ProgressDeadlineAnnotationKey,
204208
}
209+
LoadBalancingPolicyAnnotation = kmap.KeyPriority{
210+
LoadBalancingPolicyKey,
211+
}
205212
)

pkg/apis/serving/v1/revision_types.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,6 @@ type RevisionSpec struct {
100100
// unspecified, a system default will be provided.
101101
// +optional
102102
IdleTimeoutSeconds *int64 `json:"idleTimeoutSeconds,omitempty"`
103-
104-
// LoadBalancingPolicy is the load balancing algorithm used by the
105-
// activator to route requests to application pods. If unspecified,
106-
// a suggested default is applied depending on ContainerConcurrency
107-
// +optional
108-
LoadBalancingPolicy *string `json:"loadBalancingPolicy,omitempty"`
109103
}
110104

111105
const (

pkg/apis/serving/v1/revision_validation.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
func (r *Revision) Validate(ctx context.Context) *apis.FieldError {
3838
errs := serving.ValidateObjectMetadata(ctx, r.GetObjectMeta(), true).Also(
3939
r.ValidateLabels().ViaField("labels")).ViaField("metadata")
40+
errs = errs.Also(validateLoadBalancingPolicyAnnotation(r.GetAnnotations()).ViaField("metadata.annotations"))
4041
errs = errs.Also(r.Status.Validate(apis.WithinStatus(ctx)).ViaField("status"))
4142

4243
if apis.IsInUpdate(ctx) {
@@ -72,6 +73,7 @@ func (rts *RevisionTemplateSpec) Validate(ctx context.Context) *apis.FieldError
7273
errs = errs.Also(validateRevisionName(ctx, rts.Name, rts.GenerateName))
7374
errs = errs.Also(validateQueueSidecarResourceAnnotations(rts.Annotations).ViaField("metadata.annotations"))
7475
errs = errs.Also(validateProgressDeadlineAnnotation(rts.Annotations).ViaField("metadata.annotations"))
76+
errs = errs.Also(validateLoadBalancingPolicyAnnotation(rts.Annotations).ViaField("metadata.annotations"))
7577
return errs
7678
}
7779

@@ -117,10 +119,6 @@ func (rs *RevisionSpec) Validate(ctx context.Context) *apis.FieldError {
117119
errs = errs.Also(serving.ValidateContainerConcurrency(ctx, rs.ContainerConcurrency).ViaField("containerConcurrency"))
118120
}
119121

120-
if rs.LoadBalancingPolicy != nil {
121-
errs = errs.Also(serving.ValidateLoadBalancingPolicy(ctx, rs.LoadBalancingPolicy).ViaField("loadBalancingPolicy"))
122-
}
123-
124122
return errs
125123
}
126124

@@ -247,3 +245,14 @@ func validateProgressDeadlineAnnotation(annos map[string]string) *apis.FieldErro
247245
}
248246
return nil
249247
}
248+
249+
// validateLoadBalancingPolicyAnnotation validates the load balancing policy annotation.
250+
func validateLoadBalancingPolicyAnnotation(annos map[string]string) *apis.FieldError {
251+
if k, v, _ := serving.LoadBalancingPolicyAnnotation.Get(annos); v != "" {
252+
if v != "round-robin" && v != "random-choice-2" && v != "least-connections" && v != "first-available" {
253+
return apis.ErrInvalidValue(
254+
v, k, "load balancing policy should be one of `random-choice-2`, `round-robin`, `least-connections` or `first-available`")
255+
}
256+
}
257+
return nil
258+
}

pkg/apis/serving/v1/revision_validation_test.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,16 @@ func TestRevisionValidation(t *testing.T) {
8080
r: &Revision{
8181
ObjectMeta: metav1.ObjectMeta{
8282
Name: "valid-lb-policy",
83+
Annotations: map[string]string{
84+
"serving.knative.dev/load-balancing-policy": "round-robin",
85+
},
8386
},
8487
Spec: RevisionSpec{
8588
PodSpec: corev1.PodSpec{
8689
Containers: []corev1.Container{{
8790
Image: "busybox",
8891
}},
8992
},
90-
LoadBalancingPolicy: ptr.String("round-robin"),
9193
},
9294
},
9395
want: nil,
@@ -96,14 +98,16 @@ func TestRevisionValidation(t *testing.T) {
9698
r: &Revision{
9799
ObjectMeta: metav1.ObjectMeta{
98100
Name: "valid-lb-policy",
101+
Annotations: map[string]string{
102+
"serving.knative.dev/load-balancing-policy": "random-choice-2",
103+
},
99104
},
100105
Spec: RevisionSpec{
101106
PodSpec: corev1.PodSpec{
102107
Containers: []corev1.Container{{
103108
Image: "busybox",
104109
}},
105110
},
106-
LoadBalancingPolicy: ptr.String("random-choice-2"),
107111
},
108112
},
109113
want: nil,
@@ -112,14 +116,16 @@ func TestRevisionValidation(t *testing.T) {
112116
r: &Revision{
113117
ObjectMeta: metav1.ObjectMeta{
114118
Name: "valid-lb-policy",
119+
Annotations: map[string]string{
120+
"serving.knative.dev/load-balancing-policy": "least-connections",
121+
},
115122
},
116123
Spec: RevisionSpec{
117124
PodSpec: corev1.PodSpec{
118125
Containers: []corev1.Container{{
119126
Image: "busybox",
120127
}},
121128
},
122-
LoadBalancingPolicy: ptr.String("least-connections"),
123129
},
124130
},
125131
want: nil,
@@ -128,14 +134,16 @@ func TestRevisionValidation(t *testing.T) {
128134
r: &Revision{
129135
ObjectMeta: metav1.ObjectMeta{
130136
Name: "valid-lb-policy",
137+
Annotations: map[string]string{
138+
"serving.knative.dev/load-balancing-policy": "first-available",
139+
},
131140
},
132141
Spec: RevisionSpec{
133142
PodSpec: corev1.PodSpec{
134143
Containers: []corev1.Container{{
135144
Image: "busybox",
136145
}},
137146
},
138-
LoadBalancingPolicy: ptr.String("first-available"),
139147
},
140148
},
141149
want: nil,
@@ -144,18 +152,20 @@ func TestRevisionValidation(t *testing.T) {
144152
r: &Revision{
145153
ObjectMeta: metav1.ObjectMeta{
146154
Name: "invalid-lb-policy",
155+
Annotations: map[string]string{
156+
"serving.knative.dev/load-balancing-policy": "random",
157+
},
147158
},
148159
Spec: RevisionSpec{
149160
PodSpec: corev1.PodSpec{
150161
Containers: []corev1.Container{{
151162
Image: "busybox",
152163
}},
153164
},
154-
LoadBalancingPolicy: ptr.String("random"),
155165
},
156166
},
157167
want: apis.ErrInvalidValue(
158-
"random", "spec.loadBalancingPolicy",
168+
"random", "metadata.annotations.serving.knative.dev/load-balancing-policy",
159169
"load balancing policy should be one of `random-choice-2`, `round-robin`, `least-connections` or `first-available`"),
160170
}, {
161171
name: "nil load balancing policy is valid",
@@ -169,7 +179,6 @@ func TestRevisionValidation(t *testing.T) {
169179
Image: "busybox",
170180
}},
171181
},
172-
LoadBalancingPolicy: nil,
173182
},
174183
},
175184
want: nil,

0 commit comments

Comments
 (0)