From 020f77a6610e78b7b0cc4291ef23cf58c7a45fd5 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sat, 7 Oct 2023 07:48:09 +0200
Subject: [PATCH 1/5] fix(deps): update golang.org/x/exp digest to 7918f67
(main) (#3013)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
go.mod | 12 ++++++------
go.sum | 26 +++++++++++++-------------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/go.mod b/go.mod
index 0191e3087b..6e9da999e1 100644
--- a/go.mod
+++ b/go.mod
@@ -29,7 +29,7 @@ require (
github.com/thoas/go-funk v0.9.3
go.uber.org/atomic v1.11.0
go.uber.org/zap v1.26.0
- golang.org/x/exp v0.0.0-20231005195138-3e424a577f31
+ golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/sys v0.13.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.28.2
@@ -87,14 +87,14 @@ require (
github.com/xlab/treeprint v1.2.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/crypto v0.13.0 // indirect
- golang.org/x/net v0.15.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
+ golang.org/x/net v0.16.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
- golang.org/x/sync v0.3.0 // indirect
- golang.org/x/term v0.12.0 // indirect
+ golang.org/x/sync v0.4.0 // indirect
+ golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
- golang.org/x/tools v0.13.0 // indirect
+ golang.org/x/tools v0.14.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
diff --git a/go.sum b/go.sum
index 2e56fa0595..8538219b77 100644
--- a/go.sum
+++ b/go.sum
@@ -214,11 +214,11 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20231005195138-3e424a577f31 h1:9k5exFQKQglLo+RoP+4zMjOFE14P6+vyR0baDAi0Rcs=
-golang.org/x/exp v0.0.0-20231005195138-3e424a577f31/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
+golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@@ -226,7 +226,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
+golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -237,8 +237,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos=
+golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
@@ -249,8 +249,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
-golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
+golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -266,8 +266,8 @@ golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -284,8 +284,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
-golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
+golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
+golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
From 9356daa5bddc77ec15e0350447e04dac55ca2e0a Mon Sep 17 00:00:00 2001
From: John Long
Date: Sat, 7 Oct 2023 04:56:43 -0400
Subject: [PATCH 2/5] feat: allow to configure ephemeral-storage limit (#2830)
Closes #1548
Signed-off-by: John Long
Signed-off-by: Jonathan Gonzalez V
Signed-off-by: Leonardo Cecchi
Signed-off-by: Armando Ruocco
Signed-off-by: Gabriele Bartolini
Co-authored-by: Jonathan Gonzalez V
Co-authored-by: Leonardo Cecchi
Co-authored-by: Armando Ruocco
Co-authored-by: Gabriele Bartolini
---
.wordlist-en-custom.txt | 6 +++
api/v1/cluster_types.go | 32 +++++++++++++++
api/v1/cluster_types_test.go | 19 +++++++++
api/v1/cluster_webhook.go | 13 ++++++
api/v1/cluster_webhook_test.go | 32 +++++++++++++++
api/v1/zz_generated.deepcopy.go | 30 ++++++++++++++
.../bases/postgresql.cnpg.io_clusters.yaml | 20 ++++++++++
docs/src/cloudnative-pg.v1.md | 40 +++++++++++++++++++
docs/src/cluster_conf.md | 19 +++++++++
docs/src/postgresql_conf.md | 10 +++++
pkg/specs/volumes.go | 7 +++-
11 files changed, 226 insertions(+), 2 deletions(-)
diff --git a/.wordlist-en-custom.txt b/.wordlist-en-custom.txt
index e81e14ba53..708c737ead 100644
--- a/.wordlist-en-custom.txt
+++ b/.wordlist-en-custom.txt
@@ -123,6 +123,8 @@ EnterpriseDB's
EnvFrom
EnvFromSource
EnvVar
+EphemeralVolumesSizeLimit
+EphemeralVolumesSizeLimitConfiguration
ExternalCluster
Fei
Filesystem
@@ -366,6 +368,7 @@ TCP
TLS
TOC
TODO
+TemporaryData
TimelineId
TopologyKey
TopologySpreadConstraint
@@ -419,6 +422,7 @@ apiGroup
apiGroups
apiVersion
apidoc
+apimachinery
apis
apiserver
apparmor
@@ -623,6 +627,7 @@ endpointURL
enterprisedb
env
envFrom
+ephemeralVolumesSizeLimit
executables
expirations
extensibility
@@ -1077,6 +1082,7 @@ targetXID
tbody
tcp
td
+temporaryData
th
thead
timeLineID
diff --git a/api/v1/cluster_types.go b/api/v1/cluster_types.go
index 723954853d..e3136eac88 100644
--- a/api/v1/cluster_types.go
+++ b/api/v1/cluster_types.go
@@ -315,6 +315,10 @@ type ClusterSpec struct {
// +optional
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
+ // EphemeralVolumesSizeLimit allows the user to set the limits for the ephemeral
+ // volumes
+ EphemeralVolumesSizeLimit *EphemeralVolumesSizeLimitConfiguration `json:"ephemeralVolumesSizeLimit,omitempty"`
+
// Name of the priority class which will be used in every generated Pod, if the PriorityClass
// specified does not exist, the pod will not be able to schedule. Please refer to
// https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass
@@ -429,6 +433,34 @@ const (
PhaseApplyingConfiguration = "Applying configuration"
)
+// EphemeralVolumesSizeLimitConfiguration contains the configuration of the ephemeral
+// storage
+type EphemeralVolumesSizeLimitConfiguration struct {
+ // Shm is the size limit of the shared memory volume
+ Shm *resource.Quantity `json:"shm,omitempty"`
+
+ // TemporaryData is the size limit of the temporary data volume
+ TemporaryData *resource.Quantity `json:"temporaryData,omitempty"`
+}
+
+// GetShmLimit gets the `/dev/shm` memory size limit
+func (e *EphemeralVolumesSizeLimitConfiguration) GetShmLimit() *resource.Quantity {
+ if e == nil {
+ return nil
+ }
+
+ return e.Shm
+}
+
+// GetTemporaryDataLimit gets the temporary storage size limit
+func (e *EphemeralVolumesSizeLimitConfiguration) GetTemporaryDataLimit() *resource.Quantity {
+ if e == nil {
+ return nil
+ }
+
+ return e.TemporaryData
+}
+
// ServiceAccountTemplate contains the template needed to generate the service accounts
type ServiceAccountTemplate struct {
// Metadata are the metadata to be used for the generated
diff --git a/api/v1/cluster_types_test.go b/api/v1/cluster_types_test.go
index 342612c315..a78b2ea327 100644
--- a/api/v1/cluster_types_test.go
+++ b/api/v1/cluster_types_test.go
@@ -18,6 +18,7 @@ package v1
import (
corev1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/api/resource"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
@@ -952,3 +953,21 @@ var _ = Describe("Cluster ShouldRecoveryCreateApplicationDatabase", func() {
Expect(result).To(BeFalse())
})
})
+
+var _ = Describe("Ephemeral volume size limits", func() {
+ It("doesn't panic if the specification is nil", func() {
+ var spec *EphemeralVolumesSizeLimitConfiguration
+ Expect(spec.GetShmLimit()).To(BeNil())
+ Expect(spec.GetTemporaryDataLimit()).To(BeNil())
+ })
+
+ It("works correctly when fully specified", func() {
+ spec := &EphemeralVolumesSizeLimitConfiguration{
+ Shm: ptr.To(resource.MustParse("10Mi")),
+ TemporaryData: ptr.To(resource.MustParse("20Mi")),
+ }
+
+ Expect(spec.GetShmLimit().String()).To(Equal("10Mi"))
+ Expect(spec.GetTemporaryDataLimit().String()).To(Equal("20Mi"))
+ })
+})
diff --git a/api/v1/cluster_webhook.go b/api/v1/cluster_webhook.go
index a9b3c27b9d..ea879b0d32 100644
--- a/api/v1/cluster_webhook.go
+++ b/api/v1/cluster_webhook.go
@@ -987,6 +987,19 @@ func (r *Cluster) validateResources() field.ErrorList {
}
}
+ ephemeralStorageRequest := r.Spec.Resources.Requests.StorageEphemeral()
+ ephemeralStorageLimits := r.Spec.Resources.Limits.StorageEphemeral()
+ if !ephemeralStorageRequest.IsZero() && !ephemeralStorageLimits.IsZero() {
+ ephemeralStorageRequestGtThanLimit := ephemeralStorageRequest.Cmp(*ephemeralStorageLimits) > 0
+ if ephemeralStorageRequestGtThanLimit {
+ result = append(result, field.Invalid(
+ field.NewPath("spec", "resources", "requests", "storage"),
+ ephemeralStorageRequest.String(),
+ "Ephemeral storage request is greater than the limit",
+ ))
+ }
+ }
+
return result
}
diff --git a/api/v1/cluster_webhook_test.go b/api/v1/cluster_webhook_test.go
index d548c6aca4..12c5fdc47a 100644
--- a/api/v1/cluster_webhook_test.go
+++ b/api/v1/cluster_webhook_test.go
@@ -3236,6 +3236,38 @@ var _ = Describe("validateResources", func() {
Expect(errors[0].Detail).To(Equal("Memory request is greater than the limit"))
})
+ It("returns no error when the ephemeral storage request is correctly set", func() {
+ cluster.Spec.Resources.Requests["ephemeral-storage"] = resource.MustParse("1")
+ cluster.Spec.Resources.Limits["ephemeral-storage"] = resource.MustParse("1")
+
+ errors := cluster.validateResources()
+ Expect(errors).To(BeEmpty())
+ })
+
+ It("returns an error when the ephemeral storage request is greater than ephemeral storage limit", func() {
+ cluster.Spec.Resources.Requests["ephemeral-storage"] = resource.MustParse("2")
+ cluster.Spec.Resources.Limits["ephemeral-storage"] = resource.MustParse("1")
+
+ errors := cluster.validateResources()
+ Expect(errors).To(HaveLen(1))
+ Expect(errors[0].Detail).To(Equal("Ephemeral storage request is greater than the limit"))
+ })
+
+ It("returns three errors when CPU, Memory, and ephemeral storage requests are greater than limits", func() {
+ cluster.Spec.Resources.Requests["cpu"] = resource.MustParse("2")
+ cluster.Spec.Resources.Limits["cpu"] = resource.MustParse("1")
+ cluster.Spec.Resources.Requests["memory"] = resource.MustParse("2Gi")
+ cluster.Spec.Resources.Limits["memory"] = resource.MustParse("1Gi")
+ cluster.Spec.Resources.Requests["ephemeral-storage"] = resource.MustParse("2")
+ cluster.Spec.Resources.Limits["ephemeral-storage"] = resource.MustParse("1")
+
+ errors := cluster.validateResources()
+ Expect(errors).To(HaveLen(3))
+ Expect(errors[0].Detail).To(Equal("CPU request is greater than the limit"))
+ Expect(errors[1].Detail).To(Equal("Memory request is greater than the limit"))
+ Expect(errors[2].Detail).To(Equal("Ephemeral storage request is greater than the limit"))
+ })
+
It("returns two errors when both CPU and Memory requests are greater than their limits", func() {
cluster.Spec.Resources.Requests["cpu"] = resource.MustParse("2")
cluster.Spec.Resources.Limits["cpu"] = resource.MustParse("1")
diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go
index ca85e5df40..acdd98bd63 100644
--- a/api/v1/zz_generated.deepcopy.go
+++ b/api/v1/zz_generated.deepcopy.go
@@ -684,6 +684,11 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
}
}
in.Resources.DeepCopyInto(&out.Resources)
+ if in.EphemeralVolumesSizeLimit != nil {
+ in, out := &in.EphemeralVolumesSizeLimit, &out.EphemeralVolumesSizeLimit
+ *out = new(EphemeralVolumesSizeLimitConfiguration)
+ (*in).DeepCopyInto(*out)
+ }
if in.Backup != nil {
in, out := &in.Backup, &out.Backup
*out = new(BackupConfiguration)
@@ -940,6 +945,31 @@ func (in *EmbeddedObjectMetadata) DeepCopy() *EmbeddedObjectMetadata {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *EphemeralVolumesSizeLimitConfiguration) DeepCopyInto(out *EphemeralVolumesSizeLimitConfiguration) {
+ *out = *in
+ if in.Shm != nil {
+ in, out := &in.Shm, &out.Shm
+ x := (*in).DeepCopy()
+ *out = &x
+ }
+ if in.TemporaryData != nil {
+ in, out := &in.TemporaryData, &out.TemporaryData
+ x := (*in).DeepCopy()
+ *out = &x
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EphemeralVolumesSizeLimitConfiguration.
+func (in *EphemeralVolumesSizeLimitConfiguration) DeepCopy() *EphemeralVolumesSizeLimitConfiguration {
+ if in == nil {
+ return nil
+ }
+ out := new(EphemeralVolumesSizeLimitConfiguration)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalCluster) DeepCopyInto(out *ExternalCluster) {
*out = *in
diff --git a/config/crd/bases/postgresql.cnpg.io_clusters.yaml b/config/crd/bases/postgresql.cnpg.io_clusters.yaml
index 2609d8979f..0d0b10e051 100644
--- a/config/crd/bases/postgresql.cnpg.io_clusters.yaml
+++ b/config/crd/bases/postgresql.cnpg.io_clusters.yaml
@@ -1842,6 +1842,26 @@ spec:
x-kubernetes-map-type: atomic
type: object
type: array
+ ephemeralVolumesSizeLimit:
+ description: EphemeralVolumesSizeLimit allows the user to set the
+ limits for the ephemeral volumes
+ properties:
+ shm:
+ anyOf:
+ - type: integer
+ - type: string
+ description: Shm is the size limit of the shared memory volume
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ temporaryData:
+ anyOf:
+ - type: integer
+ - type: string
+ description: TemporaryData is the size limit of the temporary
+ data volume
+ pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+ x-kubernetes-int-or-string: true
+ type: object
externalClusters:
description: The list of external clusters which are used in the configuration
items:
diff --git a/docs/src/cloudnative-pg.v1.md b/docs/src/cloudnative-pg.v1.md
index d64398fe3e..3e801a225f 100644
--- a/docs/src/cloudnative-pg.v1.md
+++ b/docs/src/cloudnative-pg.v1.md
@@ -1546,6 +1546,14 @@ https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
for more information.
+ephemeralVolumesSizeLimit [Required]
+EphemeralVolumesSizeLimitConfiguration
+ |
+
+ EphemeralVolumesSizeLimit allows the user to set the limits for the ephemeral
+volumes
+ |
+
priorityClassName
string
|
@@ -2160,6 +2168,38 @@ a Role in a PostgreSQL instance
+## EphemeralVolumesSizeLimitConfiguration {#postgresql-cnpg-io-v1-EphemeralVolumesSizeLimitConfiguration}
+
+
+**Appears in:**
+
+- [ClusterSpec](#postgresql-cnpg-io-v1-ClusterSpec)
+
+
+EphemeralVolumesSizeLimitConfiguration contains the configuration of the ephemeral
+storage
+
+
+
+Field | Description |
+
+shm [Required]
+k8s.io/apimachinery/pkg/api/resource.Quantity
+ |
+
+ Shm is the size limit of the shared memory volume
+ |
+
+temporaryData [Required]
+k8s.io/apimachinery/pkg/api/resource.Quantity
+ |
+
+ TemporaryData is the size limit of the temporary data volume
+ |
+
+
+
+
## ExternalCluster {#postgresql-cnpg-io-v1-ExternalCluster}
diff --git a/docs/src/cluster_conf.md b/docs/src/cluster_conf.md
index fd37d32454..c46ee7f2b1 100644
--- a/docs/src/cluster_conf.md
+++ b/docs/src/cluster_conf.md
@@ -35,6 +35,25 @@ spec:
You can find a complete example using projected volume template to mount Secret and Configmap in
the [cluster-example-projected-volume.yaml](samples/cluster-example-projected-volume.yaml) deployment manifest.
+## Ephemeral volumes
+
+CloudNativePG relies on [ephemeral volumes](https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/)
+for part of the internal activities. Ephemeral volumes exist for the sole duration of
+a pod's life, without persisting across pod restarts.
+
+### Volume for temporary storage
+
+An ephemeral volume used for temporary storage. An upper bound on the size can be
+configured via the `spec.ephemeralVolumesSizeLimit.temporaryData` field in the cluster
+spec.
+
+### Volume for shared memory
+
+This volume is used as shared memory space for Postgres, also an ephemeral type but
+stored in-memory. An upper bound on the size can be configured via the
+`spec.ephemeralVolumesSizeLimit.shm` field in the cluster spec. This is used only
+in case of [PostgreSQL running with `posix` shared memory dynamic allocation](postgresql_conf.md#dynamic-shared-memory-settings).
+
## Environment variables
Some system behavior can be customized using environment variables. One example is
diff --git a/docs/src/postgresql_conf.md b/docs/src/postgresql_conf.md
index 34fa3349b5..f69dd4fedb 100644
--- a/docs/src/postgresql_conf.md
+++ b/docs/src/postgresql_conf.md
@@ -440,6 +440,16 @@ You should get something similar to the following output:
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=******)
```
+If you would like to set a maximum size for the `shm` volume, you can do so by
+setting the `spec.ephemeralVolumesSizeLimit.shm` field in the `Cluster` resource.
+For example:
+
+```yaml
+spec:
+ ephemeralVolumesSizeLimit:
+ shm: 1Gi
+```
+
### System V shared memory
In case your Kubernetes cluster has a high enough value for the `SHMMAX`
diff --git a/pkg/specs/volumes.go b/pkg/specs/volumes.go
index a31bb856a7..1b15c6ce09 100644
--- a/pkg/specs/volumes.go
+++ b/pkg/specs/volumes.go
@@ -44,14 +44,17 @@ func createPostgresVolumes(cluster apiv1.Cluster, podName string) []corev1.Volum
{
Name: "scratch-data",
VolumeSource: corev1.VolumeSource{
- EmptyDir: &corev1.EmptyDirVolumeSource{},
+ EmptyDir: &corev1.EmptyDirVolumeSource{
+ SizeLimit: cluster.Spec.EphemeralVolumesSizeLimit.GetTemporaryDataLimit(),
+ },
},
},
{
Name: "shm",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{
- Medium: "Memory",
+ Medium: "Memory",
+ SizeLimit: cluster.Spec.EphemeralVolumesSizeLimit.GetShmLimit(),
},
},
},
From 948327c92c83e822aa76c3c97f69f8eb0d08fcbc Mon Sep 17 00:00:00 2001
From: Leonardo Cecchi
Date: Sat, 7 Oct 2023 11:12:21 +0200
Subject: [PATCH 3/5] fix: typo (#3019)
Signed-off-by: Leonardo Cecchi
---
pkg/management/postgres/instance.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pkg/management/postgres/instance.go b/pkg/management/postgres/instance.go
index 53f91bd661..118622ae3e 100644
--- a/pkg/management/postgres/instance.go
+++ b/pkg/management/postgres/instance.go
@@ -961,7 +961,7 @@ func (instance *Instance) GetInstanceCommandChan() <-chan InstanceCommand {
}
// RequestFastImmediateShutdown request the lifecycle manager to shut down
-// PostegreSQL using the fast strategy and then the immediate strategy.
+// PostgreSQL using the fast strategy and then the immediate strategy.
func (instance *Instance) RequestFastImmediateShutdown() {
instance.instanceCommandChan <- ShutDownFastImmediate
}
From dedf003241db7b4c1cbb94b63ae218340ac39094 Mon Sep 17 00:00:00 2001
From: Steven Miller
Date: Sat, 7 Oct 2023 05:22:22 -0400
Subject: [PATCH 4/5] docs: S3 lifecycle policies (#2594)
Signed-off-by: Steven Miller
Signed-off-by: Gabriele Bartolini
Co-authored-by: Gabriele Bartolini
---
docs/src/appendixes/object_stores.md | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/docs/src/appendixes/object_stores.md b/docs/src/appendixes/object_stores.md
index a2ca00b5ba..6863a25d36 100644
--- a/docs/src/appendixes/object_stores.md
+++ b/docs/src/appendixes/object_stores.md
@@ -94,6 +94,17 @@ spec:
[...]
```
+### S3 lifecycle policy
+
+Barman Cloud writes objects to S3, then does not update them until they are
+deleted by the Barman Cloud retention policy. A recommended approach for an S3
+lifecycle policy is to expire the current version of objects a few days longer
+than the Barman retention policy, enable object versioning, and expire
+non-current versions after a number of days. Such a policy protects against
+accidental deletion, and also allows for restricting permissions to the
+CloudNativePG workload so that it may delete objects from S3 without granting
+permissions to permanently delete objects.
+
### Other S3-compatible Object Storages providers
In case you're using S3-compatible object storage, like **MinIO** or
From 311018a690b1b9d0145aca37a1f244eff83c88a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niccol=C3=B2=20Fei?=
Date: Mon, 9 Oct 2023 12:16:35 +0200
Subject: [PATCH 5/5] chore: investigate rolling-update E2Es failures
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Niccolò Fei
---
tests/e2e/rolling_update_test.go | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/tests/e2e/rolling_update_test.go b/tests/e2e/rolling_update_test.go
index ff146ffcc5..44adeebae1 100644
--- a/tests/e2e/rolling_update_test.go
+++ b/tests/e2e/rolling_update_test.go
@@ -17,8 +17,11 @@ limitations under the License.
package e2e
import (
+ "bytes"
+ "fmt"
"os"
"strconv"
+ "strings"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
@@ -245,6 +248,27 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun
Expect(err).ToNot(HaveOccurred())
clusterInstances := cluster.Spec.Instances
+ // Dump logs on failure
+ var buf bytes.Buffer
+ GinkgoWriter.Println("Putting Tail on the cluster logs")
+ go func() {
+ err = env.TailClusterLogs(cluster, &buf, false)
+ if err != nil {
+ _, _ = fmt.Fprintf(GinkgoWriter, "\nError tailing cluster logs: %v\n", err)
+ }
+ }()
+ DeferCleanup(func(ctx SpecContext) {
+ if CurrentSpecReport().Failed() {
+ specName := CurrentSpecReport().FullText()
+ capLines := 10
+ GinkgoWriter.Printf("DUMPING tailed Cluster Logs with error/warning (at most %v lines). Failed Spec: %v\n",
+ capLines, specName)
+ GinkgoWriter.Println("================================================================================")
+ saveLogs(&buf, "cluster_logs_", strings.ReplaceAll(specName, " ", "_"), GinkgoWriter, capLines)
+ GinkgoWriter.Println("================================================================================")
+ }
+ })
+
By("Gathering info on the current state", func() {
originalPodNames, originalPodUID, originalPVCUID, err = gatherClusterInfo(namespace, clusterName)
Expect(err).ToNot(HaveOccurred())
@@ -284,7 +308,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun
})
}
- Context("Three Instances", func() {
+ FContext("Three Instances", func() {
const namespacePrefix = "cluster-rolling-e2e-three-instances"
const sampleFile = fixturesDir + "/rolling_updates/cluster-three-instances.yaml.template"
const clusterName = "postgresql-three-instances"