Skip to content

Commit 4689dad

Browse files
authored
K8SPG-761: add support for the PGO_WORKERS env var (#1135)
* K8SPG-761: add support for the `PGO_WORKERS` env var https://perconadev.atlassian.net/browse/K8SPG-761 * fix unit-tests * fix * fix unit-test
1 parent 7fa7676 commit 4689dad

File tree

9 files changed

+61
-58
lines changed

9 files changed

+61
-58
lines changed

cmd/postgres-operator/main.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import (
4141
"github.com/percona/percona-postgresql-operator/percona/controller/pgcluster"
4242
"github.com/percona/percona-postgresql-operator/percona/controller/pgrestore"
4343
perconaPGUpgrade "github.com/percona/percona-postgresql-operator/percona/controller/pgupgrade"
44-
"github.com/percona/percona-postgresql-operator/percona/k8s"
4544
perconaRuntime "github.com/percona/percona-postgresql-operator/percona/runtime"
4645
"github.com/percona/percona-postgresql-operator/percona/utils/registry"
4746
v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2"
@@ -111,15 +110,13 @@ func main() {
111110
// deprecation warnings when using an older version of a resource for backwards compatibility).
112111
rest.SetDefaultWarningHandler(rest.NoWarnings{})
113112

114-
namespaces, err := k8s.GetWatchNamespace()
113+
options, err := initManager(ctx)
115114
assertNoError(err)
116115

117116
mgr, err := perconaRuntime.CreateRuntimeManager(
118-
namespaces,
119117
cfg,
120-
false,
121-
false,
122118
features,
119+
options,
123120
)
124121
assertNoError(err)
125122

@@ -260,8 +257,8 @@ func addControllersToManager(ctx context.Context, mgr manager.Manager) error {
260257

261258
//+kubebuilder:rbac:groups="coordination.k8s.io",resources="leases",verbs={get,create,update}
262259

263-
func initManager() (runtime.Options, error) {
264-
log := logging.FromContext(context.Background())
260+
func initManager(ctx context.Context) (runtime.Options, error) {
261+
log := logging.FromContext(ctx)
265262

266263
options := runtime.Options{}
267264
options.Cache.SyncPeriod = initialize.Pointer(time.Hour)
@@ -279,6 +276,10 @@ func initManager() (runtime.Options, error) {
279276
options.LeaderElection = true
280277
options.LeaderElectionID = lease
281278
options.LeaderElectionNamespace = os.Getenv("PGO_NAMESPACE")
279+
} else {
280+
// K8SPG-761
281+
options.LeaderElection = true
282+
options.LeaderElectionID = perconaRuntime.ElectionID
282283
}
283284

284285
// Check PGO_TARGET_NAMESPACE for backwards compatibility with

cmd/postgres-operator/main_test.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package main
66

77
import (
8+
"context"
89
"reflect"
910
"testing"
1011
"time"
@@ -14,8 +15,9 @@ import (
1415
)
1516

1617
func TestInitManager(t *testing.T) {
18+
ctx := context.Background()
1719
t.Run("Defaults", func(t *testing.T) {
18-
options, err := initManager()
20+
options, err := initManager(ctx)
1921
assert.NilError(t, err)
2022

2123
if assert.Check(t, options.Cache.SyncPeriod != nil) {
@@ -30,12 +32,14 @@ func TestInitManager(t *testing.T) {
3032
})
3133

3234
assert.Assert(t, options.Cache.DefaultNamespaces == nil)
33-
assert.Assert(t, options.LeaderElection == false)
35+
assert.Assert(t, options.LeaderElection == true)
3436

3537
{
3638
options.Cache.SyncPeriod = nil
3739
options.Controller.GroupKindConcurrency = nil
3840
options.HealthProbeBindAddress = ""
41+
options.LeaderElection = false
42+
options.LeaderElectionID = ""
3943

4044
assert.Assert(t, reflect.ValueOf(options).IsZero(),
4145
"expected remaining fields to be unset:\n%+v", options)
@@ -48,7 +52,7 @@ func TestInitManager(t *testing.T) {
4852
t.Run("Invalid", func(t *testing.T) {
4953
t.Setenv("PGO_CONTROLLER_LEASE_NAME", "INVALID_NAME")
5054

51-
options, err := initManager()
55+
options, err := initManager(ctx)
5256
assert.ErrorContains(t, err, "PGO_CONTROLLER_LEASE_NAME")
5357
assert.ErrorContains(t, err, "invalid")
5458

@@ -59,7 +63,7 @@ func TestInitManager(t *testing.T) {
5963
t.Run("Valid", func(t *testing.T) {
6064
t.Setenv("PGO_CONTROLLER_LEASE_NAME", "valid-name")
6165

62-
options, err := initManager()
66+
options, err := initManager(ctx)
6367
assert.NilError(t, err)
6468
assert.Assert(t, options.LeaderElection == true)
6569
assert.Equal(t, options.LeaderElectionNamespace, "test-namespace")
@@ -70,7 +74,7 @@ func TestInitManager(t *testing.T) {
7074
t.Run("PGO_TARGET_NAMESPACE", func(t *testing.T) {
7175
t.Setenv("PGO_TARGET_NAMESPACE", "some-such")
7276

73-
options, err := initManager()
77+
options, err := initManager(ctx)
7478
assert.NilError(t, err)
7579
assert.Assert(t, cmp.Len(options.Cache.DefaultNamespaces, 1),
7680
"expected only one configured namespace")
@@ -81,7 +85,7 @@ func TestInitManager(t *testing.T) {
8185
t.Run("PGO_TARGET_NAMESPACES", func(t *testing.T) {
8286
t.Setenv("PGO_TARGET_NAMESPACES", "some-such,another-one")
8387

84-
options, err := initManager()
88+
options, err := initManager(ctx)
8589
assert.NilError(t, err)
8690
assert.Assert(t, cmp.Len(options.Cache.DefaultNamespaces, 2),
8791
"expect two configured namespaces")
@@ -95,7 +99,7 @@ func TestInitManager(t *testing.T) {
9599
for _, v := range []string{"-3", "0", "3.14"} {
96100
t.Setenv("PGO_WORKERS", v)
97101

98-
options, err := initManager()
102+
options, err := initManager(ctx)
99103
assert.NilError(t, err)
100104
assert.DeepEqual(t, options.Controller.GroupKindConcurrency,
101105
map[string]int{
@@ -107,7 +111,7 @@ func TestInitManager(t *testing.T) {
107111
t.Run("Valid", func(t *testing.T) {
108112
t.Setenv("PGO_WORKERS", "19")
109113

110-
options, err := initManager()
114+
options, err := initManager(ctx)
111115
assert.NilError(t, err)
112116
assert.DeepEqual(t, options.Controller.GroupKindConcurrency,
113117
map[string]int{

config/manager/default/manager.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ spec:
3535
value: INFO
3636
- name: DISABLE_TELEMETRY
3737
value: "false"
38+
- name: PGO_WORKERS
39+
value: "1"
3840
ports:
3941
- containerPort: 8080
4042
name: metrics

deploy/bundle.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -47675,6 +47675,8 @@ spec:
4767547675
value: INFO
4767647676
- name: DISABLE_TELEMETRY
4767747677
value: "false"
47678+
- name: PGO_WORKERS
47679+
value: "1"
4767847680
image: perconalab/percona-postgresql-operator:main
4767947681
imagePullPolicy: Always
4768047682
livenessProbe:

deploy/cw-bundle.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -47673,6 +47673,8 @@ spec:
4767347673
value: INFO
4767447674
- name: DISABLE_TELEMETRY
4767547675
value: "false"
47676+
- name: PGO_WORKERS
47677+
value: "1"
4767647678
image: perconalab/percona-postgresql-operator:main
4767747679
imagePullPolicy: Always
4767847680
livenessProbe:

deploy/cw-operator.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ spec:
4242
value: INFO
4343
- name: DISABLE_TELEMETRY
4444
value: "false"
45+
- name: PGO_WORKERS
46+
value: "1"
4547
image: perconalab/percona-postgresql-operator:main
4648
imagePullPolicy: Always
4749
livenessProbe:

deploy/operator.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ spec:
4545
value: INFO
4646
- name: DISABLE_TELEMETRY
4747
value: "false"
48+
- name: PGO_WORKERS
49+
value: "1"
4850
image: perconalab/percona-postgresql-operator:main
4951
imagePullPolicy: Always
5052
livenessProbe:

percona/controller/pgcluster/controller_test.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88
"crypto/md5" //nolint:gosec
99
"fmt"
10+
"os"
1011
"strconv"
1112
"sync"
1213
"time"
@@ -24,8 +25,10 @@ import (
2425
"k8s.io/apimachinery/pkg/types"
2526
ctrl "sigs.k8s.io/controller-runtime"
2627
"sigs.k8s.io/controller-runtime/pkg/client"
28+
metricsServer "sigs.k8s.io/controller-runtime/pkg/metrics/server"
2729

2830
"github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster"
31+
internalRuntime "github.com/percona/percona-postgresql-operator/internal/controller/runtime"
2932
"github.com/percona/percona-postgresql-operator/internal/feature"
3033
"github.com/percona/percona-postgresql-operator/internal/naming"
3134
perconaController "github.com/percona/percona-postgresql-operator/percona/controller"
@@ -539,7 +542,15 @@ var _ = Describe("Watching secrets", Ordered, func() {
539542
Expect(err).NotTo(HaveOccurred())
540543

541544
Expect(err).To(Not(HaveOccurred()))
542-
mgr, err := runtime.CreateRuntimeManager(namespace.Name, cfg, true, true, gate)
545+
546+
os.Setenv("PGO_TARGET_NAMESPACE", "")
547+
mgr, err := runtime.CreateRuntimeManager(cfg, gate, internalRuntime.Options{
548+
LeaderElection: false,
549+
HealthProbeBindAddress: "0",
550+
Metrics: metricsServer.Options{
551+
BindAddress: "0",
552+
},
553+
})
543554
Expect(err).To(Succeed())
544555
Expect(v2.AddToScheme(mgr.GetScheme())).To(Succeed())
545556

percona/runtime/runtime.go

+19-42
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,34 @@ import (
66
"time"
77

88
"k8s.io/client-go/rest"
9-
"k8s.io/client-go/util/flowcontrol"
109
"sigs.k8s.io/controller-runtime/pkg/cache"
1110
"sigs.k8s.io/controller-runtime/pkg/manager"
12-
metricsServer "sigs.k8s.io/controller-runtime/pkg/metrics/server"
1311

1412
r "github.com/percona/percona-postgresql-operator/internal/controller/runtime"
1513
"github.com/percona/percona-postgresql-operator/internal/feature"
14+
"github.com/percona/percona-postgresql-operator/internal/initialize"
15+
"github.com/percona/percona-postgresql-operator/percona/k8s"
1616
)
1717

1818
// default refresh interval in minutes
19-
var refreshInterval = 60 * time.Minute
19+
const refreshInterval time.Duration = 60 * time.Minute
2020

21-
const electionID string = "08db3feb.percona.com"
21+
const ElectionID string = "08db3feb.percona.com"
2222

23-
// CreateRuntimeManager does the same thing as `internal/controller/runtime.CreateRuntimeManager`,
24-
// excet it configures the manager to watch multiple namespaces.
25-
func CreateRuntimeManager(namespaces string, config *rest.Config, disableMetrics, disableLeaderElection bool, features feature.MutableGate) (manager.Manager, error) {
26-
27-
var leaderElectionID string
28-
if !disableLeaderElection {
29-
leaderElectionID = electionID
30-
}
31-
32-
options := manager.Options{
33-
Cache: cache.Options{
34-
SyncPeriod: &refreshInterval,
35-
},
36-
Scheme: r.Scheme,
37-
LeaderElection: !disableLeaderElection,
38-
LeaderElectionID: leaderElectionID,
23+
// CreateRuntimeManager wraps internal/controller/runtime.NewManager and modifies the given options:
24+
// - Fully overwrites the Cache field
25+
// - Sets Cache.SyncPeriod to refreshInterval const
26+
// - Sets Cache.DefaultNamespaces by using k8s.GetWatchNamespace() split by ","
27+
// - Sets BaseContext to include the provided feature gates
28+
func CreateRuntimeManager(config *rest.Config, features feature.MutableGate, options manager.Options) (manager.Manager, error) {
29+
namespaces, err := k8s.GetWatchNamespace()
30+
if err != nil {
31+
return nil, err
3932
}
4033

41-
options.BaseContext = func() context.Context {
42-
ctx := context.Background()
43-
return feature.NewContext(ctx, features)
34+
options.Cache = cache.Options{
35+
SyncPeriod: initialize.Pointer(refreshInterval),
4436
}
45-
4637
nn := strings.Split(namespaces, ",")
4738
if len(nn) > 0 && nn[0] != "" {
4839
namespaces := make(map[string]cache.Config)
@@ -52,24 +43,10 @@ func CreateRuntimeManager(namespaces string, config *rest.Config, disableMetrics
5243
options.Cache.DefaultNamespaces = namespaces
5344
}
5445

55-
if disableMetrics {
56-
options.HealthProbeBindAddress = "0"
57-
options.Metrics = metricsServer.Options{
58-
BindAddress: "0",
59-
}
60-
}
61-
62-
// Create a copy of the config to avoid modifying the original
63-
configCopy := rest.CopyConfig(config)
64-
65-
// Ensure throttling is disabled by setting a fake rate limiter
66-
configCopy.RateLimiter = flowcontrol.NewFakeAlwaysRateLimiter()
67-
68-
// create controller runtime manager
69-
mgr, err := manager.New(configCopy, options)
70-
if err != nil {
71-
return nil, err
46+
options.BaseContext = func() context.Context {
47+
ctx := context.Background()
48+
return feature.NewContext(ctx, features)
7249
}
7350

74-
return mgr, nil
51+
return r.NewManager(config, options)
7552
}

0 commit comments

Comments
 (0)