Skip to content

Commit e799e8d

Browse files
committed
Add support for freeze in budgets
Provide a new API to freeze budgets and metrics to track its usage as API
1 parent 78fa998 commit e799e8d

14 files changed

+336
-2
lines changed

DOC.md

+82
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ ApplicationDisruptionBudgetSpec defines the desired state of ApplicationDisrupti
9494
A NodeDisruption is allowed if at most "maxDisruptions" nodes selected by selectors are unavailable after the disruption.<br/>
9595
</td>
9696
<td>true</td>
97+
</tr><tr>
98+
<td><b><a href="#applicationdisruptionbudgetspecfreeze">freeze</a></b></td>
99+
<td>object</td>
100+
<td>
101+
Define the freeze status of the budget. Frozen budget reject all disruptions ignoring any other constraints<br/>
102+
</td>
103+
<td>false</td>
97104
</tr><tr>
98105
<td><b><a href="#applicationdisruptionbudgetspechealthhook">healthHook</a></b></td>
99106
<td>object</td>
@@ -121,6 +128,40 @@ Maintenance will proceed only if the endpoint responds 2XX.<br/>
121128
</table>
122129

123130

131+
### ApplicationDisruptionBudget.spec.freeze
132+
<sup><sup>[↩ Parent](#applicationdisruptionbudgetspec)</sup></sup>
133+
134+
135+
136+
Define the freeze status of the budget. Frozen budget reject all disruptions ignoring any other constraints
137+
138+
<table>
139+
<thead>
140+
<tr>
141+
<th>Name</th>
142+
<th>Type</th>
143+
<th>Description</th>
144+
<th>Required</th>
145+
</tr>
146+
</thead>
147+
<tbody><tr>
148+
<td><b>enabled</b></td>
149+
<td>boolean</td>
150+
<td>
151+
Freeze the budget to prevent any disruptions<br/>
152+
</td>
153+
<td>false</td>
154+
</tr><tr>
155+
<td><b>reason</b></td>
156+
<td>string</td>
157+
<td>
158+
Reason of the freeze<br/>
159+
</td>
160+
<td>false</td>
161+
</tr></tbody>
162+
</table>
163+
164+
124165
### ApplicationDisruptionBudget.spec.healthHook
125166
<sup><sup>[↩ Parent](#applicationdisruptionbudgetspec)</sup></sup>
126167

@@ -492,6 +533,13 @@ NodeDisruptionBudgetSpec defines the desired state of NodeDisruptionBudget
492533
A NodeDisruption is allowed if at most "minUndisruptedNodes" nodes selected by selectors are unavailable after the disruption.<br/>
493534
</td>
494535
<td>true</td>
536+
</tr><tr>
537+
<td><b><a href="#nodedisruptionbudgetspecfreeze">freeze</a></b></td>
538+
<td>object</td>
539+
<td>
540+
Define the freeze status of the budget. Frozen budget reject all disruptions ignoring any other constraints<br/>
541+
</td>
542+
<td>false</td>
495543
</tr><tr>
496544
<td><b><a href="#nodedisruptionbudgetspecnodeselector">nodeSelector</a></b></td>
497545
<td>object</td>
@@ -503,6 +551,40 @@ NodeDisruptionBudgetSpec defines the desired state of NodeDisruptionBudget
503551
</table>
504552

505553

554+
### NodeDisruptionBudget.spec.freeze
555+
<sup><sup>[↩ Parent](#nodedisruptionbudgetspec)</sup></sup>
556+
557+
558+
559+
Define the freeze status of the budget. Frozen budget reject all disruptions ignoring any other constraints
560+
561+
<table>
562+
<thead>
563+
<tr>
564+
<th>Name</th>
565+
<th>Type</th>
566+
<th>Description</th>
567+
<th>Required</th>
568+
</tr>
569+
</thead>
570+
<tbody><tr>
571+
<td><b>enabled</b></td>
572+
<td>boolean</td>
573+
<td>
574+
Freeze the budget to prevent any disruptions<br/>
575+
</td>
576+
<td>false</td>
577+
</tr><tr>
578+
<td><b>reason</b></td>
579+
<td>string</td>
580+
<td>
581+
Reason of the freeze<br/>
582+
</td>
583+
<td>false</td>
584+
</tr></tbody>
585+
</table>
586+
587+
506588
### NodeDisruptionBudget.spec.nodeSelector
507589
<sup><sup>[↩ Parent](#nodedisruptionbudgetspec)</sup></sup>
508590

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ test: manifests generate fmt vet envtest lint ## Run tests.
7575
##@ Build
7676

7777
.PHONY: build
78-
build: manifests generate fmt vet ## Build manager binary.
78+
build: manifests generate fmt vet gen-doc ## Build manager binary.
7979
CGO_ENABLED=0 go build -o bin/manager cmd/main.go
8080

8181
.PHONY: run

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ In some cases, an application can be unhealthy even if all its pods are running.
162162
163163
You can select Pods and/or PVCs.
164164
165-
166165
##### PVC selector
167166
168167
The main reason of using a PVC selector is to ensure that node that contains data don't enter maintenance
@@ -182,6 +181,11 @@ The hook will be called with a POST method containing the JSON encoded NodeDisru
182181
183182
Note: It is not a replacement for readiness probes but a complement.
184183
184+
##### Freeze
185+
186+
Budgets support freezing disruptions. By setting `spec.Freeze.Enabled`, the budget will reject all disruptions and give the reason specified in `spec.Freeze.Reason`.
187+
It is equivalent to setting 0 as the max disruptions but it provide better messages.
188+
185189
#### Sample object
186190

187191
```yaml

api/v1alpha1/applicationdisruptionbudget_types.go

+10
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ type ApplicationDisruptionBudgetSpec struct {
4343
// Maintenance will proceed only if the endpoint responds 2XX.
4444
// +kubebuilder:validation:Optional
4545
HealthHook HealthHookSpec `json:"healthHook,omitempty"`
46+
// Define the freeze status of the budget. Frozen budget reject all disruptions ignoring any other constraints
47+
Freeze FreezeSpec `json:"freeze,omitempty"`
48+
}
49+
50+
// FreezeSpec defines the freeze status of the budget
51+
type FreezeSpec struct {
52+
// Freeze the budget to prevent any disruptions
53+
Enabled bool `json:"enabled,omitempty"`
54+
// Reason of the freeze
55+
Reason string `json:"reason,omitempty"`
4656
}
4757

4858
type HealthHookSpec struct {

api/v1alpha1/nodedisruptionbudget_types.go

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ type NodeDisruptionBudgetSpec struct {
3737
MinUndisruptedNodes int `json:"minUndisruptedNodes"`
3838
// NodeSelector query over pods whose nodes are managed by the disruption budget.
3939
NodeSelector metav1.LabelSelector `json:"nodeSelector,omitempty"`
40+
// Define the freeze status of the budget. Frozen budget reject all disruptions ignoring any other constraints
41+
Freeze FreezeSpec `json:"freeze,omitempty"`
4042
}
4143

4244
//+kubebuilder:object:root=true

api/v1alpha1/zz_generated.deepcopy.go

+17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chart/templates/applicationdisruptionbudget-crd.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ spec:
5454
description: ApplicationDisruptionBudgetSpec defines the desired state of
5555
ApplicationDisruptionBudget
5656
properties:
57+
freeze:
58+
description: Define the freeze status of the budget. Frozen budget reject
59+
all disruptions ignoring any other constraints
60+
properties:
61+
enabled:
62+
description: Freeze the budget to prevent any disruptions
63+
type: boolean
64+
reason:
65+
description: Reason of the freeze
66+
type: string
67+
type: object
5768
healthHook:
5869
description: |-
5970
Define a optional hook to call when validating a NodeDisruption.

chart/templates/nodedisruptionbudget-crd.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ spec:
5656
spec:
5757
description: NodeDisruptionBudgetSpec defines the desired state of NodeDisruptionBudget
5858
properties:
59+
freeze:
60+
description: Define the freeze status of the budget. Frozen budget reject
61+
all disruptions ignoring any other constraints
62+
properties:
63+
enabled:
64+
description: Freeze the budget to prevent any disruptions
65+
type: boolean
66+
reason:
67+
description: Reason of the freeze
68+
type: string
69+
type: object
5970
maxDisruptedNodes:
6071
description: A NodeDisruption is allowed if at most "maxDisruptedNodes"
6172
nodes selected by selectors are unavailable after the disruption.

config/crd/bases/nodedisruption.criteo.com_applicationdisruptionbudgets.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ spec:
5353
description: ApplicationDisruptionBudgetSpec defines the desired state
5454
of ApplicationDisruptionBudget
5555
properties:
56+
freeze:
57+
description: Define the freeze status of the budget. Frozen budget
58+
reject all disruptions ignoring any other constraints
59+
properties:
60+
enabled:
61+
description: Freeze the budget to prevent any disruptions
62+
type: boolean
63+
reason:
64+
description: Reason of the freeze
65+
type: string
66+
type: object
5667
healthHook:
5768
description: |-
5869
Define a optional hook to call when validating a NodeDisruption.

config/crd/bases/nodedisruption.criteo.com_nodedisruptionbudgets.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ spec:
5555
spec:
5656
description: NodeDisruptionBudgetSpec defines the desired state of NodeDisruptionBudget
5757
properties:
58+
freeze:
59+
description: Define the freeze status of the budget. Frozen budget
60+
reject all disruptions ignoring any other constraints
61+
properties:
62+
enabled:
63+
description: Freeze the budget to prevent any disruptions
64+
type: boolean
65+
reason:
66+
description: Reason of the freeze
67+
type: string
68+
type: object
5869
maxDisruptedNodes:
5970
description: A NodeDisruption is allowed if at most "maxDisruptedNodes"
6071
nodes selected by selectors are unavailable after the disruption.

internal/controller/applicationdisruptionbudget_controller.go

+14
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ func PruneADBMetrics(ref nodedisruptionv1alpha1.NamespacedName) {
115115
// UpdateADBMetrics update metrics for an ADB
116116
func UpdateADBMetrics(ref nodedisruptionv1alpha1.NamespacedName, adb *nodedisruptionv1alpha1.ApplicationDisruptionBudget) {
117117
DisruptionBudgetMaxDisruptions.WithLabelValues(ref.Namespace, ref.Name, ref.Kind).Set(float64(adb.Spec.MaxDisruptions))
118+
if adb.Spec.Freeze.Enabled {
119+
DisruptionBudgetFrozen.WithLabelValues(ref.Namespace, ref.Name, ref.Kind).Set(1)
120+
} else {
121+
DisruptionBudgetFrozen.WithLabelValues(ref.Namespace, ref.Name, ref.Kind).Set(0)
122+
}
123+
118124
UpdateBudgetStatusMetrics(ref, adb.Status)
119125
}
120126

@@ -200,6 +206,14 @@ func (r *ApplicationDisruptionBudgetResolver) IsImpacted(disruptedNodes resolver
200206

201207
// Return the number of disruption allowed considering a list of current node disruptions
202208
func (r *ApplicationDisruptionBudgetResolver) TryValidateDisruptionFromBudgetConstraints(_ resolver.NodeSet) nodedisruptionv1alpha1.DisruptedBudgetStatus {
209+
if r.ApplicationDisruptionBudget.Spec.Freeze.Enabled {
210+
return nodedisruptionv1alpha1.DisruptedBudgetStatus{
211+
Reference: r.GetNamespacedName(),
212+
Reason: fmt.Sprintf("Budget frozen: %s", r.ApplicationDisruptionBudget.Spec.Freeze.Reason),
213+
Ok: false,
214+
}
215+
}
216+
203217
if r.ApplicationDisruptionBudget.Status.DisruptionsAllowed-1 >= 0 {
204218
return nodedisruptionv1alpha1.DisruptedBudgetStatus{
205219
Reference: r.GetNamespacedName(),

internal/controller/metrics.go

+7
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,11 @@ var (
139139
},
140140
[]string{"disruption_budget_namespace", "disruption_budget_name", "disruption_budget_kind", "node_disruption_name"},
141141
)
142+
DisruptionBudgetFrozen = promauto.With(metrics.Registry).NewGaugeVec(
143+
prometheus.GaugeOpts{
144+
Name: METIC_PREFIX + "budget_disruption_frozen",
145+
Help: "Budget frozen",
146+
},
147+
[]string{"disruption_budget_namespace", "disruption_budget_name", "disruption_budget_kind"},
148+
)
142149
)

0 commit comments

Comments
 (0)