Skip to content

Commit

Permalink
feat: add ephemeralStorage option to cluster spec.
Browse files Browse the repository at this point in the history
Allow the user to optionally set the ephemeralStorage option in the
cluster spec.

Refs:
 - #3677
 - #317

Signed-off-by: Josh Fyne <josh.fyne@gmail.com>
  • Loading branch information
jfyne committed Jan 10, 2024
1 parent 7222979 commit 48584e9
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 8 deletions.
4 changes: 4 additions & 0 deletions api/v1/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ type ClusterSpec struct {
// +optional
WalStorage *StorageConfiguration `json:"walStorage,omitempty"`

// EphemeralVolumeSource allows the user to configure the source of ephemeral volumes.
// +optional
EphemeralVolumeSource *corev1.EphemeralVolumeSource `json:"ephemeralStorage,omitempty"`

// The time in seconds that is allowed for a PostgreSQL instance to
// successfully start up (default 3600).
// The startup probe failure threshold is derived from this value using the formula:
Expand Down
5 changes: 5 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.

248 changes: 248 additions & 0 deletions config/crd/bases/postgresql.cnpg.io_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,254 @@ spec:
x-kubernetes-map-type: atomic
type: object
type: array
ephemeralStorage:
description: EphemeralVolumeSource allows the user to configure the
source of ephemeral volumes.
properties:
volumeClaimTemplate:
description: "Will be used to create a stand-alone PVC to provision
the volume. The pod in which this EphemeralVolumeSource is embedded
will be the owner of the PVC, i.e. the PVC will be deleted together
with the pod. The name of the PVC will be `<pod name>-<volume
name>` where `<volume name>` is the name from the `PodSpec.Volumes`
array entry. Pod validation will reject the pod if the concatenated
name is not valid for a PVC (for example, too long). \n An existing
PVC with that name that is not owned by the pod will *not* be
used for the pod to avoid using an unrelated volume by mistake.
Starting the pod is then blocked until the unrelated PVC is
removed. If such a pre-created PVC is meant to be used by the
pod, the PVC has to updated with an owner reference to the pod
once the pod exists. Normally this should not be necessary,
but it may be useful when manually reconstructing a broken cluster.
\n This field is read-only and no changes will be made by Kubernetes
to the PVC after it has been created. \n Required, must not
be nil."
properties:
metadata:
description: May contain labels and annotations that will
be copied into the PVC when creating it. No other fields
are allowed and will be rejected during validation.
type: object
spec:
description: The specification for the PersistentVolumeClaim.
The entire content is copied unchanged into the PVC that
gets created from this template. The same fields as in a
PersistentVolumeClaim are also valid here.
properties:
accessModes:
description: 'accessModes contains the desired access
modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1'
items:
type: string
type: array
dataSource:
description: 'dataSource field can be used to specify
either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot)
* An existing PVC (PersistentVolumeClaim) If the provisioner
or an external controller can support the specified
data source, it will create a new volume based on the
contents of the specified data source. When the AnyVolumeDataSource
feature gate is enabled, dataSource contents will be
copied to dataSourceRef, and dataSourceRef contents
will be copied to dataSource when dataSourceRef.namespace
is not specified. If the namespace is specified, then
dataSourceRef will not be copied to dataSource.'
properties:
apiGroup:
description: APIGroup is the group for the resource
being referenced. If APIGroup is not specified,
the specified Kind must be in the core API group.
For any other third-party types, APIGroup is required.
type: string
kind:
description: Kind is the type of resource being referenced
type: string
name:
description: Name is the name of resource being referenced
type: string
required:
- kind
- name
type: object
x-kubernetes-map-type: atomic
dataSourceRef:
description: 'dataSourceRef specifies the object from
which to populate the volume with data, if a non-empty
volume is desired. This may be any object from a non-empty
API group (non core object) or a PersistentVolumeClaim
object. When this field is specified, volume binding
will only succeed if the type of the specified object
matches some installed volume populator or dynamic provisioner.
This field will replace the functionality of the dataSource
field and as such if both fields are non-empty, they
must have the same value. For backwards compatibility,
when namespace isn''t specified in dataSourceRef, both
fields (dataSource and dataSourceRef) will be set to
the same value automatically if one of them is empty
and the other is non-empty. When namespace is specified
in dataSourceRef, dataSource isn''t set to the same
value and must be empty. There are three important differences
between dataSource and dataSourceRef: * While dataSource
only allows two specific types of objects, dataSourceRef
allows any non-core object, as well as PersistentVolumeClaim
objects. * While dataSource ignores disallowed values
(dropping them), dataSourceRef preserves all values,
and generates an error if a disallowed value is specified.
* While dataSource only allows local objects, dataSourceRef
allows objects in any namespaces. (Beta) Using this
field requires the AnyVolumeDataSource feature gate
to be enabled. (Alpha) Using the namespace field of
dataSourceRef requires the CrossNamespaceVolumeDataSource
feature gate to be enabled.'
properties:
apiGroup:
description: APIGroup is the group for the resource
being referenced. If APIGroup is not specified,
the specified Kind must be in the core API group.
For any other third-party types, APIGroup is required.
type: string
kind:
description: Kind is the type of resource being referenced
type: string
name:
description: Name is the name of resource being referenced
type: string
namespace:
description: Namespace is the namespace of resource
being referenced Note that when a namespace is specified,
a gateway.networking.k8s.io/ReferenceGrant object
is required in the referent namespace to allow that
namespace's owner to accept the reference. See the
ReferenceGrant documentation for details. (Alpha)
This field requires the CrossNamespaceVolumeDataSource
feature gate to be enabled.
type: string
required:
- kind
- name
type: object
resources:
description: 'resources represents the minimum resources
the volume should have. If RecoverVolumeExpansionFailure
feature is enabled users are allowed to specify resource
requirements that are lower than previous value but
must still be higher than capacity recorded in the status
field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources'
properties:
claims:
description: "Claims lists the names of resources,
defined in spec.resourceClaims, that are used by
this container. \n This is an alpha field and requires
enabling the DynamicResourceAllocation feature gate.
\n This field is immutable. It can only be set for
containers."
items:
description: ResourceClaim references one entry
in PodSpec.ResourceClaims.
properties:
name:
description: Name must match the name of one
entry in pod.spec.resourceClaims of the Pod
where this field is used. It makes that resource
available inside a container.
type: string
required:
- name
type: object
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
limits:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Limits describes the maximum amount
of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
requests:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Requests describes the minimum amount
of compute resources required. If Requests is omitted
for a container, it defaults to Limits if that is
explicitly specified, otherwise to an implementation-defined
value. Requests cannot exceed Limits. More info:
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
selector:
description: selector is a label query over volumes to
consider for binding.
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In,
NotIn, Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values
array must be non-empty. If the operator is
Exists or DoesNotExist, the values array must
be empty. This array is replaced during a
strategic merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field
is "key", the operator is "In", and the values array
contains only "value". The requirements are ANDed.
type: object
type: object
x-kubernetes-map-type: atomic
storageClassName:
description: 'storageClassName is the name of the StorageClass
required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1'
type: string
volumeMode:
description: volumeMode defines what type of volume is
required by the claim. Value of Filesystem is implied
when not included in claim spec.
type: string
volumeName:
description: volumeName is the binding reference to the
PersistentVolume backing this claim.
type: string
type: object
required:
- spec
type: object
type: object
ephemeralVolumesSizeLimit:
description: EphemeralVolumesSizeLimit allows the user to set the
limits for the ephemeral volumes
Expand Down
24 changes: 16 additions & 8 deletions pkg/specs/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,7 @@ func createPostgresVolumes(cluster apiv1.Cluster, podName string) []corev1.Volum
},
},
},
{
Name: "scratch-data",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{
SizeLimit: cluster.Spec.EphemeralVolumesSizeLimit.GetTemporaryDataLimit(),
},
},
},
createEphemeralVolume(cluster),
{
Name: "shm",
VolumeSource: corev1.VolumeSource{
Expand Down Expand Up @@ -325,6 +318,21 @@ func getSortedTablespaceList(cluster apiv1.Cluster) []string {
return tbsNames
}

func createEphemeralVolume(cluster apiv1.Cluster) corev1.Volume {
scratchVolumeSource := corev1.VolumeSource{}
if cluster.Spec.EphemeralVolumeSource != nil {
scratchVolumeSource.Ephemeral = cluster.Spec.EphemeralVolumeSource
} else {
scratchVolumeSource.EmptyDir = &corev1.EmptyDirVolumeSource{
SizeLimit: cluster.Spec.EphemeralVolumesSizeLimit.GetTemporaryDataLimit(),
}
}
return corev1.Volume{
Name: "scratch-data",
VolumeSource: scratchVolumeSource,
}
}

func createProjectedVolume(cluster apiv1.Cluster) corev1.Volume {
return corev1.Volume{
Name: "projected",
Expand Down

0 comments on commit 48584e9

Please sign in to comment.