diff --git a/charts/postgres-operator/crds/operatorconfigurations.yaml b/charts/postgres-operator/crds/operatorconfigurations.yaml index 472f15720..d0c2dca66 100644 --- a/charts/postgres-operator/crds/operatorconfigurations.yaml +++ b/charts/postgres-operator/crds/operatorconfigurations.yaml @@ -281,6 +281,9 @@ spec: pod_antiaffinity_topology_key: type: string default: "kubernetes.io/hostname" + pod_antiaffinity_preferred_during_scheduling: + type: boolean + default: false pod_environment_configmap: type: string pod_environment_secret: diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml index 37dc9c2e4..50977bd8a 100644 --- a/charts/postgres-operator/values.yaml +++ b/charts/postgres-operator/values.yaml @@ -167,6 +167,8 @@ configKubernetes: pdb_name_format: "postgres-{cluster}-pdb" # override topology key for pod anti affinity pod_antiaffinity_topology_key: "kubernetes.io/hostname" + # switches pod anti affinity type to `preferredDuringSchedulingIgnoredDuringExecution` + # pod_antiaffinity_preferred_during_scheduling: true # namespaced name of the ConfigMap with environment variables to populate on every pod # pod_environment_configmap: "default/my-custom-config" # name of the Secret (in cluster namespace) with environment variables to populate on every pod diff --git a/docs/administrator.md b/docs/administrator.md index 1a0f730b8..cd56289b4 100644 --- a/docs/administrator.md +++ b/docs/administrator.md @@ -15,7 +15,7 @@ CRDs set `enable_crd_registration` config option to `false`. CRDs are defined with a `openAPIV3Schema` structural schema against which new manifests of [`postgresql`](https://github.com/zalando/postgres-operator/blob/master/manifests/postgresql.crd.yaml) or [`OperatorConfiguration`](https://github.com/zalando/postgres-operator/blob/master/manifests/operatorconfiguration.crd.yaml) -resources will be validated. On creation you can bypass the validation with +resources will be validated. On creation you can bypass the validation with `kubectl create --validate=false`. By default, the operator will register the CRDs in the `all` category so @@ -516,6 +516,9 @@ configuration: enable_pod_antiaffinity: true ``` +By default the type of pod anti affinity is `requiredDuringSchedulingIgnoredDuringExecution`, +you can switch to `preferredDuringSchedulingIgnoredDuringExecution` by setting `pod_antiaffinity_preferred_during_scheduling: true`. + By default the topology key for the pod anti affinity is set to `kubernetes.io/hostname`, you can set another topology key e.g. `failure-domain.beta.kubernetes.io/zone`. See [built-in node labels](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#interlude-built-in-node-labels) for available topology keys. @@ -1091,7 +1094,7 @@ data: USE_WALG_BACKUP: "true" USE_WALG_RESTORE: "true" CLONE_USE_WALG_RESTORE: "true" - WALG_AZ_PREFIX: "azure://container-name/$(SCOPE)/$(PGVERSION)" # Enables Azure Backups (SCOPE = Cluster name) (PGVERSION = Postgres version) + WALG_AZ_PREFIX: "azure://container-name/$(SCOPE)/$(PGVERSION)" # Enables Azure Backups (SCOPE = Cluster name) (PGVERSION = Postgres version) ``` 3. Setup your operator configuration values. With the `psql-backup-creds` diff --git a/pkg/apis/acid.zalan.do/v1/crds.go b/pkg/apis/acid.zalan.do/v1/crds.go index 645a30883..84028bb20 100644 --- a/pkg/apis/acid.zalan.do/v1/crds.go +++ b/pkg/apis/acid.zalan.do/v1/crds.go @@ -1378,6 +1378,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{ "pod_antiaffinity_topology_key": { Type: "string", }, + "pod_antiaffinity_preferred_during_scheduling": { + Type: "boolean", + }, "pod_environment_configmap": { Type: "string", }, 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 4f6ef96af..b3251b217 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -91,16 +91,17 @@ type KubernetesMetaConfiguration struct { NodeReadinessLabelMerge string `json:"node_readiness_label_merge,omitempty"` CustomPodAnnotations map[string]string `json:"custom_pod_annotations,omitempty"` // TODO: use a proper toleration structure? - PodToleration map[string]string `json:"toleration,omitempty"` - PodEnvironmentConfigMap spec.NamespacedName `json:"pod_environment_configmap,omitempty"` - PodEnvironmentSecret string `json:"pod_environment_secret,omitempty"` - PodPriorityClassName string `json:"pod_priority_class_name,omitempty"` - MasterPodMoveTimeout Duration `json:"master_pod_move_timeout,omitempty"` - EnablePodAntiAffinity bool `json:"enable_pod_antiaffinity,omitempty"` - PodAntiAffinityTopologyKey string `json:"pod_antiaffinity_topology_key,omitempty"` - PodManagementPolicy string `json:"pod_management_policy,omitempty"` - EnableReadinessProbe bool `json:"enable_readiness_probe,omitempty"` - EnableCrossNamespaceSecret bool `json:"enable_cross_namespace_secret,omitempty"` + PodToleration map[string]string `json:"toleration,omitempty"` + PodEnvironmentConfigMap spec.NamespacedName `json:"pod_environment_configmap,omitempty"` + PodEnvironmentSecret string `json:"pod_environment_secret,omitempty"` + PodPriorityClassName string `json:"pod_priority_class_name,omitempty"` + MasterPodMoveTimeout Duration `json:"master_pod_move_timeout,omitempty"` + EnablePodAntiAffinity bool `json:"enable_pod_antiaffinity,omitempty"` + PodAntiAffinityTopologyKey string `json:"pod_antiaffinity_topology_key,omitempty"` + PodAntiAffinityPreferredDuringScheduling bool `json:"pod_antiaffinity_preferred_during_scheduling,omitempty"` + PodManagementPolicy string `json:"pod_management_policy,omitempty"` + EnableReadinessProbe bool `json:"enable_readiness_probe,omitempty"` + EnableCrossNamespaceSecret bool `json:"enable_cross_namespace_secret,omitempty"` } // PostgresPodResourcesDefaults defines the spec of default resources diff --git a/pkg/cluster/connection_pooler.go b/pkg/cluster/connection_pooler.go index c83c41233..fd8b9251c 100644 --- a/pkg/cluster/connection_pooler.go +++ b/pkg/cluster/connection_pooler.go @@ -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 } diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index 8836e2e5f..6b7688816 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -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 { diff --git a/pkg/cluster/k8sres_test.go b/pkg/cluster/k8sres_test.go index 223fdb787..cd8bf14e7 100644 --- a/pkg/cluster/k8sres_test.go +++ b/pkg/cluster/k8sres_test.go @@ -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] diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index 379a92be5..4e347b079 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -123,6 +123,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.MasterPodMoveTimeout = util.CoalesceDuration(time.Duration(fromCRD.Kubernetes.MasterPodMoveTimeout), "10m") result.EnablePodAntiAffinity = fromCRD.Kubernetes.EnablePodAntiAffinity result.PodAntiAffinityTopologyKey = util.Coalesce(fromCRD.Kubernetes.PodAntiAffinityTopologyKey, "kubernetes.io/hostname") + result.PodAntiAffinityPreferredDuringScheduling = fromCRD.Kubernetes.PodAntiAffinityPreferredDuringScheduling result.PodToleration = fromCRD.Kubernetes.PodToleration // Postgres Pod resources diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index fcf1f607b..75c7043cb 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -170,72 +170,73 @@ type Config struct { SidecarContainers []v1.Container `name:"sidecars"` PodServiceAccountName string `name:"pod_service_account_name" default:"postgres-pod"` // value of this string must be valid JSON or YAML; see initPodServiceAccount - PodServiceAccountDefinition string `name:"pod_service_account_definition" default:""` - PodServiceAccountRoleBindingDefinition string `name:"pod_service_account_role_binding_definition" default:""` - MasterPodMoveTimeout time.Duration `name:"master_pod_move_timeout" default:"20m"` - DbHostedZone string `name:"db_hosted_zone" default:"db.example.com"` - AWSRegion string `name:"aws_region" default:"eu-central-1"` - WALES3Bucket string `name:"wal_s3_bucket"` - LogS3Bucket string `name:"log_s3_bucket"` - KubeIAMRole string `name:"kube_iam_role"` - WALGSBucket string `name:"wal_gs_bucket"` - GCPCredentials string `name:"gcp_credentials"` - WALAZStorageAccount string `name:"wal_az_storage_account"` - AdditionalSecretMount string `name:"additional_secret_mount"` - AdditionalSecretMountPath string `name:"additional_secret_mount_path" default:"/meta/credentials"` - EnableEBSGp3Migration bool `name:"enable_ebs_gp3_migration" default:"false"` - EnableEBSGp3MigrationMaxSize int64 `name:"enable_ebs_gp3_migration_max_size" default:"1000"` - DebugLogging bool `name:"debug_logging" default:"true"` - EnableDBAccess bool `name:"enable_database_access" default:"true"` - EnableTeamsAPI bool `name:"enable_teams_api" default:"true"` - EnableTeamSuperuser bool `name:"enable_team_superuser" default:"false"` - TeamAdminRole string `name:"team_admin_role" default:"admin"` - RoleDeletionSuffix string `name:"role_deletion_suffix" default:"_deleted"` - EnableTeamMemberDeprecation bool `name:"enable_team_member_deprecation" default:"false"` - EnableAdminRoleForUsers bool `name:"enable_admin_role_for_users" default:"true"` - EnablePostgresTeamCRD bool `name:"enable_postgres_team_crd" default:"false"` - EnablePostgresTeamCRDSuperusers bool `name:"enable_postgres_team_crd_superusers" default:"false"` - EnableMasterLoadBalancer bool `name:"enable_master_load_balancer" default:"true"` - EnableMasterPoolerLoadBalancer bool `name:"enable_master_pooler_load_balancer" default:"false"` - EnableReplicaLoadBalancer bool `name:"enable_replica_load_balancer" default:"false"` - EnableReplicaPoolerLoadBalancer bool `name:"enable_replica_pooler_load_balancer" default:"false"` - CustomServiceAnnotations map[string]string `name:"custom_service_annotations"` - CustomPodAnnotations map[string]string `name:"custom_pod_annotations"` - EnablePodAntiAffinity bool `name:"enable_pod_antiaffinity" default:"false"` - PodAntiAffinityTopologyKey string `name:"pod_antiaffinity_topology_key" default:"kubernetes.io/hostname"` - StorageResizeMode string `name:"storage_resize_mode" default:"pvc"` - EnableLoadBalancer *bool `name:"enable_load_balancer"` // deprecated and kept for backward compatibility - ExternalTrafficPolicy string `name:"external_traffic_policy" default:"Cluster"` - MasterDNSNameFormat StringTemplate `name:"master_dns_name_format" default:"{cluster}.{namespace}.{hostedzone}"` - ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{namespace}.{hostedzone}"` - PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"` - EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"` - EnableInitContainers *bool `name:"enable_init_containers" default:"true"` - EnableSidecars *bool `name:"enable_sidecars" default:"true"` - SharePGSocketWithSidecars *bool `name:"share_pg_socket_with_sidecars" default:"false"` - Workers uint32 `name:"workers" default:"8"` - APIPort int `name:"api_port" default:"8080"` - RingLogLines int `name:"ring_log_lines" default:"100"` - ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"` - TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"` - PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"` - PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"` - EnableReadinessProbe bool `name:"enable_readiness_probe" default:"false"` - ProtectedRoles []string `name:"protected_role_names" default:"admin,cron_admin"` - PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""` - SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"` - EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"` - EnableCrossNamespaceSecret bool `name:"enable_cross_namespace_secret" default:"false"` - EnablePgVersionEnvVar bool `name:"enable_pgversion_env_var" default:"true"` - EnableSpiloWalPathCompat bool `name:"enable_spilo_wal_path_compat" default:"false"` - EnableTeamIdClusternamePrefix bool `name:"enable_team_id_clustername_prefix" default:"false"` - MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"off"` - MajorVersionUpgradeTeamAllowList []string `name:"major_version_upgrade_team_allow_list" default:""` - MinimalMajorVersion string `name:"minimal_major_version" default:"11"` - TargetMajorVersion string `name:"target_major_version" default:"14"` - PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"` - PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"` - EnablePatroniFailsafeMode *bool `name:"enable_patroni_failsafe_mode" default:"false"` + PodServiceAccountDefinition string `name:"pod_service_account_definition" default:""` + PodServiceAccountRoleBindingDefinition string `name:"pod_service_account_role_binding_definition" default:""` + MasterPodMoveTimeout time.Duration `name:"master_pod_move_timeout" default:"20m"` + DbHostedZone string `name:"db_hosted_zone" default:"db.example.com"` + AWSRegion string `name:"aws_region" default:"eu-central-1"` + WALES3Bucket string `name:"wal_s3_bucket"` + LogS3Bucket string `name:"log_s3_bucket"` + KubeIAMRole string `name:"kube_iam_role"` + WALGSBucket string `name:"wal_gs_bucket"` + GCPCredentials string `name:"gcp_credentials"` + WALAZStorageAccount string `name:"wal_az_storage_account"` + AdditionalSecretMount string `name:"additional_secret_mount"` + AdditionalSecretMountPath string `name:"additional_secret_mount_path" default:"/meta/credentials"` + EnableEBSGp3Migration bool `name:"enable_ebs_gp3_migration" default:"false"` + EnableEBSGp3MigrationMaxSize int64 `name:"enable_ebs_gp3_migration_max_size" default:"1000"` + DebugLogging bool `name:"debug_logging" default:"true"` + EnableDBAccess bool `name:"enable_database_access" default:"true"` + EnableTeamsAPI bool `name:"enable_teams_api" default:"true"` + EnableTeamSuperuser bool `name:"enable_team_superuser" default:"false"` + TeamAdminRole string `name:"team_admin_role" default:"admin"` + RoleDeletionSuffix string `name:"role_deletion_suffix" default:"_deleted"` + EnableTeamMemberDeprecation bool `name:"enable_team_member_deprecation" default:"false"` + EnableAdminRoleForUsers bool `name:"enable_admin_role_for_users" default:"true"` + EnablePostgresTeamCRD bool `name:"enable_postgres_team_crd" default:"false"` + EnablePostgresTeamCRDSuperusers bool `name:"enable_postgres_team_crd_superusers" default:"false"` + EnableMasterLoadBalancer bool `name:"enable_master_load_balancer" default:"true"` + EnableMasterPoolerLoadBalancer bool `name:"enable_master_pooler_load_balancer" default:"false"` + EnableReplicaLoadBalancer bool `name:"enable_replica_load_balancer" default:"false"` + EnableReplicaPoolerLoadBalancer bool `name:"enable_replica_pooler_load_balancer" default:"false"` + CustomServiceAnnotations map[string]string `name:"custom_service_annotations"` + CustomPodAnnotations map[string]string `name:"custom_pod_annotations"` + EnablePodAntiAffinity bool `name:"enable_pod_antiaffinity" default:"false"` + PodAntiAffinityTopologyKey string `name:"pod_antiaffinity_topology_key" default:"kubernetes.io/hostname"` + PodAntiAffinityPreferredDuringScheduling bool `name:"pod_antiaffinity_preferred_during_scheduling" default:"false"` + StorageResizeMode string `name:"storage_resize_mode" default:"pvc"` + EnableLoadBalancer *bool `name:"enable_load_balancer"` // deprecated and kept for backward compatibility + ExternalTrafficPolicy string `name:"external_traffic_policy" default:"Cluster"` + MasterDNSNameFormat StringTemplate `name:"master_dns_name_format" default:"{cluster}.{namespace}.{hostedzone}"` + ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{namespace}.{hostedzone}"` + PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"` + EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"` + EnableInitContainers *bool `name:"enable_init_containers" default:"true"` + EnableSidecars *bool `name:"enable_sidecars" default:"true"` + SharePGSocketWithSidecars *bool `name:"share_pg_socket_with_sidecars" default:"false"` + Workers uint32 `name:"workers" default:"8"` + APIPort int `name:"api_port" default:"8080"` + RingLogLines int `name:"ring_log_lines" default:"100"` + ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"` + TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"` + PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"` + PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"` + EnableReadinessProbe bool `name:"enable_readiness_probe" default:"false"` + ProtectedRoles []string `name:"protected_role_names" default:"admin,cron_admin"` + PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""` + SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"` + EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"` + EnableCrossNamespaceSecret bool `name:"enable_cross_namespace_secret" default:"false"` + EnablePgVersionEnvVar bool `name:"enable_pgversion_env_var" default:"true"` + EnableSpiloWalPathCompat bool `name:"enable_spilo_wal_path_compat" default:"false"` + EnableTeamIdClusternamePrefix bool `name:"enable_team_id_clustername_prefix" default:"false"` + MajorVersionUpgradeMode string `name:"major_version_upgrade_mode" default:"off"` + MajorVersionUpgradeTeamAllowList []string `name:"major_version_upgrade_team_allow_list" default:""` + MinimalMajorVersion string `name:"minimal_major_version" default:"9.6"` + TargetMajorVersion string `name:"target_major_version" default:"14"` + PatroniAPICheckInterval time.Duration `name:"patroni_api_check_interval" default:"1s"` + PatroniAPICheckTimeout time.Duration `name:"patroni_api_check_timeout" default:"5s"` + EnablePatroniFailsafeMode *bool `name:"enable_patroni_failsafe_mode" default:"false"` } // MustMarshal marshals the config or panics