Skip to content

Commit 8cc0ad1

Browse files
authored
Default to minAvailable: 1 in Servings PodDisruptionBudgets (#2985)
* Default to minAvailable: 1 in Servings PodDisruptionBudgetsi * Add PDBs to extension tests
1 parent bdf7b95 commit 8cc0ad1

File tree

4 files changed

+145
-4
lines changed

4 files changed

+145
-4
lines changed

openshift-knative-operator/pkg/serving/extension.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ func (e *extension) Reconcile(ctx context.Context, comp base.KComponent) error {
141141
}
142142
}
143143

144+
// Default to `1` as PodDisruptionBudget if not specified.
145+
defaultToOneAsPodDisruptionBudget(ks)
146+
144147
// Apply an Ingress config with Kourier enabled if nothing else is defined.
145148
defaultToKourier(ks)
146149
common.ConfigureIfUnset(&ks.Spec.CommonSpec, "network", "ingress.class", defaultIngressClass(ks))

openshift-knative-operator/pkg/serving/extension_test.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,20 @@ import (
1515
configv1 "github.com/openshift/api/config/v1"
1616
routev1 "github.com/openshift/api/route/v1"
1717
corev1 "k8s.io/api/core/v1"
18+
policyv1 "k8s.io/api/policy/v1"
1819
"k8s.io/apimachinery/pkg/api/resource"
1920
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2021
"k8s.io/apimachinery/pkg/runtime"
22+
"k8s.io/apimachinery/pkg/util/intstr"
2123
"k8s.io/apimachinery/pkg/version"
2224
fakediscovery "k8s.io/client-go/discovery/fake"
25+
"k8s.io/utils/ptr"
2326
"knative.dev/operator/pkg/apis/operator/base"
2427
operatorv1beta1 "knative.dev/operator/pkg/apis/operator/v1beta1"
2528
operator "knative.dev/operator/pkg/reconciler/common"
2629
"knative.dev/pkg/apis"
2730
kubeclient "knative.dev/pkg/client/injection/kube/client"
2831
kubefake "knative.dev/pkg/client/injection/kube/client/fake"
29-
"knative.dev/pkg/ptr"
3032
)
3133

3234
var (
@@ -81,13 +83,13 @@ func TestReconcile(t *testing.T) {
8183
Spec: operatorv1beta1.KnativeServingSpec{
8284
CommonSpec: base.CommonSpec{
8385
HighAvailability: &base.HighAvailability{
84-
Replicas: ptr.Int32(3),
86+
Replicas: ptr.To(int32(3)),
8587
},
8688
},
8789
},
8890
},
8991
expected: ks(func(ks *operatorv1beta1.KnativeServing) {
90-
ks.Spec.HighAvailability.Replicas = ptr.Int32(3)
92+
ks.Spec.HighAvailability.Replicas = ptr.To(int32(3))
9193
}),
9294
}, {
9395
name: "different certificate settings",
@@ -504,7 +506,20 @@ func ks(mods ...func(*operatorv1beta1.KnativeServing)) *operatorv1beta1.KnativeS
504506
Spec: operatorv1beta1.KnativeServingSpec{
505507
CommonSpec: base.CommonSpec{
506508
HighAvailability: &base.HighAvailability{
507-
Replicas: ptr.Int32(2),
509+
Replicas: ptr.To(int32(2)),
510+
},
511+
PodDisruptionBudgetOverride: []base.PodDisruptionBudgetOverride{
512+
{
513+
Name: "activator-pdb",
514+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
515+
MinAvailable: ptr.To(intstr.IntOrString{IntVal: 1, Type: intstr.Int}),
516+
},
517+
}, {
518+
Name: "webhook-pdb",
519+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
520+
MinAvailable: ptr.To(intstr.IntOrString{IntVal: 1, Type: intstr.Int}),
521+
},
522+
},
508523
},
509524
Config: base.ConfigMapData{
510525
"deployment": map[string]string{
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package serving
2+
3+
import (
4+
policyv1 "k8s.io/api/policy/v1"
5+
"k8s.io/apimachinery/pkg/util/intstr"
6+
"k8s.io/utils/ptr"
7+
"knative.dev/operator/pkg/apis/operator/base"
8+
operatorv1beta1 "knative.dev/operator/pkg/apis/operator/v1beta1"
9+
)
10+
11+
var servingPDBNames = []string{"activator-pdb", "webhook-pdb"}
12+
13+
// Upstream has a PodDisruptionBudgetOverride with minAvailable: 80% which does not work with
14+
// HighAvailability of two Pods. We need to override this to minAvailable: 1 if the user did not specify
15+
// another value.
16+
func defaultToOneAsPodDisruptionBudget(ks *operatorv1beta1.KnativeServing) {
17+
overrides := ks.GetSpec().GetPodDisruptionBudgetOverride()
18+
19+
if overrides == nil {
20+
overrides = []base.PodDisruptionBudgetOverride{}
21+
}
22+
23+
for _, pdbName := range servingPDBNames {
24+
if !hasOverride(overrides, pdbName) {
25+
ks.Spec.PodDisruptionBudgetOverride = append(ks.Spec.PodDisruptionBudgetOverride, base.PodDisruptionBudgetOverride{
26+
Name: pdbName,
27+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
28+
MinAvailable: ptr.To(intstr.IntOrString{Type: intstr.Int, IntVal: 1}),
29+
},
30+
})
31+
}
32+
}
33+
}
34+
35+
func hasOverride(overrides []base.PodDisruptionBudgetOverride, pdbName string) bool {
36+
for _, override := range overrides {
37+
if override.Name == pdbName {
38+
return true
39+
}
40+
}
41+
return false
42+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package serving
2+
3+
import (
4+
"testing"
5+
6+
"github.com/google/go-cmp/cmp"
7+
policyv1 "k8s.io/api/policy/v1"
8+
"k8s.io/apimachinery/pkg/util/intstr"
9+
"k8s.io/utils/ptr"
10+
"knative.dev/operator/pkg/apis/operator/base"
11+
operatorv1beta1 "knative.dev/operator/pkg/apis/operator/v1beta1"
12+
)
13+
14+
func TestDefaultToOneAsPodDisruptionBudget(t *testing.T) {
15+
tests := []struct {
16+
name string
17+
ks *operatorv1beta1.KnativeServing
18+
expected []base.PodDisruptionBudgetOverride
19+
}{
20+
{
21+
name: "no overrides",
22+
ks: &operatorv1beta1.KnativeServing{
23+
Spec: operatorv1beta1.KnativeServingSpec{},
24+
},
25+
expected: []base.PodDisruptionBudgetOverride{
26+
{
27+
Name: "activator-pdb",
28+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
29+
MinAvailable: ptr.To(intstr.IntOrString{Type: intstr.Int, IntVal: 1}),
30+
},
31+
},
32+
{
33+
Name: "webhook-pdb",
34+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
35+
MinAvailable: ptr.To(intstr.IntOrString{Type: intstr.Int, IntVal: 1}),
36+
},
37+
},
38+
},
39+
},
40+
{
41+
name: "with existing overrides",
42+
ks: &operatorv1beta1.KnativeServing{
43+
Spec: operatorv1beta1.KnativeServingSpec{
44+
CommonSpec: base.CommonSpec{
45+
PodDisruptionBudgetOverride: []base.PodDisruptionBudgetOverride{
46+
{
47+
Name: "activator-pdb",
48+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
49+
MinAvailable: ptr.To(intstr.IntOrString{Type: intstr.Int, IntVal: 2}),
50+
},
51+
},
52+
},
53+
},
54+
},
55+
},
56+
expected: []base.PodDisruptionBudgetOverride{
57+
{
58+
Name: "activator-pdb",
59+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
60+
MinAvailable: ptr.To(intstr.IntOrString{Type: intstr.Int, IntVal: 2}),
61+
},
62+
},
63+
{
64+
Name: "webhook-pdb",
65+
PodDisruptionBudgetSpec: policyv1.PodDisruptionBudgetSpec{
66+
MinAvailable: ptr.To(intstr.IntOrString{Type: intstr.Int, IntVal: 1}),
67+
},
68+
},
69+
},
70+
},
71+
}
72+
73+
for _, tt := range tests {
74+
t.Run(tt.name, func(t *testing.T) {
75+
defaultToOneAsPodDisruptionBudget(tt.ks)
76+
if diff := cmp.Diff(tt.expected, tt.ks.Spec.PodDisruptionBudgetOverride); diff != "" {
77+
t.Errorf("PodDisruptionBudgetOverride mismatch (-want +got):\n%s", diff)
78+
}
79+
})
80+
}
81+
}

0 commit comments

Comments
 (0)