Skip to content

Commit bf80f52

Browse files
Introduce higher and lower bounds for the number of instances (zalando#178)
* Introduce higher and lower bounds for the number of instances Reduce the number of instances to the min_instances if it is lower and to the max_instances if it is higher. -1 for either of those means there is no lower or upper bound. In addition, terminate the operator when there is a nonsense in the configuration (i.e. max_instances < min_instances). Reviewed by Jan Mußler and Sergey Dudoladov.
1 parent 0e255f8 commit bf80f52

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ This ConfigMap is then added as a source of environment variables to the Postgre
180180

181181
:exclamation: Note that there are environment variables defined by the operator itself in order to pass parameters to the Spilo image. The values from the operator for those variables will take precedence over those defined in the `pod_environment_configmap`.
182182

183+
### Limiting the number of instances in clusters with `min_instances` and `max_instances`
184+
185+
As a preventive measure, one can restrict the minimum and the maximum number of instances permitted by each Postgres cluster managed by the operator.
186+
If either `min_instances` or `max_instances` is set to a non-zero value, the operator may adjust the number of instances specified in the cluster manifest to match either the min or the max boundary.
187+
For instance, of a cluster manifest has 1 instance and the min_instances is set to 3, the cluster will be created with 3 instances. By default, both parameters are set to -1.
188+
183189
# Setup development environment
184190

185191
The following steps guide you through the setup to work on the operator itself.

pkg/cluster/k8sres.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,14 +464,16 @@ func (c *Cluster) generateStatefulSet(spec *spec.PostgresSpec) (*v1beta1.Statefu
464464
return nil, fmt.Errorf("could not generate volume claim template: %v", err)
465465
}
466466

467+
numberOfInstances := c.getNumberOfInstances(spec)
468+
467469
statefulSet := &v1beta1.StatefulSet{
468470
ObjectMeta: metav1.ObjectMeta{
469471
Name: c.statefulSetName(),
470472
Namespace: c.Namespace,
471473
Labels: c.labelsSet(),
472474
},
473475
Spec: v1beta1.StatefulSetSpec{
474-
Replicas: &spec.NumberOfInstances,
476+
Replicas: &numberOfInstances,
475477
ServiceName: c.serviceName(Master),
476478
Template: *podTemplate,
477479
VolumeClaimTemplates: []v1.PersistentVolumeClaim{*volumeClaimTemplate},
@@ -481,6 +483,25 @@ func (c *Cluster) generateStatefulSet(spec *spec.PostgresSpec) (*v1beta1.Statefu
481483
return statefulSet, nil
482484
}
483485

486+
func (c *Cluster) getNumberOfInstances(spec *spec.PostgresSpec) (newcur int32) {
487+
min := c.OpConfig.MinInstances
488+
max := c.OpConfig.MaxInstances
489+
cur := spec.NumberOfInstances
490+
newcur = cur
491+
492+
if max >= 0 && newcur > max {
493+
newcur = max
494+
}
495+
if min >= 0 && newcur < min {
496+
newcur = min
497+
}
498+
if newcur != cur {
499+
c.logger.Infof("adjusted number of instances from %d to %d (min: %d, max: %d)", cur, newcur, min, max)
500+
}
501+
502+
return
503+
}
504+
484505
func generatePersistentVolumeClaimTemplate(volumeSize, volumeStorageClass string) (*v1.PersistentVolumeClaim, error) {
485506
metadata := metav1.ObjectMeta{
486507
Name: constants.DataVolumeName,

pkg/cluster/sync.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ func (c *Cluster) syncStatefulSet() error {
267267
c.logger.Infof("found pods without the statefulset: trigger rolling update")
268268

269269
} else {
270-
// statefulset is alrady there, make sure we use its definition in order to compare with the spec.
270+
// statefulset is already there, make sure we use its definition in order to compare with the spec.
271271
c.Statefulset = sset
272272

273273
desiredSS, err := c.generateStatefulSet(&c.Spec)

pkg/util/config/config.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strings"
66
"time"
77

8+
"fmt"
89
"github.com/zalando-incubator/postgres-operator/pkg/spec"
910
)
1011

@@ -33,6 +34,8 @@ type Resources struct {
3334
PodEnvironmentConfigMap string `name:"pod_environment_configmap" default:""`
3435
NodeEOLLabel map[string]string `name:"node_eol_label" default:"lifecycle-status:pending-decommission"`
3536
NodeReadinessLabel map[string]string `name:"node_readiness_label" default:"lifecycle-status:ready"`
37+
MaxInstances int32 `name:"max_instances" default:"-1"`
38+
MinInstances int32 `name:"min_instances" default:"-1"`
3639
}
3740

3841
// Auth describes authentication specific configuration parameters
@@ -108,6 +111,9 @@ func NewFromMap(m map[string]string) *Config {
108111
panic(err)
109112
}
110113
}
114+
if err := validate(&cfg); err != nil {
115+
panic(err)
116+
}
111117

112118
return &cfg
113119
}
@@ -123,3 +129,14 @@ func Copy(c *Config) Config {
123129

124130
return cfg
125131
}
132+
133+
func validate(cfg *Config) (err error) {
134+
if cfg.MinInstances > 0 && cfg.MaxInstances > 0 && cfg.MinInstances > cfg.MaxInstances {
135+
err = fmt.Errorf("minimum number of instances %d is set higher than the maximum number %d",
136+
cfg.MinInstances, cfg.MaxInstances)
137+
}
138+
if cfg.Workers == 0 {
139+
err = fmt.Errorf("number of workers should be higher than 0")
140+
}
141+
return
142+
}

0 commit comments

Comments
 (0)