mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-09-30 17:01:16 +02:00
add preferred during scheduling pod anti affinity (#2048)
* add preferred during scheduling pod anti affinity Co-authored-by: Felix Kunde <felix-kunde@gmx.de>
This commit is contained in:
co-authored by
Felix Kunde
parent
93a253bde1
commit
be7b52db92
@@ -354,7 +354,12 @@ func (c *Cluster) generateConnectionPoolerPodTemplate(role PostgresRole) (
|
||||
nodeAffinity := c.nodeAffinity(c.OpConfig.NodeReadinessLabel, spec.NodeAffinity)
|
||||
if c.OpConfig.EnablePodAntiAffinity {
|
||||
labelsSet := labels.Set(c.connectionPoolerLabels(role, false).MatchLabels)
|
||||
podTemplate.Spec.Affinity = generatePodAffinity(labelsSet, c.OpConfig.PodAntiAffinityTopologyKey, nodeAffinity)
|
||||
podTemplate.Spec.Affinity = generatePodAffinity(
|
||||
labelsSet,
|
||||
c.OpConfig.PodAntiAffinityTopologyKey,
|
||||
nodeAffinity,
|
||||
c.OpConfig.PodAntiAffinityPreferredDuringScheduling,
|
||||
)
|
||||
} else if nodeAffinity != nil {
|
||||
podTemplate.Spec.Affinity = nodeAffinity
|
||||
}
|
||||
|
||||
+28
-10
@@ -495,17 +495,27 @@ func (c *Cluster) nodeAffinity(nodeReadinessLabel map[string]string, nodeAffinit
|
||||
}
|
||||
}
|
||||
|
||||
func generatePodAffinity(labels labels.Set, topologyKey string, nodeAffinity *v1.Affinity) *v1.Affinity {
|
||||
func generatePodAffinity(labels labels.Set, topologyKey string, nodeAffinity *v1.Affinity, preferredDuringScheduling bool) *v1.Affinity {
|
||||
// generate pod anti-affinity to avoid multiple pods of the same Postgres cluster in the same topology , e.g. node
|
||||
podAffinity := v1.Affinity{
|
||||
PodAntiAffinity: &v1.PodAntiAffinity{
|
||||
RequiredDuringSchedulingIgnoredDuringExecution: []v1.PodAffinityTerm{{
|
||||
LabelSelector: &metav1.LabelSelector{
|
||||
MatchLabels: labels,
|
||||
},
|
||||
TopologyKey: topologyKey,
|
||||
}},
|
||||
|
||||
podAffinityTerm := v1.PodAffinityTerm{
|
||||
LabelSelector: &metav1.LabelSelector{
|
||||
MatchLabels: labels,
|
||||
},
|
||||
TopologyKey: topologyKey,
|
||||
}
|
||||
|
||||
podAffinity := v1.Affinity{
|
||||
PodAntiAffinity: &v1.PodAntiAffinity{},
|
||||
}
|
||||
|
||||
if preferredDuringScheduling {
|
||||
podAffinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution = []v1.WeightedPodAffinityTerm{{
|
||||
Weight: 1,
|
||||
PodAffinityTerm: podAffinityTerm,
|
||||
}}
|
||||
} else {
|
||||
podAffinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution = []v1.PodAffinityTerm{podAffinityTerm}
|
||||
}
|
||||
|
||||
if nodeAffinity != nil && nodeAffinity.NodeAffinity != nil {
|
||||
@@ -727,6 +737,7 @@ func (c *Cluster) generatePodTemplate(
|
||||
shmVolume *bool,
|
||||
podAntiAffinity bool,
|
||||
podAntiAffinityTopologyKey string,
|
||||
podAntiAffinityPreferredDuringScheduling bool,
|
||||
additionalSecretMount string,
|
||||
additionalSecretMountPath string,
|
||||
additionalVolumes []acidv1.AdditionalVolume,
|
||||
@@ -767,7 +778,12 @@ func (c *Cluster) generatePodTemplate(
|
||||
}
|
||||
|
||||
if podAntiAffinity {
|
||||
podSpec.Affinity = generatePodAffinity(labels, podAntiAffinityTopologyKey, nodeAffinity)
|
||||
podSpec.Affinity = generatePodAffinity(
|
||||
labels,
|
||||
podAntiAffinityTopologyKey,
|
||||
nodeAffinity,
|
||||
podAntiAffinityPreferredDuringScheduling,
|
||||
)
|
||||
} else if nodeAffinity != nil {
|
||||
podSpec.Affinity = nodeAffinity
|
||||
}
|
||||
@@ -1376,6 +1392,7 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef
|
||||
mountShmVolumeNeeded(c.OpConfig, spec),
|
||||
c.OpConfig.EnablePodAntiAffinity,
|
||||
c.OpConfig.PodAntiAffinityTopologyKey,
|
||||
c.OpConfig.PodAntiAffinityPreferredDuringScheduling,
|
||||
c.OpConfig.AdditionalSecretMount,
|
||||
c.OpConfig.AdditionalSecretMountPath,
|
||||
additionalVolumes)
|
||||
@@ -2122,6 +2139,7 @@ func (c *Cluster) generateLogicalBackupJob() (*batchv1.CronJob, error) {
|
||||
util.False(),
|
||||
false,
|
||||
"",
|
||||
false,
|
||||
c.OpConfig.AdditionalSecretMount,
|
||||
c.OpConfig.AdditionalSecretMountPath,
|
||||
[]acidv1.AdditionalVolume{}); err != nil {
|
||||
|
||||
@@ -1360,6 +1360,95 @@ func TestNodeAffinity(t *testing.T) {
|
||||
assert.Equal(t, s.Spec.Template.Spec.Affinity.NodeAffinity, nodeAff, "cluster template has correct node affinity")
|
||||
}
|
||||
|
||||
func TestPodAntiAffinityrRequiredDuringScheduling(t *testing.T) {
|
||||
var err error
|
||||
var spiloRunAsUser = int64(101)
|
||||
var spiloRunAsGroup = int64(103)
|
||||
var spiloFSGroup = int64(103)
|
||||
|
||||
spec := acidv1.PostgresSpec{
|
||||
TeamID: "myapp", NumberOfInstances: 1,
|
||||
Resources: &acidv1.Resources{
|
||||
ResourceRequests: acidv1.ResourceDescription{CPU: "1", Memory: "10"},
|
||||
ResourceLimits: acidv1.ResourceDescription{CPU: "1", Memory: "10"},
|
||||
},
|
||||
Volume: acidv1.Volume{
|
||||
Size: "1G",
|
||||
},
|
||||
}
|
||||
|
||||
cluster := New(
|
||||
Config{
|
||||
OpConfig: config.Config{
|
||||
PodManagementPolicy: "ordered_ready",
|
||||
ProtectedRoles: []string{"admin"},
|
||||
Auth: config.Auth{
|
||||
SuperUsername: superUserName,
|
||||
ReplicationUsername: replicationUserName,
|
||||
},
|
||||
Resources: config.Resources{
|
||||
SpiloRunAsUser: &spiloRunAsUser,
|
||||
SpiloRunAsGroup: &spiloRunAsGroup,
|
||||
SpiloFSGroup: &spiloFSGroup,
|
||||
},
|
||||
EnablePodAntiAffinity: true,
|
||||
},
|
||||
}, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder)
|
||||
|
||||
s, err := cluster.generateStatefulSet(&spec)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.Nil(t, s.Spec.Template.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution, "pod anti-affinity should not use preferredDuringScheduling")
|
||||
assert.NotNil(t, s.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution, "pod anti-affinity should use requiredDuringScheduling")
|
||||
}
|
||||
|
||||
func TestPodAntiAffinityPreferredDuringScheduling(t *testing.T) {
|
||||
var err error
|
||||
var spiloRunAsUser = int64(101)
|
||||
var spiloRunAsGroup = int64(103)
|
||||
var spiloFSGroup = int64(103)
|
||||
|
||||
spec := acidv1.PostgresSpec{
|
||||
TeamID: "myapp", NumberOfInstances: 1,
|
||||
Resources: &acidv1.Resources{
|
||||
ResourceRequests: acidv1.ResourceDescription{CPU: "1", Memory: "10"},
|
||||
ResourceLimits: acidv1.ResourceDescription{CPU: "1", Memory: "10"},
|
||||
},
|
||||
Volume: acidv1.Volume{
|
||||
Size: "1G",
|
||||
},
|
||||
}
|
||||
|
||||
cluster := New(
|
||||
Config{
|
||||
OpConfig: config.Config{
|
||||
PodManagementPolicy: "ordered_ready",
|
||||
ProtectedRoles: []string{"admin"},
|
||||
Auth: config.Auth{
|
||||
SuperUsername: superUserName,
|
||||
ReplicationUsername: replicationUserName,
|
||||
},
|
||||
Resources: config.Resources{
|
||||
SpiloRunAsUser: &spiloRunAsUser,
|
||||
SpiloRunAsGroup: &spiloRunAsGroup,
|
||||
SpiloFSGroup: &spiloFSGroup,
|
||||
},
|
||||
EnablePodAntiAffinity: true,
|
||||
PodAntiAffinityPreferredDuringScheduling: true,
|
||||
},
|
||||
}, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder)
|
||||
|
||||
s, err := cluster.generateStatefulSet(&spec)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
assert.NotNil(t, s.Spec.Template.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution, "pod anti-affinity should use preferredDuringScheduling")
|
||||
assert.Nil(t, s.Spec.Template.Spec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution, "pod anti-affinity should not use requiredDuringScheduling")
|
||||
}
|
||||
|
||||
func testDeploymentOwnerReference(cluster *Cluster, deployment *appsv1.Deployment) error {
|
||||
owner := deployment.ObjectMeta.OwnerReferences[0]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user