diff --git a/charts/postgres-operator/crds/operatorconfigurations.yaml b/charts/postgres-operator/crds/operatorconfigurations.yaml index bf4ae34b1..5976c80ff 100644 --- a/charts/postgres-operator/crds/operatorconfigurations.yaml +++ b/charts/postgres-operator/crds/operatorconfigurations.yaml @@ -692,6 +692,9 @@ spec: enable_patroni_failsafe_mode: type: boolean default: false + allow_ephemeral_volumes: + type: boolean + default: false status: type: object additionalProperties: diff --git a/charts/postgres-operator/crds/postgresqls.yaml b/charts/postgres-operator/crds/postgresqls.yaml index 0498625f2..d950946e0 100644 --- a/charts/postgres-operator/crds/postgresqls.yaml +++ b/charts/postgres-operator/crds/postgresqls.yaml @@ -577,6 +577,9 @@ spec: - PreferNoSchedule tolerationSeconds: type: integer + useEphemeralVolume: + type: boolean + default: false useLoadBalancer: type: boolean description: deprecated diff --git a/charts/postgres-operator/templates/operatorconfiguration.yaml b/charts/postgres-operator/templates/operatorconfiguration.yaml index b72bfb899..d09a682c2 100644 --- a/charts/postgres-operator/templates/operatorconfiguration.yaml +++ b/charts/postgres-operator/templates/operatorconfiguration.yaml @@ -42,4 +42,5 @@ configuration: {{ tpl (toYaml .Values.configConnectionPooler) . | indent 4 }} patroni: {{ tpl (toYaml .Values.configPatroni) . | indent 4 }} + allow_ephemeral_volumes: {{ .Values.allowEphemeralVolumes }} {{- end }} diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml index 5700ff783..9326f1639 100644 --- a/charts/postgres-operator/values.yaml +++ b/charts/postgres-operator/values.yaml @@ -454,6 +454,9 @@ configPatroni: # Zalando's internal CDC stream feature enableStreams: false +# Allow ephemeral instances +allowEphemeralVolumes: false + rbac: # Specifies whether RBAC resources should be created create: true diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml index 7f76d0b33..2122afa14 100644 --- a/manifests/configmap.yaml +++ b/manifests/configmap.yaml @@ -7,6 +7,7 @@ data: # additional_pod_capabilities: "SYS_NICE" # additional_secret_mount: "some-secret-name" # additional_secret_mount_path: "/some/dir" + # allow_ephemeral_volumes: true api_port: "8080" aws_region: eu-central-1 cluster_domain: cluster.local diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index 887577940..804ecabba 100644 --- a/manifests/operatorconfiguration.crd.yaml +++ b/manifests/operatorconfiguration.crd.yaml @@ -690,6 +690,9 @@ spec: enable_patroni_failsafe_mode: type: boolean default: false + allow_ephemeral_volumes: + type: boolean + default: false status: type: object additionalProperties: diff --git a/manifests/postgresql-operator-default-configuration.yaml b/manifests/postgresql-operator-default-configuration.yaml index ee3123e32..2a401f1cf 100644 --- a/manifests/postgresql-operator-default-configuration.yaml +++ b/manifests/postgresql-operator-default-configuration.yaml @@ -220,3 +220,4 @@ configuration: # connection_pooler_user: "pooler" patroni: enable_patroni_failsafe_mode: false + allow_ephemeral_volumes: false \ No newline at end of file diff --git a/manifests/postgresql.crd.yaml b/manifests/postgresql.crd.yaml index 4bd757f38..f487ed312 100644 --- a/manifests/postgresql.crd.yaml +++ b/manifests/postgresql.crd.yaml @@ -575,6 +575,9 @@ spec: - PreferNoSchedule tolerationSeconds: type: integer + useEphemeralVolume: + type: boolean + default: false useLoadBalancer: type: boolean description: deprecated diff --git a/pkg/apis/acid.zalan.do/v1/crds.go b/pkg/apis/acid.zalan.do/v1/crds.go index 9e65869e7..286a9c46b 100644 --- a/pkg/apis/acid.zalan.do/v1/crds.go +++ b/pkg/apis/acid.zalan.do/v1/crds.go @@ -898,6 +898,9 @@ var PostgresCRDResourceValidation = apiextv1.CustomResourceValidation{ }, }, }, + "useEphemeralVolume": { + Type: "boolean", + }, "useLoadBalancer": { Type: "boolean", Description: "deprecated", @@ -1966,6 +1969,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{ }, }, }, + "allow_ephemeral_volums": { + Type: "boolean", + }, }, }, "status": { diff --git a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go index 48fd0a13c..9a42102c9 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -287,6 +287,8 @@ type OperatorConfigurationData struct { MinInstances int32 `json:"min_instances,omitempty"` MaxInstances int32 `json:"max_instances,omitempty"` IgnoreInstanceLimitsAnnotationKey string `json:"ignore_instance_limits_annotation_key,omitempty"` + + AllowEphemeralVolumes *bool `json:"allow_ephemeral_volumes,omitempty"` } // Duration shortens this frequently used name diff --git a/pkg/apis/acid.zalan.do/v1/postgresql_type.go b/pkg/apis/acid.zalan.do/v1/postgresql_type.go index 612cf7041..fe69788c8 100644 --- a/pkg/apis/acid.zalan.do/v1/postgresql_type.go +++ b/pkg/apis/acid.zalan.do/v1/postgresql_type.go @@ -93,6 +93,9 @@ type PostgresSpec struct { // deprecated json tags InitContainersOld []v1.Container `json:"init_containers,omitempty"` PodPriorityClassNameOld string `json:"pod_priority_class_name,omitempty"` + + // Ephemeral settings + UseEphemeralVolume *bool `json:"useEphemeralVolume,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go index 80bc7b34d..a88875cf7 100644 --- a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go +++ b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go @@ -461,6 +461,11 @@ func (in *OperatorConfigurationData) DeepCopyInto(out *OperatorConfigurationData out.LogicalBackup = in.LogicalBackup in.ConnectionPooler.DeepCopyInto(&out.ConnectionPooler) in.Patroni.DeepCopyInto(&out.Patroni) + if in.AllowEphemeralVolumes != nil { + in, out := &in.AllowEphemeralVolumes, &out.AllowEphemeralVolumes + *out = new(bool) + **out = **in + } return } @@ -876,6 +881,11 @@ func (in *PostgresSpec) DeepCopyInto(out *PostgresSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.UseEphemeralVolume != nil { + in, out := &in.UseEphemeralVolume, &out.UseEphemeralVolume + *out = new(bool) + **out = **in + } return } diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index eb4402f03..60bf18812 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -1289,10 +1289,12 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef initContainers []v1.Container sidecarContainers []v1.Container podTemplate *v1.PodTemplateSpec - volumeClaimTemplate *v1.PersistentVolumeClaim + volumeClaimTemplate *[]v1.PersistentVolumeClaim additionalVolumes = spec.AdditionalVolumes ) + useEphemeralVolume := c.OpConfig.AllowEphemeralVolumes != nil && spec.UseEphemeralVolume != nil && (*c.OpConfig.AllowEphemeralVolumes && *spec.UseEphemeralVolume) + defaultResources := makeDefaultResources(&c.OpConfig) resourceRequirements, err := c.generateResourceRequirements( spec.Resources, defaultResources, constants.PostgresContainerName) @@ -1493,9 +1495,23 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef return nil, fmt.Errorf("could not generate pod template: %v", err) } - if volumeClaimTemplate, err = c.generatePersistentVolumeClaimTemplate(spec.Volume.Size, - spec.Volume.StorageClass, spec.Volume.Selector); err != nil { - return nil, fmt.Errorf("could not generate volume claim template: %v", err) + // Generate the volumes, optionally using an ephemeral volume + if useEphemeralVolume { + empty := make([]v1.PersistentVolumeClaim, 0) + volumeClaimTemplate = &empty + + // Also add the ephemeral volume to the spec + podTemplate.Spec.Volumes = append(podTemplate.Spec.Volumes, v1.Volume{ + Name: constants.DataVolumeName, + VolumeSource: v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }) + } else { + if volumeClaimTemplate, err = c.generatePersistentVolumeClaimTemplate(spec.Volume.Size, + spec.Volume.StorageClass, spec.Volume.Selector); err != nil { + return nil, fmt.Errorf("could not generate volume claim template: %v", err) + } } // global minInstances and maxInstances settings can overwrite manifest @@ -1540,7 +1556,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef Selector: c.labelsSelector(), ServiceName: c.serviceName(Master), Template: *podTemplate, - VolumeClaimTemplates: []v1.PersistentVolumeClaim{*volumeClaimTemplate}, + VolumeClaimTemplates: *volumeClaimTemplate, UpdateStrategy: updateStrategy, PodManagementPolicy: podManagementPolicy, PersistentVolumeClaimRetentionPolicy: &persistentVolumeClaimRetentionPolicy, @@ -1848,7 +1864,7 @@ func (c *Cluster) addAdditionalVolumes(podSpec *v1.PodSpec, } func (c *Cluster) generatePersistentVolumeClaimTemplate(volumeSize, volumeStorageClass string, - volumeSelector *metav1.LabelSelector) (*v1.PersistentVolumeClaim, error) { + volumeSelector *metav1.LabelSelector) (*[]v1.PersistentVolumeClaim, error) { var storageClassName *string if volumeStorageClass != "" { @@ -1861,7 +1877,7 @@ func (c *Cluster) generatePersistentVolumeClaimTemplate(volumeSize, volumeStorag } volumeMode := v1.PersistentVolumeFilesystem - volumeClaim := &v1.PersistentVolumeClaim{ + volumeClaim := v1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ Name: constants.DataVolumeName, Annotations: c.annotationsSet(nil), @@ -1880,7 +1896,7 @@ func (c *Cluster) generatePersistentVolumeClaimTemplate(volumeSize, volumeStorag }, } - return volumeClaim, nil + return &[]v1.PersistentVolumeClaim{volumeClaim}, nil } func (c *Cluster) generateUserSecrets() map[string]*v1.Secret { diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index 88f1d73c0..fb6cd01fd 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -277,5 +277,8 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur fromCRD.ConnectionPooler.MaxDBConnections, k8sutil.Int32ToPointer(constants.ConnectionPoolerMaxDBConnections)) + // Ephemeral config + result.AllowEphemeralVolumes = util.CoalesceBool(fromCRD.AllowEphemeralVolumes, util.False()) + return result } diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index 829c1d19e..a38a25cd8 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -253,6 +253,7 @@ type Config struct { EnableSecretsDeletion *bool `name:"enable_secrets_deletion" default:"true"` EnablePersistentVolumeClaimDeletion *bool `name:"enable_persistent_volume_claim_deletion" default:"true"` PersistentVolumeClaimRetentionPolicy map[string]string `name:"persistent_volume_claim_retention_policy" default:"when_deleted:retain,when_scaled:retain"` + AllowEphemeralVolumes *bool `json:"allow_ephemeral_volumes,omitempty"` } // MustMarshal marshals the config or panics