Skip to content

Commit d032e47

Browse files
FxKuSergey Shatunov
andauthored
LoadBalancer toggles for master and replica pooler pods (#1799)
* Add support for pooler load balancer Signed-off-by: Sergey Shatunov <me@prok.pw> * Rename to enable_master_pooler_load_balancer Signed-off-by: Sergey Shatunov <me@prok.pw> * target port should be intval * enhance pooler e2e test * add new options to crds.go Co-authored-by: Sergey Shatunov <me@prok.pw>
1 parent 695ad44 commit d032e47

25 files changed

+428
-126
lines changed

charts/postgres-operator/crds/operatorconfigurations.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,15 @@ spec:
380380
enable_master_load_balancer:
381381
type: boolean
382382
default: true
383+
enable_master_pooler_load_balancer:
384+
type: boolean
385+
default: false
383386
enable_replica_load_balancer:
384387
type: boolean
385388
default: false
389+
enable_replica_pooler_load_balancer:
390+
type: boolean
391+
default: false
386392
external_traffic_policy:
387393
type: string
388394
enum:

charts/postgres-operator/crds/postgresqls.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,12 @@ spec:
197197
type: boolean
198198
enableMasterLoadBalancer:
199199
type: boolean
200+
enableMasterPoolerLoadBalancer:
201+
type: boolean
200202
enableReplicaLoadBalancer:
201203
type: boolean
204+
enableReplicaPoolerLoadBalancer:
205+
type: boolean
202206
enableShmVolume:
203207
type: boolean
204208
init_containers:

charts/postgres-operator/values.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,12 @@ configLoadBalancer:
228228

229229
# toggles service type load balancer pointing to the master pod of the cluster
230230
enable_master_load_balancer: false
231+
# toggles service type load balancer pointing to the master pooler pod of the cluster
232+
enable_master_pooler_load_balancer: false
231233
# toggles service type load balancer pointing to the replica pod of the cluster
232234
enable_replica_load_balancer: false
235+
# toggles service type load balancer pointing to the replica pooler pod of the cluster
236+
enable_replica_pooler_load_balancer: false
233237
# define external traffic policy for the load balancer
234238
external_traffic_policy: "Cluster"
235239
# defines the DNS name string template for the master load balancer cluster

docs/administrator.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,11 @@ lead to K8s removing this field from the manifest due to its
750750
Then the resultant manifest will not contain the necessary change, and the
751751
operator will respectively do nothing with the existing source ranges.
752752

753+
Load balancer services can also be enabled for the [connection pooler](user.md#connection-pooler)
754+
pods with manifest flags `enableMasterPoolerLoadBalancer` and/or
755+
`enableReplicaPoolerLoadBalancer` or in the operator configuration with
756+
`enable_master_pooler_load_balancer` and/or `enable_replica_pooler_load_balancer`.
757+
753758
## Running periodic 'autorepair' scans of K8s objects
754759

755760
The Postgres Operator periodically scans all K8s objects belonging to each

docs/reference/cluster_manifest.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,23 @@ These parameters are grouped directly under the `spec` key in the manifest.
9191
`enable_master_load_balancer` parameter) to define whether to enable the load
9292
balancer pointing to the Postgres primary. Optional.
9393

94+
* **enableMasterPoolerLoadBalancer**
95+
boolean flag to override the operator defaults (set by the
96+
`enable_master_pooler_load_balancer` parameter) to define whether to enable
97+
the load balancer for master pooler pods pointing to the Postgres primary.
98+
Optional.
99+
94100
* **enableReplicaLoadBalancer**
95101
boolean flag to override the operator defaults (set by the
96102
`enable_replica_load_balancer` parameter) to define whether to enable the
97103
load balancer pointing to the Postgres standby instances. Optional.
98104

105+
* **enableReplicaPoolerLoadBalancer**
106+
boolean flag to override the operator defaults (set by the
107+
`enable_replica_pooler_load_balancer` parameter) to define whether to enable
108+
the load balancer for replica pooler pods pointing to the Postgres standby
109+
instances. Optional.
110+
99111
* **allowedSourceRanges**
100112
when one or more load balancers are enabled for the cluster, this parameter
101113
defines the comma-separated range of IP networks (in CIDR-notation). The

docs/reference/operator_parameters.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,11 +546,21 @@ In the CRD-based configuration they are grouped under the `load_balancer` key.
546546
toggles service type load balancer pointing to the master pod of the cluster.
547547
Can be overridden by individual cluster settings. The default is `true`.
548548

549+
* **enable_master_pooler_load_balancer**
550+
toggles service type load balancer pointing to the master pooler pod of the
551+
cluster. Can be overridden by individual cluster settings. The default is
552+
`false`.
553+
549554
* **enable_replica_load_balancer**
550-
toggles service type load balancer pointing to the replica pod of the
551-
cluster. Can be overridden by individual cluster settings. The default is
555+
toggles service type load balancer pointing to the replica pod(s) of the
556+
cluster. Can be overridden by individual cluster settings. The default is
552557
`false`.
553558

559+
* **enable_replica_pooler_load_balancer**
560+
toggles service type load balancer pointing to the replica pooler pod(s) of
561+
the cluster. Can be overridden by individual cluster settings. The default
562+
is `false`.
563+
554564
* **external_traffic_policy** defines external traffic policy for load
555565
balancers. Allowed values are `Cluster` (default) and `Local`.
556566

e2e/tests/test_e2e.py

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,9 @@ def test_enable_disable_connection_pooler(self):
467467
the end turn connection pooler off to not interfere with other tests.
468468
'''
469469
k8s = self.k8s
470+
pooler_label = 'application=db-connection-pooler,cluster-name=acid-minimal-cluster'
471+
master_pooler_label = 'connection-pooler=acid-minimal-cluster-pooler'
472+
replica_pooler_label = master_pooler_label + '-repl'
470473
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
471474

472475
k8s.api.custom_objects_api.patch_namespaced_custom_object(
@@ -476,22 +479,23 @@ def test_enable_disable_connection_pooler(self):
476479
'spec': {
477480
'enableConnectionPooler': True,
478481
'enableReplicaConnectionPooler': True,
482+
'enableMasterPoolerLoadBalancer': True,
483+
'enableReplicaPoolerLoadBalancer': True,
479484
}
480485
})
486+
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
481487

482-
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(), 2,
483-
"Deployment replicas is 2 default")
484-
self.eventuallyEqual(lambda: k8s.count_running_pods(
485-
"connection-pooler=acid-minimal-cluster-pooler"),
486-
2, "No pooler pods found")
487-
self.eventuallyEqual(lambda: k8s.count_running_pods(
488-
"connection-pooler=acid-minimal-cluster-pooler-repl"),
489-
2, "No pooler replica pods found")
490-
self.eventuallyEqual(lambda: k8s.count_services_with_label(
491-
'application=db-connection-pooler,cluster-name=acid-minimal-cluster'),
492-
2, "No pooler service found")
493-
self.eventuallyEqual(lambda: k8s.count_secrets_with_label('application=db-connection-pooler,cluster-name=acid-minimal-cluster'),
494-
1, "Pooler secret not created")
488+
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(), 2, "Deployment replicas is 2 default")
489+
self.eventuallyEqual(lambda: k8s.count_running_pods(master_pooler_label), 2, "No pooler pods found")
490+
self.eventuallyEqual(lambda: k8s.count_running_pods(replica_pooler_label), 2, "No pooler replica pods found")
491+
self.eventuallyEqual(lambda: k8s.count_services_with_label(pooler_label), 2, "No pooler service found")
492+
self.eventuallyEqual(lambda: k8s.count_secrets_with_label(pooler_label), 1, "Pooler secret not created")
493+
self.eventuallyEqual(lambda: k8s.get_service_type(master_pooler_label+","+pooler_label),
494+
'LoadBalancer',
495+
"Expected LoadBalancer service type for master pooler pod, found {}")
496+
self.eventuallyEqual(lambda: k8s.get_service_type(replica_pooler_label+","+pooler_label),
497+
'LoadBalancer',
498+
"Expected LoadBalancer service type for replica pooler pod, found {}")
495499

496500
# Turn off only master connection pooler
497501
k8s.api.custom_objects_api.patch_namespaced_custom_object(
@@ -504,20 +508,17 @@ def test_enable_disable_connection_pooler(self):
504508
}
505509
})
506510

507-
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"},
508-
"Operator does not get in sync")
511+
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
512+
509513
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(name="acid-minimal-cluster-pooler-repl"), 2,
510514
"Deployment replicas is 2 default")
511-
self.eventuallyEqual(lambda: k8s.count_running_pods(
512-
"connection-pooler=acid-minimal-cluster-pooler"),
515+
self.eventuallyEqual(lambda: k8s.count_running_pods(master_pooler_label),
513516
0, "Master pooler pods not deleted")
514-
self.eventuallyEqual(lambda: k8s.count_running_pods(
515-
"connection-pooler=acid-minimal-cluster-pooler-repl"),
517+
self.eventuallyEqual(lambda: k8s.count_running_pods(replica_pooler_label),
516518
2, "Pooler replica pods not found")
517-
self.eventuallyEqual(lambda: k8s.count_services_with_label(
518-
'application=db-connection-pooler,cluster-name=acid-minimal-cluster'),
519+
self.eventuallyEqual(lambda: k8s.count_services_with_label(pooler_label),
519520
1, "No pooler service found")
520-
self.eventuallyEqual(lambda: k8s.count_secrets_with_label('application=db-connection-pooler,cluster-name=acid-minimal-cluster'),
521+
self.eventuallyEqual(lambda: k8s.count_secrets_with_label(pooler_label),
521522
1, "Secret not created")
522523

523524
# Turn off only replica connection pooler
@@ -528,20 +529,24 @@ def test_enable_disable_connection_pooler(self):
528529
'spec': {
529530
'enableConnectionPooler': True,
530531
'enableReplicaConnectionPooler': False,
532+
'enableMasterPoolerLoadBalancer': False,
531533
}
532534
})
533535

534-
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"},
535-
"Operator does not get in sync")
536+
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
537+
536538
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(), 2,
537539
"Deployment replicas is 2 default")
538-
self.eventuallyEqual(lambda: k8s.count_running_pods("connection-pooler=acid-minimal-cluster-pooler"),
540+
self.eventuallyEqual(lambda: k8s.count_running_pods(master_pooler_label),
539541
2, "Master pooler pods not found")
540-
self.eventuallyEqual(lambda: k8s.count_running_pods("connection-pooler=acid-minimal-cluster-pooler-repl"),
542+
self.eventuallyEqual(lambda: k8s.count_running_pods(replica_pooler_label),
541543
0, "Pooler replica pods not deleted")
542-
self.eventuallyEqual(lambda: k8s.count_services_with_label('application=db-connection-pooler,cluster-name=acid-minimal-cluster'),
544+
self.eventuallyEqual(lambda: k8s.count_services_with_label(pooler_label),
543545
1, "No pooler service found")
544-
self.eventuallyEqual(lambda: k8s.count_secrets_with_label('application=db-connection-pooler,cluster-name=acid-minimal-cluster'),
546+
self.eventuallyEqual(lambda: k8s.get_service_type(master_pooler_label+","+pooler_label),
547+
'ClusterIP',
548+
"Expected LoadBalancer service type for master, found {}")
549+
self.eventuallyEqual(lambda: k8s.count_secrets_with_label(pooler_label),
545550
1, "Secret not created")
546551

547552
# scale up connection pooler deployment
@@ -558,7 +563,7 @@ def test_enable_disable_connection_pooler(self):
558563

559564
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(), 3,
560565
"Deployment replicas is scaled to 3")
561-
self.eventuallyEqual(lambda: k8s.count_running_pods("connection-pooler=acid-minimal-cluster-pooler"),
566+
self.eventuallyEqual(lambda: k8s.count_running_pods(master_pooler_label),
562567
3, "Scale up of pooler pods does not work")
563568

564569
# turn it off, keeping config should be overwritten by false
@@ -569,12 +574,13 @@ def test_enable_disable_connection_pooler(self):
569574
'spec': {
570575
'enableConnectionPooler': False,
571576
'enableReplicaConnectionPooler': False,
577+
'enableReplicaPoolerLoadBalancer': False,
572578
}
573579
})
574580

575-
self.eventuallyEqual(lambda: k8s.count_running_pods("connection-pooler=acid-minimal-cluster-pooler"),
581+
self.eventuallyEqual(lambda: k8s.count_running_pods(master_pooler_label),
576582
0, "Pooler pods not scaled down")
577-
self.eventuallyEqual(lambda: k8s.count_services_with_label('application=db-connection-pooler,cluster-name=acid-minimal-cluster'),
583+
self.eventuallyEqual(lambda: k8s.count_services_with_label(pooler_label),
578584
0, "Pooler service not removed")
579585
self.eventuallyEqual(lambda: k8s.count_secrets_with_label('application=spilo,cluster-name=acid-minimal-cluster'),
580586
4, "Secrets not deleted")
@@ -1177,10 +1183,11 @@ def test_node_readiness_label(self):
11771183

11781184
@timeout_decorator.timeout(TEST_TIMEOUT_SEC)
11791185
def test_overwrite_pooler_deployment(self):
1186+
pooler_name = 'acid-minimal-cluster-pooler'
11801187
k8s = self.k8s
11811188
k8s.create_with_kubectl("manifests/minimal-fake-pooler-deployment.yaml")
11821189
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
1183-
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(name="acid-minimal-cluster-pooler"), 1,
1190+
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(name=pooler_name), 1,
11841191
"Initial broken deployment not rolled out")
11851192

11861193
k8s.api.custom_objects_api.patch_namespaced_custom_object(
@@ -1193,7 +1200,7 @@ def test_overwrite_pooler_deployment(self):
11931200
})
11941201

11951202
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
1196-
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(name="acid-minimal-cluster-pooler"), 2,
1203+
self.eventuallyEqual(lambda: k8s.get_deployment_replica_count(name=pooler_name), 2,
11971204
"Operator did not succeed in overwriting labels")
11981205

11991206
k8s.api.custom_objects_api.patch_namespaced_custom_object(
@@ -1206,7 +1213,7 @@ def test_overwrite_pooler_deployment(self):
12061213
})
12071214

12081215
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")
1209-
self.eventuallyEqual(lambda: k8s.count_running_pods("connection-pooler=acid-minimal-cluster-pooler"),
1216+
self.eventuallyEqual(lambda: k8s.count_running_pods("connection-pooler="+pooler_name),
12101217
0, "Pooler pods not scaled down")
12111218

12121219
@timeout_decorator.timeout(TEST_TIMEOUT_SEC)

manifests/configmap.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ data:
4444
# enable_init_containers: "true"
4545
# enable_lazy_spilo_upgrade: "false"
4646
enable_master_load_balancer: "false"
47+
enable_master_pooler_load_balancer: "false"
4748
enable_password_rotation: "false"
4849
enable_pgversion_env_var: "true"
4950
# enable_pod_antiaffinity: "false"
5051
# enable_pod_disruption_budget: "true"
5152
# enable_postgres_team_crd: "false"
5253
# enable_postgres_team_crd_superusers: "false"
5354
enable_replica_load_balancer: "false"
55+
enable_replica_pooler_load_balancer: "false"
5456
# enable_shm_volume: "true"
5557
# enable_sidecars: "true"
5658
enable_spilo_wal_path_compat: "true"

manifests/operatorconfiguration.crd.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,15 @@ spec:
378378
enable_master_load_balancer:
379379
type: boolean
380380
default: true
381+
enable_master_pooler_load_balancer:
382+
type: boolean
383+
default: false
381384
enable_replica_load_balancer:
382385
type: boolean
383386
default: false
387+
enable_replica_pooler_load_balancer:
388+
type: boolean
389+
default: false
384390
external_traffic_policy:
385391
type: string
386392
enum:

manifests/postgresql-operator-default-configuration.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ configuration:
119119
# keyy: valuey
120120
# db_hosted_zone: ""
121121
enable_master_load_balancer: false
122+
enable_master_pooler_load_balancer: false
122123
enable_replica_load_balancer: false
124+
enable_replica_pooler_load_balancer: false
123125
external_traffic_policy: "Cluster"
124126
master_dns_name_format: "{cluster}.{team}.{hostedzone}"
125127
replica_dns_name_format: "{cluster}-repl.{team}.{hostedzone}"

0 commit comments

Comments
 (0)