Add set_memory_request_to_limit option

This commit is contained in:
Sergey Dudoladov 2018-11-08 13:49:30 +01:00
parent 96e3ea9511
commit 90db0e545b
11 changed files with 50 additions and 16 deletions

View File

@ -90,6 +90,8 @@ cd postgres-operator
./run_operator_locally.sh ./run_operator_locally.sh
``` ```
Note we provide the `/manifests` directory as an example only; you should consider adjusting the manifests to your particular setting.
## Running and testing the operator ## Running and testing the operator
The best way to test the operator is to run it locally in [minikube](https://kubernetes.io/docs/getting-started-guides/minikube/). See developer docs(`docs/developer.yaml`) for details. The best way to test the operator is to run it locally in [minikube](https://kubernetes.io/docs/getting-started-guides/minikube/). See developer docs(`docs/developer.yaml`) for details.

View File

@ -41,12 +41,12 @@ manifests:
```bash ```bash
$ kubectl create namespace test $ kubectl create namespace test
$ kubectl config set-context --namespace=test $ kubectl config set-context $(kubectl config current-context) --namespace=test
``` ```
All subsequent `kubectl` commands will work with the `test` namespace. The All subsequent `kubectl` commands will work with the `test` namespace. The
operator will run in this namespace and look up needed resources - such as its operator will run in this namespace and look up needed resources - such as its
config map - there. config map - there. Please note that the namespace for service accounts and cluster role bindings in [operator RBAC rules](manifests/operator-service-account-rbac.yaml) needs to be adjusted to the non-default value.
## Specify the namespace to watch ## Specify the namespace to watch

View File

@ -221,6 +221,9 @@ CRD-based configuration.
memory limits for the postgres containers, unless overridden by cluster-specific memory limits for the postgres containers, unless overridden by cluster-specific
settings. The default is `1Gi`. settings. The default is `1Gi`.
* **set_memory_request_to_limit**
Set `memory_request` to `memory_limit` for all Postgres clusters (the default value is also increased). This prevents certain cases of memory overcommitment at the cost of overprovisioning memory and potential scheduling problems for Postgres pods with high memory limits due to the lack of memory on Kubernetes cluster nodes. This affects sidecar containers as well. The default is `false`.
## Operator timeouts ## Operator timeouts
This set of parameters define various timeouts related to some operator This set of parameters define various timeouts related to some operator

View File

@ -6,7 +6,7 @@ metadata:
spec: spec:
teamId: "ACID" teamId: "ACID"
volume: volume:
size: 5Gi size: 1Gi
numberOfInstances: 2 numberOfInstances: 2
users: #Application/Robot users users: #Application/Robot users
zalando: zalando:
@ -31,7 +31,7 @@ spec:
memory: 100Mi memory: 100Mi
limits: limits:
cpu: 300m cpu: 300m
memory: 3000Mi memory: 300Mi
patroni: patroni:
initdb: initdb:
encoding: "UTF8" encoding: "UTF8"

View File

@ -15,6 +15,7 @@ data:
secret_name_template: '{username}.{cluster}.credentials' secret_name_template: '{username}.{cluster}.credentials'
super_username: postgres super_username: postgres
enable_teams_api: "false" enable_teams_api: "false"
set_memory_request_to_limit: "true"
# postgres_superuser_teams: "postgres_superusers" # postgres_superuser_teams: "postgres_superusers"
# enable_team_superuser: "false" # enable_team_superuser: "false"
# team_admin_role: "admin" # team_admin_role: "admin"

View File

@ -90,8 +90,8 @@ type ResourceDescription struct {
// Resources describes requests and limits for the cluster resouces. // Resources describes requests and limits for the cluster resouces.
type Resources struct { type Resources struct {
ResourceRequest ResourceDescription `json:"requests,omitempty"` ResourceRequests ResourceDescription `json:"requests,omitempty"`
ResourceLimits ResourceDescription `json:"limits,omitempty"` ResourceLimits ResourceDescription `json:"limits,omitempty"`
} }
// Patroni contains Patroni-specific configuration // Patroni contains Patroni-specific configuration

View File

@ -240,8 +240,8 @@ var unmarshalCluster = []struct {
Slots: map[string]map[string]string{"permanent_logical_1": {"type": "logical", "database": "foo", "plugin": "pgoutput"}}, Slots: map[string]map[string]string{"permanent_logical_1": {"type": "logical", "database": "foo", "plugin": "pgoutput"}},
}, },
Resources: Resources{ Resources: Resources{
ResourceRequest: ResourceDescription{CPU: "10m", Memory: "50Mi"}, ResourceRequests: ResourceDescription{CPU: "10m", Memory: "50Mi"},
ResourceLimits: ResourceDescription{CPU: "300m", Memory: "3000Mi"}, ResourceLimits: ResourceDescription{CPU: "300m", Memory: "3000Mi"},
}, },
TeamID: "ACID", TeamID: "ACID",

View File

@ -573,7 +573,7 @@ func (in *ResourceDescription) DeepCopy() *ResourceDescription {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Resources) DeepCopyInto(out *Resources) { func (in *Resources) DeepCopyInto(out *Resources) {
*out = *in *out = *in
out.ResourceRequest = in.ResourceRequest out.ResourceRequests = in.ResourceRequests
out.ResourceLimits = in.ResourceLimits out.ResourceLimits = in.ResourceLimits
return return
} }

View File

@ -92,18 +92,18 @@ func (c *Cluster) makeDefaultResources() acidv1.Resources {
defaultRequests := acidv1.ResourceDescription{CPU: config.DefaultCPURequest, Memory: config.DefaultMemoryRequest} defaultRequests := acidv1.ResourceDescription{CPU: config.DefaultCPURequest, Memory: config.DefaultMemoryRequest}
defaultLimits := acidv1.ResourceDescription{CPU: config.DefaultCPULimit, Memory: config.DefaultMemoryLimit} defaultLimits := acidv1.ResourceDescription{CPU: config.DefaultCPULimit, Memory: config.DefaultMemoryLimit}
return acidv1.Resources{ResourceRequest: defaultRequests, ResourceLimits: defaultLimits} return acidv1.Resources{ResourceRequests: defaultRequests, ResourceLimits: defaultLimits}
} }
func generateResourceRequirements(resources acidv1.Resources, defaultResources acidv1.Resources) (*v1.ResourceRequirements, error) { func generateResourceRequirements(resources acidv1.Resources, defaultResources acidv1.Resources) (*v1.ResourceRequirements, error) {
var err error var err error
specRequests := resources.ResourceRequest specRequests := resources.ResourceRequests
specLimits := resources.ResourceLimits specLimits := resources.ResourceLimits
result := v1.ResourceRequirements{} result := v1.ResourceRequirements{}
result.Requests, err = fillResourceList(specRequests, defaultResources.ResourceRequest) result.Requests, err = fillResourceList(specRequests, defaultResources.ResourceRequests)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not fill resource requests: %v", err) return nil, fmt.Errorf("could not fill resource requests: %v", err)
} }
@ -377,8 +377,8 @@ func generateSidecarContainers(sidecars []acidv1.Sidecar,
resources, err := generateResourceRequirements( resources, err := generateResourceRequirements(
makeResources( makeResources(
sidecar.Resources.ResourceRequest.CPU, sidecar.Resources.ResourceRequests.CPU,
sidecar.Resources.ResourceRequest.Memory, sidecar.Resources.ResourceRequests.Memory,
sidecar.Resources.ResourceLimits.CPU, sidecar.Resources.ResourceLimits.CPU,
sidecar.Resources.ResourceLimits.Memory, sidecar.Resources.ResourceLimits.Memory,
), ),
@ -625,7 +625,7 @@ func getBucketScopeSuffix(uid string) string {
func makeResources(cpuRequest, memoryRequest, cpuLimit, memoryLimit string) acidv1.Resources { func makeResources(cpuRequest, memoryRequest, cpuLimit, memoryLimit string) acidv1.Resources {
return acidv1.Resources{ return acidv1.Resources{
ResourceRequest: acidv1.ResourceDescription{ ResourceRequests: acidv1.ResourceDescription{
CPU: cpuRequest, CPU: cpuRequest,
Memory: memoryRequest, Memory: memoryRequest,
}, },
@ -644,6 +644,18 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*v1beta1.State
podTemplate *v1.PodTemplateSpec podTemplate *v1.PodTemplateSpec
volumeClaimTemplate *v1.PersistentVolumeClaim volumeClaimTemplate *v1.PersistentVolumeClaim
) )
if c.OpConfig.SetMemoryRequestToLimit {
if spec.Resources.ResourceLimits.Memory > spec.Resources.ResourceRequests.Memory {
c.logger.Warningf("The memory request of %v for the Postgres container is increased to match the memory limit of %v.", spec.Resources.ResourceRequests.Memory, spec.Resources.ResourceLimits.Memory)
spec.Resources.ResourceRequests.Memory = spec.Resources.ResourceLimits.Memory
}
// controller adjusts default and Spilo sidecar container requests (those do not need Sync)
}
defaultResources := c.makeDefaultResources() defaultResources := c.makeDefaultResources()
resourceRequirements, err := generateResourceRequirements(spec.Resources, defaultResources) resourceRequirements, err := generateResourceRequirements(spec.Resources, defaultResources)

View File

@ -110,6 +110,21 @@ func (c *Controller) initOperatorConfig() {
c.opConfig = config.NewFromMap(configMapData) c.opConfig = config.NewFromMap(configMapData)
c.warnOnDeprecatedOperatorParameters() c.warnOnDeprecatedOperatorParameters()
if c.opConfig.SetMemoryRequestToLimit {
if c.opConfig.DefaultMemoryLimit > c.opConfig.DefaultMemoryRequest {
c.logger.Warningf("The default memory request of %v for Postgres containers is increased to match the default memory limit of %v.", c.opConfig.DefaultMemoryRequest, c.opConfig.DefaultMemoryLimit)
c.opConfig.DefaultMemoryRequest = c.opConfig.DefaultMemoryLimit
}
if c.opConfig.ScalyrMemoryLimit > c.opConfig.ScalyrMemoryRequest {
c.logger.Warningf("The memory request of %v for the Scalyr sidecar container is increased to match the memory limit of %v.", c.opConfig.ScalyrMemoryRequest, c.opConfig.ScalyrMemoryLimit)
c.opConfig.ScalyrMemoryRequest = c.opConfig.ScalyrMemoryLimit
}
// generateStatefulSet adjusts values for individual Postgres clusters
}
} }
func (c *Controller) modifyConfigFromEnvironment() { func (c *Controller) modifyConfigFromEnvironment() {

View File

@ -104,6 +104,7 @@ type Config struct {
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"` PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
ProtectedRoles []string `name:"protected_role_names" default:"admin"` ProtectedRoles []string `name:"protected_role_names" default:"admin"`
PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""` PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""`
SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" defaults:"false"`
} }
// MustMarshal marshals the config or panics // MustMarshal marshals the config or panics