Make PodDisruptionBudget master label selector optional (#2364)

* Make PDB master label selector optional

* Update pkg/apis/acid.zalan.do/v1/crds.go

---------

Co-authored-by: Felix Kunde <felix-kunde@gmx.de>
This commit is contained in:
Davide Bizzarri 2024-01-04 15:58:24 +01:00 committed by GitHub
parent 182a6d9b65
commit 3ca26d0dc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 52 additions and 5 deletions

View File

@ -323,6 +323,11 @@ configuration they are grouped under the `kubernetes` key.
replaced by the cluster name. Only the `{cluster}` placeholders is allowed in replaced by the cluster name. Only the `{cluster}` placeholders is allowed in
the template. the template.
* **pdb_master_label_selector**
By default the PDB will match the master role hence preventing nodes to be
drained if the node_readiness_label is not used. This option if set to `false`
will not add the `spilo-role=master` selector to the PDB.
* **enable_pod_disruption_budget** * **enable_pod_disruption_budget**
PDB is enabled by default to protect the cluster from voluntarily disruptions PDB is enabled by default to protect the cluster from voluntarily disruptions
and hence unwanted DB downtime. However, on some cloud providers it could be and hence unwanted DB downtime. However, on some cloud providers it could be

View File

@ -1394,6 +1394,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
"pdb_name_format": { "pdb_name_format": {
Type: "string", Type: "string",
}, },
"pdb_master_label_selector": {
Type: "boolean",
},
"persistent_volume_claim_retention_policy": { "persistent_volume_claim_retention_policy": {
Type: "object", Type: "object",
Properties: map[string]apiextv1.JSONSchemaProps{ Properties: map[string]apiextv1.JSONSchemaProps{

View File

@ -68,6 +68,7 @@ type KubernetesMetaConfiguration struct {
AdditionalPodCapabilities []string `json:"additional_pod_capabilities,omitempty"` AdditionalPodCapabilities []string `json:"additional_pod_capabilities,omitempty"`
WatchedNamespace string `json:"watched_namespace,omitempty"` WatchedNamespace string `json:"watched_namespace,omitempty"`
PDBNameFormat config.StringTemplate `json:"pdb_name_format,omitempty"` PDBNameFormat config.StringTemplate `json:"pdb_name_format,omitempty"`
PDBMasterLabelSelector *bool `json:"pdb_master_label_selector,omitempty"`
EnablePodDisruptionBudget *bool `json:"enable_pod_disruption_budget,omitempty"` EnablePodDisruptionBudget *bool `json:"enable_pod_disruption_budget,omitempty"`
StorageResizeMode string `json:"storage_resize_mode,omitempty"` StorageResizeMode string `json:"storage_resize_mode,omitempty"`
EnableInitContainers *bool `json:"enable_init_containers,omitempty"` EnableInitContainers *bool `json:"enable_init_containers,omitempty"`

View File

@ -178,6 +178,11 @@ func (in *KubernetesMetaConfiguration) DeepCopyInto(out *KubernetesMetaConfigura
*out = make([]string, len(*in)) *out = make([]string, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.PDBMasterLabelSelector != nil {
in, out := &in.PDBMasterLabelSelector, &out.PDBMasterLabelSelector
*out = new(bool)
**out = **in
}
if in.EnablePodDisruptionBudget != nil { if in.EnablePodDisruptionBudget != nil {
in, out := &in.EnablePodDisruptionBudget, &out.EnablePodDisruptionBudget in, out := &in.EnablePodDisruptionBudget, &out.EnablePodDisruptionBudget
*out = new(bool) *out = new(bool)

View File

@ -2150,12 +2150,19 @@ func (c *Cluster) generateStandbyEnvironment(description *acidv1.StandbyDescript
func (c *Cluster) generatePodDisruptionBudget() *policyv1.PodDisruptionBudget { func (c *Cluster) generatePodDisruptionBudget() *policyv1.PodDisruptionBudget {
minAvailable := intstr.FromInt(1) minAvailable := intstr.FromInt(1)
pdbEnabled := c.OpConfig.EnablePodDisruptionBudget pdbEnabled := c.OpConfig.EnablePodDisruptionBudget
pdbMasterLabelSelector := c.OpConfig.PDBMasterLabelSelector
// if PodDisruptionBudget is disabled or if there are no DB pods, set the budget to 0. // if PodDisruptionBudget is disabled or if there are no DB pods, set the budget to 0.
if (pdbEnabled != nil && !(*pdbEnabled)) || c.Spec.NumberOfInstances <= 0 { if (pdbEnabled != nil && !(*pdbEnabled)) || c.Spec.NumberOfInstances <= 0 {
minAvailable = intstr.FromInt(0) minAvailable = intstr.FromInt(0)
} }
// define label selector and add the master role selector if enabled
labels := c.labelsSet(false)
if pdbMasterLabelSelector == nil || *c.OpConfig.PDBMasterLabelSelector {
labels[c.OpConfig.PodRoleLabel] = string(Master)
}
return &policyv1.PodDisruptionBudget{ return &policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: c.podDisruptionBudgetName(), Name: c.podDisruptionBudgetName(),
@ -2166,7 +2173,7 @@ func (c *Cluster) generatePodDisruptionBudget() *policyv1.PodDisruptionBudget {
Spec: policyv1.PodDisruptionBudgetSpec{ Spec: policyv1.PodDisruptionBudgetSpec{
MinAvailable: &minAvailable, MinAvailable: &minAvailable,
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: c.roleLabelsSet(false, Master), MatchLabels: labels,
}, },
}, },
} }

View File

@ -2379,6 +2379,30 @@ func TestGeneratePodDisruptionBudget(t *testing.T) {
}, },
}, },
}, },
// With PDBMasterLabelSelector disabled.
{
New(
Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-pdb", PDBMasterLabelSelector: util.False()}},
k8sutil.KubernetesClient{},
acidv1.Postgresql{
ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"},
Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 3}},
logger,
eventRecorder),
policyv1.PodDisruptionBudget{
ObjectMeta: metav1.ObjectMeta{
Name: "postgres-myapp-database-pdb",
Namespace: "myapp",
Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"},
},
Spec: policyv1.PodDisruptionBudgetSpec{
MinAvailable: util.ToIntStr(1),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"cluster-name": "myapp-database"},
},
},
},
},
} }
for _, tt := range tests { for _, tt := range tests {

View File

@ -82,6 +82,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
result.ClusterDomain = util.Coalesce(fromCRD.Kubernetes.ClusterDomain, "cluster.local") result.ClusterDomain = util.Coalesce(fromCRD.Kubernetes.ClusterDomain, "cluster.local")
result.WatchedNamespace = fromCRD.Kubernetes.WatchedNamespace result.WatchedNamespace = fromCRD.Kubernetes.WatchedNamespace
result.PDBNameFormat = fromCRD.Kubernetes.PDBNameFormat result.PDBNameFormat = fromCRD.Kubernetes.PDBNameFormat
result.PDBMasterLabelSelector = util.CoalesceBool(fromCRD.Kubernetes.PDBMasterLabelSelector, util.True())
result.EnablePodDisruptionBudget = util.CoalesceBool(fromCRD.Kubernetes.EnablePodDisruptionBudget, util.True()) result.EnablePodDisruptionBudget = util.CoalesceBool(fromCRD.Kubernetes.EnablePodDisruptionBudget, util.True())
result.StorageResizeMode = util.Coalesce(fromCRD.Kubernetes.StorageResizeMode, "pvc") result.StorageResizeMode = util.Coalesce(fromCRD.Kubernetes.StorageResizeMode, "pvc")
result.EnableInitContainers = util.CoalesceBool(fromCRD.Kubernetes.EnableInitContainers, util.True()) result.EnableInitContainers = util.CoalesceBool(fromCRD.Kubernetes.EnableInitContainers, util.True())

View File

@ -220,6 +220,7 @@ type Config struct {
ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{namespace}.{hostedzone}"` ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{namespace}.{hostedzone}"`
ReplicaLegacyDNSNameFormat StringTemplate `name:"replica_legacy_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"` ReplicaLegacyDNSNameFormat StringTemplate `name:"replica_legacy_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"`
PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"` PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"`
PDBMasterLabelSelector *bool `name:"pdb_master_label_selector" default:"true"`
EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"` EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"`
EnableInitContainers *bool `name:"enable_init_containers" default:"true"` EnableInitContainers *bool `name:"enable_init_containers" default:"true"`
EnableSidecars *bool `name:"enable_sidecars" default:"true"` EnableSidecars *bool `name:"enable_sidecars" default:"true"`