diff --git a/api/v1alpha1/etcd_types.go b/api/v1alpha1/etcd_types.go index dddc029c7..6aaed6282 100644 --- a/api/v1alpha1/etcd_types.go +++ b/api/v1alpha1/etcd_types.go @@ -42,6 +42,11 @@ const ( DefaultCompression CompressionPolicy = GzipCompression // DefaultCompressionEnabled is constant to define whether to compress the snapshots or not. DefaultCompressionEnabled = false + + // Periodic is a constant to set auto-compaction-mode 'periodic' for duration based retention. + Periodic CompactionMode = "periodic" + // Revision is a constant to set auto-compaction-mode 'revision' for revision number based retention. + Revision CompactionMode = "revision" ) // MetricsLevel defines the level 'basic' or 'extensive'. @@ -59,6 +64,11 @@ type StorageProvider string // +kubebuilder:validation:Enum=gzip;lzw;zlib type CompressionPolicy string +// CompactionMode defines the auto-compaction-mode: 'periodic' or 'revision'. +// 'periodic' for duration based retention and 'revision' for revision number based retention. +// +kubebuilder:validation:Enum=periodic;revision +type CompactionMode string + // StoreSpec defines parameters related to ObjectStore persisting backups type StoreSpec struct { // +optional @@ -154,6 +164,16 @@ type EtcdConfig struct { TLS *TLSConfig `json:"tls,omitempty"` } +// SharedConfig defines parameters shared and used by Etcd as well as backup-restore sidecar. +type SharedConfig struct { + // AutoCompactionMode defines the auto-compaction-mode:'periodic' mode or 'revision' mode for etcd and embedded-Etcd of backup-restore sidecar. + // +optional + AutoCompactionMode *CompactionMode `json:"autoCompactionMode,omitempty"` + //AutoCompactionRetention defines the auto-compaction-retention length for etcd as well as for embedded-Etcd of backup-restore sidecar. + // +optional + AutoCompactionRetention *string `json:"autoCompactionRetention,omitempty"` +} + // EtcdSpec defines the desired state of Etcd type EtcdSpec struct { // selector is a label query over pods that should match the replica count. @@ -168,6 +188,8 @@ type EtcdSpec struct { Etcd EtcdConfig `json:"etcd"` // +required Backup BackupSpec `json:"backup"` + // +optional + Common SharedConfig `json:"sharedConfig,omitempty"` // +required Replicas int `json:"replicas"` // PriorityClassName is the name of a priority class that shall be used for the etcd pods. diff --git a/charts/etcd/templates/etcd-bootstrap-configmap.yaml b/charts/etcd/templates/etcd-bootstrap-configmap.yaml index 7c3de3bcf..cc692a7cb 100644 --- a/charts/etcd/templates/etcd-bootstrap-configmap.yaml +++ b/charts/etcd/templates/etcd-bootstrap-configmap.yaml @@ -125,9 +125,17 @@ data: # Initial cluster state ('new' or 'existing'). initial-cluster-state: {{ .Values.etcd.initialClusterState }} - # keep one day of history - auto-compaction-mode: periodic - auto-compaction-retention: "24" + {{- if .Values.sharedConfig }} + # auto-compaction-mode ("periodic" or "revision"). + {{- if .Values.sharedConfig.autoCompactionMode }} + auto-compaction-mode: {{ .Values.sharedConfig.autoCompactionMode }} + {{- end }} + + # auto-compaction-retention defines Auto compaction retention length for etcd. + {{- if .Values.sharedConfig.autoCompactionRetention }} + auto-compaction-retention: {{ .Values.sharedConfig.autoCompactionRetention }} + {{- end }} + {{- end }} {{- if .Values.etcd.enableTLS }} client-transport-security: diff --git a/charts/etcd/templates/etcd-statefulset.yaml b/charts/etcd/templates/etcd-statefulset.yaml index d8326dd3d..7b925e8a7 100644 --- a/charts/etcd/templates/etcd-statefulset.yaml +++ b/charts/etcd/templates/etcd-statefulset.yaml @@ -166,6 +166,14 @@ spec: {{- if .Values.backup.compression.policy }} - --compression-policy={{ .Values.backup.compression.policy }} {{- end }} +{{- end }} +{{- if .Values.sharedConfig }} + {{- if .Values.sharedConfig.autoCompactionMode }} + - --auto-compaction-mode={{ .Values.sharedConfig.autoCompactionMode }} + {{- end }} + {{- if .Values.sharedConfig.autoCompactionRetention }} + - --auto-compaction-retention={{ .Values.sharedConfig.autoCompactionRetention }} + {{- end }} {{- end }} - --snapstore-temp-directory={{ .Values.backup.snapstoreTempDir }} image: {{ .Values.backup.image }} diff --git a/charts/etcd/values.yaml b/charts/etcd/values.yaml index e0ce8183f..323261d82 100644 --- a/charts/etcd/values.yaml +++ b/charts/etcd/values.yaml @@ -49,6 +49,14 @@ backup: # enabled: true # policy: "gzip" +# sharedConfig defines parameters shared and used by Etcd as well as backup-restore sidecar. +sharedConfig: + # autoCompaction defines the specification to be used by Etcd as well as by embedded-Etcd of backup-restore sidecar during restoration. + # auto-compaction mode: 'periodic' mode or 'revision' mode for etcd as well as for embedded-Etcd of backup-restore sidecar. + # auto-compaction retention length for etcd as well as for embedded-Etcd of backup-restore sidecar. + autoCompactionMode: periodic + autoCompactionRetention: "30m" + volumeClaimTemplateName: test storageClass: "" storageCapacity: 16Gi diff --git a/config/crd/bases/druid.gardener.cloud_etcds.yaml b/config/crd/bases/druid.gardener.cloud_etcds.yaml index 9948cc065..6d293101d 100644 --- a/config/crd/bases/druid.gardener.cloud_etcds.yaml +++ b/config/crd/bases/druid.gardener.cloud_etcds.yaml @@ -310,6 +310,19 @@ spec: 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 + sharedConfig: + description: SharedConfig defines parameters shared and used by Etcd as well as backup-restore sidecar. + properties: + autoCompactionMode: + description: AutoCompactionMode defines the auto-compaction-mode:'periodic' mode or 'revision' mode for etcd and embedded-Etcd of backup-restore sidecar. + enum: + - periodic + - revision + type: string + autoCompactionRetention: + description: AutoCompactionRetention defines the auto-compaction-retention length for etcd as well as for embedded-Etcd of backup-restore sidecar. + type: string + type: object storageCapacity: anyOf: - type: integer diff --git a/config/samples/druid_v1alpha1_etcd.yaml b/config/samples/druid_v1alpha1_etcd.yaml index ebaf2a523..2d5d02904 100644 --- a/config/samples/druid_v1alpha1_etcd.yaml +++ b/config/samples/druid_v1alpha1_etcd.yaml @@ -37,7 +37,7 @@ spec: clientPort: 2379 serverPort: 2380 backup: - image: eu.gcr.io/gardener-project/gardener/etcdbrctl:v0.12.0-dev-e6df91b7463cf784f651bd6cc6ac7fc4d2e5a70b + image: eu.gcr.io/gardener-project/gardener/etcdbrctl:v0.12.0-dev-34f854c06838d14d6e7b08099d6cfa6fca2ad50d port: 8080 fullSnapshotSchedule: "0 */24 * * *" resources: @@ -57,6 +57,11 @@ spec: compression: enabled: false policy: "gzip" + + sharedConfig: + autoCompactionMode: periodic + autoCompactionRetention: "30m" + replicas: 1 # priorityClassName: foo storageClass: gardener.cloud-fast diff --git a/controllers/etcd_controller.go b/controllers/etcd_controller.go index 0f02acfb3..79153d797 100644 --- a/controllers/etcd_controller.go +++ b/controllers/etcd_controller.go @@ -81,6 +81,8 @@ const ( DefaultInterval = 5 * time.Second // EtcdReady implies that etcd is ready EtcdReady = true + // DefaultAutoCompactionRetention defines the default auto-compaction-retention length for etcd. + DefaultAutoCompactionRetention = "30m" ) var ( @@ -938,6 +940,19 @@ func (r *EtcdReconciler) getMapFromEtcd(etcd *druidv1alpha1.Etcd) (map[string]in volumeClaimTemplateName = *etcd.Spec.VolumeClaimTemplate } + sharedConfigValues := map[string]interface{}{ + "autoCompactionMode": druidv1alpha1.Periodic, + "autoCompactionRetention": DefaultAutoCompactionRetention, + } + + if etcd.Spec.Common.AutoCompactionMode != nil { + sharedConfigValues["autoCompactionMode"] = etcd.Spec.Common.AutoCompactionMode + } + + if etcd.Spec.Common.AutoCompactionRetention != nil { + sharedConfigValues["autoCompactionRetention"] = etcd.Spec.Common.AutoCompactionRetention + } + values := map[string]interface{}{ "name": etcd.Name, "uid": etcd.UID, @@ -946,6 +961,7 @@ func (r *EtcdReconciler) getMapFromEtcd(etcd *druidv1alpha1.Etcd) (map[string]in "annotations": etcd.Spec.Annotations, "etcd": etcdValues, "backup": backupValues, + "sharedConfig": sharedConfigValues, "replicas": etcd.Spec.Replicas, "statefulsetReplicas": statefulsetReplicas, "serviceName": fmt.Sprintf("%s-client", etcd.Name), diff --git a/controllers/etcd_controller_test.go b/controllers/etcd_controller_test.go index 1b2d5d0a8..d3d9f1651 100644 --- a/controllers/etcd_controller_test.go +++ b/controllers/etcd_controller_test.go @@ -82,6 +82,8 @@ var ( storageClass = "gardener.fast" priorityClassName = "class_priority" deltaSnapShotMemLimit = resource.MustParse("100Mi") + autoCompactionMode = druidv1alpha1.Periodic + autoCompactionRetention = "2m" quota = resource.MustParse("8Gi") provider = druidv1alpha1.StorageProvider("Local") prefix = "/tmp" @@ -661,8 +663,8 @@ func validateEtcdWithDefaults(s *appsv1.StatefulSet, cm *corev1.ConfigMap, svc * "advertise-client-urls": Equal(fmt.Sprintf("http://0.0.0.0:%d", clientPort)), "initial-cluster-token": Equal("initial"), "initial-cluster-state": Equal("new"), - "auto-compaction-mode": Equal("periodic"), - "auto-compaction-retention": Equal("24"), + "auto-compaction-mode": Equal(string(druidv1alpha1.Periodic)), + "auto-compaction-retention": Equal(DefaultAutoCompactionRetention), })) Expect(*svc).To(MatchFields(IgnoreExtras, Fields{ @@ -861,6 +863,8 @@ func validateEtcdWithDefaults(s *appsv1.StatefulSet, cm *corev1.ConfigMap, svc * fmt.Sprintf("--endpoints=http://%s-local:%d", instance.Name, clientPort): Equal(fmt.Sprintf("--endpoints=http://%s-local:%d", instance.Name, clientPort)), fmt.Sprintf("--embedded-etcd-quota-bytes=%d", int64(quota.Value())): Equal(fmt.Sprintf("--embedded-etcd-quota-bytes=%d", int64(quota.Value()))), fmt.Sprintf("--max-backups=%d", maxBackups): Equal(fmt.Sprintf("--max-backups=%d", maxBackups)), + fmt.Sprintf("--auto-compaction-mode=%s", druidv1alpha1.Periodic): Equal(fmt.Sprintf("--auto-compaction-mode=%s", druidv1alpha1.Periodic)), + fmt.Sprintf("--auto-compaction-retention=%s", DefaultAutoCompactionRetention): Equal(fmt.Sprintf("--auto-compaction-retention=%s", DefaultAutoCompactionRetention)), }), "Ports": ConsistOf([]corev1.ContainerPort{ corev1.ContainerPort{ @@ -1011,8 +1015,8 @@ func validateEtcd(s *appsv1.StatefulSet, cm *corev1.ConfigMap, svc *corev1.Servi "advertise-client-urls": Equal(fmt.Sprintf("https://0.0.0.0:%d", *instance.Spec.Etcd.ClientPort)), "initial-cluster-token": Equal("initial"), "initial-cluster-state": Equal("new"), - "auto-compaction-mode": Equal("periodic"), - "auto-compaction-retention": Equal("24"), + "auto-compaction-mode": Equal(string(*instance.Spec.Common.AutoCompactionMode)), + "auto-compaction-retention": Equal(*instance.Spec.Common.AutoCompactionRetention), "client-transport-security": MatchKeys(IgnoreExtras, Keys{ "cert-file": Equal("/var/etcd/ssl/server/tls.crt"), @@ -1247,6 +1251,8 @@ func validateEtcd(s *appsv1.StatefulSet, cm *corev1.ConfigMap, svc *corev1.Servi fmt.Sprintf("--embedded-etcd-quota-bytes=%d", int64(instance.Spec.Etcd.Quota.Value())): Equal(fmt.Sprintf("--embedded-etcd-quota-bytes=%d", int64(instance.Spec.Etcd.Quota.Value()))), fmt.Sprintf("%s=%s", "--delta-snapshot-period", instance.Spec.Backup.DeltaSnapshotPeriod.Duration.String()): Equal(fmt.Sprintf("%s=%s", "--delta-snapshot-period", instance.Spec.Backup.DeltaSnapshotPeriod.Duration.String())), fmt.Sprintf("%s=%s", "--garbage-collection-period", instance.Spec.Backup.GarbageCollectionPeriod.Duration.String()): Equal(fmt.Sprintf("%s=%s", "--garbage-collection-period", instance.Spec.Backup.GarbageCollectionPeriod.Duration.String())), + fmt.Sprintf("%s=%s", "--auto-compaction-mode", *instance.Spec.Common.AutoCompactionMode): Equal(fmt.Sprintf("%s=%s", "--auto-compaction-mode", autoCompactionMode)), + fmt.Sprintf("%s=%s", "--auto-compaction-retention", *instance.Spec.Common.AutoCompactionRetention): Equal(fmt.Sprintf("%s=%s", "--auto-compaction-retention", autoCompactionRetention)), }), "Ports": ConsistOf([]corev1.ContainerPort{ corev1.ContainerPort{ @@ -1989,6 +1995,7 @@ func getEtcdWithDefault(name, namespace string) *druidv1alpha1.Etcd { Replicas: 1, Backup: druidv1alpha1.BackupSpec{}, Etcd: druidv1alpha1.EtcdConfig{}, + Common: druidv1alpha1.SharedConfig{}, }, } return instance @@ -2068,6 +2075,10 @@ func getEtcd(name, namespace string, tlsEnabled bool) *druidv1alpha1.Etcd { ClientPort: &clientPort, ServerPort: &serverPort, }, + Common: druidv1alpha1.SharedConfig{ + AutoCompactionMode: &autoCompactionMode, + AutoCompactionRetention: &autoCompactionRetention, + }, }, }