Introduce higher and lower bounds for the number of instances (#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.
This commit is contained in:
Oleksii Kliukin 2017-12-15 16:02:50 +01:00 committed by GitHub
parent 0e255f82c6
commit bf80f5225e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 2 deletions

View File

@ -180,6 +180,12 @@ This ConfigMap is then added as a source of environment variables to the Postgre
: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`.
### Limiting the number of instances in clusters with `min_instances` and `max_instances`
As a preventive measure, one can restrict the minimum and the maximum number of instances permitted by each Postgres cluster managed by the operator.
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.
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.
# Setup development environment
The following steps guide you through the setup to work on the operator itself.

View File

@ -464,6 +464,8 @@ func (c *Cluster) generateStatefulSet(spec *spec.PostgresSpec) (*v1beta1.Statefu
return nil, fmt.Errorf("could not generate volume claim template: %v", err)
}
numberOfInstances := c.getNumberOfInstances(spec)
statefulSet := &v1beta1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: c.statefulSetName(),
@ -471,7 +473,7 @@ func (c *Cluster) generateStatefulSet(spec *spec.PostgresSpec) (*v1beta1.Statefu
Labels: c.labelsSet(),
},
Spec: v1beta1.StatefulSetSpec{
Replicas: &spec.NumberOfInstances,
Replicas: &numberOfInstances,
ServiceName: c.serviceName(Master),
Template: *podTemplate,
VolumeClaimTemplates: []v1.PersistentVolumeClaim{*volumeClaimTemplate},
@ -481,6 +483,25 @@ func (c *Cluster) generateStatefulSet(spec *spec.PostgresSpec) (*v1beta1.Statefu
return statefulSet, nil
}
func (c *Cluster) getNumberOfInstances(spec *spec.PostgresSpec) (newcur int32) {
min := c.OpConfig.MinInstances
max := c.OpConfig.MaxInstances
cur := spec.NumberOfInstances
newcur = cur
if max >= 0 && newcur > max {
newcur = max
}
if min >= 0 && newcur < min {
newcur = min
}
if newcur != cur {
c.logger.Infof("adjusted number of instances from %d to %d (min: %d, max: %d)", cur, newcur, min, max)
}
return
}
func generatePersistentVolumeClaimTemplate(volumeSize, volumeStorageClass string) (*v1.PersistentVolumeClaim, error) {
metadata := metav1.ObjectMeta{
Name: constants.DataVolumeName,

View File

@ -267,7 +267,7 @@ func (c *Cluster) syncStatefulSet() error {
c.logger.Infof("found pods without the statefulset: trigger rolling update")
} else {
// statefulset is alrady there, make sure we use its definition in order to compare with the spec.
// statefulset is already there, make sure we use its definition in order to compare with the spec.
c.Statefulset = sset
desiredSS, err := c.generateStatefulSet(&c.Spec)

View File

@ -5,6 +5,7 @@ import (
"strings"
"time"
"fmt"
"github.com/zalando-incubator/postgres-operator/pkg/spec"
)
@ -33,6 +34,8 @@ type Resources struct {
PodEnvironmentConfigMap string `name:"pod_environment_configmap" default:""`
NodeEOLLabel map[string]string `name:"node_eol_label" default:"lifecycle-status:pending-decommission"`
NodeReadinessLabel map[string]string `name:"node_readiness_label" default:"lifecycle-status:ready"`
MaxInstances int32 `name:"max_instances" default:"-1"`
MinInstances int32 `name:"min_instances" default:"-1"`
}
// Auth describes authentication specific configuration parameters
@ -108,6 +111,9 @@ func NewFromMap(m map[string]string) *Config {
panic(err)
}
}
if err := validate(&cfg); err != nil {
panic(err)
}
return &cfg
}
@ -123,3 +129,14 @@ func Copy(c *Config) Config {
return cfg
}
func validate(cfg *Config) (err error) {
if cfg.MinInstances > 0 && cfg.MaxInstances > 0 && cfg.MinInstances > cfg.MaxInstances {
err = fmt.Errorf("minimum number of instances %d is set higher than the maximum number %d",
cfg.MinInstances, cfg.MaxInstances)
}
if cfg.Workers == 0 {
err = fmt.Errorf("number of workers should be higher than 0")
}
return
}