Skip to content

Commit b6f202e

Browse files
vmagent and vmanomaly: create PDB per shard
1 parent 3bf9ad3 commit b6f202e

File tree

11 files changed

+445
-428
lines changed

11 files changed

+445
-428
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,13 +362,13 @@ OPM = $(LOCALBIN)/opm-$(OPM_VERSION)
362362
YQ = $(LOCALBIN)/yq-$(YQ_VERSION)
363363
CRD_REF_DOCS = $(LOCALBIN)/crd-ref-docs-$(CRD_REF_DOCS_VERSION)
364364
GINKGO_BIN ?= $(LOCALBIN)/ginkgo-$(GINKGO_VERSION)
365-
GINKGO_VERSION ?= v2.23.0
365+
GINKGO_VERSION ?= v2.26.0
366366

367367
## Tool Versions
368368
KUSTOMIZE_VERSION ?= v5.6.0
369369
CONTROLLER_TOOLS_VERSION ?= v0.18.0
370370
ENVTEST_VERSION ?= release-0.20
371-
GOLANGCI_LINT_VERSION ?= v2.4.0
371+
GOLANGCI_LINT_VERSION ?= v2.5.0
372372
CODEGENERATOR_VERSION ?= v0.32.2
373373
KIND_VERSION ?= v0.27.0
374374
OLM_VERSION ?= 0.31.0

api/operator/v1beta1/vmagent_types.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,14 @@ func (cr *VMAgent) UnmarshalJSON(src []byte) error {
402402
return nil
403403
}
404404

405+
// GetShardCount returns shard count for vmagent
406+
func (cr *VMAgent) GetShardCount() int {
407+
if cr == nil || cr.Spec.ShardCount == nil {
408+
return 0
409+
}
410+
return *cr.Spec.ShardCount
411+
}
412+
405413
// UnmarshalJSON implements json.Unmarshaler interface
406414
func (cr *VMAgentSpec) UnmarshalJSON(src []byte) error {
407415
type pcr VMAgentSpec

docs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ aliases:
2525

2626
* BUGFIX: [vmoperator](https://docs.victoriametrics.com/operator/): fix an issue where the return value from a couple of controllers was always `nil`. See [#1532](https://github.com/VictoriaMetrics/operator/pull/1532) for details.
2727
* BUGFIX: [VMCluster](https://docs.victoriametrics.com/operator/resources/vmcluster/): emit warning if `vmcluster.spec.vmselect.persistentVolume` is set, previously it was emitted for `vmcluster.spec.vmselect.storage`.
28+
* BUGFIX: [vmagent](https://docs.victoriametrics.com/operator/resources/vmagent/) and [vmanomaly](https://docs.victoriametrics.com/operator/resources/vmanomaly/): create PDB per shard. See [#1548](https://github.com/VictoriaMetrics/operator/issues/1548).
2829

2930

3031
## [v0.63.0](https://github.com/VictoriaMetrics/operator/releases/tag/v0.63.0)

go.mod

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ require (
1515
github.com/google/go-cmp v0.7.0
1616
github.com/google/uuid v1.6.0
1717
github.com/hashicorp/go-version v1.7.0
18-
github.com/onsi/ginkgo/v2 v2.23.0
19-
github.com/onsi/gomega v1.36.2
18+
github.com/onsi/ginkgo/v2 v2.26.0
19+
github.com/onsi/gomega v1.38.2
2020
github.com/pires/go-proxyproto v0.8.0
2121
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.84.0
2222
github.com/prometheus/client_golang v1.22.0
2323
github.com/stretchr/testify v1.10.0
2424
go.uber.org/zap v1.27.0
25-
golang.org/x/net v0.41.0
25+
golang.org/x/net v0.43.0
2626
golang.org/x/sync v0.16.0
2727
gopkg.in/yaml.v2 v2.4.0
2828
k8s.io/api v0.33.2
@@ -53,7 +53,7 @@ require (
5353
github.com/gogo/protobuf v1.3.2 // indirect
5454
github.com/google/btree v1.1.3 // indirect
5555
github.com/google/gnostic-models v0.6.9 // indirect
56-
github.com/google/pprof v0.0.0-20250302191652-9094ed2288e7 // indirect
56+
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
5757
github.com/jmespath/go-jmespath v0.4.0 // indirect
5858
github.com/josharian/intern v1.0.0 // indirect
5959
github.com/jpillora/backoff v1.0.0 // indirect
@@ -80,16 +80,19 @@ require (
8080
github.com/valyala/histogram v1.2.0 // indirect
8181
github.com/valyala/quicktemplate v1.8.0 // indirect
8282
github.com/x448/float16 v0.8.4 // indirect
83+
go.uber.org/automaxprocs v1.6.0 // indirect
8384
go.uber.org/multierr v1.11.0 // indirect
8485
go.yaml.in/yaml/v2 v2.4.2 // indirect
86+
go.yaml.in/yaml/v3 v3.0.4 // indirect
87+
golang.org/x/mod v0.27.0 // indirect
8588
golang.org/x/oauth2 v0.28.0 // indirect
86-
golang.org/x/sys v0.33.0 // indirect
87-
golang.org/x/term v0.32.0 // indirect
88-
golang.org/x/text v0.27.0 // indirect
89+
golang.org/x/sys v0.35.0 // indirect
90+
golang.org/x/term v0.34.0 // indirect
91+
golang.org/x/text v0.28.0 // indirect
8992
golang.org/x/time v0.11.0 // indirect
90-
golang.org/x/tools v0.34.0 // indirect
93+
golang.org/x/tools v0.36.0 // indirect
9194
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
92-
google.golang.org/protobuf v1.36.6 // indirect
95+
google.golang.org/protobuf v1.36.7 // indirect
9396
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
9497
gopkg.in/inf.v0 v0.9.1 // indirect
9598
gopkg.in/yaml.v3 v3.0.1 // indirect

go.sum

Lines changed: 48 additions & 20 deletions
Large diffs are not rendered by default.

internal/controller/operator/factory/build/common.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package build
22

33
import (
4+
"iter"
45
"sort"
56
)
67

@@ -36,3 +37,30 @@ func (s *keysSorter[T]) Swap(i, j int) {
3637
s.target[i], s.target[j] = s.target[j], s.target[i]
3738
s.sorter[i], s.sorter[j] = s.sorter[j], s.sorter[i]
3839
}
40+
41+
// ShardNumIter iterates over shardCount in order defined in backward
42+
func ShardNumIter(backward bool, shardCount int) iter.Seq[*int] {
43+
if shardCount <= 1 {
44+
return func(yield func(*int) bool) {
45+
yield(nil)
46+
}
47+
}
48+
if backward {
49+
return func(yield func(*int) bool) {
50+
for shardCount > 0 {
51+
shardCount--
52+
num := shardCount
53+
if !yield(&num) {
54+
return
55+
}
56+
}
57+
}
58+
}
59+
return func(yield func(*int) bool) {
60+
for i := 0; i < shardCount; i++ {
61+
if !yield(&i) {
62+
return
63+
}
64+
}
65+
}
66+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package build
2+
3+
import (
4+
"slices"
5+
"testing"
6+
)
7+
8+
func TestShardNumIter(t *testing.T) {
9+
f := func(backward bool, upperBound int) {
10+
output := slices.Collect(ShardNumIter(backward, upperBound))
11+
if upperBound <= 1 {
12+
if len(output) != 1 || output[0] != nil {
13+
t.Errorf("invalid ShardNumIter() values, want: [nil]; got: %v", output)
14+
}
15+
return
16+
}
17+
if upperBound > 1 && len(output) != upperBound {
18+
t.Errorf("invalid ShardNumIter() items count, want: %d, got: %d", upperBound, len(output))
19+
}
20+
var lowerBound int
21+
if backward {
22+
lowerBound = upperBound - 1
23+
upperBound = 0
24+
} else {
25+
upperBound--
26+
}
27+
if *output[0] != lowerBound || *output[len(output)-1] != upperBound {
28+
t.Errorf("invalid ShardNumIter() bounds, want: [%d, %d], got: [%d, %d]", lowerBound, upperBound, *output[0], *output[len(output)-1])
29+
}
30+
}
31+
f(true, 9)
32+
f(false, 5)
33+
f(false, 1)
34+
f(true, 0)
35+
}

internal/controller/operator/factory/finalize/orphaned.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55

66
appsv1 "k8s.io/api/apps/v1"
7+
policyv1 "k8s.io/api/policy/v1"
78
"k8s.io/apimachinery/pkg/labels"
89
"sigs.k8s.io/controller-runtime/pkg/client"
910
)
@@ -14,14 +15,14 @@ type orphanedCRD interface {
1415
}
1516

1617
// RemoveOrphanedDeployments removes deployments detached from given object
17-
func RemoveOrphanedDeployments(ctx context.Context, rclient client.Client, cr orphanedCRD, keepDeployments map[string]struct{}) error {
18+
func RemoveOrphanedDeployments(ctx context.Context, rclient client.Client, cr orphanedCRD, keepNames map[string]struct{}) error {
1819
deployToRemove, err := discoverDeploymentsByLabels(ctx, rclient, cr.GetNamespace(), cr.SelectorLabels())
1920
if err != nil {
2021
return err
2122
}
2223
for i := range deployToRemove {
2324
dep := deployToRemove[i]
24-
if _, ok := keepDeployments[dep.Name]; !ok {
25+
if _, ok := keepNames[dep.Name]; !ok {
2526
// need to remove
2627
if err := RemoveFinalizer(ctx, rclient, dep); err != nil {
2728
return err
@@ -59,14 +60,14 @@ type RemoveSvcArgs struct {
5960
}
6061

6162
// RemoveOrphanedSTSs removes deployments detached from given object
62-
func RemoveOrphanedSTSs(ctx context.Context, rclient client.Client, cr orphanedCRD, keepSTSNames map[string]struct{}) error {
63+
func RemoveOrphanedSTSs(ctx context.Context, rclient client.Client, cr orphanedCRD, keepNames map[string]struct{}) error {
6364
deployToRemove, err := discoverSTSsByLabels(ctx, rclient, cr.GetNamespace(), cr.SelectorLabels())
6465
if err != nil {
6566
return err
6667
}
6768
for i := range deployToRemove {
6869
dep := deployToRemove[i]
69-
if _, ok := keepSTSNames[dep.Name]; !ok {
70+
if _, ok := keepNames[dep.Name]; !ok {
7071
// need to remove
7172
if err := RemoveFinalizer(ctx, rclient, dep); err != nil {
7273
return err
@@ -79,7 +80,7 @@ func RemoveOrphanedSTSs(ctx context.Context, rclient client.Client, cr orphanedC
7980
return nil
8081
}
8182

82-
// discoverDeploymentsByLabels - returns deployments with given args.
83+
// discoverSTSsByLabels - returns statefulsets with given args.
8384
func discoverSTSsByLabels(ctx context.Context, rclient client.Client, ns string, selector map[string]string) ([]*appsv1.StatefulSet, error) {
8485
var deps appsv1.StatefulSetList
8586
opts := client.ListOptions{
@@ -95,3 +96,41 @@ func discoverSTSsByLabels(ctx context.Context, rclient client.Client, ns string,
9596
}
9697
return resp, nil
9798
}
99+
100+
// RemoveOrphanedPDBs removes PDBs detached from given object
101+
func RemoveOrphanedPDBs(ctx context.Context, rclient client.Client, cr orphanedCRD, keepNames map[string]struct{}) error {
102+
pdbsToRemove, err := discoverPDBsByLabels(ctx, rclient, cr.GetNamespace(), cr.SelectorLabels())
103+
if err != nil {
104+
return err
105+
}
106+
for i := range pdbsToRemove {
107+
dep := pdbsToRemove[i]
108+
if _, ok := keepNames[dep.Name]; !ok {
109+
// need to remove
110+
if err := RemoveFinalizer(ctx, rclient, dep); err != nil {
111+
return err
112+
}
113+
if err := SafeDelete(ctx, rclient, dep); err != nil {
114+
return err
115+
}
116+
}
117+
}
118+
return nil
119+
}
120+
121+
// discoverPDBsByLabels - returns PDBs with given args.
122+
func discoverPDBsByLabels(ctx context.Context, rclient client.Client, ns string, selector map[string]string) ([]*policyv1.PodDisruptionBudget, error) {
123+
var pdbs policyv1.PodDisruptionBudgetList
124+
opts := client.ListOptions{
125+
Namespace: ns,
126+
LabelSelector: labels.SelectorFromSet(selector),
127+
}
128+
if err := rclient.List(ctx, &pdbs, &opts); err != nil {
129+
return nil, err
130+
}
131+
resp := make([]*policyv1.PodDisruptionBudget, 0, len(pdbs.Items))
132+
for i := range pdbs.Items {
133+
resp = append(resp, &pdbs.Items[i])
134+
}
135+
return resp, nil
136+
}

0 commit comments

Comments
 (0)