Skip to content

Commit aa97825

Browse files
committed
feat: Support PgBouncer 1.23.1
1 parent 96a8561 commit aa97825

5 files changed

Lines changed: 204 additions & 18 deletions

File tree

stackgres-k8s/e2e/spec/abstract/prometheus-integration

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,17 @@ check_grafana_secret() {
3939

4040
check_exporter_queries() {
4141
local METRIC
42-
for METRIC in $(yq -r 'keys[]' "$PROJECT_PATH"/stackgres-k8s/src/operator/src/main/resources/prometheus-postgres-exporter/queries-1.22.yaml)
42+
local QUERIES_FILE=queries.yaml
43+
local VERSION_AS_NUMBER VERSION_1_12_0
44+
VERSION_AS_NUMBER="$(get_version_as_number "$STACKGRES_VERSION")"
45+
VERSION_1_12_0="$(get_version_as_number 1.12.0)"
46+
if [ "$VERSION_AS_NUMBER" -le "$VERSION_1_12_0" ]
47+
then
48+
QUERIES_FILE=queries-1.22.yaml
49+
fi
50+
for METRIC in $(yq -r 'keys[]' "$PROJECT_PATH"/stackgres-k8s/src/operator/src/main/resources/prometheus-postgres-exporter/"$QUERIES_FILE")
4351
do
44-
QUERY="$(yq -r ".[\"$METRIC\"].query" "$PROJECT_PATH"/stackgres-k8s/src/operator/src/main/resources/prometheus-postgres-exporter/queries-1.22.yaml)"
52+
QUERY="$(yq -r ".[\"$METRIC\"].query" "$PROJECT_PATH"/stackgres-k8s/src/operator/src/main/resources/prometheus-postgres-exporter/"$QUERIES_FILE")"
4553
if wait_until eval 'kubectl exec -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-0" -c postgres-util -- \
4654
psql -v ON_ERROR_STOP=ON -c "$QUERY" > /dev/null'
4755
then

stackgres-k8s/src/operator/src/main/java/io/stackgres/operator/conciliation/factory/cluster/autoscaling/HorizontalAutoscaling.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.fabric8.kubernetes.api.model.SecretBuilder;
1414
import io.stackgres.common.EnvoyUtil;
1515
import io.stackgres.common.PatroniUtil;
16+
import io.stackgres.common.StackGresVersion;
1617
import io.stackgres.common.crd.external.keda.ScaledObjectBuilder;
1718
import io.stackgres.common.crd.external.keda.TriggerAuthenticationBuilder;
1819
import io.stackgres.common.crd.sgcluster.StackGresCluster;
@@ -30,7 +31,7 @@
3031
import jakarta.inject.Singleton;
3132

3233
@Singleton
33-
@OperatorVersionBinder
34+
@OperatorVersionBinder(startAt = StackGresVersion.V_1_13)
3435
public class HorizontalAutoscaling implements ResourceGenerator<StackGresClusterContext> {
3536

3637
public static String name(StackGresCluster cluster) {
@@ -148,20 +149,20 @@ FROM dblink(
148149
'host=/var/run/postgresql port=6432 dbname=pgbouncer user=pgbouncer',
149150
'show databases'::text)
150151
AS _(
151-
name text, host text, port integer, database text,
152-
force_user text, pool_size integer, min_pool_size integer,
153-
reserve_pool integer, pool_mode text, max_connections integer,
154-
current_connections integer, paused boolean, disabled boolean)),
152+
name text, host text, port integer, database text, force_user text,
153+
pool_size integer, min_pool_size integer, reserve_pool integer, server_lifetime integer,
154+
pool_mode text, max_connections integer, current_connections integer,
155+
paused boolean, disabled boolean)),
155156
active_connections (size) AS (
156157
SELECT SUM(_.current_connections)::numeric
157158
FROM dblink(
158159
'host=/var/run/postgresql port=6432 dbname=pgbouncer user=pgbouncer',
159160
'show databases'::text)
160161
AS _(
161-
name text, host text, port integer, database text,
162-
force_user text, pool_size integer, min_pool_size integer,
163-
reserve_pool integer, pool_mode text, max_connections integer,
164-
current_connections integer, paused boolean, disabled boolean))
162+
name text, host text, port integer, database text, force_user text,
163+
pool_size integer, min_pool_size integer, reserve_pool integer, server_lifetime integer,
164+
pool_mode text, max_connections integer, current_connections integer,
165+
paused boolean, disabled boolean))
165166
SELECT active_connections.size / max_connections.size AS connection_usage
166167
FROM max_connections, active_connections;
167168
""")))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
* Copyright (C) 2019 OnGres, Inc.
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
package io.stackgres.operator.conciliation.factory.cluster.autoscaling;
7+
8+
import java.util.Map;
9+
import java.util.Optional;
10+
import java.util.stream.Stream;
11+
12+
import io.fabric8.kubernetes.api.model.HasMetadata;
13+
import io.fabric8.kubernetes.api.model.SecretBuilder;
14+
import io.stackgres.common.EnvoyUtil;
15+
import io.stackgres.common.PatroniUtil;
16+
import io.stackgres.common.StackGresVersion;
17+
import io.stackgres.common.crd.external.keda.ScaledObjectBuilder;
18+
import io.stackgres.common.crd.external.keda.TriggerAuthenticationBuilder;
19+
import io.stackgres.common.crd.sgcluster.StackGresCluster;
20+
import io.stackgres.common.crd.sgcluster.StackGresClusterAutoscaling;
21+
import io.stackgres.common.crd.sgcluster.StackGresClusterAutoscalingHorizontal;
22+
import io.stackgres.common.crd.sgcluster.StackGresClusterPods;
23+
import io.stackgres.common.crd.sgcluster.StackGresClusterSpec;
24+
import io.stackgres.common.labels.LabelFactoryForCluster;
25+
import io.stackgres.operator.conciliation.OperatorVersionBinder;
26+
import io.stackgres.operator.conciliation.ResourceGenerator;
27+
import io.stackgres.operator.conciliation.cluster.StackGresClusterContext;
28+
import io.stackgres.operator.conciliation.factory.cluster.patroni.PatroniSecret;
29+
import io.stackgres.operatorframework.resource.ResourceUtil;
30+
import jakarta.inject.Inject;
31+
import jakarta.inject.Singleton;
32+
33+
@Singleton
34+
@OperatorVersionBinder(stopAt = StackGresVersion.V_1_12)
35+
public class HorizontalAutoscalingV1M12 implements ResourceGenerator<StackGresClusterContext> {
36+
37+
public static String name(StackGresCluster cluster) {
38+
return ResourceUtil.resourceName(cluster.getMetadata().getName());
39+
}
40+
41+
public static String secretName(StackGresCluster cluster) {
42+
return ResourceUtil.resourceName(cluster.getMetadata().getName() + "-autoscaling");
43+
}
44+
45+
private LabelFactoryForCluster<StackGresCluster> labelFactory;
46+
47+
@Inject
48+
public HorizontalAutoscalingV1M12(LabelFactoryForCluster<StackGresCluster> labelFactory) {
49+
this.labelFactory = labelFactory;
50+
}
51+
52+
@Override
53+
public Stream<HasMetadata> generateResource(StackGresClusterContext context) {
54+
StackGresCluster cluster = context.getCluster();
55+
return Optional.of(cluster.getSpec())
56+
.map(StackGresClusterSpec::getAutoscaling)
57+
.filter(StackGresClusterAutoscaling::isHorizontalPodAutoscalingEnabled)
58+
.stream()
59+
.flatMap(autoscaling -> Stream.of(
60+
new SecretBuilder()
61+
.withNewMetadata()
62+
.withLabels(labelFactory.genericLabels(cluster))
63+
.withName(secretName(cluster))
64+
.withNamespace(cluster.getMetadata().getNamespace())
65+
.endMetadata()
66+
.withData(Optional.of(PatroniSecret.getSuperuserCredentials(context))
67+
.map(credentials -> "postgresql://"
68+
+ credentials.v1 + ":" + credentials.v2
69+
+ "@" + PatroniUtil.readOnlyName(cluster)
70+
+ "." + cluster.getMetadata().getNamespace()
71+
+ ":" + String.valueOf(EnvoyUtil.PG_PORT)
72+
+ "/postgres?sslmode=prefer&default_query_exec_mode=exec")
73+
.map(connection -> Map.of("connection", connection))
74+
.map(ResourceUtil::encodeSecret)
75+
.get())
76+
.build(),
77+
new TriggerAuthenticationBuilder()
78+
.withNewMetadata()
79+
.withLabels(labelFactory.genericLabels(cluster))
80+
.withName(name(cluster))
81+
.withNamespace(cluster.getMetadata().getNamespace())
82+
.endMetadata()
83+
.withNewSpec()
84+
.addNewSecretTargetRef()
85+
.withName(secretName(cluster))
86+
.withKey("connection")
87+
.withParameter("connection")
88+
.endSecretTargetRef()
89+
.endSpec()
90+
.build(),
91+
new ScaledObjectBuilder()
92+
.withNewMetadata()
93+
.withLabels(labelFactory.genericLabels(cluster))
94+
.withName(name(cluster))
95+
.withNamespace(cluster.getMetadata().getNamespace())
96+
.endMetadata()
97+
.withNewSpec()
98+
.withNewScaleTargetRef()
99+
.withApiVersion(HasMetadata.getApiVersion(StackGresCluster.class))
100+
.withKind(HasMetadata.getKind(StackGresCluster.class))
101+
.withName(cluster.getMetadata().getName())
102+
.endScaleTargetRef()
103+
.withCooldownPeriod(Optional.ofNullable(autoscaling.getHorizontal())
104+
.map(StackGresClusterAutoscalingHorizontal::getCooldownPeriod)
105+
.orElse(300))
106+
.withPollingInterval(Optional.ofNullable(autoscaling.getHorizontal())
107+
.map(StackGresClusterAutoscalingHorizontal::getPollingInterval)
108+
.orElse(30))
109+
.withMinReplicaCount(autoscaling.getMinInstances())
110+
.withMaxReplicaCount(autoscaling.getMaxInstances())
111+
.addNewTrigger()
112+
.withNewAuthenticationRef()
113+
.withName(name(cluster))
114+
.endAuthenticationRef()
115+
.withType("postgresql")
116+
.withName("connections-used")
117+
.withMetadata(Map.ofEntries(
118+
Map.entry(
119+
"targetQueryValue",
120+
Optional.ofNullable(autoscaling.getHorizontal())
121+
.map(StackGresClusterAutoscalingHorizontal::getReplicasConnectionsUsageTarget)
122+
.orElse("0.8")),
123+
Map.entry(
124+
"query",
125+
Optional.of(cluster.getSpec().getPods())
126+
.map(StackGresClusterPods::getDisableConnectionPooling)
127+
.orElse(false)
128+
?
129+
"""
130+
WITH
131+
max_connections (size) AS (
132+
SELECT setting::numeric
133+
FROM pg_settings
134+
WHERE name = 'max_connections'),
135+
active_connections (size) AS (
136+
SELECT COUNT(*)::numeric
137+
FROM pg_stat_activity
138+
WHERE state = 'active'
139+
AND backend_type = 'client backend')
140+
SELECT active_connections.size / max_connections.size AS connection_usage
141+
FROM max_connections, active_connections;
142+
"""
143+
:
144+
"""
145+
WITH
146+
max_connections (size) AS (
147+
SELECT SUM(_.pool_size)::numeric
148+
FROM dblink(
149+
'host=/var/run/postgresql port=6432 dbname=pgbouncer user=pgbouncer',
150+
'show databases'::text)
151+
AS _(
152+
name text, host text, port integer, database text,
153+
force_user text, pool_size integer, min_pool_size integer,
154+
reserve_pool integer, pool_mode text, max_connections integer,
155+
current_connections integer, paused boolean, disabled boolean)),
156+
active_connections (size) AS (
157+
SELECT SUM(_.current_connections)::numeric
158+
FROM dblink(
159+
'host=/var/run/postgresql port=6432 dbname=pgbouncer user=pgbouncer',
160+
'show databases'::text)
161+
AS _(
162+
name text, host text, port integer, database text,
163+
force_user text, pool_size integer, min_pool_size integer,
164+
reserve_pool integer, pool_mode text, max_connections integer,
165+
current_connections integer, paused boolean, disabled boolean))
166+
SELECT active_connections.size / max_connections.size AS connection_usage
167+
FROM max_connections, active_connections;
168+
""")))
169+
.withMetricType(Optional.ofNullable(autoscaling.getHorizontal())
170+
.map(StackGresClusterAutoscalingHorizontal::getReplicasConnectionsUsageMetricType)
171+
.orElse("AverageValue"))
172+
.endTrigger()
173+
.endSpec()
174+
.build()));
175+
}
176+
177+
}

stackgres-k8s/src/operator/src/main/java/io/stackgres/operator/conciliation/factory/cluster/sidecars/pgexporter/PostgresExporter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363

6464
@Singleton
6565
@Sidecar(StackGresContainer.POSTGRES_EXPORTER)
66-
@OperatorVersionBinder(startAt = StackGresVersion.V_1_12)
66+
@OperatorVersionBinder(startAt = StackGresVersion.V_1_13)
6767
@RunningContainer(StackGresContainer.POSTGRES_EXPORTER)
6868
public class PostgresExporter implements ContainerFactory<ClusterContainerContext>,
6969
VolumeFactory<StackGresClusterContext> {

stackgres-k8s/src/operator/src/main/resources/prometheus-postgres-exporter/queries.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,19 +1142,19 @@ pgbouncer_show_databases:
11421142
_.host,
11431143
_.port,
11441144
_.database,
1145-
_.replication,
11461145
_.force_user,
11471146
_.pool_size,
11481147
_.min_pool_size,
11491148
_.reserve_pool,
1149+
_.server_lifetime,
11501150
_.pool_mode,
11511151
_.max_connections,
11521152
_.current_connections,
11531153
_.paused,
11541154
_.disabled
11551155
FROM dblink('host=/var/run/postgresql port=6432 dbname=pgbouncer user=pgbouncer', 'show databases'::text)
1156-
AS _(name text, host text, port integer, database text, replication text, force_user text, pool_size integer, min_pool_size integer,
1157-
reserve_pool integer, pool_mode text, max_connections integer, current_connections integer, paused boolean, disabled boolean);
1156+
AS _(name text, host text, port integer, database text, force_user text, pool_size integer, min_pool_size integer,
1157+
reserve_pool integer, server_lifetime integer, pool_mode text, max_connections integer, current_connections integer, paused boolean, disabled boolean);
11581158
metrics:
11591159
- name:
11601160
usage: "LABEL"
@@ -1168,9 +1168,6 @@ pgbouncer_show_databases:
11681168
- database:
11691169
usage: "LABEL"
11701170
description: "Actual database name pgbouncer connects to."
1171-
- replication:
1172-
usage: "LABEL"
1173-
description: "Replication type"
11741171
- force_user:
11751172
usage: "LABEL"
11761173
description: "When the user is part of the connection string the connection between pgbouncer and PostgreSQL is forced to the given user"
@@ -1183,6 +1180,9 @@ pgbouncer_show_databases:
11831180
- reserve_pool:
11841181
usage: "GAUGE"
11851182
description: "Maximum number of additional connections for this database"
1183+
- server_lifetime:
1184+
usage: "GAUGE"
1185+
description: "The maximum lifetime of a server connection for this database"
11861186
- pool_mode:
11871187
usage: "LABEL"
11881188
description: "The database override pool_mode"

0 commit comments

Comments
 (0)