Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: investigate rolling-update E2Es failures #71

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .wordlist-en-custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ EnterpriseDB's
EnvFrom
EnvFromSource
EnvVar
EphemeralVolumesSizeLimit
EphemeralVolumesSizeLimitConfiguration
ExternalCluster
Fei
Filesystem
Expand Down Expand Up @@ -366,6 +368,7 @@ TCP
TLS
TOC
TODO
TemporaryData
TimelineId
TopologyKey
TopologySpreadConstraint
Expand Down Expand Up @@ -419,6 +422,7 @@ apiGroup
apiGroups
apiVersion
apidoc
apimachinery
apis
apiserver
apparmor
Expand Down Expand Up @@ -623,6 +627,7 @@ endpointURL
enterprisedb
env
envFrom
ephemeralVolumesSizeLimit
executables
expirations
extensibility
Expand Down Expand Up @@ -1077,6 +1082,7 @@ targetXID
tbody
tcp
td
temporaryData
th
thead
timeLineID
Expand Down
32 changes: 32 additions & 0 deletions api/v1/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions api/v1/cluster_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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"))
})
})
13 changes: 13 additions & 0 deletions api/v1/cluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
32 changes: 32 additions & 0 deletions api/v1/cluster_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
30 changes: 30 additions & 0 deletions api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions config/crd/bases/postgresql.cnpg.io_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
11 changes: 11 additions & 0 deletions docs/src/appendixes/object_stores.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 40 additions & 0 deletions docs/src/cloudnative-pg.v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,14 @@ https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
for more information.</p>
</td>
</tr>
<tr><td><code>ephemeralVolumesSizeLimit</code> <B>[Required]</B><br/>
<a href="#postgresql-cnpg-io-v1-EphemeralVolumesSizeLimitConfiguration"><i>EphemeralVolumesSizeLimitConfiguration</i></a>
</td>
<td>
<p>EphemeralVolumesSizeLimit allows the user to set the limits for the ephemeral
volumes</p>
</td>
</tr>
<tr><td><code>priorityClassName</code><br/>
<i>string</i>
</td>
Expand Down Expand Up @@ -2160,6 +2168,38 @@ a Role in a PostgreSQL instance</p>



## EphemeralVolumesSizeLimitConfiguration {#postgresql-cnpg-io-v1-EphemeralVolumesSizeLimitConfiguration}


**Appears in:**

- [ClusterSpec](#postgresql-cnpg-io-v1-ClusterSpec)


<p>EphemeralVolumesSizeLimitConfiguration contains the configuration of the ephemeral
storage</p>


<table class="table">
<thead><tr><th width="30%">Field</th><th>Description</th></tr></thead>
<tbody>
<tr><td><code>shm</code> <B>[Required]</B><br/>
<i>k8s.io/apimachinery/pkg/api/resource.Quantity</i>
</td>
<td>
<p>Shm is the size limit of the shared memory volume</p>
</td>
</tr>
<tr><td><code>temporaryData</code> <B>[Required]</B><br/>
<i>k8s.io/apimachinery/pkg/api/resource.Quantity</i>
</td>
<td>
<p>TemporaryData is the size limit of the temporary data volume</p>
</td>
</tr>
</tbody>
</table>

## ExternalCluster {#postgresql-cnpg-io-v1-ExternalCluster}


Expand Down
19 changes: 19 additions & 0 deletions docs/src/cluster_conf.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions docs/src/postgresql_conf.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading
Loading