configurable resources for logical backup pod template (#710)

* new config options to specify resources for logical backup jobs
* bug in logical backup script for s3 dumps
* define enum for logical_backup_provider
* changed order of logical backup azure options
* fix unit test for stream comparison
This commit is contained in:
Felix Kunde
2023-01-05 15:19:36 +01:00
committed by GitHub
parent bbc0de3ffd
commit 29cec0ceda
15 changed files with 305 additions and 55 deletions
+22 -2
View File
@@ -139,6 +139,23 @@ func makeDefaultResources(config *config.Config) acidv1.Resources {
}
}
func makeLogicalBackupResources(config *config.Config) acidv1.Resources {
logicalBackupResourceRequests := acidv1.ResourceDescription{
CPU: config.LogicalBackup.LogicalBackupCPURequest,
Memory: config.LogicalBackup.LogicalBackupMemoryRequest,
}
logicalBackupResourceLimits := acidv1.ResourceDescription{
CPU: config.LogicalBackup.LogicalBackupCPULimit,
Memory: config.LogicalBackup.LogicalBackupMemoryLimit,
}
return acidv1.Resources{
ResourceRequests: logicalBackupResourceRequests,
ResourceLimits: logicalBackupResourceLimits,
}
}
func (c *Cluster) enforceMinResourceLimits(resources *v1.ResourceRequirements) error {
var (
isSmaller bool
@@ -2107,9 +2124,12 @@ func (c *Cluster) generateLogicalBackupJob() (*batchv1.CronJob, error) {
c.logger.Debug("Generating logical backup pod template")
// allocate for the backup pod the same amount of resources as for normal DB pods
// allocate configured resources for logical backup pod
logicalBackupResources := makeLogicalBackupResources(&c.OpConfig)
// if not defined only default resources from spilo pods are used
resourceRequirements, err = c.generateResourceRequirements(
c.Spec.Resources, makeDefaultResources(&c.OpConfig), logicalBackupContainerName)
&logicalBackupResources, makeDefaultResources(&c.OpConfig), logicalBackupContainerName)
if err != nil {
return nil, fmt.Errorf("could not generate resource requirements for logical backup pods: %v", err)
}
+132 -2
View File
@@ -2638,7 +2638,6 @@ func TestGenerateResourceRequirements(t *testing.T) {
clusterName := "acid-test-cluster"
namespace := "default"
clusterNameLabel := "cluster-name"
roleLabel := "spilo-role"
sidecarName := "postgres-exporter"
// enforceMinResourceLimits will be called 2 twice emitting 4 events (2x cpu, 2x memory raise)
@@ -2657,7 +2656,7 @@ func TestGenerateResourceRequirements(t *testing.T) {
DefaultMemoryLimit: "500Mi",
MaxMemoryRequest: "1Gi",
MinMemoryLimit: "250Mi",
PodRoleLabel: roleLabel,
PodRoleLabel: "spilo-role",
}
tests := []struct {
@@ -3008,6 +3007,137 @@ func TestGenerateResourceRequirements(t *testing.T) {
}
}
func TestGenerateLogicalBackupJob(t *testing.T) {
clusterName := "acid-test-cluster"
configResources := config.Resources{
DefaultCPURequest: "100m",
DefaultCPULimit: "1",
DefaultMemoryRequest: "100Mi",
DefaultMemoryLimit: "500Mi",
}
tests := []struct {
subTest string
config config.Config
specSchedule string
expectedSchedule string
expectedJobName string
expectedResources acidv1.Resources
}{
{
subTest: "test generation of logical backup pod resources when not configured",
config: config.Config{
LogicalBackup: config.LogicalBackup{
LogicalBackupJobPrefix: "logical-backup-",
LogicalBackupSchedule: "30 00 * * *",
},
Resources: configResources,
PodManagementPolicy: "ordered_ready",
SetMemoryRequestToLimit: false,
},
specSchedule: "",
expectedSchedule: "30 00 * * *",
expectedJobName: "logical-backup-acid-test-cluster",
expectedResources: acidv1.Resources{
ResourceRequests: acidv1.ResourceDescription{CPU: "100m", Memory: "100Mi"},
ResourceLimits: acidv1.ResourceDescription{CPU: "1", Memory: "500Mi"},
},
},
{
subTest: "test generation of logical backup pod resources when configured",
config: config.Config{
LogicalBackup: config.LogicalBackup{
LogicalBackupCPURequest: "10m",
LogicalBackupCPULimit: "300m",
LogicalBackupMemoryRequest: "50Mi",
LogicalBackupMemoryLimit: "300Mi",
LogicalBackupJobPrefix: "lb-",
LogicalBackupSchedule: "30 00 * * *",
},
Resources: configResources,
PodManagementPolicy: "ordered_ready",
SetMemoryRequestToLimit: false,
},
specSchedule: "30 00 * * 7",
expectedSchedule: "30 00 * * 7",
expectedJobName: "lb-acid-test-cluster",
expectedResources: acidv1.Resources{
ResourceRequests: acidv1.ResourceDescription{CPU: "10m", Memory: "50Mi"},
ResourceLimits: acidv1.ResourceDescription{CPU: "300m", Memory: "300Mi"},
},
},
{
subTest: "test generation of logical backup pod resources when partly configured",
config: config.Config{
LogicalBackup: config.LogicalBackup{
LogicalBackupCPURequest: "50m",
LogicalBackupCPULimit: "250m",
LogicalBackupJobPrefix: "",
LogicalBackupSchedule: "30 00 * * *",
},
Resources: configResources,
PodManagementPolicy: "ordered_ready",
SetMemoryRequestToLimit: false,
},
specSchedule: "",
expectedSchedule: "30 00 * * *",
expectedJobName: "acid-test-cluster",
expectedResources: acidv1.Resources{
ResourceRequests: acidv1.ResourceDescription{CPU: "50m", Memory: "100Mi"},
ResourceLimits: acidv1.ResourceDescription{CPU: "250m", Memory: "500Mi"},
},
},
{
subTest: "test generation of logical backup pod resources with SetMemoryRequestToLimit enabled",
config: config.Config{
LogicalBackup: config.LogicalBackup{
LogicalBackupMemoryRequest: "80Mi",
LogicalBackupMemoryLimit: "200Mi",
LogicalBackupJobPrefix: "test-long-prefix-so-name-must-be-trimmed-",
LogicalBackupSchedule: "30 00 * * *",
},
Resources: configResources,
PodManagementPolicy: "ordered_ready",
SetMemoryRequestToLimit: true,
},
specSchedule: "",
expectedSchedule: "30 00 * * *",
expectedJobName: "test-long-prefix-so-name-must-be-trimmed-acid-test-c",
expectedResources: acidv1.Resources{
ResourceRequests: acidv1.ResourceDescription{CPU: "100m", Memory: "200Mi"},
ResourceLimits: acidv1.ResourceDescription{CPU: "1", Memory: "200Mi"},
},
},
}
for _, tt := range tests {
var cluster = New(
Config{
OpConfig: tt.config,
}, k8sutil.NewMockKubernetesClient(), acidv1.Postgresql{}, logger, eventRecorder)
cluster.ObjectMeta.Name = clusterName
cluster.Spec.LogicalBackupSchedule = tt.specSchedule
cronJob, err := cluster.generateLogicalBackupJob()
assert.NoError(t, err)
if cronJob.Spec.Schedule != tt.expectedSchedule {
t.Errorf("%s - %s: expected schedule %s, got %s", t.Name(), tt.subTest, tt.expectedSchedule, cronJob.Spec.Schedule)
}
if cronJob.Name != tt.expectedJobName {
t.Errorf("%s - %s: expected job name %s, got %s", t.Name(), tt.subTest, tt.expectedJobName, cronJob.Name)
}
containers := cronJob.Spec.JobTemplate.Spec.Template.Spec.Containers
clusterResources, err := parseResourceRequirements(containers[0].Resources)
assert.NoError(t, err)
if !reflect.DeepEqual(tt.expectedResources, clusterResources) {
t.Errorf("%s - %s: expected resources %#v, got %#v", t.Name(), tt.subTest, tt.expectedResources, clusterResources)
}
}
}
func TestGenerateCapabilities(t *testing.T) {
tests := []struct {
subTest string
+1 -2
View File
@@ -2,7 +2,6 @@ package cluster
import (
"fmt"
"reflect"
"strings"
"context"
@@ -389,7 +388,7 @@ func TestUpdateFabricEventStream(t *testing.T) {
assert.NoError(t, err)
result := cluster.generateFabricEventStream(appId)
if !reflect.DeepEqual(result.Spec.EventStreams, streams.Items[0].Spec.EventStreams) {
if match, _ := sameStreams(streams.Items[0].Spec.EventStreams, result.Spec.EventStreams); !match {
t.Errorf("Malformed FabricEventStream, expected %#v, got %#v", streams.Items[0], result)
}
}