Skip to content

Commit 185a9e2

Browse files
Jonathan S. Katzjkatz
authored andcommitted
Allow one-off specifications of CPU / Memory
Previously the only way to specify container resources (CPU/RAM) for a PostgreSQL cluster was to customize the "resource config" in the pgo.yaml file and reference it from the "pgo create cluster" command. This introduces the "--cpu" and "--memory" flags to the "pgo create cluster" command to allow one to specify custom values for the PostgreSQL cluster at cluster creation time. Issue: [ch6658] Issue: #1268
1 parent 5375789 commit 185a9e2

File tree

9 files changed

+110
-33
lines changed

9 files changed

+110
-33
lines changed

apiserver/clusterservice/clusterimpl.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,23 @@ func CreateCluster(request *msgs.CreateClusterRequest, ns, pgouser string) msgs.
554554
}
555555
}
556556

557+
// evaluate if the CPU / Memory have been set to custom values
558+
if request.CPURequest != "" {
559+
if err := apiserver.ValidateQuantity(request.CPURequest); err != nil {
560+
resp.Status.Code = msgs.Error
561+
resp.Status.Msg = fmt.Sprintf(apiserver.ErrMessageCPURequest, request.CPURequest, err.Error())
562+
return resp
563+
}
564+
}
565+
566+
if request.MemoryRequest != "" {
567+
if err := apiserver.ValidateQuantity(request.MemoryRequest); err != nil {
568+
resp.Status.Code = msgs.Error
569+
resp.Status.Msg = fmt.Sprintf(apiserver.ErrMessageMemoryRequest, request.MemoryRequest, err.Error())
570+
return resp
571+
}
572+
}
573+
557574
// validate the storage type for each specified tablespace actually exists.
558575
// if a PVCSize is passed in, also validate that it follows the Kubernetes
559576
// format
@@ -950,6 +967,19 @@ func getClusterParams(request *msgs.CreateClusterRequest, name string, userLabel
950967
}
951968
}
952969

970+
// if the request has overriding CPURequest and/or MemoryRequest parameters,
971+
// these will take precedence over the values set by "ContainerResources"
972+
// This will also overwrite the Limits
973+
if request.CPURequest != "" {
974+
spec.ContainerResources.RequestsCPU = request.CPURequest
975+
spec.ContainerResources.LimitsCPU = ""
976+
}
977+
978+
if request.MemoryRequest != "" {
979+
spec.ContainerResources.RequestsMemory = request.MemoryRequest
980+
spec.ContainerResources.LimitsMemory = ""
981+
}
982+
953983
spec.PrimaryStorage, _ = apiserver.Pgo.GetStorageSpec(apiserver.Pgo.PrimaryStorage)
954984
if request.StorageConfig != "" {
955985
spec.PrimaryStorage, _ = apiserver.Pgo.GetStorageSpec(request.StorageConfig)

apiserver/common.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,23 @@ import (
2828
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2929
)
3030

31+
const (
32+
// ErrMessageCPURequest provides a standard error message when a CPURequest
33+
// is not specified to the Kubernetes sstandard
34+
ErrMessageCPURequest = `could not parse CPU request "%s":%s (hint: try a value like "1" or "100m")`
35+
// ErrMessageMemoryRequest provides a standard error message when a MemoryRequest
36+
// is not specified to the Kubernetes sstandard
37+
ErrMessageMemoryRequest = `could not parse memory request "%s":%s (hint: try a value like "1Gi")`
38+
// ErrMessagePVCSize provides a standard error message when a PVCSize is not
39+
// specified to the Kubernetes stnadard
40+
ErrMessagePVCSize = `could not parse PVC size "%s": %s (hint: try a value like "1Gi")`
41+
)
42+
3143
var (
3244
backrestStorageTypes = []string{"local", "s3"}
3345
// ErrDBContainerNotFound is an error that indicates that a "database" container
3446
// could not be found in a specific pod
3547
ErrDBContainerNotFound = errors.New("\"database\" container not found in pod")
36-
// ErrMessagePVCSize provides a standard error message when a PVCSize is not
37-
// specified to the Kubernetes stnadard
38-
ErrMessagePVCSize = `could not parse PVC size "%s": %s (hint: try a value like "1Gi")`
3948
// ErrStandbyNotAllowed contains the error message returned when an API call is not
4049
// permitted because it involves a cluster that is in standby mode
4150
ErrStandbyNotAllowed = errors.New("Action not permitted because standby mode is enabled")

apiserver/root.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -531,12 +531,6 @@ func validateWithKube() {
531531

532532
// GetContainerResources ...
533533
func GetContainerResourcesJSON(resources *crv1.PgContainerResources) string {
534-
535-
//test for the case where no container resources are specified
536-
if resources.RequestsMemory == "" || resources.RequestsCPU == "" ||
537-
resources.LimitsMemory == "" || resources.LimitsCPU == "" {
538-
return ""
539-
}
540534
fields := containerResourcesTemplateFields{}
541535
fields.RequestsMemory = resources.RequestsMemory
542536
fields.RequestsCPU = resources.RequestsCPU

apiservermsgs/clustermsgs.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ type CreateClusterRequest struct {
108108
// CASecret is the name of the secret that contains the CA to use along with
109109
// the TLS keypair for deploying a TLS-enabled PostgreSQL cluster
110110
CASecret string
111+
// CPURequest is the value of how much CPU should be requested for deploying
112+
// the PostgreSQL cluster
113+
CPURequest string
114+
// MemoryRequest is the value of how much RAM should be requested for
115+
// deploying the PostgreSQL cluster
116+
MemoryRequest string
111117
}
112118

113119
// CreateClusterDetail provides details about the PostgreSQL cluster that is
Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
1-
"resources": {
2-
"requests": {
3-
"memory": "{{.RequestsMemory}}",
4-
"cpu": "{{.RequestsCPU}}"
5-
},
6-
"limits": {
7-
"memory": "{{.LimitsMemory}}",
8-
"cpu": "{{.LimitsCPU}}"
9-
}
10-
},
1+
"resources": {
2+
{{ if or .RequestsMemory .RequestsCPU }}
3+
"requests": {
4+
{{ if .RequestsCPU }}
5+
"cpu": "{{.RequestsCPU}}"{{ if .RequestsMemory }},{{ end }}
6+
{{ end }}
7+
{{ if .RequestsMemory }}
8+
"memory": "{{.RequestsMemory}}"
9+
{{ end }}
10+
}{{ if or .LimitsCPU .LimitsMemory }},{{ end }}
11+
{{ end }}
12+
{{ if or .LimitsCPU .LimitsMemory }}
13+
"limits": {
14+
{{ if .LimitsCPU }}
15+
"cpu": "{{.LimitsCPU}}"{{ if .LimitsMemory }},{{ end }}
16+
{{ end }}
17+
{{ if .LimitsMemory }}
18+
"memory": "{{.LimitsMemory}}"
19+
{{ end }}
20+
}
21+
{{ end }}
22+
},

docs/content/pgo-client/reference/pgo_create_cluster.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ pgo create cluster [flags]
2020
```
2121
--ccp-image string The CCPImage name to use for cluster creation. If specified, overrides the value crunchy-postgres.
2222
-c, --ccp-image-tag string The CCPImageTag to use for cluster creation. If specified, overrides the pgo.yaml setting.
23+
--cpu string Set the number of millicores to request for the CPU, e.g. "100m" or "0.1". Overrides the value in "resources-config"
2324
--custom-config string The name of a configMap that holds custom PostgreSQL configuration files used to override defaults.
2425
-d, --database string If specified, sets the name of the initial database that is created for the user. Defaults to the value set in the PostgreSQL Operator configuration, or if that is not present, the name of the cluster
2526
--disable-autofail Disables autofail capabitilies in the cluster following cluster initialization.
2627
-h, --help help for cluster
2728
-l, --labels string The labels to apply to this cluster.
29+
--memory string Set the amount of RAM to request, e.g. 1GiB. Overrides the value in "resources-config"
2830
--metrics Adds the crunchy-collect container to the database pod.
2931
--node-label string The node label (key=value) to use in placing the primary database. If not set, any node is used.
3032
--password string The password to use for standard user account created during cluster initialization.
@@ -88,4 +90,4 @@ pgo create cluster [flags]
8890

8991
* [pgo create](/pgo-client/reference/pgo_create/) - Create a Postgres Operator resource
9092

91-
###### Auto generated by spf13/cobra on 19-Mar-2020
93+
###### Auto generated by spf13/cobra on 26-Mar-2020

operator/common.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -124,23 +124,19 @@ func Initialize(clientset *kubernetes.Clientset) {
124124
log.Info("EventTCPAddress set to " + EventTCPAddress)
125125
}
126126

127-
// GetContainerResources ...
127+
// GetContainerResources is a legacy method that creates the JSON snippet that
128+
// is applied for setting the CPU and memory in a container.
128129
func GetContainerResourcesJSON(resources *crv1.PgContainerResources) string {
129-
130-
//test for the case where no container resources are specified
131-
if resources.RequestsMemory == "" || resources.RequestsCPU == "" ||
132-
resources.LimitsMemory == "" || resources.LimitsCPU == "" {
133-
return ""
130+
fields := containerResourcesTemplateFields{
131+
LimitsCPU: resources.LimitsCPU,
132+
LimitsMemory: resources.LimitsMemory,
133+
RequestsCPU: resources.RequestsCPU,
134+
RequestsMemory: resources.RequestsMemory,
134135
}
135-
fields := containerResourcesTemplateFields{}
136-
fields.RequestsMemory = resources.RequestsMemory
137-
fields.RequestsCPU = resources.RequestsCPU
138-
fields.LimitsMemory = resources.LimitsMemory
139-
fields.LimitsCPU = resources.LimitsCPU
140136

141137
doc := bytes.Buffer{}
142-
err := config.ContainerResourcesTemplate.Execute(&doc, fields)
143-
if err != nil {
138+
139+
if err := config.ContainerResourcesTemplate.Execute(&doc, fields); err != nil {
144140
log.Error(err.Error())
145141
return ""
146142
}

pgo/cmd/cluster.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
"github.com/crunchydata/postgres-operator/pgo/api"
2828
"github.com/crunchydata/postgres-operator/pgo/util"
2929
log "github.com/sirupsen/logrus"
30+
31+
"k8s.io/apimachinery/pkg/api/resource"
3032
)
3133

3234
// below are the tablespace parameters and the expected values of each
@@ -283,6 +285,26 @@ func createCluster(args []string, ns string, createClusterCmd *cobra.Command) {
283285
r.SyncReplication = &SyncReplication
284286
}
285287

288+
// if the user provided resources for CPU or Memory, validate them to ensure
289+
// they are valid Kubernetes values
290+
if CPURequest != "" {
291+
if _, err := resource.ParseQuantity(CPURequest); err != nil {
292+
fmt.Println("Error:", err.Error(), `"`+CPURequest+`"`)
293+
os.Exit(1)
294+
}
295+
296+
r.CPURequest = CPURequest
297+
}
298+
299+
if MemoryRequest != "" {
300+
if _, err := resource.ParseQuantity(MemoryRequest); err != nil {
301+
fmt.Println("Error:", err.Error(), `"`+MemoryRequest+`"`)
302+
os.Exit(1)
303+
}
304+
305+
r.MemoryRequest = MemoryRequest
306+
}
307+
286308
response, err := api.CreateCluster(httpclient, &SessionCredentials, r)
287309
if err != nil {
288310
fmt.Println("Error: ", err)

pgo/cmd/create.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ var ArchiveFlag, DisableAutofailFlag, EnableAutofailFlag, PgbouncerFlag, Metrics
3232
var BackrestRestoreFrom string
3333
var CCPImage string
3434
var CCPImageTag string
35+
var CPURequest string
3536
var Database string
37+
var MemoryRequest string
3638
var Password string
3739
var SecretFrom string
3840
var PoliciesFlag, PolicyFile, PolicyURL string
@@ -254,10 +256,14 @@ func init() {
254256
// flags for "pgo create cluster"
255257
createClusterCmd.Flags().StringVarP(&CCPImage, "ccp-image", "", "", "The CCPImage name to use for cluster creation. If specified, overrides the value crunchy-postgres.")
256258
createClusterCmd.Flags().StringVarP(&CCPImageTag, "ccp-image-tag", "c", "", "The CCPImageTag to use for cluster creation. If specified, overrides the pgo.yaml setting.")
259+
createClusterCmd.Flags().StringVar(&CPURequest, "cpu", "", "Set the number of millicores to request for the CPU, e.g. "+
260+
"\"100m\" or \"0.1\". Overrides the value in \"resources-config\"")
257261
createClusterCmd.Flags().StringVarP(&CustomConfig, "custom-config", "", "", "The name of a configMap that holds custom PostgreSQL configuration files used to override defaults.")
258262
createClusterCmd.Flags().StringVarP(&Database, "database", "d", "", "If specified, sets the name of the initial database that is created for the user. Defaults to the value set in the PostgreSQL Operator configuration, or if that is not present, the name of the cluster")
259263
createClusterCmd.Flags().BoolVarP(&DisableAutofailFlag, "disable-autofail", "", false, "Disables autofail capabitilies in the cluster following cluster initialization.")
260264
createClusterCmd.Flags().StringVarP(&UserLabels, "labels", "l", "", "The labels to apply to this cluster.")
265+
createClusterCmd.Flags().StringVar(&MemoryRequest, "memory", "", "Set the amount of RAM to request, e.g. "+
266+
"1GiB. Overrides the value in \"resources-config\"")
261267
createClusterCmd.Flags().BoolVarP(&MetricsFlag, "metrics", "", false, "Adds the crunchy-collect container to the database pod.")
262268
createClusterCmd.Flags().StringVarP(&NodeLabel, "node-label", "", "", "The node label (key=value) to use in placing the primary database. If not set, any node is used.")
263269
createClusterCmd.Flags().StringVarP(&Password, "password", "", "", "The password to use for standard user account created during cluster initialization.")

0 commit comments

Comments
 (0)