Skip to content
2 changes: 2 additions & 0 deletions charts/postgres-operator/crds/operatorconfigurations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ spec:
format: int32
minimum: 1
type: integer
connection_pooler_priority_class_name:
type: string
connection_pooler_schema:
default: pooler
type: string
Expand Down
2 changes: 2 additions & 0 deletions charts/postgres-operator/crds/postgresqls.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ spec:
format: int32
minimum: 1
type: integer
priorityClassName:
type: string
resources:
description: Resources describes requests and limits for the cluster
resouces.
Expand Down
2 changes: 2 additions & 0 deletions charts/postgres-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ configConnectionPooler:
connection_pooler_mode: "transaction"
# number of pooler instances
connection_pooler_number_of_instances: 2
# priorityClassName to assign to pooler pods
# connection_pooler_priority_class_name: ""
# default resources
connection_pooler_default_cpu_request: 500m
connection_pooler_default_memory_request: 100Mi
Expand Down
8 changes: 8 additions & 0 deletions docs/reference/cluster_manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,14 @@ for both master and replica pooler services (if `enableReplicaConnectionPooler`
* **mode**
In which mode to run connection pooler, transaction or session.

* **priorityClassName**
a name of the [priority
class](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass)
that should be assigned to the connection pooler pods. When not specified, the
value is taken from the `connection_pooler_priority_class_name` operator
parameter, if not set then the default priority class is taken. The priority
class itself must be defined in advance. Optional.

* **resources**
Resource configuration for connection pooler deployment.

Expand Down
6 changes: 6 additions & 0 deletions docs/reference/operator_parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,12 @@ operator being able to provide some reasonable defaults.
* **connection_pooler_mode**
Default pooler mode, `session` or `transaction`. Default is `transaction`.

* **connection_pooler_priority_class_name**
The name of the priority class to assign to connection pooler pods by default.
A cluster can override this with `connectionPooler.priorityClassName`. When
unset, the pooler pods use no priority class. The empty string signifies no
assignment.

* **connection_pooler_default_cpu_request**
**connection_pooler_default_memory_reques**
**connection_pooler_default_cpu_limit**
Expand Down
1 change: 1 addition & 0 deletions manifests/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ data:
connection_pooler_max_db_connections: "60"
connection_pooler_mode: "transaction"
connection_pooler_number_of_instances: "2"
# connection_pooler_priority_class_name: ""
connection_pooler_schema: "pooler"
connection_pooler_user: "pooler"
crd_categories: "all"
Expand Down
2 changes: 2 additions & 0 deletions manifests/operatorconfiguration.crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ spec:
format: int32
minimum: 1
type: integer
connection_pooler_priority_class_name:
type: string
connection_pooler_schema:
default: pooler
type: string
Expand Down
1 change: 1 addition & 0 deletions manifests/postgresql-operator-default-configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ configuration:
# connection_pooler_max_db_connections: 60
connection_pooler_mode: "transaction"
connection_pooler_number_of_instances: 2
# connection_pooler_priority_class_name: ""
# connection_pooler_schema: "pooler"
# connection_pooler_user: "pooler"
patroni:
Expand Down
2 changes: 2 additions & 0 deletions manifests/postgresql.crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ spec:
format: int32
minimum: 1
type: integer
priorityClassName:
type: string
resources:
description: Resources describes requests and limits for the cluster
resouces.
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/acid.zalan.do/v1/operator_configuration_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ type ConnectionPoolerConfiguration struct {
DefaultCPULimit string `json:"connection_pooler_default_cpu_limit,omitempty"`
// +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$`
DefaultMemoryLimit string `json:"connection_pooler_default_memory_limit,omitempty"`
PriorityClassName string `json:"connection_pooler_priority_class_name,omitempty"`
}

// OperatorLogicalBackupConfiguration defines configuration for logical backup
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ spec:
format: int32
minimum: 1
type: integer
connection_pooler_priority_class_name:
type: string
connection_pooler_schema:
default: pooler
type: string
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/acid.zalan.do/v1/postgresql.crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ spec:
format: int32
minimum: 1
type: integer
priorityClassName:
type: string
resources:
description: Resources describes requests and limits for the cluster
resouces.
Expand Down
7 changes: 4 additions & 3 deletions pkg/apis/acid.zalan.do/v1/postgresql_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,10 @@ type ConnectionPooler struct {
Schema string `json:"schema,omitempty"`
User string `json:"user,omitempty"`
// +kubebuilder:validation:Enum=session;transaction
Mode string `json:"mode,omitempty"`
DockerImage string `json:"dockerImage,omitempty"`
MaxDBConnections *int32 `json:"maxDBConnections,omitempty"`
Mode string `json:"mode,omitempty"`
DockerImage string `json:"dockerImage,omitempty"`
MaxDBConnections *int32 `json:"maxDBConnections,omitempty"`
PriorityClassName string `json:"priorityClassName,omitempty"`

*Resources `json:"resources,omitempty"`
}
Expand Down
13 changes: 13 additions & 0 deletions pkg/cluster/connection_pooler.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,9 @@ func (c *Cluster) generateConnectionPoolerPodTemplate(role PostgresRole) (
Volumes: poolerVolumes,
SecurityContext: &securityContext,
ServiceAccountName: c.OpConfig.PodServiceAccountName,
PriorityClassName: util.Coalesce(
connectionPoolerSpec.PriorityClassName,
c.OpConfig.ConnectionPooler.PriorityClassName),
},
}

Expand Down Expand Up @@ -893,6 +896,16 @@ func (c *Cluster) needSyncConnectionPoolerDefaults(Config *Config, spec *acidv1.
reasons = append(reasons, msg)
}

if spec.PriorityClassName == "" {
expectedPriorityClassName := config.PriorityClassName
if podTemplate.Spec.PriorityClassName != expectedPriorityClassName {
sync = true
msg := fmt.Sprintf("priorityClassName is different (having %s, required %s)",
podTemplate.Spec.PriorityClassName, expectedPriorityClassName)
reasons = append(reasons, msg)
}
}

expectedResources, err := c.generateResourceRequirements(spec.Resources,
makeDefaultConnectionPoolerResources(&Config.OpConfig),
connectionPoolerContainer)
Expand Down
66 changes: 66 additions & 0 deletions pkg/cluster/connection_pooler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,72 @@ func TestConnectionPoolerDeploymentSpec(t *testing.T) {
}
}

func TestConnectionPoolerPriorityClassName(t *testing.T) {
newCluster := func(specPooler, opPooler, specPod, opPod string) *Cluster {
c := New(
Config{
OpConfig: config.Config{
Resources: config.Resources{
PodPriorityClassName: opPod,
},
ConnectionPooler: config.ConnectionPooler{
PriorityClassName: opPooler,
},
},
}, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder)
c.Spec = acidv1.PostgresSpec{
PodPriorityClassName: specPod,
ConnectionPooler: &acidv1.ConnectionPooler{PriorityClassName: specPooler},
}
return c
}

tests := []struct {
subTest string
cluster *Cluster
expected string
}{
{
subTest: "pooler spec wins over everything",
cluster: newCluster("pooler-spec", "pooler-op", "pod-spec", "pod-op"),
expected: "pooler-spec",
},
{
subTest: "pooler operator default when spec empty",
cluster: newCluster("", "pooler-op", "pod-spec", "pod-op"),
expected: "pooler-op",
},
{
subTest: "does not inherit cluster pod priority class",
cluster: newCluster("", "", "pod-spec", "pod-op"),
expected: "",
},
{
subTest: "does not inherit operator pod priority class",
cluster: newCluster("", "", "", "pod-op"),
expected: "",
},
{
subTest: "empty when nothing set",
cluster: newCluster("", "", "", ""),
expected: "",
},
}

for _, role := range [2]PostgresRole{Master, Replica} {
for _, tt := range tests {
podSpec, err := tt.cluster.generateConnectionPoolerPodTemplate(role)
if err != nil {
t.Fatalf("%s [%s]: unexpected error %v", role, tt.subTest, err)
}
if podSpec.Spec.PriorityClassName != tt.expected {
t.Errorf("%s [%s]: got priorityClassName %q, expected %q",
role, tt.subTest, podSpec.Spec.PriorityClassName, tt.expected)
}
}
}
}

func testServiceAccount(cluster *Cluster, podSpec *v1.PodTemplateSpec, role PostgresRole) error {
poolerServiceAccount := podSpec.Spec.ServiceAccountName

Expand Down
1 change: 1 addition & 0 deletions pkg/controller/operator_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
result.ConnectionPooler.ConnectionPoolerDefaultMemoryRequest = fromCRD.ConnectionPooler.DefaultMemoryRequest
result.ConnectionPooler.ConnectionPoolerDefaultCPULimit = fromCRD.ConnectionPooler.DefaultCPULimit
result.ConnectionPooler.ConnectionPoolerDefaultMemoryLimit = fromCRD.ConnectionPooler.DefaultMemoryLimit
result.ConnectionPooler.PriorityClassName = fromCRD.ConnectionPooler.PriorityClassName

result.ConnectionPooler.MaxDBConnections = util.CoalesceInt32(
fromCRD.ConnectionPooler.MaxDBConnections,
Expand Down
1 change: 1 addition & 0 deletions pkg/util/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ type ConnectionPooler struct {
Image string `name:"connection_pooler_image" default:"ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1"`
Mode string `name:"connection_pooler_mode" default:"transaction"`
MaxDBConnections *int32 `name:"connection_pooler_max_db_connections" default:"60"`
PriorityClassName string `name:"connection_pooler_priority_class_name"`
ConnectionPoolerDefaultCPURequest string `name:"connection_pooler_default_cpu_request"`
ConnectionPoolerDefaultMemoryRequest string `name:"connection_pooler_default_memory_request"`
ConnectionPoolerDefaultCPULimit string `name:"connection_pooler_default_cpu_limit"`
Expand Down